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
58 changes: 42 additions & 16 deletions .github/workflows/publish-docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,33 @@ name: publish-docker
# tagged x.y.z-<base>, pushed to Docker Hub as
# apache/skywalking-java-agent.
#
# The release trigger is `released` rather than `published`, so publishing a
# pre-release does not ship official images. Creating the GitHub Release is the
# last step of `tools/releasing/release.sh vote-passed`.
# Releases publish by dispatch, deliberately, rather than by a `release` trigger.
# For a `release` event GitHub runs the workflow as it exists **at the tag**, and
# the tag is cut at `prepare` while the GitHub Release is published at
# `vote-passed`, at least 72 hours later. Anything changed here in between would
# silently not apply to the release in flight - that window is how 9.7.0 shipped
# with no workflow run at all. A dispatch always runs the workflow from the
# default branch, so what is on main is what publishes.
#
# `release.sh github-release` creates the Release and then dispatches this
# workflow, so this stays automatic; running it by hand from the Actions tab is
# how you retry a release whose images failed to push.
on:
push:
branches:
- main
release:
types:
- released
workflow_dispatch:
inputs:
version:
description: 'Release version to publish to Docker Hub, e.g. 9.7.0. Leave blank to build a development image from main.'
required: false
default: ''

env:
SKIP_TEST: true
# Non-empty exactly when this run publishes an official release. Everything
# below keys off this rather than the event name.
RELEASE_TAG: ${{ github.event.inputs.version }}

jobs:
# One agent package feeds every image. The variants differ only in the JRE they
Expand All @@ -56,19 +70,19 @@ jobs:

# Development images are compiled from the branch.
- name: Cache local Maven repository
if: github.event_name != 'release'
if: env.RELEASE_TAG == ''
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-publish-docker-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-publish-docker-
- uses: actions/setup-java@v2
if: github.event_name != 'release'
if: env.RELEASE_TAG == ''
with:
distribution: temurin
java-version: 17
- name: Build Agent
if: github.event_name != 'release'
if: env.RELEASE_TAG == ''
run: make build

# A release is never rebuilt. The published image has to carry the artifact
Expand All @@ -79,11 +93,10 @@ jobs:
# from dist/dev to dist/release immediately before the GitHub Release that
# triggers this workflow, so the file is in place by the time this runs.
- name: Download the released agent package
if: github.event_name == 'release'
if: env.RELEASE_TAG != ''
run: |
set -euo pipefail
TAG=${{ github.event.release.tag_name }}
VERSION=${TAG#v}
VERSION=${RELEASE_TAG#v}
BASE="https://dist.apache.org/repos/dist/release/skywalking/java-agent/${VERSION}"
TARBALL="apache-skywalking-java-agent-${VERSION}.tgz"

Expand Down Expand Up @@ -120,18 +133,32 @@ jobs:
# A release publishes the complete set the previous manual `make
# docker.push.*` produced, alpine included. Per-commit development
# images keep the existing JRE-only set.
base: ${{ github.event_name == 'release' && fromJSON('["alpine","java8","java11","java17","java21","java25"]') || fromJSON('["java8","java11","java17","java21","java25"]') }}
base: ${{ github.event.inputs.version && fromJSON('["alpine","java8","java11","java17","java21","java25"]') || fromJSON('["java8","java11","java17","java21","java25"]') }}
steps:
- uses: actions/checkout@v2
with:
submodules: true
# The workflow file necessarily comes from the default branch on a
# dispatch - that is the point, it is what makes the run deterministic. The
# tree it builds must not. Dockerfile and Makefile decide what the image
# actually is, so for a release take them from the tag, exactly as the
# release:perform build and the source tarball did.
- name: Check out the released tag
if: env.RELEASE_TAG != ''
run: |
set -euo pipefail
VERSION=${RELEASE_TAG#v}
git fetch --depth 1 origin "refs/tags/v${VERSION}:refs/tags/v${VERSION}"
git checkout "refs/tags/v${VERSION}"
git submodule update --init --depth 1
git --no-pager log -1 --format='building from %h %d'
- uses: actions/download-artifact@v4
with:
name: skywalking-agent
path: skywalking-agent
- name: Set environment variables
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
if [[ -n "${RELEASE_TAG}" ]]; then
# Provisioned by ASF INFRA on request, as for apache/skywalking.
# Without them docker/login-action fails with an opaque error, so say
# what is actually missing.
Expand All @@ -149,8 +176,7 @@ jobs:
echo "DOCKER_REGISTRY=docker.io" >> $GITHUB_ENV
echo "DOCKER_USERNAME=${{ secrets.DOCKERHUB_USER }}" >> $GITHUB_ENV
echo "DOCKER_PASSWORD=${{ secrets.DOCKERHUB_TOKEN }}" >> $GITHUB_ENV
TAG=${{ github.event.release.tag_name }}
echo "TAG=${TAG#v}" >> $GITHUB_ENV
echo "TAG=${RELEASE_TAG#v}" >> $GITHUB_ENV
else
echo "HUB=ghcr.io/apache/skywalking-java" >> $GITHUB_ENV
echo "DOCKER_REGISTRY=ghcr.io" >> $GITHUB_ENV
Expand Down
29 changes: 22 additions & 7 deletions docs/en/contribution/release-java-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,29 @@ After the vote passes, run `vote-passed` which executes:
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`

### 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`](../../../.github/workflows/publish-docker.yaml),
which builds every base variant and pushes
Docker images are published by GitHub Actions, not from your machine. `github-release`
publishes the GitHub Release and then dispatches
[`.github/workflows/publish-docker.yaml`](../../../.github/workflows/publish-docker.yaml)
with the release version. It 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.
Hub for `linux/amd64` and `linux/arm64`. Watch that workflow.

If it fails, run it again: **Actions → publish-docker → Run workflow**, entering the
version (`9.7.0`). That is the same path `github-release` takes, so retrying is safe and
idempotent.

> [!NOTE]
> There is deliberately **no `release:` trigger**. GitHub runs a release event's workflow as
> it exists *at the tag*, and the tag is cut at `prepare` while the Release is published at
> `vote-passed`, at least 72 hours later — so any change to the workflow in between would
> silently not apply to the release in flight. That window is why 9.7.0 published with no
> workflow run at all. Dispatching instead means the workflow always comes from `main`,
> while everything it acts on comes from the tag: the tree it builds is checked out at
> `vx.y.z`, and the agent package is the verified tarball from `dist/release`.

As a last resort you can push 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
Expand Down
23 changes: 19 additions & 4 deletions tools/releasing/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -689,11 +689,26 @@ cmd_github_release() {
fi

gh release create "${tag}" --title "${version}" "${notes_args[@]}"

info "GitHub Release ${tag} published."
info " publish-docker.yaml is now pushing to Docker Hub:"
info " apache/skywalking-java-agent:${version}-{alpine,java8,java11,java17,java21,java25}"
info " Watch: https://github.com/apache/skywalking-java/actions/workflows/publish-docker.yaml"

# Dispatch rather than let a `release` trigger fire. GitHub runs a release
# event's workflow as it exists at the tag, and the tag is cut at `prepare`
# while this runs at `vote-passed`, at least 72 hours later - anything
# changed in publish-docker.yaml in between would silently not apply. A
# dispatch always runs the workflow from the default branch, so the release
# publishes with what is on main, and builds from the tag.
info "Dispatching publish-docker for ${version}..."
if gh workflow run publish-docker.yaml -f version="${version}"; then
info " Pushing to Docker Hub:"
info " apache/skywalking-java-agent:${version}-{alpine,java8,java11,java17,java21,java25}"
info " Watch: https://github.com/apache/skywalking-java/actions/workflows/publish-docker.yaml"
else
warn " Could not dispatch publish-docker. The release itself is published;"
warn " only the images are missing. Retry with:"
warn " gh workflow run publish-docker.yaml -f version=${version}"
warn " or from Actions -> publish-docker -> Run workflow, or as a last resort"
warn " $0 docker ${version}"
fi
}

# ============================================================
Expand Down
Loading