Apache SkyWalking Java Agent Release Guide
If you’re a committer, you can learn how to release SkyWalking in The Apache Way and start the voting process by reading this document.
Set up your development environment
Follow the steps in the Apache maven deployment environment document to set gpg tool and encrypt passwords.
Use the following block as a template and place it in ~/.m2/settings.xml.
<settings>
...
<servers>
<!-- To publish a snapshot of some part of Maven -->
<server>
<id>apache.snapshots.https</id>
<username> <!-- YOUR APACHE LDAP USERNAME --> </username>
<password> <!-- YOUR APACHE LDAP PASSWORD (encrypted) --> </password>
</server>
<!-- To stage a release of some part of Maven -->
<server>
<id>apache.releases.https</id>
<username> <!-- YOUR APACHE LDAP USERNAME --> </username>
<password> <!-- YOUR APACHE LDAP PASSWORD (encrypted) --> </password>
</server>
...
</servers>
</settings>
Add your GPG public key
- Add your GPG public key into the SkyWalking GPG KEYS file. If you are a committer, use your Apache ID and password to log in this svn, and update the file. Don’t override the existing file.
- Upload your GPG public key to the public GPG site, such as MIT’s site. This site should be in the Apache maven staging repository checklist.
Release using the release script
The release script tools/releasing/release.sh automates the full release workflow. The release is a two-step process with a vote in between.
Quick start
# Step 1: Build, stage, upload, and generate vote email
./tools/releasing/release.sh prepare-vote x.y.z
# (send vote email to dev@skywalking.apache.org, wait 72h for vote to pass)
# Step 2: Promote, publish the GitHub Release, generate announce email, and clean up
./tools/releasing/release.sh vote-passed
Run ./tools/releasing/release.sh without arguments to see all available commands, including individual steps if you need to run them separately.
Pre-flight checks
Before starting, the script verifies:
- Required tools are installed (git, gpg, svn, shasum, mvn, java, tar, gh)
- GPG signing works without password prompt (critical for maven release)
- Maven settings contain Apache server credentials
- Git working tree is clean
If GPG signing fails, configure gpg-agent to cache the passphrase:
# ~/.gnupg/gpg-agent.conf
default-cache-ttl 86400
max-cache-ttl 86400
Then run gpgconf --kill gpg-agent and gpg --sign /dev/null to cache it.
prepare-vote
prepare-vote runs the following steps in sequence:
- preflight — verify tools and environment
- prepare — create
release/x.y.zbranch, runmvn release:prepare(creates tagvx.y.zwith full CHANGES.md), then archive changelog and reset for next version, push branch and tag, create PR - stage — run
mvn release:perform, build source and binary tars with GPG signatures and sha512 checksums - upload — upload to Apache SVN
dist/dev(prompts for SVN credentials) - email vote — print vote email template with pre-filled version, commit ID, submodule commit, and checksums
Before the long build starts, prepare asks for the GitHub milestone ID of the next
development version, which it writes into the reset CHANGES.md. Look up the
Java - <next_version> milestone at https://github.com/apache/skywalking/milestones and
enter its number. The ID is checked against that milestone’s title, and you are warned if
they disagree. Set NEXT_MILESTONE=<id> to answer non-interactively; leave the prompt
blank to keep the milestone/xxx placeholder and edit it by hand before merging the
release PR.
Copy the generated email and send it to dev@skywalking.apache.org. Voting remains open for at least 72 hours. At least 3 (+1 binding) PMC votes with more +1 than -1 are required.
Vote Check
All PMC members and committers should check these before casting +1 votes.
- Features test.
- All artifacts in staging repository are published with
.asc,.md5, and*sha1files. - Source code and distribution package (
apache-skywalking-java-agent-x.y.z-src.tar.gz,apache-skywalking-java-agent-x.y.z.tar.gz) are found inhttps://dist.apache.org/repos/dist/dev/skywalking/java-agent/x.y.zwith.ascand.sha512. LICENSEandNOTICEare in the source code and distribution package.- Check
shasum -c apache-skywalking-java-agent-x.y.z-src.tgz.sha512. - Check
gpg --verify apache-skywalking-java-agent-x.y.z-src.tgz.asc apache-skywalking-apm-x.y.z-src.tgz - Build a distribution package from the source code package (
apache-skywalking-java-agent-x.y.z-src.tar.gz). - Check the Apache License Header. Run
docker run --rm -v $(pwd):/github/workspace apache/skywalking-eyes header check. (No binaries in source codes)
vote-passed
Every step after prepare identifies the release by its tag (vx.y.z), never by the
checked-out branch. By the time you run vote-passed, the release PR has normally been
merged and release/x.y.z deleted, and main has already moved on to the next
-SNAPSHOT; the tag is the only thing that still pins the release. The version defaults to
the most recently created vx.y.z tag, and can be overridden with a positional
argument (./release.sh docker 9.7.0) or RELEASE_VERSION=9.7.0.
vote-passed never takes the versions positionally — they do opposite things, and swapping
them would delete the release that was just promoted. Name them, or be asked:
./tools/releasing/release.sh vote-passed --release 9.7.0 --old_version 9.6.0
./tools/releasing/release.sh vote-passed --release 9.7.0 --no-cleanup
./tools/releasing/release.sh vote-passed # asks for both
- Release version — the one being published. Defaults to the most recently created
vx.y.ztag, not the highest one: a9.6.1patch cut from the9.6.0line after9.7.0has shipped is newer in time but lower in version. - Old version — removed from
dist/release, which ASF policy keeps to just the current release. Defaults to what is published there now, excluding the version being released. Answernoneto skip.
RELEASE_VERSION and OLD_VERSION are honoured too; the flags win over them. Both versions
are validated as x.y.z, the release version must already be tagged, and the two being equal
is refused.
After the vote passes, run vote-passed which executes:
- promote — move packages from
dist/devtodist/releasein Apache SVN (prompts for SVN credentials), then release the Nexus staging repository at https://repository.apache.org and update the website download page - github-release — publish the GitHub Release for the tag, using
changes/changes-x.y.z.mdas its notes - email announce — print announcement email template. Copy and send to
dev@skywalking.apache.organdannounce@apache.org - cleanup (optional) — if old version is provided, remove it from
dist/release. Update download page links to point tohttps://archive.apache.org/dist/skywalking
Docker images
Docker images are published by GitHub Actions, not from your machine. Publishing the
GitHub Release fires the release: released trigger in
.github/workflows/publish-docker.yaml,
which builds every base variant and pushes
apache/skywalking-java-agent:x.y.z-{alpine,java8,java11,java17,java21,java25} to Docker
Hub for linux/amd64 and linux/arm64. Watch that workflow; if it fails you can fall back
to pushing from your machine with ./tools/releasing/release.sh docker x.y.z, which needs
you to be logged in to Docker Hub with push access to the apache organisation.
The image contains the exact tarball that was voted on. The workflow downloads
apache-skywalking-java-agent-x.y.z.tgz from dist/release, checks it against the
published .sha512, and verifies the .asc signature against the project
KEYS file before it goes into an image — it
does not rebuild the agent from source.
The same workflow keeps publishing per-commit development images to
ghcr.io/apache/skywalking-java on every push to main; only the release event
publishes official versioned images.
Docker Hub credentials
The release path needs the DOCKERHUB_USER and DOCKERHUB_TOKEN repository secrets. These
are the names used across the other Apache SkyWalking repositories (apache/skywalking,
skywalking-python, skywalking-mcp, …). They are not self-service: .asf.yaml
cannot set secrets. File an ASF INFRA JIRA
ticket asking for them to be added to apache/skywalking-java, referencing that
apache/skywalking already has them; INFRA holds the Docker Hub account credentials. See
GitHub Actions and Secrets.
Until they exist, the release run fails early with an explicit error and you should publish
with ./tools/releasing/release.sh docker x.y.z instead. Because github-release is
idempotent, you can also add the secrets later and just re-run the failed workflow from the
Actions tab — there is no need to delete and recreate the GitHub Release.