Skip to content

Commit afede1b

Browse files
authored
Release tooling: tag-based versioning, milestone prompt, and Docker images via GitHub Actions (#821)
1 parent 3db419e commit afede1b

3 files changed

Lines changed: 335 additions & 41 deletions

File tree

.github/workflows/publish-docker.yaml

Lines changed: 101 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,90 @@
1616

1717
name: publish-docker
1818

19+
# Two kinds of image come out of this workflow:
20+
#
21+
# push to main -> per-commit development images, tagged with the commit SHA,
22+
# pushed to GitHub Container Registry.
23+
# release -> the official versioned images for a passed release vote,
24+
# tagged x.y.z-<base>, pushed to Docker Hub as
25+
# apache/skywalking-java-agent.
26+
#
27+
# The release trigger is `released` rather than `published`, so publishing a
28+
# pre-release does not ship official images. Creating the GitHub Release is the
29+
# last step of `tools/releasing/release.sh vote-passed`.
1930
on:
2031
push:
2132
branches:
2233
- main
34+
release:
35+
types:
36+
- released
2337

2438
env:
2539
SKIP_TEST: true
26-
HUB: ghcr.io/apache/skywalking-java
2740

2841
jobs:
29-
build-tar:
42+
# One agent package feeds every image. The variants differ only in the JRE they
43+
# sit on: the Dockerfile takes BASE_IMAGE and ADDs the same DIST directory, and
44+
# the agent itself is Java 8 bytecode that runs on all of them. So this is built
45+
# (or downloaded) exactly once and handed to the matrix below as an artifact,
46+
# rather than each variant fetching its own copy.
47+
agent-package:
3048
if: github.repository == 'apache/skywalking-java'
31-
name: Build Agent
49+
name: Prepare Agent Package
3250
runs-on: ubuntu-latest
3351
timeout-minutes: 30
3452
steps:
3553
- uses: actions/checkout@v2
3654
with:
3755
submodules: true
56+
57+
# Development images are compiled from the branch.
3858
- name: Cache local Maven repository
59+
if: github.event_name != 'release'
3960
uses: actions/cache@v4
4061
with:
4162
path: ~/.m2/repository
4263
key: ${{ runner.os }}-maven-publish-docker-${{ hashFiles('**/pom.xml') }}
4364
restore-keys: ${{ runner.os }}-maven-publish-docker-
4465
- uses: actions/setup-java@v2
66+
if: github.event_name != 'release'
4567
with:
4668
distribution: temurin
4769
java-version: 17
4870
- name: Build Agent
71+
if: github.event_name != 'release'
4972
run: make build
73+
74+
# A release is never rebuilt. The published image has to carry the artifact
75+
# the PMC voted on, so take it from the Apache distribution area and prove
76+
# it is that one: the sha512 rules out a truncated download, and verifying
77+
# the detached signature against the project KEYS file rules out anything
78+
# the release manager did not sign. `release.sh promote` does the svn mv
79+
# from dist/dev to dist/release immediately before the GitHub Release that
80+
# triggers this workflow, so the file is in place by the time this runs.
81+
- name: Download the released agent package
82+
if: github.event_name == 'release'
83+
run: |
84+
set -euo pipefail
85+
TAG=${{ github.event.release.tag_name }}
86+
VERSION=${TAG#v}
87+
BASE="https://dist.apache.org/repos/dist/release/skywalking/java-agent/${VERSION}"
88+
TARBALL="apache-skywalking-java-agent-${VERSION}.tgz"
89+
90+
curl -fsSL --retry 5 --retry-delay 10 -O "${BASE}/${TARBALL}"
91+
curl -fsSL --retry 5 --retry-delay 10 -O "${BASE}/${TARBALL}.asc"
92+
curl -fsSL --retry 5 --retry-delay 10 -O "${BASE}/${TARBALL}.sha512"
93+
94+
sha512sum -c "${TARBALL}.sha512"
95+
96+
curl -fsSL --retry 5 --retry-delay 10 https://downloads.apache.org/skywalking/KEYS | gpg --import
97+
gpg --verify "${TARBALL}.asc" "${TARBALL}"
98+
99+
tar -xzf "${TARBALL}"
100+
# The Makefile passes this directory to the Dockerfile as ARG DIST.
101+
test -d skywalking-agent
102+
50103
- uses: actions/upload-artifact@v4
51104
name: Upload Agent
52105
with:
@@ -55,7 +108,7 @@ jobs:
55108

56109
build-docker:
57110
if: github.repository == 'apache/skywalking-java'
58-
needs: [ build-tar ]
111+
needs: [ agent-package ]
59112
name: Build and Push Docker
60113
runs-on: ubuntu-latest
61114
permissions:
@@ -64,9 +117,10 @@ jobs:
64117
timeout-minutes: 60
65118
strategy:
66119
matrix:
67-
java-version: [ 8, 11, 17, 21, 25 ]
68-
env:
69-
TAG: ${{ github.sha }}
120+
# A release publishes the complete set the previous manual `make
121+
# docker.push.*` produced, alpine included. Per-commit development
122+
# images keep the existing JRE-only set.
123+
base: ${{ github.event_name == 'release' && fromJSON('["alpine","java8","java11","java17","java21","java25"]') || fromJSON('["java8","java11","java17","java21","java25"]') }}
70124
steps:
71125
- uses: actions/checkout@v2
72126
with:
@@ -75,6 +129,35 @@ jobs:
75129
with:
76130
name: skywalking-agent
77131
path: skywalking-agent
132+
- name: Set environment variables
133+
run: |
134+
if [[ "${{ github.event_name }}" == "release" ]]; then
135+
# Provisioned by ASF INFRA on request, as for apache/skywalking.
136+
# Without them docker/login-action fails with an opaque error, so say
137+
# what is actually missing.
138+
if [[ -z "${{ secrets.DOCKERHUB_USER }}" || -z "${{ secrets.DOCKERHUB_TOKEN }}" ]]; then
139+
echo "::error::DOCKERHUB_USER / DOCKERHUB_TOKEN are not set on this repository."
140+
echo "::error::Ask ASF INFRA to add them (see docs/en/contribution/release-java-agent.md),"
141+
echo "::error::or publish from a workstation with './tools/releasing/release.sh docker <version>'."
142+
exit 1
143+
fi
144+
# apache/skywalking-java-agent:x.y.z-<base> on Docker Hub.
145+
# NAME differs from the development images, which is why it is set
146+
# here rather than left to the Makefile default.
147+
echo "HUB=apache" >> $GITHUB_ENV
148+
echo "NAME=skywalking-java-agent" >> $GITHUB_ENV
149+
echo "DOCKER_REGISTRY=docker.io" >> $GITHUB_ENV
150+
echo "DOCKER_USERNAME=${{ secrets.DOCKERHUB_USER }}" >> $GITHUB_ENV
151+
echo "DOCKER_PASSWORD=${{ secrets.DOCKERHUB_TOKEN }}" >> $GITHUB_ENV
152+
TAG=${{ github.event.release.tag_name }}
153+
echo "TAG=${TAG#v}" >> $GITHUB_ENV
154+
else
155+
echo "HUB=ghcr.io/apache/skywalking-java" >> $GITHUB_ENV
156+
echo "DOCKER_REGISTRY=ghcr.io" >> $GITHUB_ENV
157+
echo "DOCKER_USERNAME=${{ github.actor }}" >> $GITHUB_ENV
158+
echo "DOCKER_PASSWORD=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV
159+
echo "TAG=${{ github.sha }}" >> $GITHUB_ENV
160+
fi
78161
- name: Disable containerd image store
79162
run: |
80163
DAEMON_JSON="/etc/docker/daemon.json"
@@ -93,8 +176,14 @@ jobs:
93176
- name: Log in to the Container registry
94177
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
95178
with:
96-
registry: ${{ env.HUB }}
97-
username: ${{ github.actor }}
98-
password: ${{ secrets.GITHUB_TOKEN }}
99-
- name: Build docker image
100-
run: make docker.push.java${{ matrix.java-version }} || make docker.push.java${{ matrix.java-version }}
179+
registry: ${{ env.DOCKER_REGISTRY }}
180+
username: ${{ env.DOCKER_USERNAME }}
181+
password: ${{ env.DOCKER_PASSWORD }}
182+
# The Makefile builds linux/amd64 and linux/arm64, which needs emulation
183+
# and the docker-container buildx driver.
184+
- name: Set up QEMU
185+
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
186+
- name: Set up Docker Buildx
187+
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
188+
- name: Build and push docker image
189+
run: make docker.push.${{ matrix.base }} || make docker.push.${{ matrix.base }}

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ Then run `gpgconf --kill gpg-agent` and `gpg --sign /dev/null` to cache it.
7676
4. **upload** — upload to Apache SVN `dist/dev` (prompts for SVN credentials)
7777
5. **email vote** — print vote email template with pre-filled version, commit ID, submodule commit, and checksums
7878

79+
Before the long build starts, **prepare** asks for the GitHub milestone ID of the next
80+
development version, which it writes into the reset `CHANGES.md`. Look up the
81+
`Java - <next_version>` milestone at https://github.com/apache/skywalking/milestones and
82+
enter its number. The ID is checked against that milestone's title, and you are warned if
83+
they disagree. Set `NEXT_MILESTONE=<id>` to answer non-interactively; leave the prompt
84+
blank to keep the `milestone/xxx` placeholder and edit it by hand before merging the
85+
release PR.
86+
7987
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.
8088

8189
## Vote Check
@@ -92,8 +100,49 @@ are found in `https://dist.apache.org/repos/dist/dev/skywalking/java-agent/x.y.z
92100
1. Check the Apache License Header. Run `docker run --rm -v $(pwd):/github/workspace apache/skywalking-eyes header check`. (No binaries in source codes)
93101

94102
## vote-passed
103+
Every step after `prepare` identifies the release by its **tag** (`vx.y.z`), never by the
104+
checked-out branch. By the time you run `vote-passed`, the release PR has normally been
105+
merged and `release/x.y.z` deleted, and `main` has already moved on to the next
106+
`-SNAPSHOT`; the tag is the only thing that still pins the release. The version defaults to
107+
the highest `vx.y.z` tag in the repository, and can be overridden with a positional
108+
argument (`./release.sh docker 9.7.0`) or `RELEASE_VERSION=9.7.0`.
109+
95110
After the vote passes, run `vote-passed` which executes:
96111
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
97-
2. **docker**build and push all Docker image variants (alpine, java8, java11, java17, java21, java25)
112+
2. **github-release**publish the GitHub Release for the tag, using `changes/changes-x.y.z.md` as its notes
98113
3. **email announce** — print announcement email template. Copy and send to `dev@skywalking.apache.org` and `announce@apache.org`
99114
4. **cleanup** (optional) — if old version is provided, remove it from `dist/release`. Update download page links to point to `https://archive.apache.org/dist/skywalking`
115+
116+
### Docker images
117+
Docker images are published by GitHub Actions, not from your machine. Publishing the
118+
GitHub Release fires the `release: released` trigger in
119+
[`.github/workflows/publish-docker.yaml`](../../../.github/workflows/publish-docker.yaml),
120+
which builds every base variant and pushes
121+
`apache/skywalking-java-agent:x.y.z-{alpine,java8,java11,java17,java21,java25}` to Docker
122+
Hub for `linux/amd64` and `linux/arm64`. Watch that workflow; if it fails you can fall back
123+
to pushing from your machine with `./tools/releasing/release.sh docker x.y.z`, which needs
124+
you to be logged in to Docker Hub with push access to the `apache` organisation.
125+
126+
The image contains the exact tarball that was voted on. The workflow downloads
127+
`apache-skywalking-java-agent-x.y.z.tgz` from `dist/release`, checks it against the
128+
published `.sha512`, and verifies the `.asc` signature against the project
129+
[KEYS](https://downloads.apache.org/skywalking/KEYS) file before it goes into an image — it
130+
does not rebuild the agent from source.
131+
132+
The same workflow keeps publishing per-commit development images to
133+
`ghcr.io/apache/skywalking-java` on every push to `main`; only the `release` event
134+
publishes official versioned images.
135+
136+
#### Docker Hub credentials
137+
The release path needs the `DOCKERHUB_USER` and `DOCKERHUB_TOKEN` repository secrets. These
138+
are the names used across the other Apache SkyWalking repositories (`apache/skywalking`,
139+
`skywalking-python`, `skywalking-mcp`, ...). They are **not** self-service: `.asf.yaml`
140+
cannot set secrets. File an [ASF INFRA JIRA](https://issues.apache.org/jira/browse/INFRA)
141+
ticket asking for them to be added to `apache/skywalking-java`, referencing that
142+
`apache/skywalking` already has them; INFRA holds the Docker Hub account credentials. See
143+
[GitHub Actions and Secrets](https://infra.apache.org/github-actions-secrets.html).
144+
145+
Until they exist, the release run fails early with an explicit error and you should publish
146+
with `./tools/releasing/release.sh docker x.y.z` instead. Because `github-release` is
147+
idempotent, you can also add the secrets later and just re-run the failed workflow from the
148+
Actions tab — there is no need to delete and recreate the GitHub Release.

0 commit comments

Comments
 (0)