Files
plainpages/.gitea/workflows/release.yml
T
2026-08-22 11:27:35 +02:00

93 lines
4.4 KiB
YAML

name: Release
on:
push:
tags: ['v[0-9]+.[0-9]+.[0-9]+']
# The overview has its own door: a stale page is exactly the state you cannot fix by cutting a
# release, so republishing it must not require one.
workflow_dispatch:
inputs:
overview_version:
description: 'Version the overview should tell adopters to pull (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: |
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: |
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; }
for TAG in "$VERSION" "${VERSION%.*}" "${VERSION%%.*}" latest; 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: |
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
for TAG in "$VERSION" "${VERSION%.*}" "${VERSION%%.*}" latest; do
docker tag "$REPO:$COMMIT" "$DOCKERHUB_IMAGE:$TAG"
docker push "$DOCKERHUB_IMAGE:$TAG"
done
- name: Log out of the registries
if: always()
run: |
docker logout gitea.larvit.se
docker logout docker.io
# Its own job, not a step: the images are already pushed and irreversible by this point, so a Hub
# API outage or an under-scoped token leaves the promotion green and the images untouched (the run
# still shows red — the failure is real, it just is not the release's).
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
- 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: |
VERSION=${INPUT_VERSION:-${GIT_TAG#v}}
# The manual door carries the same invariant as the tag door: this rejects a non-semver
# VERSION (an empty input falls back to the branch name) and one whose major.minor
# disagrees with the tree whose apiVersion sample is about to be published.
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"