A caller can grant narrower permissions than the release job needs. The release then fails at the end, when it creates the tag or pushes an image. The preflight job now declares the same contents and packages permissions as the release job and probes with the real token. A git push dry run checks that the token can create the tag and release. A ghcr.io token request and a blob upload session check that the token can push the image. The upload session creates no package. The release-cgo workflow probes ghcr only when the GoReleaser config builds ghcr.io images. The release workflow probes it when docker-enabled is true and the registry is ghcr.io. A probe that cannot reach a verdict warns and does not fail.
6.3 KiB
Shared GitHub Actions
Reusable workflows and composite actions for Go projects.
Reusable Workflows
Runner selection
Every reusable workflow accepts runner (label, or a JSON object to pick a runner group):
with:
runner: self-hosted
# or
runner: '{"group":"ci-linux","labels":["x64"]}'
Resolution order: inputs.runner, repository/org variable SHARED_ACTIONS_RUNNER, ubuntu-latest.
Set the variable once to move every consumer. In go-release-cgo.yaml the build matrix keeps its
per-platform os; runner covers the other jobs. Runner groups exist only for organisations and enterprises.
go-release.yaml
Standard Go release workflow using GoReleaser.
jobs:
release:
uses: lukaszraczylo/shared-actions/.github/workflows/go-release.yaml@main
with:
go-version: ">=1.24"
docker-enabled: true # optional
secrets: inherit
Inputs:
| Input | Default | Description |
|---|---|---|
go-version |
>=1.24 |
Go version |
semver-config |
semver.yaml |
Path to semver config |
docker-enabled |
false |
Enable Docker builds |
docker-registry |
ghcr.io |
Docker registry |
rolling-release-tag |
"" |
Rolling release tag (e.g., v1) |
go-release-cgo.yaml
Go release workflow for CGO-enabled projects. Builds natively on each platform.
jobs:
release:
uses: lukaszraczylo/shared-actions/.github/workflows/go-release-cgo.yaml@main
with:
go-version: ">=1.24"
node-enabled: true
node-build-script: "cd ui && npm ci && npm run build"
secrets: inherit
Inputs:
| Input | Default | Description |
|---|---|---|
go-version |
>=1.24 |
Go version |
semver-config |
semver.yaml |
Path to semver config |
rolling-release-tag |
"" |
Rolling release tag |
node-enabled |
false |
Enable Node.js |
node-version |
20 |
Node.js version |
node-build-script |
"" |
Frontend build script |
platforms |
(all 4) | JSON array of platforms |
go-pr.yaml
Pull request checks: tests, linting, security scans.
go vet/staticcheckfindings show as inline annotations on the PR diff; gosec and CodeQL post to code scanning.- The
reportjob posts one sticky comment with every check's result and coverage, and fails if any check fails or coverage is belowcoverage-threshold. RequirePR Checks Reportin branch protection. - A push to a branch with an open PR skips the duplicate run; stale runs on the same branch are cancelled.
- Fork PRs cannot receive the comment; the report still lands in the job summary.
jobs:
pr-checks:
uses: lukaszraczylo/shared-actions/.github/workflows/go-pr.yaml@main
with:
go-version: ">=1.24"
secrets: inherit
go-autoupdate.yaml
Automatic dependency updates.
jobs:
autoupdate:
uses: lukaszraczylo/shared-actions/.github/workflows/go-autoupdate.yaml@main
with:
go-version: ">=1.24"
release-workflow: "release.yaml"
secrets: inherit
Composite Actions
actions/go-test
Run Go tests.
- uses: lukaszraczylo/shared-actions/.github/actions/go-test@main
with:
go-version: ">=1.24"
cgo-enabled: "1" # optional, default "0"
actions/semver
Calculate semantic version.
- id: semver
uses: lukaszraczylo/shared-actions/.github/actions/semver@main
with:
config-file: semver.yaml
- run: echo "Version: ${{ steps.semver.outputs.version_tag }}"
actions/goreleaser
Run GoReleaser with mode support.
# Full release (single runner)
- uses: lukaszraczylo/shared-actions/.github/actions/goreleaser@main
with:
version-tag: v1.0.0
mode: full
github-token: ${{ secrets.GITHUB_TOKEN }}
# Split build (matrix)
- uses: lukaszraczylo/shared-actions/.github/actions/goreleaser@main
with:
version-tag: v1.0.0
mode: split
cgo-enabled: "1"
github-token: ${{ secrets.GITHUB_TOKEN }}
# Merge artifacts
- uses: lukaszraczylo/shared-actions/.github/actions/goreleaser@main
with:
version-tag: v1.0.0
mode: merge
github-token: ${{ secrets.GITHUB_TOKEN }}
actions/preflight
Fail in seconds when a prerequisite is missing, instead of at the end of a long run. Reads names from the step env, so map secrets there.
- uses: lukaszraczylo/shared-actions/.github/actions/preflight@main
with:
require: GITHUB_TOKEN,NPM_TOKEN # must be non-empty
repo-access: lukaszraczylo/helm-charts # token needs push access
repo-token-env: HOMEBREW_TAP_TOKEN
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
Optional probes use the real token, so they catch caller permissions: that are too narrow:
release-write: "true"runsgit push --dry-run, which fails when the token cannot push (no tag or release possible).ghcr-push: true|autoasks ghcr.io for a push token and opens a blob upload session (no package is created).autoprobes only when the config hasdockers/dockers_v2/docker_manifestsand mentionsghcr.io. The image is the firstghcr.io/...path in the config, else the repository (ghcr-imageoverrides).- A probe that cannot reach a verdict (network error, odd status) warns and does not fail.
It also scans .goreleaser.y*ml and requires every {{ .Env.NAME }} (comment lines ignored) to be set. All problems are listed in one run.
go-release.yaml and go-release-cgo.yaml run it in a first preflight job before tests. Set preflight: false to skip it, and preflight-repos to check access to a tap or helm-charts repo. An empty secret usually means the caller omitted secrets: inherit.
actions/rolling-release
Create/update a rolling release tag.
- uses: lukaszraczylo/shared-actions/.github/actions/rolling-release@main
with:
tag: v1
version-tag: v1.2.3
github-token: ${{ secrets.GITHUB_TOKEN }}
actions/node-build
Setup Node.js and run build script.
- uses: lukaszraczylo/shared-actions/.github/actions/node-build@main
with:
node-version: "20"
build-script: "cd ui && npm ci && npm run build"
Outputs
Both release workflows output:
version- Calculated version withoutvprefix (e.g.,1.2.3)version_tag- Version withvprefix (e.g.,v1.2.3)