Skip to content

beta release

beta release #79

Workflow file for this run

name: beta release
on:
workflow_dispatch:
inputs:
version:
description: "Immutable prerelease tag, for example v0.128.0-beta.1"
required: true
type: string
permissions:
contents: write
packages: write
concurrency:
group: beta-${{ inputs.version }}
cancel-in-progress: false
jobs:
tag:
name: validate and anchor beta tag
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
state_schema: ${{ steps.version.outputs.state_schema }}
steps:
- name: Checkout selected commit
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Validate and create immutable tag
id: version
env:
TAG: ${{ inputs.version }}
run: |
set -euo pipefail
if [[ ! "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-beta\.[0-9]+$ ]]; then
echo "version must match vX.Y.Z-beta.N" >&2
exit 1
fi
PACKAGE_VERSION="$(node -p "require('./package.json').version")"
BASE_VERSION="${TAG#v}"
BASE_VERSION="${BASE_VERSION%-beta.*}"
if [ "${BASE_VERSION}" != "${PACKAGE_VERSION}" ]; then
echo "${TAG} does not match package.json version ${PACKAGE_VERSION}" >&2
exit 1
fi
STATE_SCHEMA="$(node -p "require('./state-schema.json').version")"
if [[ ! "${STATE_SCHEMA}" =~ ^[1-9][0-9]*$ ]]; then
echo "state-schema.json must contain a positive integer version" >&2
exit 1
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then
git fetch --force origin "refs/tags/${TAG}:refs/tags/${TAG}"
TAG_COMMIT="$(git rev-list -n 1 "${TAG}")"
if [ "${TAG_COMMIT}" != "${GITHUB_SHA}" ]; then
echo "${TAG} already points to ${TAG_COMMIT}, not ${GITHUB_SHA}" >&2
exit 1
fi
else
git tag -a "${TAG}" -m "Beta release ${TAG}" "${GITHUB_SHA}"
git push origin "refs/tags/${TAG}"
fi
echo "version=${TAG}" >> "${GITHUB_OUTPUT}"
echo "state_schema=${STATE_SCHEMA}" >> "${GITHUB_OUTPUT}"
docker:
name: beta docker (${{ matrix.target }})
runs-on: ubuntu-latest
needs: tag
strategy:
fail-fast: false
matrix:
include:
- target: main
dockerfile: ./Dockerfile
image_suffix: ""
- target: updater
dockerfile: ./Dockerfile.updater
image_suffix: "-updater"
steps:
- name: Checkout beta tag
uses: actions/checkout@v5
with:
ref: ${{ needs.tag.outputs.version }}
# drivers/ is gitignored and fetched from the commit pinned in
# drivers/BUNDLED_SOURCE.json. The image copies it, so it has to exist
# in the build context before buildx runs.
- name: Fetch the bundled drivers
run: make drivers
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to canonical GHCR namespace
uses: docker/login-action@v4.5.2
with:
registry: ghcr.io
username: ${{ vars.SOURCEFUL_GHCR_USER || github.actor }}
password: ${{ secrets.SOURCEFUL_GHCR_TOKEN || secrets.GITHUB_TOKEN }}
- name: Build and publish beta image
id: build
uses: docker/build-push-action@v7
with:
context: .
file: ${{ matrix.dockerfile }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/srcfl/ftw${{ matrix.image_suffix }}:${{ needs.tag.outputs.version }}
ghcr.io/srcfl/ftw${{ matrix.image_suffix }}:beta
labels: |
org.opencontainers.image.source=https://github.com/srcfl/ftw
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.version=${{ needs.tag.outputs.version }}
org.opencontainers.image.licenses=Apache-2.0
build-args: |
VERSION=${{ needs.tag.outputs.version }}
BUILD_SHA=${{ github.sha }}
# Reuse the same content-addressed layers as stable.
cache-from: type=gha,scope=${{ matrix.target }}
cache-to: type=gha,mode=max,scope=${{ matrix.target }}
- name: Login to compatibility GHCR namespace
uses: docker/login-action@v4.5.2
with:
registry: ghcr.io
username: frahlg
password: ${{ secrets.LEGACY_GHCR_TOKEN || secrets.GITHUB_TOKEN }}
- name: Mirror exact beta manifests to compatibility namespace
env:
IMAGE_SUFFIX: ${{ matrix.image_suffix }}
SOURCE_DIGEST: ${{ steps.build.outputs.digest }}
VERSION: ${{ needs.tag.outputs.version }}
run: |
set -euo pipefail
test -n "${SOURCE_DIGEST}"
for tag in "${VERSION}" beta; do
source="ghcr.io/srcfl/ftw${IMAGE_SUFFIX}:${tag}"
legacy="ghcr.io/frahlg/forty-two-watts${IMAGE_SUFFIX}:${tag}"
docker buildx imagetools create --prefer-index=false --tag "${legacy}" "${source}"
legacy_digest="$(scripts/inspect-image-digest.sh "${legacy}")"
test "${SOURCE_DIGEST}" = "${legacy_digest}"
done
release:
name: publish GitHub prerelease
runs-on: ubuntu-latest
needs: [tag, docker]
steps:
- name: Publish prerelease after images are available
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ needs.tag.outputs.version }}
STATE_SCHEMA: ${{ needs.tag.outputs.state_schema }}
run: |
set -euo pipefail
if gh release view "${TAG}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
echo "GitHub prerelease ${TAG} already exists"
exit 0
fi
gh release create "${TAG}" \
--repo "${GITHUB_REPOSITORY}" \
--title "${TAG}" \
--prerelease \
--notes "<!-- ftw-state-schema:${STATE_SCHEMA} -->" \
--generate-notes