name: Release on: push: tags: ['v[0-9]+.[0-9]+.[0-9]+'] workflow_dispatch: inputs: overview_version: description: 'Released version to republish the overview for, without the leading v (e.g. 0.1.0)' required: true jobs: retag-image: if: github.event_name == 'push' runs-on: docker-host steps: - uses: actions/checkout@v7.0.1 # Before anything is published: the contract version IS the release version, so a tag that # disagrees would ship a host misreporting itself to every plugin's compatibility check. - name: Refuse a tag that disagrees with HOST_API_VERSION env: GIT_TAG: ${{ github.ref_name }} run: | set -euo pipefail docker run --rm -v "$PWD:/repo" -w /repo node:24.19.0-alpine3.24 \ node release-tooling/contract-version.ts "$GIT_TAG" src/plugin-host/plugin.ts - name: Promote the commit-hash image to semver + latest env: GIT_TAG: ${{ github.ref_name }} REGISTRY_TOKEN: ${{ secrets.DOCKER_REGISTRY_TOKEN }} REGISTRY_USER: ${{ vars.DOCKER_REGISTRY_USER }} REPO: gitea.larvit.se/${{ github.repository }} run: | set -euo pipefail COMMIT=$(git rev-parse 'HEAD^{commit}') VERSION=${GIT_TAG#v} printf '%s' "$REGISTRY_TOKEN" | docker login gitea.larvit.se -u "$REGISTRY_USER" --password-stdin docker pull "$REPO:$COMMIT" \ || { echo "No image $REPO:$COMMIT - release tags must point at a commit whose branch passed the CI gate"; exit 1; } # No bare-major tag while major is 0: a 0.x minor is a contract break, so `:0` would move # across one and abort boot for everything tracking it. `:0.1` only moves across patches. TAGS="$VERSION ${VERSION%.*} latest" if [ "${VERSION%%.*}" != "0" ]; then TAGS="$TAGS ${VERSION%%.*}"; fi for TAG in $TAGS; do docker tag "$REPO:$COMMIT" "$REPO:$TAG" docker push "$REPO:$TAG" done - name: Sync the release tags to Docker Hub env: DOCKERHUB_IMAGE: docker.io/${{ github.repository }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} DOCKERHUB_USER: ${{ vars.DOCKERHUB_USER }} GIT_TAG: ${{ github.ref_name }} REPO: gitea.larvit.se/${{ github.repository }} run: | set -euo pipefail COMMIT=$(git rev-parse 'HEAD^{commit}') VERSION=${GIT_TAG#v} [ -n "$DOCKERHUB_USER" ] && [ -n "$DOCKERHUB_TOKEN" ] \ || { echo "Set the DOCKERHUB_USER variable + DOCKERHUB_TOKEN secret (README -> CI/CD)"; exit 1; } printf '%s' "$DOCKERHUB_TOKEN" | docker login docker.io -u "$DOCKERHUB_USER" --password-stdin TAGS="$VERSION ${VERSION%.*} latest" if [ "${VERSION%%.*}" != "0" ]; then TAGS="$TAGS ${VERSION%%.*}"; fi for TAG in $TAGS; do docker tag "$REPO:$COMMIT" "$DOCKERHUB_IMAGE:$TAG" docker push "$DOCKERHUB_IMAGE:$TAG" done - name: Log out of the registries if: always() run: | set -uo pipefail # Cleanup, and the runner's Docker config is shared (AGENTS.md) — a lost race here must not # fail a release that published, nor skip the overview job that follows. docker logout gitea.larvit.se || true docker logout docker.io || true publish-overview: if: always() && (github.event_name == 'workflow_dispatch' || needs.retag-image.result == 'success') needs: [retag-image] runs-on: docker-host steps: - uses: actions/checkout@v7.0.1 if: github.event_name == 'push' # Publish the named release's own tree, so the page never pairs one Plainpages tag with another # release's sidecar pins. A version that was never released fails here. - uses: actions/checkout@v7.0.1 if: github.event_name == 'workflow_dispatch' with: ref: refs/tags/v${{ inputs.overview_version }} - name: Publish the Docker Hub overview env: DOCKERHUB_OVERVIEW_TOKEN: ${{ secrets.DOCKERHUB_OVERVIEW_TOKEN }} DOCKERHUB_REPO: ${{ github.repository }} DOCKERHUB_USER: ${{ vars.DOCKERHUB_USER }} GIT_TAG: ${{ github.ref_name }} INPUT_VERSION: ${{ inputs.overview_version }} run: | set -euo pipefail VERSION=${INPUT_VERSION:-${GIT_TAG#v}} VERSION=${VERSION#v} # An empty dispatch input falls back to the branch name, so gate this like a tag. docker run --rm -v "$PWD:/repo" -w /repo node:24.19.0-alpine3.24 \ node release-tooling/contract-version.ts "$VERSION" src/plugin-host/plugin.ts docker run --rm -v "$PWD:/repo" -w /repo \ -e DOCKERHUB_OVERVIEW_TOKEN -e DOCKERHUB_REPO -e DOCKERHUB_USER \ node:24.19.0-alpine3.24 \ node release-tooling/dockerhub-overview.ts "$VERSION"