fix(release): require RELEASE_PAT for tag and release updates
All checks were successful
Push Validation / coverage-badge (push) Successful in 1m11s
Push Validation / recommend-release (push) Successful in 24s

Stop using GITHUB_TOKEN/GITEA_TOKEN fallbacks in prepare/do-release/publish mutation paths. Require explicit PAT wiring via secrets.RELEASE_PAT for commit/push/tag and release update operations so downstream workflows trigger reliably.
This commit is contained in:
Micheal Wilkinson
2026-03-21 16:17:17 +00:00
parent 925c99bb9e
commit d5170b6874
7 changed files with 34 additions and 17 deletions

View File

@@ -28,7 +28,7 @@ jobs:
run: run:
shell: bash shell: bash
env: env:
RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN }} RELEASE_TOKEN: ${{ secrets.RELEASE_PAT }}
SUMMARY_FILE: ${{ runner.temp }}/do-release-summary.md SUMMARY_FILE: ${{ runner.temp }}/do-release-summary.md
steps: steps:
- name: Checkout - name: Checkout
@@ -137,7 +137,7 @@ jobs:
set -euo pipefail set -euo pipefail
if [[ -z "${RELEASE_TOKEN:-}" ]]; then if [[ -z "${RELEASE_TOKEN:-}" ]]; then
echo "No release token available. Set GITEA_TOKEN (or GITHUB_TOKEN on GitHub)." >&2 echo "No release token available. Set secrets.RELEASE_PAT." >&2
exit 1 exit 1
fi fi
@@ -163,7 +163,7 @@ jobs:
id: publish id: publish
uses: ./publish uses: ./publish
with: with:
token: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN }} token: ${{ secrets.RELEASE_PAT }}
version: ${{ steps.resolve-version.outputs.version }} version: ${{ steps.resolve-version.outputs.version }}
- name: Build release binaries - name: Build release binaries
@@ -284,7 +284,7 @@ jobs:
- name: Download released binary - name: Download released binary
env: env:
TOKEN: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN }} TOKEN: ${{ secrets.RELEASE_PAT }}
TAG_NAME: ${{ needs.release.outputs.tag }} TAG_NAME: ${{ needs.release.outputs.tag }}
RELEASE_VERSION: ${{ needs.release.outputs.version }} RELEASE_VERSION: ${{ needs.release.outputs.version }}
ASSET_ARCH: ${{ matrix.asset_arch }} ASSET_ARCH: ${{ matrix.asset_arch }}

View File

@@ -124,6 +124,7 @@ jobs:
VOCIFERATE_CACHE_TOKEN: ${{ steps.cache-token.outputs.value }} VOCIFERATE_CACHE_TOKEN: ${{ steps.cache-token.outputs.value }}
with: with:
version: ${{ steps.resolve-version.outputs.tag }} version: ${{ steps.resolve-version.outputs.tag }}
token: ${{ secrets.RELEASE_PAT }}
git-add-files: CHANGELOG.md release-version README.md AGENTS.md git-add-files: CHANGELOG.md release-version README.md AGENTS.md
- name: Summarize prepared release - name: Summarize prepared release

View File

@@ -30,7 +30,7 @@ Apply these checks before invoking actions:
- Checkout repository first. - Checkout repository first.
- For prepare/publish flows that depend on tags/history, use full history checkout (`fetch-depth: 0`). - For prepare/publish flows that depend on tags/history, use full history checkout (`fetch-depth: 0`).
- Use valid credentials for release/comment API calls. On GitHub, `secrets.GITHUB_TOKEN` is used; on self-hosted Gitea, set `secrets.GITEA_TOKEN`. - Use `secrets.RELEASE_PAT` for release/tag/update operations (prepare/publish/do-release) so tag pushes trigger downstream workflows reliably.
- `do-release` and `decorate-pr` now run preflight API checks and fail fast when token credentials are missing or insufficient. - `do-release` and `decorate-pr` now run preflight API checks and fail fast when token credentials are missing or insufficient.
- Set required vars/secrets for coverage uploads: - Set required vars/secrets for coverage uploads:
- `vars.ARTEFACT_BUCKET_NAME` - `vars.ARTEFACT_BUCKET_NAME`

View File

@@ -30,6 +30,7 @@ A `### Breaking` section is used in addition to Keep a Changelog's standard sect
- `publish` now extracts tagged release notes through the `vociferate` Go CLI instead of duplicating changelog section parsing in shell. - `publish` now extracts tagged release notes through the `vociferate` Go CLI instead of duplicating changelog section parsing in shell.
- Composite actions now share a centralized `run-vociferate` orchestration flow, with binary-versus-source execution delegated through shared composite actions and single-use runtime/download logic folded back into `run-vociferate.binary`. - Composite actions now share a centralized `run-vociferate` orchestration flow, with binary-versus-source execution delegated through shared composite actions and single-use runtime/download logic folded back into `run-vociferate.binary`.
- `run-vociferate` now contains both binary and source execution flows directly in a single action implementation, removing nested local action wrappers for better runner compatibility. - `run-vociferate` now contains both binary and source execution flows directly in a single action implementation, removing nested local action wrappers for better runner compatibility.
- Release automation now requires `secrets.RELEASE_PAT` for prepare/publish/do-release operations instead of defaulting to `GITHUB_TOKEN`/`GITEA_TOKEN`.
### Removed ### Removed
@@ -40,6 +41,7 @@ A `### Breaking` section is used in addition to Keep a Changelog's standard sect
- Fixed version resolution in `do-release` workflow by moving version calculation before checkout, resolving from inputs/git tags, and always passing explicit version to `publish` action. - Fixed version resolution in `do-release` workflow by moving version calculation before checkout, resolving from inputs/git tags, and always passing explicit version to `publish` action.
- Fixed tag detection in `do-release` to prioritize the tag at current HEAD (created by `prepare-release`) over the globally latest tag, ensuring correct version is detected when called from `prepare-release` workflow. - Fixed tag detection in `do-release` to prioritize the tag at current HEAD (created by `prepare-release`) over the globally latest tag, ensuring correct version is detected when called from `prepare-release` workflow.
- Fixed `do-release` workflow_call resolution on Teacup runners by explicitly falling back to `needs.prepare.outputs.tag` and normalizing `%!t(string=...)` wrapped values before choosing a release tag. - Fixed `do-release` workflow_call resolution on Teacup runners by explicitly falling back to `needs.prepare.outputs.tag` and normalizing `%!t(string=...)` wrapped values before choosing a release tag.
- Fixed release-chain triggering by using a PAT for release commit/tag pushes so downstream release workflows are triggered reliably.
- Made `publish` action version resolution more robust with clearer error messages when version input is missing and workflow is not running from a tag push. - Made `publish` action version resolution more robust with clearer error messages when version input is missing and workflow is not running from a tag push.
- Fixed `do-release` workflow to always checkout the resolved release tag, eliminating conditional checkout logic that could skip the checkout when called from `prepare-release` workflow. - Fixed `do-release` workflow to always checkout the resolved release tag, eliminating conditional checkout logic that could skip the checkout when called from `prepare-release` workflow.
- Pinned `securego/gosec` and `golang/govulncheck-action` to concrete version tags (`v2.22.4` and `v1.0.4`) so self-hosted Gitea runners can resolve them via direct git clone without relying on the GitHub Actions floating-tag API. - Pinned `securego/gosec` and `golang/govulncheck-action` to concrete version tags (`v2.22.4` and `v1.0.4`) so self-hosted Gitea runners can resolve them via direct git clone without relying on the GitHub Actions floating-tag API.

View File

@@ -63,13 +63,14 @@ and `version-pattern`:
```yaml ```yaml
- uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.0.2 - uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.0.2
with: with:
token: ${{ secrets.RELEASE_PAT }}
version-file: internal/myapp/version/version.go version-file: internal/myapp/version/version.go
version-pattern: 'const Version = "([^"]+)"' version-pattern: 'const Version = "([^"]+)"'
git-add-files: CHANGELOG.md internal/myapp/version/version.go git-add-files: CHANGELOG.md internal/myapp/version/version.go
``` ```
`prepare` uses `github.token` internally for authenticated fetch/push operations, `prepare` requires a PAT input for authenticated commit/push/tag operations.
so no token input is required. Pass `token: ${{ secrets.RELEASE_PAT }}` when invoking the action.
### `publish` — create release with changelog notes ### `publish` — create release with changelog notes
@@ -96,9 +97,8 @@ Gitea/GitHub release with those notes. The `version` input is optional — when
omitted it is derived from the current tag ref automatically. omitted it is derived from the current tag ref automatically.
The reusable `Do Release` workflow now runs preflight checks before publish to The reusable `Do Release` workflow now runs preflight checks before publish to
fail fast when the release token is missing or lacks API access. On fail fast when the release token is missing or lacks API access. Set
self-hosted Gitea, set `secrets.GITEA_TOKEN`; on GitHub, `secrets.GITHUB_TOKEN` `secrets.RELEASE_PAT` and use it for prepare/publish release operations.
is used automatically.
The `publish` action outputs `release-id` so you can upload additional release The `publish` action outputs `release-id` so you can upload additional release
assets after it runs: assets after it runs:
@@ -110,7 +110,7 @@ assets after it runs:
- name: Upload my binary - name: Upload my binary
run: | run: |
curl --fail-with-body -X POST \ curl --fail-with-body -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ -H "Authorization: token ${{ secrets.RELEASE_PAT }}" \
-H "Content-Type: application/octet-stream" \ -H "Content-Type: application/octet-stream" \
"${{ github.api_url }}/repos/${{ github.repository }}/releases/${{ steps.publish.outputs.release-id }}/assets?name=myapp" \ "${{ github.api_url }}/repos/${{ github.repository }}/releases/${{ steps.publish.outputs.release-id }}/assets?name=myapp" \
--data-binary "@dist/myapp" --data-binary "@dist/myapp"

View File

@@ -42,6 +42,11 @@ inputs:
custom version-file. custom version-file.
required: false required: false
default: 'CHANGELOG.md release-version' default: 'CHANGELOG.md release-version'
token:
description: >
Personal access token used to authenticate commit, push, and tag
operations. Required to ensure downstream workflows trigger on tag push.
required: true
outputs: outputs:
version: version:
@@ -114,7 +119,7 @@ runs:
- name: Commit and push release - name: Commit and push release
shell: bash shell: bash
env: env:
TOKEN: ${{ github.token }} TOKEN: ${{ inputs.token }}
GIT_USER_NAME: ${{ inputs.git-user-name }} GIT_USER_NAME: ${{ inputs.git-user-name }}
GIT_USER_EMAIL: ${{ inputs.git-user-email }} GIT_USER_EMAIL: ${{ inputs.git-user-email }}
GIT_ADD_FILES: ${{ inputs.git-add-files }} GIT_ADD_FILES: ${{ inputs.git-add-files }}
@@ -124,6 +129,11 @@ runs:
run: | run: |
set -euo pipefail set -euo pipefail
if [[ -z "${TOKEN:-}" ]]; then
echo "A release PAT is required. Provide inputs.token (for example secrets.RELEASE_PAT)." >&2
exit 1
fi
case "$GITHUB_SERVER_URL" in case "$GITHUB_SERVER_URL" in
https://*) https://*)
authed_remote="https://oauth2:${TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git" authed_remote="https://oauth2:${TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git"

View File

@@ -7,10 +7,9 @@ description: >
inputs: inputs:
token: token:
description: > description: >
Token used to authenticate release API calls. Defaults to the Personal access token used to authenticate release API calls.
workflow token. Required to support release updates across workflow boundaries.
required: false required: true
default: ''
version: version:
description: > description: >
Semantic version to publish (with or without leading v). When omitted, Semantic version to publish (with or without leading v). When omitted,
@@ -91,7 +90,7 @@ runs:
id: create-release id: create-release
shell: bash shell: bash
env: env:
TOKEN: ${{ inputs.token != '' && inputs.token || github.token }} TOKEN: ${{ inputs.token }}
TAG_NAME: ${{ steps.resolve-version.outputs.tag }} TAG_NAME: ${{ steps.resolve-version.outputs.tag }}
RELEASE_NOTES_FILE: ${{ steps.write-notes.outputs.notes_file }} RELEASE_NOTES_FILE: ${{ steps.write-notes.outputs.notes_file }}
GITHUB_API_URL: ${{ github.api_url }} GITHUB_API_URL: ${{ github.api_url }}
@@ -101,6 +100,11 @@ runs:
run: | run: |
set -euo pipefail set -euo pipefail
if [[ -z "${TOKEN:-}" ]]; then
echo "inputs.token is required (set to secrets.RELEASE_PAT)." >&2
exit 1
fi
release_notes="$(cat "$RELEASE_NOTES_FILE")" release_notes="$(cat "$RELEASE_NOTES_FILE")"
escaped_release_notes="$(printf '%s' "$release_notes" | sed 's/\\/\\\\/g; s/"/\\"/g; :a;N;$!ba;s/\n/\\n/g')" escaped_release_notes="$(printf '%s' "$release_notes" | sed 's/\\/\\\\/g; s/"/\\"/g; :a;N;$!ba;s/\n/\\n/g')"
release_api="${GITHUB_API_URL:-${GITHUB_SERVER_URL%/}/api/v1}/repos/${GITHUB_REPOSITORY}/releases" release_api="${GITHUB_API_URL:-${GITHUB_SERVER_URL%/}/api/v1}/repos/${GITHUB_REPOSITORY}/releases"