Repository navigation
ci: run CI once per commit and start release only when VERSION changes - #5
Merged
Merged
Conversation
Every merge to main started two workflows: ci (full run) and release (plan job only). A release commit even ran the full CI twice, once from ci.yml and once inside release.yml. release.yml now starts only for pushes that change VERSION (every release commit does), and ci.yml skips its push run for "chore(release): vX.Y.Z" commits, whose CI runs inside release.yml (github.workflow is "release" there). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The release trigger and CI skip conditions disagree, leaving supported release commits without replacement CI or automatic publication.
1 open issue
What changed in this PR
This PR aims to avoid duplicate CI runs in Pickup’s release process and prevent release workflows from starting on ordinary pushes.
Changes:
- Restricts automatic release runs to pushes that change
VERSION. - Skips standalone push-CI jobs for release-prefixed commits, relying on reusable CI from the release workflow.
- Documents the intended CI and release behavior.
| File | Description |
|---|---|
docs/RELEASING.md |
Documents CI deduplication and the release trigger. |
.github/workflows/release.yml |
Adds the VERSION push-path filter. |
.github/workflows/ci.yml |
Adds release-commit skip conditions to all eight jobs. |
Review effort: Balanced
Review: the release trigger (paths: VERSION) and the CI skip (commit subject) selected different commits, so a release commit without a VERSION change, a fork with CI enabled, or a VERSION change without the release prefix ended up with no CI or with two runs. scripts/release-decision.sh now decides for both: a push in macx/pickup that changes VERSION and whose tag does not exist yet (or a manual run of release.yml). A route job in ci.yml applies it to all eight jobs; release.yml's plan job uses it too. The same-version first release is history (v0.1.0 exists). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

What and why
Every merge to
mainstarted two workflows:ci(full run) andrelease(only theplanjob, which then found "not a release commit"). A release commit even ran the full CI twice: once fromci.yml(push) and once insiderelease.yml(reusableci.ymlbefore releasing). Requested by the maintainer.scripts/release-decision.shdecides whether a commit is released: official repository (macx/pickup), a push that changesVERSIONagainst its parent, and the tagvX.Y.Zdoes not exist yet; or a manual run ofrelease.yml.release.yml:pushtomainhaspaths: [VERSION], and theplanjob uses the shared rule. Every release commit fromprepare-releasebumpsVERSION.workflow_dispatch(re-run after a failure) is unchanged.ci.yml: a smallroutejob (ubuntu) applies the same rule to its own push run; all eight jobs need it and are skipped only whenrelease.ymlwill run CI for the commit. Inside the call fromrelease.yml(github.workflowisrelease), and for pull requests, the schedule and manual runs, every job runs as before. Forks with CI enabled never match the rule, so their CI always runs.releaseonly shows up for real releases.docs/RELEASING.mdupdated.How it was tested
actionlinton all workflows,scripts/pin-actions.sh --check,shellcheck,scripts/security-checks.shscripts/release-decision.shexercised in a throwaway worktree: normal push, fork, manual run with existing tag, release commit 0.1.0 → 0.2.0, same commit in a fork, pull_request event, VERSION changed but tag existsmain. To check after merging: the next normal merge starts onlyci; the next release commit startsrelease(with CI inside) and skips the jobs of the push run ofci.Checklist
🤖 Generated with Claude Code