Skip to content

Commit 0b8be8f

Browse files
authored
ci(release): support maintenance releases (#105)
Necessary to automatically include latest PaperMC builds and security patches.
1 parent 4e96a3b commit 0b8be8f

File tree

7 files changed

+123
-27
lines changed

7 files changed

+123
-27
lines changed

.github/semantic-release/package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/semantic-release/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"@commitlint/cli": "19.8.0",
55
"@commitlint/config-conventional": "19.8.0",
66
"semantic-release": "24.2.3",
7-
"@semantic-release/exec": "7.0.3"
7+
"@semantic-release/exec": "7.0.3",
8+
"semver": "7.7.1"
89
},
910
"overrides": {
1011
"conventional-changelog-conventionalcommits_": "Temporary workaround: https://github.com/semantic-release/release-notes-generator/issues/657",

.github/semantic-release/release.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env sh
2+
# TODO: rename folder "release"
23

34
set -eu
45

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
name: CI
22

33
on:
4-
workflow_dispatch:
4+
workflow_dispatch: { }
55
push:
6-
branches: [main, '+.x', next, next-major, beta, alpha]
6+
branches: [ main, '+.x', next, next-major, beta, alpha ]
77
pull_request:
8-
branches: [main, '+.x', next, next-major, beta, alpha]
8+
branches: [ main, '+.x', next, next-major, beta, alpha ]
99
schedule:
10-
- cron: '16 5 * * *' # Every day at 05:16
10+
- cron: '16 5 * * *' # Every day at 05:16 UTC
1111

12-
permissions: {}
12+
permissions: { }
1313

1414
# TODO: explore more options: https://docs.docker.com/build/ci/github-actions/
1515
# TODO: Experiment GitHub deployments

.github/workflows/conventional-commit.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
name: Conventional Commit
22

33
on:
4-
workflow_dispatch:
4+
workflow_dispatch: { }
55
push:
6-
branches: [main, '+.x', next, next-major, beta, alpha]
6+
branches: [ main, '+.x', next, next-major, beta, alpha ]
77
pull_request:
8-
branches: [main, '+.x', next, next-major, beta, alpha]
8+
branches: [ main, '+.x', next, next-major, beta, alpha ]
99

10-
permissions: {}
10+
permissions: { }
1111

1212
jobs:
1313
commit-check:

.github/workflows/openssf.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
name: OpenSSF
22

33
on:
4-
workflow_dispatch:
4+
workflow_dispatch: { }
55
branch_protection_rule:
66
push:
7-
branches: [main, '+.x', next, next-major, beta, alpha]
7+
branches: [ main, '+.x', next, next-major, beta, alpha ]
88
schedule:
9-
- cron: '24 3 * * *' # At 03:24 every day
9+
- cron: '24 3 * * *' # At 03:24 UTC every day
1010

1111
permissions: read-all
1212

.github/workflows/release.yml

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
name: Release
22

3-
# TODO: actually doesn't work if semver not incremented. Better to make a separated workflow for this?
43
on:
5-
workflow_dispatch:
4+
workflow_dispatch: { }
65
push:
76
# next and next-major branches are not supported (never used so far & adjustments required)
8-
branches: [main, '+.x', beta, alpha]
7+
branches: [ main, '+.x', beta, alpha ]
98
schedule:
10-
- cron: '7 8 * * 6' # Every Saturday at 08:07 (weekly release)
9+
- cron: '19 6 3,18 * *' # At 06:19 UTC on day-of-month 3 and 18 (bi-monthly maintenance releases)
1110

1211
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency
1312
concurrency:
1413
# Prevent concurrent releases on the same branch to avoid tag conflicts (e.g., "latest" on the main branch)
15-
# Concurrent releases on different branches are allowed, as their tags don't overlap
14+
# Concurrent releases on different branches are allowed, as their tags don't overlap.
1615
#
1716
# Note: GitHub's concurrency model cancels any *pending* job in the same group when a new one is queued.
1817
# This means that if multiple release requests are made in quick succession on the *same* branch,
@@ -26,14 +25,21 @@ concurrency:
2625
# Never cancel an ongoing release to prevent harmful interruptions
2726
cancel-in-progress: false
2827

29-
permissions: {}
28+
permissions: { }
3029

30+
# The release workflow is split into two separate jobs:
31+
# 1. release-on-change: triggered by push events (e.g., new commits)
32+
# 2. release-on-maintenance: triggered by schedule events (e.g., weekly releases)
33+
#
34+
# The maintenance releases are necessary to include the latest PaperMC builds and security patches.
3135
jobs:
32-
release:
33-
name: Release
36+
release-on-change:
37+
name: On Change
3438
runs-on: ubuntu-24.04
3539
timeout-minutes: 15
3640

41+
if: github.event_name == 'push'
42+
3743
permissions:
3844
contents: write # Required to publish a GitHub release
3945
issues: write # Required to comment on released issues
@@ -42,13 +48,11 @@ jobs:
4248
steps:
4349
# Firewall rules:
4450
# -> "*.github.com": Standard interactions with GitHub
45-
# -> "objects.githubusercontent.com": Uploading of security reports
4651
# -> "raw.githubusercontent.com": Retrieve license file when building OCI image
4752
# -> "*.docker.io" & "*.docker.com": Standard interactions with Docker
4853
# -> "*.alpinelinux.org": Standard interactions with Alpine Linux package repositories
4954
# -> "cdn.fwupd.org": Firmware updates (Alpine)
5055
# -> "api.papermc.io": Dynamic retrieval of the PaperMC server
51-
# -> "mirror.gcr.io": Downloading of the Trivy security scanner
5256
# -> "api.nuget.org" & "registry.npmjs.org": Downloading semantic-release CLI
5357
- name: Harden runner
5458
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
@@ -58,7 +62,6 @@ jobs:
5862
allowed-endpoints: >
5963
github.com:443
6064
api.github.com:443
61-
objects.githubusercontent.com:443
6265
raw.githubusercontent.com:443
6366
uploads.github.com:443
6467
*.docker.io:443
@@ -82,7 +85,7 @@ jobs:
8285
cache: npm
8386
cache-dependency-path: .github/semantic-release/package-lock.json
8487

85-
- name: Install semantic-release
88+
- name: Install semantic-release CLI
8689
working-directory: .github/semantic-release/
8790
run: npm clean-install
8891

@@ -104,11 +107,101 @@ jobs:
104107
- name: Retrieve Git commit timestamp
105108
run: echo "GIT_COMMIT_TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
106109

107-
- name: Release
110+
- name: Release (on change)
108111
env:
109112
GITHUB_TOKEN: ${{ github.token }}
110113
ROOT_PROJECT_DIR: ${{ github.workspace }}
111114
REVISION: ${{ github.sha }}
112115
SOURCE_DATE_EPOCH: ${{ env.GIT_COMMIT_TIMESTAMP }} # Reproducible build: https://reproducible-builds.org/docs/source-date-epoch/
113116
working-directory: .github/semantic-release/
114117
run: npx --no-install semantic-release
118+
119+
release-on-maintenance:
120+
name: On Maintenance
121+
runs-on: ubuntu-24.04
122+
timeout-minutes: 15
123+
124+
# This job is triggered by the schedule or workflow_dispatch events
125+
# and only runs on the default branch (i.e., main).
126+
if: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.ref_name == 'main' }}
127+
128+
steps:
129+
# Firewall rules:
130+
# -> "*.github.com": Standard interactions with GitHub
131+
# -> "raw.githubusercontent.com": Retrieve license file when building OCI image
132+
# -> "*.docker.io" & "*.docker.com": Standard interactions with Docker
133+
# -> "*.alpinelinux.org": Standard interactions with Alpine Linux package repositories
134+
# -> "cdn.fwupd.org": Firmware updates (Alpine)
135+
# -> "api.papermc.io": Dynamic retrieval of the PaperMC server
136+
# -> "api.nuget.org" & "registry.npmjs.org": Downloading semver CLI
137+
- name: Harden runner
138+
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
139+
with:
140+
disable-sudo: true
141+
egress-policy: block
142+
allowed-endpoints: >
143+
github.com:443
144+
api.github.com:443
145+
raw.githubusercontent.com:443
146+
uploads.github.com:443
147+
*.docker.io:443
148+
production.cloudflare.docker.com:443
149+
dl-cdn.alpinelinux.org:443
150+
cdn.fwupd.org:443
151+
152+
- name: Checkout repository
153+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
154+
with:
155+
persist-credentials: false
156+
fetch-depth: 0 # Required to list all tags
157+
158+
- name: Setup Node.js
159+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
160+
with:
161+
node-version: lts/jod
162+
cache: npm
163+
cache-dependency-path: .github/semantic-release/package-lock.json
164+
165+
- name: Install semver CLI
166+
working-directory: .github/semantic-release/
167+
run: npm clean-install
168+
169+
- name: Login to Docker Hub
170+
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
171+
with:
172+
username: ${{ vars.DOCKERHUB_USERNAME }}
173+
password: ${{ secrets.DOCKERHUB_TOKEN }}
174+
175+
# Setup of QEMU x Buildx
176+
# Required for multi-arch builds (typically for ARM architecture support)
177+
# TODO: rely on native ARM64 native node instead of QEMU: https://docs.docker.com/build/ci/github-actions/multi-platform/
178+
- name: Set up QEMU
179+
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
180+
181+
- name: Set up Docker Buildx
182+
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
183+
184+
- name: Retrieve Git commit timestamp
185+
run: echo "GIT_COMMIT_TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
186+
187+
- name: Retrieve latest SemVer tag
188+
working-directory: .github/semantic-release/
189+
run: |
190+
# Retrieve all SemVer tags starting with 'v' and extract the latest version by sorting tags first
191+
LATEST_VERSION=$(npx --no-install semver $(git tag --list 'v*.*.*') | tail -n 1)
192+
193+
# Print the latest version for verification
194+
echo "Latest version: LATEST_VERSION"
195+
196+
# Set the latest version as an environment variable
197+
echo "LATEST_VERSION=$LATEST_VERSION" >> $GITHUB_ENV
198+
199+
# TODO: from dry-run mode to release one
200+
# - name: Release (on maintenance)
201+
# env:
202+
# GITHUB_TOKEN: ${{ github.token }}
203+
# ROOT_PROJECT_DIR: ${{ github.workspace }}
204+
# REVISION: ${{ github.sha }}
205+
# SOURCE_DATE_EPOCH: ${{ env.GIT_COMMIT_TIMESTAMP }} # Reproducible build: https://reproducible-builds.org/docs/source-date-epoch/
206+
# working-directory: .github/semantic-release/
207+
# run: ./release.sh "$LATEST_VERSION"

0 commit comments

Comments
 (0)