Skip to content

Release

Release #36

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g. 1.3.0 or 1.3.0-beta.0)'
required: true
type: string
jobs:
verify:
# Only `main` may be released, and the checked-out commit must already carry the requested
# version so the artifacts and the tag can never disagree.
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout release commit
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.sha }}
- name: Check package versions match the requested version
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
for pkg in package.json client/package.json; do
actual="$(jq -r .version "$pkg")"
if [[ "$actual" != "$VERSION" ]]; then
echo "::error::$pkg is at $actual but release $VERSION was requested (commit ${GITHUB_SHA})"
exit 1
fi
done
- name: Check tag does not already exist
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/v${VERSION}" >/dev/null 2>&1; then
echo "::error::tag v${VERSION} already exists; it must be created by publishing the draft release"
exit 1
fi
publish-docker:
needs: verify
runs-on: ubuntu-latest
environment: Production
permissions:
id-token: write
contents: read
packages: write
steps:
- name: Checkout release commit
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.sha }}
- name: Tag release commit locally for version metadata
run: git tag "v${{ inputs.version }}"
- name: Set up QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Configure AWS Credentials via OIDC
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION || 'us-east-2' }}
- name: Login to Amazon ECR
id: ecr_login
uses: aws-actions/amazon-ecr-login@b040164c4934333d597f3f9c67502ff28f814e9c # v2.1.6
- name: Docker meta
id: docker_meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: |
ghcr.io/${{ github.repository }}
hirosystems/${{ github.event.repository.name }}
${{ steps.ecr_login.outputs.registry }}/${{ vars.AWS_ECR_REPOSITORY }}
tags: |
type=semver,pattern={{version}},value=${{ inputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ inputs.version }}
type=semver,pattern={{major}},value=${{ inputs.version }}
type=raw,value=latest,enable=${{ !contains(inputs.version, '-') }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
username: ${{ secrets.HIROSYSTEMS_DOCKERHUB_USERNAME }}
password: ${{ secrets.HIROSYSTEMS_DOCKERHUB_TOKEN }}
- name: Build/Tag/Push Image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
platforms: linux/amd64,linux/arm64
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
push: true
publish-npm:
needs: publish-docker
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout release commit
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.sha }}
- name: Tag release commit locally for version metadata
run: git tag "v${{ inputs.version }}"
- name: Use Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: '.nvmrc'
- name: Install deps
run: npm ci --audit=false
- name: Install client deps
run: npm ci --audit=false
working-directory: client
- name: Publish client to npm
working-directory: client
run: |
VERSION="${{ inputs.version }}"
if [[ "$VERSION" == *-* ]]; then
# Extract the prerelease identifier (e.g. "next" from "9.0.0-next.30")
TAG="${VERSION#*-}"
TAG="${TAG%%.*}"
npm publish --provenance --access public --tag "$TAG"
else
npm publish --provenance --access public
fi
github-release:
needs: publish-npm
runs-on: ubuntu-latest
environment: Production
permissions:
contents: write
steps:
- name: Checkout release commit
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.sha }}
- name: Create draft GitHub Release (tag is created on publish)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
PRERELEASE_FLAG=""
if echo "$VERSION" | grep -q "-"; then
PRERELEASE_FLAG="--prerelease"
fi
# Fill the template: VERSION, date, and the auto-generated changelog.
# The tag does not exist yet, so the notes are generated against the
# release commit; the API computes the previous tag automatically.
export VERSION
export RELEASE_DATE="$(date -u +%Y-%m-%d)"
export CHANGELOG="$(gh api "repos/${GITHUB_REPOSITORY}/releases/generate-notes" \
-f tag_name="v$VERSION" -f target_commitish="$GITHUB_SHA" --jq '.body')"
envsubst '${VERSION} ${RELEASE_DATE} ${CHANGELOG}' \
< .github/RELEASE_TEMPLATE.md > release-notes.md
# No tag is created for a draft; GitHub creates `v$VERSION` at
# `$GITHUB_SHA` when the draft is published.
gh release create "v$VERSION" \
--draft \
--target "$GITHUB_SHA" \
--notes-file release-notes.md \
$PRERELEASE_FLAG