lukaszraczylo 413f9c3064 feat(autoupdate): add a Renovate workflow for Go and Node projects
Renovate batches every minor and patch update in one PR. The workflow
tests that branch with go build and go test for Go and with the
package.json scripts for npm, pnpm and yarn. It squash-merges the PR only
when every test passes. Major updates get their own PR and never merge by
themselves. A renovate.json in the calling repo adds project rules.
2026-10-03 16:01:34 +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.
  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:
  contents: write
  pull-requests: write

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

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
include-major false Put major updates in the batch. When false, each major gets its own PR that is never merged automatically.
minimum-release-age 2 days Skip releases younger than this
renovate-version 44 Renovate version
commit-subject chore(deps): update dependencies Squash commit subject
admin-merge true Merge with --admin
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. The workflow uses RENOVATE_TOKEN, then HOMEBREW_TAP_TOKEN, then github.token. With github.token the merge push does not trigger other workflows, so a release workflow on push will not run. Use a PAT or App token for repositories that release on push.

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%