Lint every Go repository with one shared configuration and version, reporting only what a change brings

This commit is contained in:
meda committed 2026-10-28 10:22:42 +01:00
commit 89089b1e2f
3 files changed
+193

No files matched your search

+27
View File
@@ -0,0 +1,27 @@
# go-lint
golangci-lint for every Go repository, with one shared configuration
(`golangci.yml` here) and one pinned version. Add it as a step after the tests:
```yaml
- name: Lint
uses: https://lab.zlymeda.dynu.net/actions/go-lint@master
```
It reports only issues in what the run brings: the pushed commits, or what a
pull request or a new branch adds to its target. A repository that was never
linted therefore does not go red, and its old code is cleaned as it is touched.
`new_from_rev: ''` reports everything, for a repository that is already clean.
A repository with its own `.golangci.yml` is linted with that instead, for rules
only it needs. Copy the shared file and add to it, so the common rules stay.
The version is the one baked into the go-executor image; another runner, or a
different `version`, installs it first. Bump both together.
Locally, with the same rules:
```sh
curl -sSfo /tmp/golangci.yml https://lab.zlymeda.dynu.net/actions/go-lint/raw/branch/master/golangci.yml
golangci-lint run --config /tmp/golangci.yml
```
+76
View File
@@ -0,0 +1,76 @@
name: Go lint
description: >
Run golangci-lint with the shared configuration, or the repository's own
.golangci.yml when it has one, reporting only issues in the code a push or
pull request changed.
inputs:
version:
description: golangci-lint version, installed when the runner has a different one
default: 2.15.0
config:
description: Configuration file; empty uses the repository's .golangci.yml, else the shared one
default: ''
new_from_rev:
description: >
Report issues only after this revision. auto: the pushed range, or the merge
base with the pull request's target; empty: report everything.
default: auto
working_directory:
description: Directory of the Go module
default: .
args:
description: Extra golangci-lint arguments
default: ''
runs:
using: composite
steps:
- name: Lint
shell: bash
working-directory: ${{ inputs.working_directory }}
env:
VERSION: ${{ inputs.version }}
CONFIG: ${{ inputs.config }}
NEW_FROM_REV: ${{ inputs.new_from_rev }}
ARGS: ${{ inputs.args }}
SHARED_CONFIG: ${{ github.action_path }}/golangci.yml
EVENT: ${{ github.event_name }}
BEFORE: ${{ github.event.before }}
BASE_REF: ${{ github.base_ref }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
set -euo pipefail
lint=golangci-lint
if ! command -v golangci-lint >/dev/null || [[ "$(golangci-lint version --short 2>/dev/null)" != "$VERSION" ]]; then
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b "$RUNNER_TEMP/golangci" "v$VERSION"
lint="$RUNNER_TEMP/golangci/golangci-lint"
fi
if [ -z "$CONFIG" ]; then
CONFIG=$(ls .golangci.yml .golangci.yaml 2>/dev/null | head -1 || true)
CONFIG=${CONFIG:-$SHARED_CONFIG}
fi
echo "config: $CONFIG"
# The checkout is usually shallow, and a shallow history has no base to compare against.
[ "$(git rev-parse --is-shallow-repository)" = true ] && git fetch -q --unshallow
new=()
if [ "$NEW_FROM_REV" = auto ]; then
if [ "$EVENT" = pull_request ] && [ -n "$BASE_REF" ]; then
git fetch -q origin "$BASE_REF"
new=(--new-from-merge-base="origin/$BASE_REF")
elif [ -n "$BEFORE" ] && [[ ! "$BEFORE" =~ ^0+$ ]] && git cat-file -e "$BEFORE^{commit}" 2>/dev/null; then
new=(--new-from-rev="$BEFORE")
else
# A new branch or a manual run: what the branch adds to the default branch.
git fetch -q origin "${DEFAULT_BRANCH:-master}"
new=(--new-from-merge-base="origin/${DEFAULT_BRANCH:-master}")
fi
elif [ -n "$NEW_FROM_REV" ]; then
new=(--new-from-rev="$NEW_FROM_REV")
fi
echo "reporting: ${new[*]:-everything}"
# shellcheck disable=SC2086
"$lint" run --config "$CONFIG" "${new[@]}" $ARGS
+90
View File
@@ -0,0 +1,90 @@
version: "2"
run:
timeout: 5m
tests: true
linters:
default: standard
enable:
# Baseline & Core Analyzers
- errcheck
- govet
- ineffassign
- staticcheck
- unused
- unconvert
- unparam
- misspell
# Error Handling & Precision
- errorlint
- nilerr
# Concurrency & Context
- contextcheck
- durationcheck
- noctx
# Diagnostics & Code Quality
- gocritic
- copyloopvar
- prealloc
- revive
exclusions:
rules:
- path: _test\.go
linters:
- unparam
- errcheck
- contextcheck
- gocritic
- revive
- noctx
- govet
- errorlint
- prealloc
settings:
errcheck:
check-type-assertions: true
check-blank: false
govet:
enable:
- shadow
- nilness
- unusedwrite
errorlint:
errorf: true
asserts: true
comparison: true
misspell:
ignore-rules:
- marginable
gocritic:
enabled-tags:
- diagnostic
- performance
disabled-checks:
- commentFormatting
- hugeParam
- commentedOutCode
- captLocal
- assignOp
- rangeValCopy
- unnecessaryDefer
- sloppyReassign
revive:
rules:
- name: exported
disabled: true
formatters:
enable:
- gofmt
- goimports
issues:
max-issues-per-linter: 0
max-same-issues: 0