Skip to main content

golangci-lint-action, but reimplemented in Go

Project description

golangci-lint-action-go

A Go reimplementation of the golangci-lint GitHub Action. Drop-in replacement that ships as a single self-contained binary — no Node.js runtime required.

Quick start

# .github/workflows/lint.yml
name: Lint

on:
  push:
    branches: [main]
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-go@v5
        with:
          go-version-file: go.mod

      - uses: StevenACoffman/golangci-lint-action-go@v1

Why a Go reimplementation?

The upstream action is a Node.js composite action. This version replaces the JS runtime with a compiled Go binary:

  • No Node.js on the runner — one fewer tool in the dependency chain
  • Faster startup — no module resolution or JIT warmup
  • Auditable — the same go build / go test workflow as the rest of your project
  • Behaviorally identical — same inputs, same cache key format, same exit codes

Common patterns

Pin to a specific version

- uses: StevenACoffman/golangci-lint-action-go@v1
  with:
    version: v2.3.4
    args: --timeout=5m

Version can be v2.3 (maps to the latest v2.3.x patch), v2.3.4 (exact), latest, or empty (auto-detected from go.mod or a version file — see Version resolution).

Lint only new issues on pull requests

- uses: StevenACoffman/golangci-lint-action-go@v1
  with:
    only-new-issues: true

On pull_request and push events the action fetches the diff from the GitHub API and passes --new-from-patch to golangci-lint so only issues touching changed lines are reported. On merge_group events it uses --new-from-rev instead (no network call needed).

Add inline PR annotations

- uses: StevenACoffman/golangci-lint-action-go@v1
  with:
    problem-matchers: true

Registers a problem matcher that parses golangci-lint output and creates inline code annotations directly on the pull request diff.

Monorepo — lint every Go module independently

- uses: StevenACoffman/golangci-lint-action-go@v1
  with:
    experimental: automatic-module-directories

Globs for **/go.mod (excluding vendor/, node_modules/, .git/, dist/) and runs golangci-lint once per discovered module directory.

Use golangci-lint already installed in the runner image

- uses: StevenACoffman/golangci-lint-action-go@v1
  with:
    install-mode: none

Skips download and version resolution; uses whatever golangci-lint is already in PATH.

Install only, then run with custom flags

- uses: StevenACoffman/golangci-lint-action-go@v1
  with:
    install-only: true

- name: Lint
  run: golangci-lint run --fix --out-format=github-actions

Build from source with go install

- uses: StevenACoffman/golangci-lint-action-go@v1
  with:
    install-mode: goinstall
    version: latest

Requires CGO (CGO_ENABLED=1) on the runner; useful when you need a custom build tag or are targeting a platform without a pre-built release binary.

Inputs

Input Default Description
version "" golangci-lint version: v2.3, v2.3.4, latest, or empty for auto-detect
version-file "" Path to .golangci-lint-version or .tool-versions; ignored when version is set
install-mode binary binary — download release archive; goinstall — build with go install; none — expect it in PATH
install-only false Install the binary, then exit without running the linter
working-directory "" Directory to run the linter in; empty means the process working directory
github-token ${{ github.token }} Token used to fetch PR/push diffs when only-new-issues: true
verify true Run golangci-lint config verify before linting
only-new-issues false Restrict lint output to issues introduced in the current diff
args "" Extra flags passed verbatim to golangci-lint run
skip-cache false Disable both cache restore and save
skip-save-cache false Disable cache save only; restore still runs
cache-invalidation-interval 7 Rotate the cache key every N days; 0 or negative gives a unique key per run
problem-matchers false Register the built-in problem matcher for inline PR annotations
debug "" Comma-separated: cache (print cache status), clean (purge cache before linting)
experimental "" Comma-separated: automatic-module-directories (lint each go.mod in the repo)

Version resolution

The version to install is determined by the first non-empty source in this order:

  1. version input — used verbatim; minor-only versions (e.g. v2.3) are mapped to the latest patch via the upstream version mapping JSON.
  2. go.mod — scans for a require github.com/golangci/golangci-lint/v2 vX.Y.Z directive.
  3. version-file — reads .golangci-lint-version (raw version string) or .tool-versions (looks for a golangci-lint X.Y.Z line).
  4. Latest — fetches the current latest from the upstream version mapping.

Minimum supported version is v2.1. Only the v2 major line is supported.

Caching

The action caches ~/.cache/golangci-lint (Windows: %USERPROFILE%\.cache\golangci-lint) between runs using the GitHub Actions cache API.

Cache key format:

golangci-lint.cache-{RUNNER_OS}-{working-directory}-{interval-bucket}-{go.mod-sha1}

The interval bucket advances every cache-invalidation-interval days (default: 7). This means the cache is shared across all runs within the same week while still rotating regularly to pick up updated lint rules. A second restore key — the same string without the SHA-1 suffix — allows partial hits when only go.mod has changed.

Set skip-cache: true to disable caching entirely, or skip-save-cache: true to restore but never write back (useful when you want to build the cache only from the default branch).

Migrating from golangci-lint-action

All input names are identical. Replace:

- uses: golangci/golangci-lint-action@v6

with:

- uses: StevenACoffman/golangci-lint-action-go@v1

No other changes needed. If you previously passed cache: false (a flag unique to the upstream action), use skip-cache: true here.

Development

# Build
go build -o golangci-lint-action-go ./...

# Test
go test ./...

# Lint
golangci-lint run ./...

See go.mod for the minimum required Go version.

Running the subcommands locally

# Phase 1 — restore cache, install, lint
INPUT_VERSION=v2.3.4 \
INPUT_ARGS="--timeout=5m" \
GITHUB_STATE=/tmp/gh-state \
GITHUB_PATH=/tmp/gh-path \
golangci-lint-action-go run

# Phase 2 — save cache (reads state written by phase 1)
STATE_CACHE_KEY=... \
GITHUB_STATE=/tmp/gh-state \
golangci-lint-action-go post-run

# Other
golangci-lint-action-go version
golangci-lint-action-go --help

Architecture

All business logic lives in internal/ as pure, testable functions. The cmd/ layer is a thin shell that wires them together in the order the spec requires — no logic of its own.

cmd/
  run/
    run.go       – subcommand registration and exec entry point
    cache.go     – cache restore (keys, GOLANGCI_LINT_CACHE, state)
    install.go   – binary install: binary / goinstall / none; plugin builder
    lint.go      – arg assembly, config verify, run, exit-code mapping
  postrun/
    postrun.go   – cache save (reads state written by run phase)

internal/
  gha/           – GitHub Actions protocol: workflow commands, env files, state
  lintver/       – version string parsing, go.mod scan, version-file, mapping fetch
  install/       – platform strings, asset URLs, archive helpers, ParseGoInstallBinPath
  actionscache/  – GitHub Actions Cache REST API client
  cache/         – cache key construction; RestoreCache / SaveCache orchestration
  patch/         – PR/push diff fetch; path-prefix rewriting for working-directory
  plugins/       – .custom-gcl.{yml,yaml,json} detection and custom-binary build
  lint/          – ParseUserArgs, OnlyNewIssuesArgs, PathModeArg, InterpretExitCode

License

See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

golangci_lint_action_go-0.5.0-py3-none-win_arm64.whl (6.9 MB view details)

Uploaded Python 3Windows ARM64

golangci_lint_action_go-0.5.0-py3-none-win_amd64.whl (7.6 MB view details)

Uploaded Python 3Windows x86-64

golangci_lint_action_go-0.5.0-py3-none-musllinux_1_2_x86_64.whl (7.4 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

golangci_lint_action_go-0.5.0-py3-none-musllinux_1_2_aarch64.whl (6.8 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

golangci_lint_action_go-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

golangci_lint_action_go-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (6.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

golangci_lint_action_go-0.5.0-py3-none-macosx_11_0_arm64.whl (6.9 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

golangci_lint_action_go-0.5.0-py3-none-macosx_10_9_x86_64.whl (7.5 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-win_arm64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 6785d557a89e22f869ad4c16aacffd3d450f0c4ab98cd751692bcf456d40fe5b
MD5 666a4d715c3112f0d68991e3ac3b52cd
BLAKE2b-256 0a9f5cfa82b94a1247e694c1871bb7d16b5ec7769f7e7af9343920449ea3244c

See more details on using hashes here.

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 c5c8bddf8e30eaadfa416880dd93522735f03545063b80e7cbe34f6b9d01399b
MD5 5e98cde39591a2cf0b51f6a9c7c8dc6c
BLAKE2b-256 a2e7ec6e888f95eeec7be8034ffad0d73be6cfb969d70205e0bdf941c583d5e1

See more details on using hashes here.

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 dea505b846763f3dd43d9e5aa69f8dbca4c7d068a5c00ceb52acb2980d7fd62f
MD5 f471a755443376b687967b6fc47f0435
BLAKE2b-256 0bcadcb121c3a1f85badadbd2632fc695413eaf489d37d3318d4f224fecda58b

See more details on using hashes here.

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 e553ffefd0dcd427234cc999f564e82aa304df3cd212ec967af30b7396a71b94
MD5 54dc61b6ff9521811b4e77e21d765c0c
BLAKE2b-256 7c5aaa46901afbae633d57431b77d4653c28db607337a62cd0dd1088a9fb4a0d

See more details on using hashes here.

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1b9cf497c77e106eb99499daad0a222ecadad746d9d2c21b7fbef40194429fc9
MD5 1519260b94693f96c72d75c179323483
BLAKE2b-256 45ebcc140b6b0b66a45be68d9843bc97b7b94c1546e56acc4e9578acbc14eef5

See more details on using hashes here.

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 cd9065e588ae5f0194bd82e4bf65c03a0b4b53a3a949a1d3296b3481f79983cb
MD5 e0cc089d7c1599cfaf25c707cb2e6c74
BLAKE2b-256 d458b8c1c83d1ee5c924fd273ea055eaf047e4238a02a92a2102477235ebced4

See more details on using hashes here.

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cc8e631792ae216f9c4f86a8fcd66de1ab041e08115f99bec1fa974da0c6db3e
MD5 c2c9b381d0a97b10625438c8a61243bc
BLAKE2b-256 6e19deafb53cc70590d20b9dbff308d715f1408c6b9308546dbe4e44f088d594

See more details on using hashes here.

File details

Details for the file golangci_lint_action_go-0.5.0-py3-none-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for golangci_lint_action_go-0.5.0-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 11c7906cb028439fb6adc8da2977bce7688ad7d1e7762f7140052ff2c19ebc7a
MD5 1a1bd3319919cb063bd4851fe5fa4954
BLAKE2b-256 879063ddce157eb95e78c264559022f4173b6cc271ee0ad430b6e46f65328804

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page