Skip to content

ci: harden workflows, add Go version matrix, fix release notes handling - #100

Open
kiro-agent[bot] wants to merge 1 commit into
mainfrom
improve-github-actions
Open

ci: harden workflows, add Go version matrix, fix release notes handling#100
kiro-agent[bot] wants to merge 1 commit into
mainfrom
improve-github-actions

Conversation

@kiro-agent

@kiro-agent kiro-agent Bot commented Sep 1, 2026

Copy link
Copy Markdown

Summary

Improves the three areas the existing workflows left exposed: version coverage, workflow hardening, and a real bug in release-note handling.

The release workflow bug (worth reviewing first)

The old workflow interpolated changelog text straight into a shell command:

gh release edit "$GITHUB_REF_NAME" --notes "${{ steps.changelog.outputs.notes }}"

The current 0.2.0 changelog entry contains backticks, so this was not hypothetical. Simulated against the real CHANGELOG.md, the shell attempted command substitution and dropped the text:

github.com/pkg/errors: No such file or directory
fmt.Errorf: command not found
- Replaced  with standard library error wrapping ( with )

Any content a maintainer writes in CHANGELOG.md was effectively executed on the runner. Notes now reach gh through --notes-file, and the tag and version reach the shell as environment variables rather than as interpolated text.

Two further fixes found while testing the extractor against the real file:

  • The trailing Keep a Changelog link-reference block ([0.2.0]: https://...) was being appended to every release body.
  • The version was interpolated into an awk regex, so . matched any character. It is now passed with -v and matched as a literal prefix.

CI

  • Go version matrix. go.mod declares go 1.21, but CI only ever ran one hardcoded toolchain, so that floor was never verified. Now runs 1.21 → stable, plus macOS and Windows.
  • Fewer redundant jobs. fmt, vet and build were three jobs each paying for its own checkout and Go setup; they are now one static-analysis job.
  • Supply-chain checks. Verifies go.mod/go.sum are tidy and that go mod verify passes, so a stale go.sum cannot reach consumers.
  • Hardening. Least-privilege permissions: contents: read, per-job timeout-minutes, and concurrency cancellation of superseded runs.
  • Coverage. Uploaded once from the stable leg instead of from every matrix leg, and a Codecov outage or a fork PR without CODECOV_TOKEN no longer turns a green build red.
  • Aggregate check. A single All checks passed job so branch protection can require one stable name instead of every matrix leg, whose names change with each Go release.

Release

Also builds and tests the tagged commit before publishing, passes --verify-tag, marks hyphenated SemVer tags (v1.0.0-rc.1) as pre-releases, and fails loudly when CHANGELOG.md has no section for the tag rather than publishing an empty body. A workflow_dispatch input allows re-publishing an existing tag after fixing the changelog.

Added

  • security.yml running govulncheck weekly, on main, and on dependency changes. Deliberately kept out of PR CI: govulncheck also reports standard-library advisories, so a new Go patch release would otherwise fail unrelated contributor PRs on an unchanged tree.
  • dependabot.yml for Go modules and GitHub Actions, with routine action bumps grouped into one PR.

Verification

  • actionlint 1.7.12 with shellcheck 0.10.0: no findings on any of the three workflows.
  • Build and go test -race pass on Go 1.21.13, 1.22.12, 1.23.8, 1.24.3 and 1.25.1 (74.5% coverage), so no matrix leg is expected to fail.
  • gofmt, go vet, go mod tidy and go mod verify are clean on the current tree.
  • Note extraction tested against the real CHANGELOG.md for a present version, a missing version, and the link-reference boundary.
  • testdata filenames checked for Windows-illegal characters and path length before adding the Windows job (query strings are md5-hashed, so they are safe).

Not included

golangci-lint is not wired in. With its default linters it reports 21 pre-existing findings (11 errcheck, 9 staticcheck, 1 ineffassign), including what looks like a genuine bug at card.go:176 and a possible nil dereference in action_test.go. Adding it here would either break the build or require a config full of suppressions, and the fixes touch exported error strings. Happy to follow up in a separate PR.

CI:
- Test against Go 1.21 (the minimum declared in go.mod) through stable,
  plus macOS and Windows. Previously only a single hardcoded Go 1.21 ran.
- Collapse the fmt/vet/build jobs into one static-analysis job, removing
  three redundant checkout+setup-go cycles.
- Verify go.mod/go.sum are tidy and that module checksums verify.
- Add least-privilege permissions, per-job timeouts, and concurrency
  cancellation for superseded runs.
- Upload coverage once (from the stable leg) rather than from every leg,
  and never fail the build on a Codecov error or a missing fork token.
- Add an aggregate "All checks passed" job so branch protection can
  require one stable check name instead of every matrix leg.

Release:
- Stop interpolating changelog text into a shell command. The 0.2.0 notes
  contain backticks, so `--notes "${{ ... }}"` would have run
  `github.com/pkg/errors` and `fmt.Errorf` as command substitutions and
  silently dropped that text from the published notes. Notes now travel
  via --notes-file, and the tag/version reach the shell as env vars.
- Pass the version to awk with -v and match it as a literal prefix, so
  dots are not treated as regex wildcards.
- Stop release notes at the trailing markdown link-reference block.
- Fail loudly when CHANGELOG.md has no section for the tag instead of
  publishing an empty release body, with workflow_dispatch for recovery.
- Build and test the tagged commit before publishing, verify the tag, and
  mark hyphenated SemVer tags as pre-releases.

Also adds a scheduled govulncheck workflow (kept out of PR CI so stdlib
CVE churn cannot block unrelated contributions) and Dependabot config for
Go modules and GitHub Actions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant