mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
ci: add PR and issue grooming workflows (#797)
## Summary - add stale triage for inactive issues and PRs with conservative close windows - add PR health labeling for branches that are behind, conflicted, or failing checks - create the maintenance labels idempotently before applying them ## Validation - `go run github.com/rhysd/actionlint/cmd/actionlint@latest .github/workflows/pr-health.yml .github/workflows/stale.yml` - `act workflow_dispatch -W .github/workflows/pr-health.yml --dryrun` - `act workflow_dispatch -W .github/workflows/stale.yml --dryrun` - `git diff --cached --check` Note: local `pre-commit` was not installed, so the commit was created with `--no-verify` after the workflow-specific validation above passed.
This commit is contained in:
parent
ae2122fda8
commit
2e6595bb08
2 changed files with 151 additions and 0 deletions
91
.github/workflows/pr-health.yml
vendored
Normal file
91
.github/workflows/pr-health.yml
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
name: PR Health
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize, ready_for_review]
|
||||
schedule:
|
||||
# Keep labels fresh even when base branches move or checks finish later.
|
||||
- cron: '23 14 * * 1-5'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
checks: read
|
||||
statuses: read
|
||||
|
||||
concurrency:
|
||||
group: pr-health-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
steps:
|
||||
- name: Ensure maintenance labels exist
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
gh label create "status: needs rebase" \
|
||||
--repo "$REPO" \
|
||||
--color "fbca04" \
|
||||
--description "Pull request branch is behind the base branch" \
|
||||
--force
|
||||
gh label create "status: has conflicts" \
|
||||
--repo "$REPO" \
|
||||
--color "d73a4a" \
|
||||
--description "Pull request has merge conflicts with the base branch" \
|
||||
--force
|
||||
gh label create "status: ci failing" \
|
||||
--repo "$REPO" \
|
||||
--color "d73a4a" \
|
||||
--description "Required or reported CI checks are failing" \
|
||||
--force
|
||||
|
||||
- name: Label open pull requests
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if jq -e '.pull_request.number' "$GITHUB_EVENT_PATH" >/dev/null; then
|
||||
pr_numbers="$(jq -r '.pull_request.number' "$GITHUB_EVENT_PATH")"
|
||||
else
|
||||
pr_numbers="$(gh pr list --repo "$REPO" --state open --limit 100 --json number --jq '.[].number')"
|
||||
fi
|
||||
|
||||
for pr in $pr_numbers; do
|
||||
data="$(gh pr view "$pr" --repo "$REPO" \
|
||||
--json mergeStateStatus,statusCheckRollup)"
|
||||
|
||||
merge_state="$(jq -r '.mergeStateStatus // "UNKNOWN"' <<<"$data")"
|
||||
check_state="$(jq -r '
|
||||
[
|
||||
.statusCheckRollup[]
|
||||
| select((.conclusion // .state // "") as $s
|
||||
| ["FAILURE", "TIMED_OUT", "ACTION_REQUIRED", "CANCELLED", "ERROR"] | index($s))
|
||||
]
|
||||
| if length > 0 then "failing" else "passing" end
|
||||
' <<<"$data")"
|
||||
|
||||
if [[ "$merge_state" == "BEHIND" ]]; then
|
||||
gh pr edit "$pr" --repo "$REPO" --add-label "status: needs rebase"
|
||||
else
|
||||
gh pr edit "$pr" --repo "$REPO" --remove-label "status: needs rebase" || true
|
||||
fi
|
||||
|
||||
if [[ "$merge_state" == "DIRTY" ]]; then
|
||||
gh pr edit "$pr" --repo "$REPO" --add-label "status: has conflicts"
|
||||
else
|
||||
gh pr edit "$pr" --repo "$REPO" --remove-label "status: has conflicts" || true
|
||||
fi
|
||||
|
||||
if [[ "$check_state" == "failing" ]]; then
|
||||
gh pr edit "$pr" --repo "$REPO" --add-label "status: ci failing"
|
||||
else
|
||||
gh pr edit "$pr" --repo "$REPO" --remove-label "status: ci failing" || true
|
||||
fi
|
||||
done
|
||||
60
.github/workflows/stale.yml
vendored
Normal file
60
.github/workflows/stale.yml
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
name: Stale Triage
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Daily weekday pass during US morning hours.
|
||||
- cron: '17 15 * * 1-5'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: stale-triage
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Ensure stale label exists
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh label create "status: stale" \
|
||||
--repo "${{ github.repository }}" \
|
||||
--color "ededed" \
|
||||
--description "No recent activity; may be closed if it stays inactive" \
|
||||
--force
|
||||
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
operations-per-run: 200
|
||||
remove-stale-when-updated: true
|
||||
exempt-all-milestones: true
|
||||
exempt-issue-labels: pinned,security,good first issue,help wanted,needs reproduction
|
||||
exempt-pr-labels: pinned,security,dependencies,release,do not merge
|
||||
|
||||
stale-issue-label: "status: stale"
|
||||
days-before-issue-stale: 60
|
||||
days-before-issue-close: 14
|
||||
stale-issue-message: >
|
||||
This issue has had no recent activity and is being marked stale.
|
||||
Please comment with new context if it is still relevant.
|
||||
close-issue-message: >
|
||||
Closing this issue due to continued inactivity. It can be reopened
|
||||
if there is new information or a clear next step.
|
||||
|
||||
stale-pr-label: "status: stale"
|
||||
days-before-pr-stale: 30
|
||||
days-before-pr-close: 14
|
||||
stale-pr-message: >
|
||||
This pull request has had no recent activity and is being marked
|
||||
stale. Please rebase, resolve conflicts, or comment if it is still
|
||||
actively being worked.
|
||||
close-pr-message: >
|
||||
Closing this pull request due to continued inactivity. It can be
|
||||
reopened when it is ready for review again.
|
||||
Loading…
Add table
Add a link
Reference in a new issue