Run the version increment check only where the base ref is fetched - #711
Merged
Merged
Conversation
`CheckVersionIncrement` compares the project version against `origin/<base>:version.gradle.kts`, but the task was a `dependsOn` of the `check` lifecycle task, so it also ran during `./gradlew build` on every CI pull request. The Ubuntu CI workflow does a shallow checkout and never fetches the base ref, so the fail-closed comparison aborted the build with `git exit code 128: invalid object name 'origin/master'`. Windows CI survived only by accident (`fetch-depth: 0`). Remove the `check` dependency. The base comparison now runs only via the `Version Guard` workflow (which fetches the base and posts the required status) and before `publishToMavenLocal` (local; no base comparison). No protected-branch PR coverage is lost — the dedicated workflow already covers it — and the fix applies to consumer-specific build workflows too, not just config's own. Add a regression test asserting `check` does not depend on the task, and correct the design note that wrongly recorded "no wiring change needed". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request fixes CI breakage caused by checkVersionIncrement running during generic ./gradlew build workflows that do not fetch the PR base branch ref, by decoupling the increment check from the check lifecycle and ensuring it runs only in contexts where its prerequisites are satisfied.
Changes:
- Removed
checkVersionIncrementfrom thechecklifecycle wiring so it no longer runs in generic CI build workflows (e.g. shallow Ubuntu builds). - Kept
checkVersionIncrementas a dependency of allpublishToMavenLocaltasks for local integration-test publishing safety. - Updated tests and task documentation to prevent regressions and to record the incident/root cause.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| buildSrc/src/main/kotlin/io/spine/gradle/publish/IncrementGuard.kt | Removes check dependency wiring; documents why the task must run only via the dedicated Version Guard workflow (with base ref fetched) and before publishToMavenLocal. |
| buildSrc/src/test/kotlin/io/spine/gradle/publish/IncrementGuardTest.kt | Updates wiring assertions: verifies publishToMavenLocal depends on the guard task and adds regression coverage that check does not. |
| .agents/tasks/version-guard-parallel-pr-revalidation.md | Corrects prior design note and records the regression incident and mitigation for future reference. |
armiol
approved these changes
Jun 26, 2026
alexander-yevsyukov
added a commit
that referenced
this pull request
Jun 26, 2026
Decoupling `checkVersionIncrement` from `check` (PR #711) was necessary but not sufficient: `./gradlew build` still pulls the task into the graph via `publishToMavenLocal` (Spine integration tests consume fresh `~/.m2` artifacts), so a consumer's Ubuntu CI build re-hit the same failure: Unable to read `version.gradle.kts` from base `origin/master` (git exit code 128): fatal: invalid object name 'origin/master'. The root cause is deeper than wiring. `checkIncrementedAgainstBase` gated on `GITHUB_BASE_REF`, which GitHub sets in *every* pull-request build — the Ubuntu and Windows CI builds as well as the dedicated Version Guard workflow — but only the Version Guard workflow fetches the base ref. So the base comparison ran (and failed closed) in builds that legitimately do a shallow checkout. Gate the comparison on an explicit signal instead: `increment-guard.yml` sets `VERSION_GUARD=true` on the step that runs the task (right after fetching the base), and `checkIncrementedAgainstBase` runs only when that signal is present (new tested predicate `IncrementGuard.shouldCompareToBase`). Outside the Version Guard workflow the comparison is skipped and `checkNotPublished` remains the guard; inside it, the fail-closed behavior is preserved. `check` stays decoupled. Co-Authored-By: Claude Opus 4.8 <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.
Problem
Applying the latest
configto a consumer repo (compiler) broke its Ubuntu CI build:Root cause
Commit 12e586f taught
CheckVersionIncrementto compare the project version against the base branch viagit show origin/<base>:version.gradle.kts, and added the base-fetch step only to the dedicatedVersion Guardworkflow (increment-guard.yml).But
checkVersionIncrementwas adependsOnof thechecklifecycle task (added in #708), so it also ran inside./gradlew buildon every CI pull request — includingbuild-on-ubuntu.yml, which does a shallow checkout and never fetchesorigin/master. The fail-closed comparison then aborted the build. Windows CI survived only by accident (it usesfetch-depth: 0, which makesorigin/masterresolvable).The design note in the task doc had even recorded the faulty assumption verbatim: "no wiring change needed (both paths inherit the task)." That "inheritance" is exactly the bug — the
checkpath fires in the plain build workflows, not just the dedicated Version Guard one.Fix
Decouple the check from the
check/buildlifecycle so it runs only where its precondition (a fetched base ref) is guaranteed:IncrementGuard.kt— removedtasks.check.configure { dependsOn(checkVersion) }(and the now-unusedbase.checkimport). The CI gate stays with theVersion Guardworkflow (which fetches the base and posts the required status); thepublishToMavenLocaldependency is unchanged for local integration-test publishes. KDoc/comments now explain why it is deliberately not wired intocheck.IncrementGuardTest.kt— replaced the old "depends oncheck" assertion with a regression guard asserting it does not, so this cannot silently regress.Why this is safe
No coverage is lost. Every case the
checkpath handled on a protected-branch PR is already covered by the dedicatedVersion Guardworkflow, and the registry's immutability remains the final publish backstop. Locally,GITHUB_BASE_REFis unset, sopublishToMavenLocalnever did the base comparison anyway. Decoupling at the task level also fixes any consumer-specific build workflow, not just config's own.Verification
JAVA_HOME=17 ./gradlew :buildSrc:build detektis green; allIncrementGuardTestcases pass, including the newkeep 'checkVersionIncrement' out of › the 'check' lifecycle task. Reviewed byspine-code-review,kotlin-engineer, andreview-docs— all APPROVE.Reviewer notes
compilerre-applies config, its Ubuntu CI will stop running the base-compare duringbuildand pass.Version Guardstatus context) is unaffected and still applies.🤖 Generated with Claude Code