diff --git a/skills/github-project/references/dependency-management.md b/skills/github-project/references/dependency-management.md index 1793b2f..876bbb0 100644 --- a/skills/github-project/references/dependency-management.md +++ b/skills/github-project/references/dependency-management.md @@ -91,6 +91,27 @@ updates: dependency-type: "development" ``` +### SHA-Pinned Actions — Comment Maintenance and Deprecation Warnings + +**Dependabot maintains the version comment, not just the SHA.** With the `github-actions` ecosystem enabled, a bump rewrites both the pinned SHA **and** the trailing `# vX.Y.Z` comment in one diff: + +```diff +- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 ++ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 +``` + +So annotating bare SHA pins once (with **API-verified** tags — resolve each SHA via `gh api repos/OWNER/ACTION/tags`) puts them in the exact format Dependabot then keeps current. Without the `github-actions` ecosystem declared, action pins are only ever updated by hand and silently drift. + +**A runtime-deprecation warning is not cleared by a version bump unless the newer release changed the runtime.** Before claiming "bumping action X fixes the Node NN deprecation", check the target version's `action.yml`: + +```bash +gh api -H "Accept: application/vnd.github.raw" \ + repos/OWNER/ACTION/contents/action.yml?ref= | grep -A1 '^runs:' +# runs.using: 'node20' → still deprecated; the bump does NOT clear the warning +``` + +An action already pinned at its latest release can still emit the warning if upstream ships no newer-runtime build — the fix is then an upstream change or a replacement action, not a bump. Don't assert the warning is fixed off the version number alone. + ## Renovate ### Auto-merge Configuration (Recommended) diff --git a/skills/github-project/references/merge-strategy.md b/skills/github-project/references/merge-strategy.md index 5e09b33..e31c7e9 100644 --- a/skills/github-project/references/merge-strategy.md +++ b/skills/github-project/references/merge-strategy.md @@ -158,6 +158,57 @@ Mitigations, in increasing strength: Neither catches a semantic conflict no test covers. Post-merge push CI on the default branch stays the last line of defence — keep it. +## Enabling a merge queue + +The classic branch-protection REST API does **not** expose a merge-queue toggle, so a repository **ruleset** is the only scriptable path. The `merge_queue` rule is **repository-level only** — an org-level ruleset rejects it, so a queue is always a per-repo decision. + +```bash +gh api -X POST repos/OWNER/REPO/rulesets --input - <<'JSON' +{ + "name": "merge-queue-main", + "target": "branch", + "enforcement": "active", + "bypass_actors": [ + { "actor_id": 5, "actor_type": "RepositoryRole", "bypass_mode": "always" } + ], + "conditions": { "ref_name": { "include": ["refs/heads/main"], "exclude": [] } }, + "rules": [ + { + "type": "merge_queue", + "parameters": { + "merge_method": "SQUASH", + "grouping_strategy": "ALLGREEN", + "check_response_timeout_minutes": 30, + "max_entries_to_build": 5, + "max_entries_to_merge": 5, + "min_entries_to_merge": 1, + "min_entries_to_merge_wait_minutes": 5 + } + }, + { + "type": "required_status_checks", + "parameters": { + "strict_required_status_checks_policy": false, + "required_status_checks": [ + { "context": "Tests (8.2)", "integration_id": 15368 } + ] + } + } + ] +} +JSON +``` + +Parameters and gotchas: + +- `merge_method`: `SQUASH` | `MERGE` | `REBASE`. The queue owns the merge method for every entry, so per-PR choice disappears. `SQUASH`/`MERGE` stay GitHub-signed; `REBASE` re-creates commits **unsigned** — on a signed-commits branch, prefer `SQUASH`/`MERGE`. +- `grouping_strategy`: `ALLGREEN` (every queued entry must pass) or `HEADGREEN` (only the group's head commit — all changes combined — must pass). `ALLGREEN` is the safe default; `HEADGREEN` only saves CI under contention. +- `check_response_timeout_minutes`: a required check that has not reported by then is treated as **failed** and the entry is ejected. Size it above one CI cycle. +- `min_entries_to_merge` + `min_entries_to_merge_wait_minutes`: the wait only holds a smaller-than-minimum group. With `min_entries_to_merge: 1` **the wait value is inert** — a single entry already meets the minimum, so it never batches. Only raise the minimum (and the wait) if you actually want to batch, e.g. a Dependabot burst. +- `required_status_checks[].integration_id: 15368` pins each required context to the **GitHub Actions app**, so another app cannot satisfy (spoof) the context. Every required-check workflow must also carry an `on: merge_group:` trigger, or its checks never report on the queue and every group times out. +- Enable the queue in **one surface only**. If a classic branch-protection rule already gates the branch, leave reviews/conversation-resolution there and put the queue + required checks in the ruleset — then set the classic `strict` ("require branches up to date") flag to **false**: the queue makes it redundant and it otherwise forces author-side update-branch churn. +- `enforcement: "evaluate"` dry-runs the ruleset (logs what it *would* block) without enforcing — a soft launch before `active`. Rollback is one call: delete the ruleset (or set `enforcement: "disabled"`) and restore the classic `strict` flag. + ## Troubleshooting ### Diagnose `mergeStateStatus: BLOCKED` before naming a cause