Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions .github/workflows/lint-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: lint-pr

# Additive PR-only layer on top of the full-scan lint gate.
#
# Master's `lint.yml` runs `golangci/golangci-lint-action` on every PR as a
# hard gate over the entire module. That keeps the bar high but the failure
# surface is a single check-run with all findings dumped in the job log,
# which is awkward when only a handful of lines actually changed.
#
# This workflow wraps the *same* linter version + config with reviewdog and
# `filter_mode: added`, so:
# - findings inside the PR diff appear as inline review comments on the
# exact line they reference (much easier to action than a log scrape),
# - pre-existing baseline noise is filtered out entirely (no duplicate
# reporting with the full-scan job),
# - the full-scan job in `lint.yml` remains the authoritative correctness
# gate, so this workflow is intentionally NON-blocking (`fail_level:
# warning` would still annotate without failing; we keep `fail_level:
# error` so a *new* hard-error inside the diff also surfaces here as a
# red check, but the master `lint.yml` is the merge gate).
#
on:
pull_request:
paths-ignore:
- "**.md"
- "docs/**"
- ".gitignore"

permissions:
contents: read
pull-requests: write # reviewdog needs this to post inline review comments (same-repo PRs only)
checks: write # for the check-run summary

jobs:
golangci-lint-diff:
name: golangci-lint (diff-only, inline)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v6.0.1
with:
# reviewdog needs the merge-base to compute the PR diff.
fetch-depth: 0

- name: Set up Go
uses: ./.github/actions/setup-go

- name: Install dependencies
run: go mod download

# Same-repo PRs: post findings as inline review comments. The default
# GITHUB_TOKEN has the `pull-requests: write` scope declared above,
# so reviewdog can call the review API. Findings are filtered to lines
# the PR actually changed (`filter_mode: added`).
#
# We deliberately do NOT set `level: warning` here: combined with
# `fail_level: error` it would downgrade every result to warning and
# silently neuter the gate. Leaving `level` unset preserves each
# finding's native severity, so error-level diagnostics (e.g. govet,
# staticcheck SA*) trip `fail_level: error` as intended.
- name: golangci-lint via reviewdog (same-repo PR — inline comments)
if: github.event.pull_request.head.repo.full_name == github.repository
# Pin to v2.10.0 (>=v2.8.0 required for golangci-lint v2 support;
# earlier reviewdog releases on the @v2 major tag still default to
# downloading golangci-lint v1.x even when a v2.x version is
# requested via the input).
uses: reviewdog/action-golangci-lint@v2.10.0
with:
go_version_file: go.mod
# Match the exact version used by master's full-scan lint gate.
golangci_lint_version: v2.11.3
golangci_lint_flags: "--config=.golangci.yml --timeout=5m"
workdir: .
# Only annotate lines actually changed by the PR.
filter_mode: added
reporter: github-pr-review
fail_level: error
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Fork PRs: GITHUB_TOKEN is strictly read-only regardless of the
# workflow-level permissions block, so neither `github-pr-review`
# (needs pull-requests: write) nor `github-pr-check` (needs
# checks: write) can post results. The `local` reporter writes
# findings to the job log only. `fail_level: error` still makes new
# error-level diagnostics fail the job, but the master `lint.yml`
# full-scan remains the actual merge gate for fork PRs.
- name: golangci-lint via reviewdog (fork PR — log-only)
if: github.event.pull_request.head.repo.full_name != github.repository
uses: reviewdog/action-golangci-lint@v2.10.0
with:
go_version_file: go.mod
golangci_lint_version: v2.11.3
golangci_lint_flags: "--config=.golangci.yml --timeout=5m"
workdir: .
filter_mode: added
reporter: local
fail_level: error
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Loading