Skip to content

Run the version increment check only where the base ref is fetched - #711

Merged
alexander-yevsyukov merged 1 commit into
masterfrom
fix-version-guard-check-wiring
Jun 26, 2026
Merged

alexander-yevsyukov merged 1 commit into
masterfrom
fix-version-guard-check-wiring

Conversation

@alexander-yevsyukov

Copy link
Copy Markdown
Contributor

Problem

Applying the latest config to a consumer repo (compiler) broke its Ubuntu CI build:

org.gradle.api.GradleException: Unable to read `version.gradle.kts` from base `origin/master`
(git exit code 128): fatal: invalid object name 'origin/master'..
Ensure the Version Guard workflow fetches the base branch before this check.

Root cause

Commit 12e586f taught CheckVersionIncrement to compare the project version against the base branch via git show origin/<base>:version.gradle.kts, and added the base-fetch step only to the dedicated Version Guard workflow (increment-guard.yml).

But checkVersionIncrement was a dependsOn of the check lifecycle task (added in #708), so it also ran inside ./gradlew build on every CI pull request — including build-on-ubuntu.yml, which does a shallow checkout and never fetches origin/master. The fail-closed comparison then aborted the build. Windows CI survived only by accident (it uses fetch-depth: 0, which makes origin/master resolvable).

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 check path fires in the plain build workflows, not just the dedicated Version Guard one.

Fix

Decouple the check from the check/build lifecycle so it runs only where its precondition (a fetched base ref) is guaranteed:

  • IncrementGuard.kt — removed tasks.check.configure { dependsOn(checkVersion) } (and the now-unused base.check import). The CI gate stays with the Version Guard workflow (which fetches the base and posts the required status); the publishToMavenLocal dependency is unchanged for local integration-test publishes. KDoc/comments now explain why it is deliberately not wired into check.
  • IncrementGuardTest.kt — replaced the old "depends on check" assertion with a regression guard asserting it does not, so this cannot silently regress.
  • task doc — corrected the falsified design note and logged the incident.

Why this is safe

No coverage is lost. Every case the check path handled on a protected-branch PR is already covered by the dedicated Version Guard workflow, and the registry's immutability remains the final publish backstop. Locally, GITHUB_BASE_REF is unset, so publishToMavenLocal never 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 detekt is green; all IncrementGuardTest cases pass, including the new keep 'checkVersionIncrement' out of › the 'check' lifecycle task. Reviewed by spine-code-review, kotlin-engineer, and review-docs — all APPROVE.

Reviewer notes

  • After this lands and compiler re-applies config, its Ubuntu CI will stop running the base-compare during build and pass.
  • The per-repo branch-protection item from the original design (requiring the Version Guard status context) is unaffected and still applies.

🤖 Generated with Claude Code

`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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 checkVersionIncrement from the check lifecycle wiring so it no longer runs in generic CI build workflows (e.g. shallow Ubuntu builds).
  • Kept checkVersionIncrement as a dependency of all publishToMavenLocal tasks 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.

@alexander-yevsyukov
alexander-yevsyukov merged commit 6b963d4 into master Jun 26, 2026
4 checks passed
@alexander-yevsyukov
alexander-yevsyukov deleted the fix-version-guard-check-wiring branch June 26, 2026 16:30
@github-project-automation github-project-automation Bot moved this from 🏗 In progress to ✅ Done in v2.0 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants