go-ci — Claude Code skill: GitHub Actions for Go CI/CD
A skill that helps your AI agent write and set up GitHub Actions for Go projects. Use it when you need a pipeline with linting, tests, security checks, and caching.
npx skills add eduardo-sl/go-agent-skills --skill go-ci -a claude-codeWhat go-ci does
go-ci provides workflow templates, golangci-lint configs, build matrices for different Go versions and platforms, and optimization rules. The agent can generate a four-stage pipeline: build, lint, test with race detection, and vulnerability scanning.
The skill includes code snippets for coverage gates, a Makefile that mirrors CI locally, and guidance on splitting jobs for speed. It covers caching via go.mod, parallel execution, and security scanning with CodeQL and gosec as SARIF uploads. Go toolchain and GitHub Actions are required.
Out of scope: writing tests, choosing dependencies, or configuring releases.
What it helps with
- Write a GitHub Actions workflow for Go with linting and testing
- Speed up CI through caching and parallel jobs
- Set a coverage gate at a minimum percentage
- Add vulnerability scanning to the pipeline
- Create a Makefile that matches your CI steps
Example prompts for the agent
- Write a GitHub Actions workflow for Go with linting and race detector tests
- How do I add a 70% coverage gate to my pipeline?
- Create a build matrix for two Go versions and three operating systems
How to install go-ci
1Skills CLI (Vercel)
npx skills add eduardo-sl/go-agent-skills --skill go-ci -a claude-code2Manually: put the files in place
~/.claude/skills/go-ci/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/go-ci/
1Skills CLI (Vercel)
npx skills add eduardo-sl/go-agent-skills --skill go-ci -a codex2Manually: put the files in place
.agents/skills/go-ci/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add eduardo-sl/go-agent-skills --skill go-ci -a cursor2Manually: put the files in place
.cursor/skills/go-ci/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install eduardo-sl/go-agent-skills go-ci2Manually: put the files in place
.github/skills/go-ci/SKILL.md1Skills CLI (Vercel)
npx skills add eduardo-sl/go-agent-skills --skill go-ci -a gemini-cli2Platform CLI
gemini skills install https://github.com/eduardo-sl/go-agent-skills --path 'skills/(workflow)/go-ci'Manually: put the files in place
.devin/skills/go-ci/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add eduardo-sl/go-agent-skills --skill go-ci -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about go-ci
How do I install go-ci in Claude Code?
Run npx skills add eduardo-sl/go-agent-skills --skill go-ci -a claude-code, then open ~/.claude/skills/go-ci/SKILL.md in your editor.
What does go-ci do?
It helps your AI agent generate GitHub Actions workflows for Go: four-stage pipelines (build, lint, test, security), Makefile definitions, build matrices, and coverage gates. It does not write test code or release configurations.
Do I need go-ci if I already use GitHub Actions?
If you have no pipeline or it runs slowly, go-ci provides ready-made solutions for parallel jobs, caching, and speed. If your workflow already works well, the skill can help you improve it.
Source text
SKILL.md · MIT
---
name: go-ci
description: >
Continuous integration for Go projects: GitHub Actions pipelines, caching,
golangci-lint setup, test/coverage gates, vulnerability scanning, SAST
(CodeQL, gosec), Dependabot, action pinning, build matrices, Makefile
targets. Use when: "set up CI", "GitHub Actions for
Go", "add lint to the pipeline", "CI is slow", "coverage gate", "build
matrix", "write a Makefile", "run govulncheck in CI".
Not for: commit conventions (git-commit), choosing or auditing
dependencies (go-dependency-audit), writing the tests themselves
(go-test-quality), releases and signing (go-build-release).
user-invocable: true
license: MIT
compatibility: Designed for Claude Code or similar AI coding agents working on Go projects. Requires the Go toolchain. Targets GitHub Actions.
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(gofmt:*) Bash(golangci-lint:*) Bash(git:*)
metadata:
author: eduardo-sl
version: "1.2.1"
---
# Go CI
A Go pipeline has exactly four gates: build, vet/lint, test with race
detector, vulnerability scan. Everything else is optimization.
Detailed reference material, loaded on demand:
- `references/security-and-automation.md` — CodeQL and gosec SARIF,
Dependabot config, SHA pinning, repository hardening, Trivy, an AI
review workflow.
Read a reference file only when the summary below is not enough.
## 1. Baseline GitHub Actions Workflow
```yaml
name: ci
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version-file: go.mod # single source of truth
cache: true # caches module + build cache
- run: go build ./...
- run: go vet ./...
- run: go test -race -shuffle=on -coverprofile=coverage.out ./...
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
- uses: golangci/golangci-lint-action@v9 # v7+ runs golangci-lint v2
with:
version: v2.6 # pin a minor; v2.6+ has `modernize`
vuln:
runs-on: ubuntu-latest
steps:
- uses: golang/govulncheck-action@v1
with:
go-version-file: go.mod
```
Action major versions move several times a year. Treat the ones above as
a snapshot, and let Dependabot's `github-actions` ecosystem keep them
current rather than editing them by hand.
Key decisions baked in:
- `go-version-file: go.mod` — never hardcode the Go version in two places.
- `cache: true` on setup-go handles module and build caches; do not add
manual `actions/cache` steps for Go on top of it.
- `-race -shuffle=on` — races and order-dependent tests fail in CI, not
production.
- `permissions: contents: read` — least privilege by default.
- Lint in a separate job — it fails fast and parallelizes with tests.
## 2. golangci-lint Configuration
Commit a `.golangci.yml`; an unconfigured linter is noise:
```yaml
version: "2" # required: golangci-lint v2 rejects v1 files
linters:
default: standard # errcheck, govet, ineffassign, staticcheck, unused
enable:
- errorlint # %w misuse, == on errors
- gosec # security patterns
- revive # style, replaces golint
- misspell
exclusions:
rules:
- path: _test\.go
linters: [gosec] # test code may use weak randomness etc.
```
golangci-lint v2 moved exclusions from `issues.exclude-rules` to
`linters.exclusions.rules` and made the `version` key mandatory. A v1 file
fails to load, and `golangci-lint migrate` converts one in place.
Start from this small set and add linters deliberately. Enabling
everything produces hundreds of findings nobody triages. `nolint`
directives require a reason: `//nolint:gosec // G404: jitter, not crypto`.
## 3. Build Matrix — Only When You Ship It
```yaml
strategy:
matrix:
go: [oldstable, stable] # the two releases the Go team supports
os: [ubuntu-latest, macos-latest, windows-latest]
```
Libraries: test the two supported Go releases. setup-go resolves
`stable`/`oldstable` at run time, so the matrix never goes stale.
Services deployed on Linux: skip the OS matrix — it doubles cost for
platforms you never ship. Cross-compilation is cheaper than emulation:
`GOOS=windows go build ./...` catches most portability breaks.
## 4. Coverage Gate
```yaml
- run: go test -race -coverprofile=coverage.out ./...
- name: enforce coverage floor
run: |
total=$(go tool cover -func=coverage.out | awk '/^total:/ {sub(/%/,"",$3); print $3}')
echo "coverage: ${total}%"
awk -v t="$total" 'BEGIN { exit (t < 70.0) }'
```
Gate on a floor that ratchets up, not a target that gets gamed. Exclude
generated code via `//go:generate`d files' build tags or grep filters,
not by lowering the floor.
## 5. Makefile — Local Mirror of CI
CI must run what developers run. One definition, two callers:
```makefile
.PHONY: build lint test vuln ci
build:
go build ./...
lint:
golangci-lint run
test:
go test -race -shuffle=on -coverprofile=coverage.out ./...
vuln:
go tool govulncheck ./... # pinned via `go get -tool` (Go 1.24+)
ci: build lint test vuln
```
If CI does anything `make ci` doesn't, developers discover failures
only after pushing. Keep them identical.
## 6. Speed Rules
- Split lint / test / vuln into parallel jobs (as in §1).
- `go test ./...` already parallelizes across packages; don't shard a
small repo.
- Integration tests behind a build tag run in a separate job or on a
schedule, not on every push: `go test -tags=integration ./...`.
- If the build cache misses constantly, check that `go.sum` is the
cache key input (setup-go does this) and that jobs don't mutate it.
## 7. Security Gates
Beyond `govulncheck`: CodeQL (`security-extended`) and gosec as SARIF
uploads to the Security tab, and Trivy on any container image you build.
Start gosec with `-no-fail` to collect a baseline, then make new findings
fail the PR.
## 8. Dependency Updates and Action Pinning
- Dependabot for both `gomod` and `github-actions`, weekly, with minor and
patch updates grouped into one PR. Majors stay separate — they need a
changelog read.
- Pin third-party actions by commit SHA with the version in a comment; a
tag can be moved to malicious code, and Dependabot updates SHA pins.
## 9. Workflow and Repository Hardening
- Per-job permissions on top of a read-only default.
- No `pull_request_target` workflow that checks out and runs fork code
with secrets available.
- Branch protection: required checks, a review, no force pushes.
- An AI reviewer loaded with the go-code-review skill is an extra reviewer,
never a check that can approve on its own.
Snippets for sections 7-9: `references/security-and-automation.md`.
Tag-triggered releases — GoReleaser, signing, SBOMs, provenance — are
owned by the go-build-release skill.
## Verification Checklist
1. Pipeline has all four gates: build, vet+lint, test -race, govulncheck
2. Go version sourced from go.mod (`go-version-file`), not duplicated
3. `permissions: contents: read` set at workflow level
4. Tests run with `-race -shuffle=on`
5. `.golangci.yml` committed with a curated linter set
6. Every `nolint` carries a linter name and a reason
7. Matrix limited to versions/platforms actually supported
8. Coverage floor enforced, generated code excluded
9. `make ci` reproduces the pipeline locally, byte-for-byte
10. Integration tests isolated behind tags, not slowing every push
11. CodeQL/gosec results uploaded as SARIF; images scanned before push
12. Dependabot covers modules and actions; third-party actions pinned by SHA
13. Per-job permissions; no fork code run with secrets
© eduardo-sl · MIT · eduardo-sl/go-agent-skills