Release - Maintenance #9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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" |