Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions skills/github-project/references/dependency-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -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=<tag> | 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)
Expand Down
51 changes: 51 additions & 0 deletions skills/github-project/references/merge-strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading