Skip to content

Release - Maintenance #9

Release - Maintenance

Release - Maintenance #9

# Maintenance releases are dispatched on a bi-monthly basis.
# This kind of release may lead to some dependencies to be automatically updated.
# This is especially useful for integrating new PaperMC builds without manual action.
name: Release - Maintenance
on:
workflow_dispatch: {}
schedule:
- cron: '19 6 3,18 * *' # At 06:19 UTC on day-of-month 3 and 18 (bi-monthly maintenance releases)
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency
concurrency:
# Prevent concurrent releases on the same branch to avoid tag conflicts (e.g., "latest" on the main branch).
# Concurrent releases on different branches are allowed, as their tags don't overlap.
#
# Note: GitHub's concurrency model cancels any *pending* job in the same group when a new one is queued.
# This means that if multiple release requests are made in quick succession on the *same* branch,
# only the latest one will proceed — which is acceptable, since it includes all previous changes.
#
# However, using the same concurrency group across *different* branches could result in a release
# request for one branch canceling a pending release for another branch — which is *not* acceptable.
#
# Therefore, we scope concurrency to both the workflow and the branch.
group: ${{ github.workflow }}-${{ github.ref }} # e.g. Release-main
# Never cancel an ongoing release to prevent harmful interruptions
cancel-in-progress: false
permissions: {}
jobs:
validate:
name: Release - Validate
uses: ./.github/workflows/ci.yml
# Only runs on the default branch (i.e., main).
if: ${{ github.ref_name == 'main' }}
permissions:
contents: read
pull-requests: write # Required to write comments to the PR about security scans results
security-events: write # Required to upload found security gaps
secrets:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
perform:
name: Release - Perform
runs-on: ubuntu-24.04
timeout-minutes: 15
# Only runs on the default branch (i.e., main).
if: ${{ github.ref_name == 'main' }}
# Validate Docker image first
needs: validate
permissions:
contents: read
steps:
# Firewall rules:
# -> "*.github.com": Standard interactions with GitHub
# -> "raw.githubusercontent.com": Retrieve license file when building OCI image
# -> "*.docker.io", "*.docker.com" & "docker-images-prod.*.r2.cloudflarestorage.com": Standard interactions with Docker
# -> "*.alpinelinux.org": Standard interactions with Alpine Linux package repositories
# -> "cdn.fwupd.org": Firmware updates (Alpine)
# -> "api.papermc.io": Dynamic retrieval of the PaperMC server
# -> "api.nuget.org" & "registry.npmjs.org": Downloading semver CLI
- name: Harden runner
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
github.com:443
*.github.com:443
*.githubusercontent.com:443
*.docker.io:443
*.docker.com:443
docker-images-prod.*.r2.cloudflarestorage.com
dl-cdn.alpinelinux.org:443
cdn.fwupd.org:443
api.papermc.io:443
api.nuget.org:443
registry.npmjs.org:443
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
fetch-depth: 0 # Required to list all tags
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: lts/jod
cache: npm
cache-dependency-path: .github/release/package-lock.json
- name: Install semver CLI
working-directory: .github/release/
run: npm clean-install --engine-strict
- name: Login to Docker Hub
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Setup of QEMU x Buildx
# Required for multi-arch builds (typically for ARM architecture support)
- name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Retrieve Git commit timestamp
run: echo "GIT_COMMIT_TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
- name: Retrieve latest SemVer tag
working-directory: .github/release/
run: |
# Retrieve all SemVer tags starting with 'v' and extract the latest version by sorting tags first
LATEST_VERSION=$(npx --no-install semver $(git tag --list 'v*.*.*') | tail -n 1)
# Print the latest version for verification
echo "Latest version: $LATEST_VERSION"
# Set the latest version as an environment variable
echo "LATEST_VERSION=$LATEST_VERSION" >> $GITHUB_ENV
- name: Release (on maintenance)
env:
GITHUB_TOKEN: ${{ github.token }}
ROOT_PROJECT_DIR: ${{ github.workspace }}
REVISION: ${{ github.sha }}
SOURCE_DATE_EPOCH: ${{ env.GIT_COMMIT_TIMESTAMP }} # Reproducible build: https://reproducible-builds.org/docs/source-date-epoch/
working-directory: .github/release/
run: ./release.sh "$LATEST_VERSION"