Skip to content

golangci-lint init source ​

Superseded. These jobs now live in aioz-ci-template and arrive through include:, pinned to a tag - see conventional/ci-cd.md. New repositories should include the library profile rather than paste this file.

This template is kept only as a reference for a repository not yet migrated. Two reasons it is not the shape to copy:

  • It ends in <<: *on_code_change, a YAML alias. Anchors are resolved by the YAML parser before GitLab merges anything, so an alias cannot see an anchor in another file - the moment this file is include:d, that key silently goes missing. The shared jobs use extends: and !reference, which are resolved after the merge.
  • It installs golangci-lint with the upstream install.sh, whose non-anchored asset match downloads ...tar.gz.sbom.json instead of ...tar.gz and dies on a checksum mismatch. The shared job uses go install, which verifies through the Go checksum database. It also pins v2.11.4, against v2.12.2 in the template repository.

Copy-paste-ready golangci-lint setup for aioz-map Go service repos (backend, crawler-service, parser-service, and future services). Built from aioz-map/backend's working config, adjusted to actually enforce what team-playbook requires instead of just reporting it.

Contents ​

FileWhat it is
.golangci.ymlgolangci-lint v2 config, the linter set + settings
lint.gitlab-ci.ymlBlocking GitLab CI lint job
Makefile.snippetmake lint / lint-fix / fmt targets

What is still current here ​

aioz-ci-template runs golangci-lint, but it does not ship a .golangci.yml - the linter set is the repository's own call, and the shared job only requires that the file exists and uses the v2 schema. So one file in this folder is still the thing to copy:

FileStatus
.golangci.ymlCurrent. Copy it to the repo root as a starting point
lint.gitlab-ci.ymlSuperseded by the shared lint job. Reference only
Makefile.snippetOptional. Handy for running the linter locally; CI does not need it

Adopting in a repo ​

  1. Copy .golangci.yml to the repo root. Update the depguard excluded path (internal/utils/log) to this repo's actual logging-wrapper package if it differs. Keep version: "2" on the first line - a v2 config in a v1 binary fails with can't load config: the format is required.

  2. Run it locally and fix what it finds, before CI does:

    sh
    go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 run ./...
  3. Get the lint job from the shared template, not from this folder - see conventional/ci-cd.md.

Why blocking, not report-only ​

aioz-map/backend's current CI lint job runs with allow_failure: true and --issues-exit-code=0: it never fails the pipeline, only feeds a checkstyle report to Sonar. team-playbook's Definition of Done requires "linter passes with zero warnings" as a Universal gate (conventional/definition-of-done.md), and the README's Code Standards section lists "linter passes before merge" as non-negotiable. lint.gitlab-ci.yml here fixes that gap: it fails the job (and blocks merge) on any finding, while still writing the checkstyle report for Sonar via artifacts: when: always.

Requirement → config traceability ​

team-playbook requirementSourceEnforced by
"Linter passes before merge"README.md §6lint.gitlab-ci.yml (blocking job, no allow_failure)
"Auto-format on save and in CI"README.md §6.golangci.yml formatters: (gofmt, goimports)
"No commented-out code" (Universal DoD)definition-of-done.md.golangci.yml gocritic (commentedOutCode check)
Linter passes with zero warnings (Universal DoD)definition-of-done.mdlint.gitlab-ci.yml blocking job + make lint locally
Package naming: lowercase, snake_case, not pluralconventional/naming.md.golangci.yml revive (package-naming rule)
Variable naming: camelCase unexported, PascalCase exportedconventional/naming.md.golangci.yml revive (var-naming rule)
File naming: snake_case, _test.go, main.go entrypointsconventional/naming.md.golangci.yml revive (filename-format rule)
No swallowed errors ("return errors with context")README.md §6.golangci.yml default errcheck (with narrow Close() exclusions)
Resource leaks (HTTP bodies, sql.Rows/Stmt, missing rows.Err())carried over from aioz-map/backendbodyclose, sqlclosecheck, rowserrcheck
Logging via log/slog onlycarried over from aioz-map/backend.golangci.yml depguard (enforce-slog rule)

Everything not listed above (SonarQube Quality Gate, commit message format, REST API conventions, PR size/review rules) is out of golangci-lint's scope and stays enforced elsewhere (Sonar CI job, commit-msg convention, code review) as described in the main README.md.