lukaszraczylo aca729f8f7 fix(autoupdate): skip major updates by default
A repo with a backlog of majors got one PR per major on the first run.
Replace include-major with major-updates: ignore (default), separate or
batch. Ignore uses a version cap, because rules that disable by update
type have no effect.
2026-10-03 16:47:43 +01:00

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 / staticcheck findings show as inline annotations on the PR diff; gosec and CodeQL post to code scanning.
  • The report job posts one sticky comment with every check's result and coverage, and fails if any check fails or coverage is below coverage-threshold. Require PR Checks Report in 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 for Go. See renovate-autoupdate.yaml for the Renovate-based replacement that also covers npm, pnpm and yarn.

jobs:
  autoupdate:
    uses: lukaszraczylo/shared-actions/.github/workflows/go-autoupdate.yaml@main
    with:
      go-version: ">=1.24"
      release-workflow: "release.yaml"
    secrets: inherit

renovate-autoupdate.yaml

Daily dependency updates for Go and npm/pnpm/yarn projects, built on Renovate. It replaces go-autoupdate.yaml.

  1. Renovate puts every minor and patch update (direct and indirect Go modules, npm, pnpm and yarn packages) in one PR on the branch deps-autoupdate/batch. Major updates are skipped unless major-updates says otherwise.
  2. The workflow checks out that branch and runs the tests: go build, go test -race -cover for Go, and the package.json scripts for Node.
  3. If everything passes, it squash-merges the PR. If a test fails, the PR stays open with a comment and Renovate retries on the next run.
name: Update dependencies

on:
  workflow_dispatch:
  schedule:
    - cron: "0 3 * * *"

permissions:
  actions: write       # only to dispatch release-workflow
  contents: write
  pull-requests: write

jobs:
  update:
    uses: lukaszraczylo/shared-actions/.github/workflows/renovate-autoupdate.yaml@main
    with:
      go-version: ">=1.24"
      release-workflow: release.yaml

The workflow finds go.mod and package.json itself and tests what exists. A repo with both, such as a Go backend with a Vue frontend, gets both tested in one run.

Inputs:

Input Default Description
go-version >=1.24 Go version
go-working-directory . Directory that holds go.mod
node-version 22 Node.js version
node-working-directory . Directory that holds package.json
node-scripts lint,typecheck,test,build Scripts to run in order. A missing script is skipped.
require-node-tests true Fail when there is no test script, so an untested update never merges
major-updates ignore ignore skips major updates. separate opens one PR per major that never merges automatically. batch puts majors in the batch.
minimum-release-age 2 days Skip releases younger than this
renovate-version 44 Renovate version
commit-subject chore(deps): update dependencies Squash commit subject
release-workflow Workflow file to dispatch after the merge, for example release.yaml. It needs a workflow_dispatch trigger. Empty means no dispatch.
admin-merge false Merge with --admin. The workflow token cannot bypass branch protection.
lfs false Git LFS checkout
runner Runner label or runner group, as in the other workflows

Package manager. pnpm is used when pnpm-lock.yaml exists, yarn for yarn.lock, otherwise npm. The install step never changes the lockfile (--frozen-lockfile, --immutable, npm ci), so a lockfile that does not match package.json fails the run. pnpm and yarn run through Corepack, so set packageManager in package.json.

Per-project rules. Put a renovate.json in the calling repository. Renovate reads it and merges it with the defaults, so no extra input is needed:

{
  "ignoreDeps": ["some/package"],
  "packageRules": [{ "matchPackageNames": ["vite"], "enabled": false }]
}

The defaults already cap typescript below 7, which breaks vue-tsc.

Token. No secret is needed. Everything runs inside the calling repository with the workflow's own token, which needs contents: write and pull-requests: write. Two repository settings matter:

  • Settings, Actions, General: tick "Allow GitHub Actions to create and approve pull requests". Without it Renovate cannot open the PR.
  • A push made with the workflow token does not trigger other workflows, so a release workflow that runs on push will not start after the merge. Set release-workflow to dispatch it explicitly, and grant actions: write.

Commit message. The squash commit uses a fixed subject and body without the words major, minor or breaking, because semver-generator matches release keywords in commit messages.

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" runs git push --dry-run, which fails when the token cannot push (no tag or release possible).
  • ghcr-push: true|auto asks ghcr.io for a push token and opens a blob upload session (no package is created). auto probes only when the config has dockers/dockers_v2/docker_manifests and mentions ghcr.io. The image is the first ghcr.io/... path in the config, else the repository (ghcr-image overrides).
  • 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 without v prefix (e.g., 1.2.3)
  • version_tag - Version with v prefix (e.g., v1.2.3)
S
Description
Mirror of github.com/lukaszraczylo/shared-actions
Readme
308 KiB
Languages
Shell 100%