Fix release workflow: ignore .kotlin and set reckon.stage=final#46
Merged
Fix release workflow: ignore .kotlin and set reckon.stage=final#46
Conversation
buildSrc/build.gradle.kts adds ../shared-build-logic as a Kotlin source dir, so the Kotlin compiler creates buildSrc/.kotlin/sessions/*.salive during the settings phase. Without .kotlin in .gitignore, JGit reports the tree as dirty during Reckon's clean check, so the tag-is-current rebuild branch (Reckoner.java:122) is skipped and a SNAPSHOT falls out instead. That broke the 0.0.17 release with "Task 'publishToSonatype' not found". Generated with Claude Code
Short-circuits Reckon's clean check: the final-stage branch in Reckoner.reckonTargetVersion returns the target normal directly, before ever reaching the rebuild branch that requires isClean(). Defensive against future tools dropping untracked cache dirs into the tree during the settings phase. Generated with Claude Code
1 task
ogolberg
added a commit
that referenced
this pull request
May 6, 2026
## Summary - Tagging `0.1.0` published as `0.1.1` to Maven Central because the release workflow passed `-Preckon.stage=final`. - With `stage` set, reckon skips the rebuild branch in `Reckoner.reckonTargetVersion` that would return the tag's exact version when `isClean() && currentVersion.isPresent() && stage == null`, and instead computes a target normal via `defaultInferredScope=patch` — bumping `0.1.0` to `0.1.1`. - The `.kotlin` → `.gitignore` change from #46 is the real fix for the untracked-file clean-check problem; the `-Preckon.stage=final` "defense in depth" is counterproductive. ## Verification At tag `0.1.0` with a clean tree: ``` $ ./gradlew properties 2>&1 | grep -E '^version:|Reckoned' Reckoned version: 0.1.0 version: 0.1.0 ``` With `-Preckon.stage=final` (the bug): ``` $ ./gradlew properties -Preckon.stage=final 2>&1 | grep -E '^version:|Reckoned' Reckoned version: 0.1.1 version: 0.1.1 ``` ## Test plan - [ ] After merge, re-push `0.1.0` (or cut a new tag) and confirm the release workflow publishes the tagged version, not tag+1. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
Root cause
The 0.0.17 release failed with
Task 'publishToSonatype' not found in root project 'testkit-plugins' and its subprojects. The failed run resolvedReckoned version: 0.0.18-SNAPSHOTrather than0.0.17, which madeisRelease()false, theif (isRelease()) { nexusPublishing { sonatype { ... } } }block skip, and thepublishToSonatypetask never get registered.The chain from release-tag-push to SNAPSHOT version:
buildSrc/build.gradle.ktsadds../shared-build-logic/src/main/kotlinas a Kotlin source dir. No equivalent in expediter.buildSrc/.kotlin/sessions/kotlin-compiler-<id>.saliveas a daemon liveness file..kotlinwas not ignored. JGit'sstatus()reports the tree as dirty withuntracked=[buildSrc/.kotlin/sessions/kotlin-compiler-...salive].GitInventorySupplier.isClean()returnsfalse(confirmed via--debug:Git repository is not clean: ... untracked=[buildSrc/.kotlin/sessions/kotlin-compiler-...salive]).Reckoner.reckonTargetVersion(reckon-core-2.0.0), the "rebuild" branch requires all three ofisClean() && currentVersion.isPresent() && stage == null. Withclean=false, that branch is skipped, falling through to the snapshot path — output0.0.18-SNAPSHOT.isRelease()checks for-SNAPSHOTsuffix → false → nosonatype {}configured → nopublishToSonatypetask registered →TaskSelectionException.Fix (defense in depth)
.kotlinto.gitignore— removes the untracked session file from Reckon's view so the clean check passes naturally. Also quietsgit statusduring local development.-Preckon.stage=finalin the release workflow — short-circuits the clean check entirely. The final-stage branch (Reckoner.reckonTargetVersion, reckon-core-2.0.0) returns the target normal before ever reaching the rebuild branch. Defensive against any future tool dropping a new untracked cache dir into the tree during the settings phase.Reproduction
Locally, fresh clone at the
0.0.17tag (matching actions/checkout'sgit init, full fetch,checkout --force refs/tags/0.0.17):With
.kotlinignored (committed + tag moved to that commit):Why expediter isn't affected
Expediter's
buildSrc/build.gradle.ktsdoesn't add external Kotlin source dirs, so the Kotlin compiler never createsbuildSrc/.kotlin/during settings evaluation. Same Reckon config, same gitignore, but no untracked file to trip Reckon's clean check. Expediter's-Preckon.stage=finaldrop ine0fcecdwith the claim it's redundant actually does hold for expediter — just not here.Test plan
0.0.17(or cut0.0.18) and confirm the release workflow publishes to Sonatype🤖 Generated with Claude Code