11name : Release
22
3- # TODO: actually doesn't work if semver not incremented. Better to make a separated workflow for this?
43on :
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
1312concurrency :
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.
3135jobs :
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
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
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