Skip to content

Commit 05c9523

Browse files
wu-shengclaude
andcommitted
Ask vote-passed for both versions instead of taking one positionally
`vote-passed <old_version>` published the version resolved from the tag and deleted the version given as the argument. Two versions, one of them positional, and the argument is the one that gets deleted - so `vote-passed 9.7.0` while releasing 9.7.0 reads as "release 9.7.0" and instead promotes it into dist/release and immediately svn rm's it. Take no arguments. Ask for each version with a label saying what will happen to it, offer a detected default, and refuse when the two are equal. Passing an argument is now an error pointing at RELEASE_VERSION / OLD_VERSION, so existing muscle memory fails loudly rather than doing something different. The release-version default also stops sorting by version number. Releases are not monotonic: a 9.6.1 patch cut from the 9.6.0 line after 9.7.0 has shipped is newer in time but lower in version, and the old ordering would have offered the already-released 9.7.0. Order by tag creation date instead - maven-release-plugin writes annotated tags, so that timestamp belongs to the tag and survives fetches. The old-version default now comes from dist/release, which is the only place that actually knows what this release replaces, with the version being released filtered out so re-running after a partial failure cannot offer to delete it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent afede1b commit 05c9523

2 files changed

Lines changed: 110 additions & 17 deletions

File tree

docs/en/contribution/release-java-agent.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ The release script `tools/releasing/release.sh` automates the full release workf
4747

4848
# (send vote email to dev@skywalking.apache.org, wait 72h for vote to pass)
4949

50-
# Step 2: Promote, push Docker images, generate announce email, and clean up
51-
./tools/releasing/release.sh vote-passed [old_version_to_remove]
50+
# Step 2: Promote, publish the GitHub Release, generate announce email, and clean up
51+
./tools/releasing/release.sh vote-passed
5252
```
5353

5454
Run `./tools/releasing/release.sh` without arguments to see all available commands, including individual steps if you need to run them separately.
@@ -107,6 +107,19 @@ merged and `release/x.y.z` deleted, and `main` has already moved on to the next
107107
the highest `vx.y.z` tag in the repository, and can be overridden with a positional
108108
argument (`./release.sh docker 9.7.0`) or `RELEASE_VERSION=9.7.0`.
109109

110+
`vote-passed` takes no arguments. It asks for two versions, because they are easy to confuse
111+
and swapping them would delete the release that was just promoted:
112+
113+
- **Release version** — the one being published. Defaults to the most recently *created*
114+
`vx.y.z` tag, not the highest one: a `9.6.1` patch cut from the `9.6.0` line after `9.7.0`
115+
has shipped is newer in time but lower in version.
116+
- **Old version** — removed from `dist/release`, which ASF policy keeps to just the current
117+
release. Defaults to what is published there now, excluding the version being released.
118+
Answer `none` to skip.
119+
120+
Set `RELEASE_VERSION` and `OLD_VERSION` to answer non-interactively:
121+
`RELEASE_VERSION=9.7.0 OLD_VERSION=9.6.0 ./tools/releasing/release.sh vote-passed`.
122+
110123
After the vote passes, run `vote-passed` which executes:
111124
1. **promote** — move packages from `dist/dev` to `dist/release` in Apache SVN (prompts for SVN credentials), then release the Nexus staging repository at https://repository.apache.org and update the website download page
112125
2. **github-release** — publish the GitHub Release for the tag, using `changes/changes-x.y.z.md` as its notes

tools/releasing/release.sh

Lines changed: 95 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727
# ./release.sh prepare-vote Run prepare + stage + upload, then generate vote email
2828
# ./release.sh email [vote|announce] Generate email content
2929
# ./release.sh promote Move from dist/dev to dist/release in SVN
30-
# ./release.sh docker Build and push Docker images
31-
# ./release.sh vote-passed Run promote + docker, then generate announce email
30+
# ./release.sh github-release Publish the GitHub Release (pushes Docker images via CI)
31+
# ./release.sh docker Push Docker images locally (fallback)
32+
# ./release.sh vote-passed Run promote + github-release + announce (asks for versions)
3233
# ./release.sh cleanup <old_version> Remove old release from dist/release
3334

3435
set -euo pipefail
@@ -46,6 +47,39 @@ info() { echo -e "${GREEN}[INFO]${NC} $*"; }
4647
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
4748
error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }
4849

50+
# ============================================================
51+
# detect_release_version — best guess at the release in flight
52+
# ============================================================
53+
# Ordered by when the tag was made, not by version number. Releases are not
54+
# monotonic: a 9.6.1 patch cut from the 9.6.0 line after 9.7.0 has shipped is
55+
# newer in time but lower in version, and sorting by version would pick the
56+
# already-released 9.7.0. maven-release-plugin writes annotated tags, so
57+
# creatordate is the tag's own timestamp and is stable across fetches.
58+
#
59+
# This is only ever a default offered to the release manager, never the final
60+
# word - vote-passed asks them to confirm it.
61+
detect_release_version() {
62+
git for-each-ref --sort=-creatordate --format='%(refname:short)' \
63+
'refs/tags/v[0-9]*.[0-9]*.[0-9]*' 2>/dev/null | head -1 | sed 's/^v//'
64+
}
65+
66+
# ============================================================
67+
# detect_old_version — the release currently published in dist/release
68+
# ============================================================
69+
# ASF policy keeps only the current release in dist/release; older ones are
70+
# served from archive.apache.org. Whatever is there now is therefore what this
71+
# release replaces. Excludes the version being released, so re-running after a
72+
# partial failure - when promote has already copied it in - does not offer to
73+
# delete the release itself. Best effort: no network, no default.
74+
detect_old_version() {
75+
local exclude="${1:-}"
76+
svn ls "https://dist.apache.org/repos/dist/release/skywalking/java-agent/" 2>/dev/null \
77+
| sed 's#/$##' \
78+
| grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' \
79+
| grep -vx "$exclude" \
80+
| sort -V | tail -1
81+
}
82+
4983
# ============================================================
5084
# resolve_version — identify the release from its tag
5185
# ============================================================
@@ -60,8 +94,8 @@ error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }
6094
# That would aim SVN moves and Docker pushes at the wrong version. Tags are
6195
# branch-independent and outlive the release branch, so select from the tag list.
6296
#
63-
# Order of precedence: explicit argument, then $RELEASE_VERSION, then the highest
64-
# vX.Y.Z tag in the repository.
97+
# Order of precedence: explicit argument, then $RELEASE_VERSION, then the most
98+
# recently created vX.Y.Z tag (see detect_release_version for why not the highest).
6599
resolve_version() {
66100
local explicit="${1:-}"
67101
[ -z "$explicit" ] && explicit="${RELEASE_VERSION:-}"
@@ -71,11 +105,11 @@ resolve_version() {
71105
version="${explicit#v}"
72106
else
73107
local latest
74-
latest=$(git tag -l 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -1)
108+
latest=$(detect_release_version)
75109
if [ -z "$latest" ]; then
76110
error "No vX.Y.Z release tag found. Pass the version explicitly, e.g. '$0 <command> 9.7.0'."
77111
fi
78-
version="${latest#v}"
112+
version="$latest"
79113
fi
80114

81115
case "$version" in
@@ -710,15 +744,59 @@ cmd_prepare_vote() {
710744
# vote-passed — run all steps after the vote passes
711745
# ============================================================
712746
cmd_vote_passed() {
713-
local old_version="${1:-}"
714-
715747
cd "$PROJECT_ROOT"
716748

717-
# Resolved from the release tag, so this works after the release branch has
718-
# been merged and deleted. Show it before touching SVN or Docker Hub, both of
719-
# which are public and awkward to undo.
720-
local version
721-
version=$(resolve_version "")
749+
# Both versions are asked for rather than taken positionally. They are easy to
750+
# confuse - one is being published, the other deleted - and getting them the
751+
# wrong way round would svn rm the release that was just promoted. Detection
752+
# only supplies the defaults; the release manager confirms them.
753+
# RELEASE_VERSION and OLD_VERSION answer non-interactively.
754+
if [ "$#" -gt 0 ]; then
755+
error "'$0 vote-passed' takes no arguments; it asks for the versions.
756+
Set RELEASE_VERSION and OLD_VERSION to answer non-interactively, e.g.
757+
RELEASE_VERSION=9.7.0 OLD_VERSION=9.6.0 $0 vote-passed"
758+
fi
759+
760+
info "Publishing a release. Two versions are needed."
761+
echo ""
762+
763+
local version="${RELEASE_VERSION:-}"
764+
if [ -z "$version" ]; then
765+
local suggested
766+
suggested=$(detect_release_version)
767+
echo " The version being released. It must already be tagged and voted on."
768+
if [ -n "$suggested" ]; then
769+
echo " Most recently tagged: ${suggested} (tag v${suggested})"
770+
fi
771+
read -rp " Release version${suggested:+ [$suggested]}: " version
772+
version="${version:-$suggested}"
773+
fi
774+
[ -z "$version" ] && error "No release version given."
775+
version=$(resolve_version "$version")
776+
echo ""
777+
778+
local old_version="${OLD_VERSION:-}"
779+
if [ -z "$old_version" ]; then
780+
local current
781+
current=$(detect_old_version "$version")
782+
echo " The version to remove from dist/release. ASF policy keeps only the"
783+
echo " current release there; older ones are served from archive.apache.org."
784+
if [ -n "$current" ]; then
785+
echo " Currently published in dist/release: ${current}"
786+
else
787+
echo " Could not read dist/release, so there is no suggestion."
788+
fi
789+
read -rp " Old version to remove${current:+ [$current]} (or 'none' to skip): " old_version
790+
old_version="${old_version:-$current}"
791+
fi
792+
# 'none' is the explicit opt out; blank accepts the suggestion above.
793+
[ "$old_version" = "none" ] && old_version=""
794+
795+
# The mistake this whole prompt exists to prevent.
796+
if [ -n "$old_version" ] && [ "$old_version" = "$version" ]; then
797+
error "Old version and release version are both ${version}; that would delete the release being published."
798+
fi
799+
echo ""
722800

723801
info "Publishing release ${version}:"
724802
echo " Release tag : v${version}"
@@ -781,7 +859,7 @@ main() {
781859
echo "Quick start (two-step release):"
782860
echo " $0 prepare-vote 9.7.0 [9.8.0] # before vote (next version auto-calculated if omitted)"
783861
echo " (wait for 72h vote to pass)"
784-
echo " $0 vote-passed [old_version] # after vote"
862+
echo " $0 vote-passed # after vote (asks for the versions)"
785863
echo ""
786864
echo "Every command after 'prepare' identifies the release by its tag (vX.Y.Z), not by the"
787865
echo "checked-out branch, so they still work once release/x.y.z has been merged and deleted."
@@ -799,7 +877,9 @@ main() {
799877
echo " the Docker images, via publish-docker.yaml"
800878
echo " docker [ver] Push Docker images from this machine (fallback"
801879
echo " for when the workflow fails)"
802-
echo " vote-passed [old_ver] Run promote + github-release + announce [+ cleanup]"
880+
echo " vote-passed Run promote + github-release + announce [+ cleanup];"
881+
echo " asks for the release version and the old version to"
882+
echo " remove. RELEASE_VERSION / OLD_VERSION answer these."
803883
echo " cleanup <old_version> Remove old release from dist/release"
804884
;;
805885
esac

0 commit comments

Comments
 (0)