mirror of
https://github.com/lukaszraczylo/shared-actions.git
synced 2026-10-14 05:23:05 +00:00
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.
274 lines
9.6 KiB
Markdown
274 lines
9.6 KiB
Markdown
# 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):
|
|
|
|
```yaml
|
|
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.
|
|
|
|
```yaml
|
|
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.
|
|
|
|
```yaml
|
|
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.
|
|
|
|
```yaml
|
|
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.
|
|
|
|
```yaml
|
|
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.
|
|
|
|
```yaml
|
|
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:
|
|
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```yaml
|
|
- 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.
|
|
|
|
```yaml
|
|
- 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.
|
|
|
|
```yaml
|
|
# 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.
|
|
|
|
```yaml
|
|
- 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.
|
|
|
|
```yaml
|
|
- 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.
|
|
|
|
```yaml
|
|
- 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`)
|