-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrelease.sh
More file actions
executable file
·128 lines (113 loc) · 5.88 KB
/
Copy pathrelease.sh
File metadata and controls
executable file
·128 lines (113 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/bin/bash
set -e # Exit the script if any command fails
# Cuts a release by setting the version, tagging, and pushing.
# Pushing the tag (vA.B.C) triggers .github/workflows/release.yml, which
# builds, signs, and deploys to Maven Central and creates the GitHub
# release. This script only prepares git state; it does NOT deploy.
if [ -z "$1" ]; then
echo "Please provide version that should be released and the next snapshot version. Example: ./release.sh 0.1.0 0.2.0-SNAPSHOT"
exit 1
fi
if [ -z "$2" ]; then
echo "Please provide version that should be released and the next snapshot version. Example: ./release.sh 0.1.0 0.2.0-SNAPSHOT"
exit 1
fi
if ! [[ "$1" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "The release version must be in the format A.B.C. Example: 0.1.0"
exit 1
fi
if ! [[ "$2" =~ ^[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT$ ]]; then
echo "The next snapshot version must be in the format A.B.C-SNAPSHOT. Example: 0.2.0-SNAPSHOT"
exit 1
fi
NEW_VERSION="$1"
NEXT_VERSION="$2"
# Best-effort: generate release/upgrade documentation with Claude Code.
# Requires the `claude` CLI (Claude Code) on this machine. Documentation is a
# "nice to have" for the release, not a gate: if the CLI is missing or the run
# fails, we log a warning and continue so a doc problem never blocks a release.
generate_release_doc() {
if ! command -v claude >/dev/null 2>&1; then
echo "WARNING: 'claude' CLI not found; skipping release documentation."
echo " Install Claude Code to auto-generate docs/releases/ on release."
return 0
fi
echo "Generating release documentation for v$NEW_VERSION with Claude Code..."
# Runs headless (-p). The /release-doc skill reads git history (Bash) and
# writes the doc into docs/releases/, so we allow exactly those tools and
# auto-accept edits — no interactive prompt is possible in a script.
if claude -p "/release-doc v$NEW_VERSION" \
--permission-mode acceptEdits \
--allowedTools "Bash Read Write Edit Glob Grep"; then
echo "Release documentation generated under docs/releases/."
else
echo "WARNING: release documentation generation failed; continuing release."
fi
}
echo "Releasing version $NEW_VERSION"
./mvnw versions:set -DnewVersion=$NEW_VERSION
# Reproducible builds: pin project.build.outputTimestamp to today's UTC date.
#
# The value has to be a literal in the POM rather than something CI computes, because
# an external verifier rebuilding this tag has no way to learn a build flag. It is
# date-granular on purpose: two releases on the same day share a stamp, which is
# irrelevant — the value only has to be deterministic, not unique.
#
# This runs BEFORE the verification build below, so the bytes verified locally are the
# bytes CI will publish.
RELEASE_DATE=$(date -u +%Y-%m-%dT00:00:00Z)
echo "Pinning project.build.outputTimestamp to $RELEASE_DATE"
./mvnw versions:set-property -Dproperty=project.build.outputTimestamp -DnewVersion="$RELEASE_DATE"
# versions:set-property does no sanity checking: if the property is absent from the POM
# it exits 0 and changes nothing, so `set -e` would happily carry on. Verify the value
# actually landed — otherwise we would tag and publish a release carrying a stale
# timestamp, and every later rebuild of this tag would disagree with Maven Central.
ACTUAL_TS=$(./mvnw -B help:evaluate -Dexpression=project.build.outputTimestamp -q -DforceStdout)
if [ "$ACTUAL_TS" != "$RELEASE_DATE" ]; then
echo "Error: project.build.outputTimestamp is '$ACTUAL_TS', expected '$RELEASE_DATE'."
echo " It must be declared in pom.xml <properties> for reproducible builds."
exit 1
fi
# Build and test locally so we never push a tag that fails CI.
#
# Use the SAME profile the release workflow's build step uses (-Pfull-build) and
# run through the `package` phase via `verify`. That triggers the full-build
# executions — Javadoc jar, sources jar and the CycloneDX SBOM — so a broken @link,
# a missing source attachment, or an SBOM failure breaks HERE, locally, instead of
# after the tag is already pushed and the release workflow is running.
#
# Safe to run without release secrets: GPG signing and the JReleaser deploy live in
# the separate deploy-release profile (not activated here), so `verify` does not
# sign or deploy anything — it just builds the artifacts the release will later
# sign and publish.
#
# This runs BEFORE the release doc is generated on purpose: if the build fails,
# `set -e` aborts the script here and we never spend AI tokens documenting a
# release that was never cut.
./mvnw -Pfull-build clean verify
# Generate the release doc only after a green build, but still before committing
# so it ships inside the release commit (and therefore the v$NEW_VERSION tag).
# The version is already set in the build file, so the skill derives the correct
# version delta.
generate_release_doc
# `commit -am` only stages modified tracked files, but the release doc is a NEW
# (untracked) file — and its exact path depends on the project's convention
# (this repo uses docs/upgrade-to-X.Y.md, others use docs/releases/vX.Y.md). Stage
# the whole docs/ tree so the freshly generated doc is included regardless of its
# name or sub-directory (guarded — docs/ should exist, but never block the release
# if it doesn't).
git add docs 2>/dev/null || true
git commit -am "Version $NEW_VERSION"
git push
# Tag and push. The vA.B.C tag triggers the release workflow that deploys
# to Maven Central and creates the GitHub release.
echo "Tagging v$NEW_VERSION (this triggers the release workflow)"
git tag "v$NEW_VERSION"
git push origin "v$NEW_VERSION"
# Only the version moves here. project.build.outputTimestamp deliberately keeps the
# release date, so snapshots built until the next release all carry the same stamp.
# That is deterministic, and snapshots are not a reproducibility target anyway.
echo "Setting version to $NEXT_VERSION"
./mvnw versions:set -DnewVersion=$NEXT_VERSION
git commit -am "Version $NEXT_VERSION"
git push