Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/contributing/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ Each learning maps to a check above.
- **v1.6.0 prep** — slimming the README to a marketing landing renamed the canonical `DocumentSession document = …` example variable to `doc`, which silently broke `DocumentationCoverageTest.readmeShouldUseCanonicalDslAndAvoidLegacyApis` because the test asserts the literal string `document.pageFlow(` is present. *Mitigation*: any rewrite of the README "Hello world" snippet must keep `DocumentSession document` as the variable name and `document.pageFlow(`, `document.buildPdf()`, `GraphCompose.document(` as the literal canonical fingerprints the guard scans for. Renaming the variable is a guard-test break, not a stylistic preference.
- **v1.6.0 post-release** — the `examples-generation` CI job introduced after v1.6.0 went red on the first run because `examples/pom.xml` and `benchmarks/pom.xml` declare a `<graphcompose.version>` property used by their `graphcompose` dependency, and `cut-release.ps1` was only flipping the project's own `<version>` tag (the first `<version>` in each file). The subordinate POMs kept `<graphcompose.version>1.6.0-beta.1</graphcompose.version>` after the release commit; CI couldn't resolve a `1.6.0-beta.1` artifact (it never existed on any registry), so `mvnw -f examples/pom.xml clean compile` failed at dependency resolution. *Mitigation*: `Update-PomVersion` in `cut-release.ps1` now flips both the first `<version>` tag *and* a `<graphcompose.version>...</graphcompose.version>` property if present, in the same call. Future agents need not touch this — running the script handles both.
- **v1.6.5 prep** — the subordinate-POM `<graphcompose.version>` property flip from the v1.6.0 lesson above is now **superseded**: `examples/` and `benchmarks/` were converted to a reactor under a non-published `aggregator/pom.xml`, so they inherit their version from `graphcompose-build` and declare `<graphcompose.version>${project.version}</graphcompose.version>` instead of a literal. The library `pom.xml` stays standalone, so JitPack coordinates never change. Version drift is now structurally impossible *and* caught by `VersionConsistencyGuardTest` (wired into CI's guard job and the section 0.B gate). `cut-release.ps1` bumps the library pom, the aggregator, both inherited parent refs, and the README install snippets in one commit; `.github/workflows/release.yml` then gates the tag on `verify` and publishes the GitHub Release automatically. *Mitigation*: section 0.D verifies all four version sites agree; the guard fails the verify gate if any hand-edit leaves them out of sync.
- **v1.6.5 cut** — `cut-release.ps1` Step 4 (`ShowcaseSync`) aborted with `Could not find artifact io.github.demchaav:graphcompose:jar:1.6.5 in central` after Step 1 bumped the four pom.xml files to `1.6.5`: the examples module depends on `graphcompose:${project.version}`, the previous release (`1.6.4`) was the only version in the local `~/.m2`, and Step 4 had no install gate to put the just-bumped version there first. Cut had to be finished by hand — install root, re-run ShowcaseSync, verify, commit, tag, push. *Mitigation*: `Run-ShowcaseSync` now runs `./mvnw -B -ntp -DskipTests install -pl .` immediately before `exec:java`, in both Release and PostReleaseOnly modes; the dry-run preview shows both steps. Pre-flight branch / clean / sync gates are now relaxed for `-DryRun` so the script can be previewed from a feature branch while iterating on it.

---

Expand Down
66 changes: 47 additions & 19 deletions scripts/cut-release.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,30 @@ function Run-ShowcaseSync {
# as a single literal argument.
$execProp = '"-Dexec.mainClass=com.demcha.examples.support.ShowcaseSync"'
if ($DryRun) {
Write-Host " [DRY RUN] $mvnw -B -ntp -DskipTests install -pl ." -ForegroundColor Yellow
Write-Host " [DRY RUN] $mvnw -f examples/pom.xml exec:java $execProp" -ForegroundColor Yellow
return
}
Push-Location $repoRoot
try {
# ShowcaseSync runs from the examples module, which depends on
# io.github.demchaav:graphcompose:${project.version}. After Step 1
# bumps the four pom.xml files to the new release version, that
# artifact is not yet in the local m2 cache — only the previous
# release is — so exec:java fails dependency resolution with
# "Could not find artifact ...:graphcompose:jar:<new-version>".
# Install the root artifact first so the examples module can
# resolve it. Bug surfaced during v1.6.5 cut: Step 4 aborted with
# exit 1; we had to install by hand and resume manually.
Write-Host " > $mvnw -B -ntp -DskipTests install -pl ." -ForegroundColor DarkGray
& $mvnw -B -ntp -DskipTests install -pl . 2>&1 | ForEach-Object {
if ($_ -match 'BUILD SUCCESS|BUILD FAILURE|ERROR') {
Write-Host " $_" -ForegroundColor DarkGray
}
}
if ($LASTEXITCODE -ne 0) {
throw "Install root artifact failed (exit $LASTEXITCODE)"
}
& $mvnw -f examples/pom.xml exec:java $execProp 2>&1 | ForEach-Object {
if ($_ -match 'Synced|Wrote manifest|BUILD SUCCESS|BUILD FAILURE|ERROR') {
Write-Host " $_" -ForegroundColor DarkGray
Expand Down Expand Up @@ -337,28 +356,37 @@ try {

Step 0 "Pre-flight checks"

# 1. On develop branch?
# In -DryRun mode the script never mutates anything, so the branch /
# working-tree / origin-sync gates are relaxed: a maintainer can preview
# what a release cut would do from a feature branch (e.g. while iterating
# on the script itself) without having to switch to develop and back.
# Live cuts still fail these gates loudly.
$branch = (git rev-parse --abbrev-ref HEAD).Trim()
if ($branch -ne 'develop') {
throw "Not on develop branch (currently on $branch). Switch to develop first."
}
Note "branch: develop OK"
if ($DryRun) {
Note "branch: $branch (gate relaxed for -DryRun)"
} else {
# 1. On develop branch?
if ($branch -ne 'develop') {
throw "Not on develop branch (currently on $branch). Switch to develop first."
}
Note "branch: develop OK"

# 2. Working tree clean?
$status = git status --porcelain
if ($status) {
throw "Working tree has uncommitted changes. Commit or stash first."
}
Note "working tree: clean OK"

# 3. In sync with origin?
git fetch origin develop --quiet
$local = (git rev-parse develop).Trim()
$remote = (git rev-parse origin/develop).Trim()
if ($local -ne $remote) {
throw "Local develop ($local) is not in sync with origin/develop ($remote). Pull/push first."
# 2. Working tree clean?
$status = git status --porcelain
if ($status) {
throw "Working tree has uncommitted changes. Commit or stash first."
}
Note "working tree: clean OK"

# 3. In sync with origin?
git fetch origin develop --quiet
$local = (git rev-parse develop).Trim()
$remote = (git rev-parse origin/develop).Trim()
if ($local -ne $remote) {
throw "Local develop ($local) is not in sync with origin/develop ($remote). Pull/push first."
}
Note "in sync with origin/develop OK"
}
Note "in sync with origin/develop OK"

# 4. Tag doesn't already exist?
$existingTag = git tag -l $tag
Expand Down