CI: least-privilege token, dedupe runs, release timeout, Node 24 actions#348
Merged
Conversation
- validate.yaml: add an explicit least-privilege 'permissions: contents: read' block (it previously ran with the repo-default token scope; release.yaml already scopes its token). - validate.yaml: add a concurrency group keyed on workflow + branch/PR so a push and its pull_request no longer run the full 3-OS matrix twice, and superseded runs are cancelled. - release.yaml: add timeout-minutes: 30 to the release job (validate already had a timeout; release had none). - Bump all actions off the deprecated Node 20 runtime (GitHub force- migrates Node 20 actions on 2026-06-02 and removes Node 20 on 2026-09-16): actions/checkout v4->v6, actions/setup-go v5->v6, goreleaser/goreleaser-action v6->v7. All target Node 24. - validate.yaml: build with -o cmd/desync/ to match the project's documented build convention.
github.ref is refs/heads/<branch> for push but refs/pull/N/merge for pull_request, so the previous key put them in different concurrency groups and the matrix still ran twice. github.ref_name is the bare branch name for push and equals github.head_ref for pull_request, so the two events now share one group and the duplicate run is cancelled.
cancel-in-progress dedupes the matrix by cancelling the duplicate push run mid-flight, which still starts 3 jobs and leaves a cancelled run in the Actions tab. Restrict the push trigger to master so a feature-branch push with an open PR never creates a push run at all; the pull_request run is the single source of CI for branches. Pushes to master (merges) still run once. The concurrency group stays for cancelling superseded in-progress runs within an event stream.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Applies the remaining CI improvements (items 5–8 from the earlier review). Workflow-only changes. Validate CI green on all 3 OSes; item 6 verified live.
5. Least-privilege token (
validate.yaml)Added
permissions: contents: read(the workflow only reads the repo; it previously ran with the repo-default token scope).release.yamlalready scopes its token tocontents: write.6. Stop running the matrix twice (
validate.yaml)A push to a branch with an open PR fired both
pushandpull_request, running the full 3-OS matrix twice.Approach: scope the
pushtrigger tobranches: [master]and keeppull_request: ['**'], plus aconcurrencygroup (github.head_ref || github.ref_name,cancel-in-progress: true) for cancelling superseded in-progress runs within an event stream.This eliminates the duplicate at the source rather than relying on
cancel-in-progressto tear down an already-started duplicate (which still spun up 3 jobs and left a cancelled run in the Actions tab). Verified live:pull_request), nopushrun, no cancelled jobsmaster→ 1 run (push)Tradeoff: a feature branch with no open PR gets no CI until a PR is opened (previously every branch push ran CI). Standard pattern; PR-driven CI is the intended coverage.
7. Release job timeout + build convention
release.yaml: addedtimeout-minutes: 30to the release job (validatealready had one;releasehad none).validate.yaml:go build ./cmd/desync→go build -o cmd/desync/ ./cmd/desyncto match the documented build convention (output is git-ignored; harmless in CI).8. Move off the deprecated Node 20 action runtime
All pinned actions ran on Node 20, which GitHub force-migrates to Node 24 on 2026-06-02 and removes on 2026-09-16. Bumped to latest majors, all Node 24:
actions/checkoutv4 → v6actions/setup-gov5 → v6 (go-version-fileinput unchanged)goreleaser/goreleaser-actionv6 → v7 (inputs unchanged; already targeting goreleaser v2)Coverage caveat
release.yamlonly runs on tag pushes, so its changes (timeout + the checkout/setup-go/goreleaser bumps there) are not exercised by this PR's CI — they're first validated on the next tagged release. Allvalidate.yamlchanges are covered by this PR's run.