Skip to content

fix(lint): let make lint bootstrap golangci-lint on a fresh machine - #1041

Merged
JonJagger merged 2 commits into
mainfrom
fix-lint-bootstrap-golangci-lint
Jul 28, 2026
Merged

fix(lint): let make lint bootstrap golangci-lint on a fresh machine#1041
JonJagger merged 2 commits into
mainfrom
fix-lint-bootstrap-golangci-lint

Conversation

@JonJagger

Copy link
Copy Markdown
Contributor

make lint could not run at all on a machine that had never installed
golangci-lint: brew upgrade requires the formula to be present already, so
the target died with "Error: golangci-lint not installed" before the linter
ran. Checking for the formula and installing it when absent makes the target
idempotent.

The env var was also never reaching brew. Make expands $H (undefined) and
leaves the literal OMEBREW_NO_AUTO_UPDATE, so every make lint triggered a
full brew update, mutating the developer's brew installation as a side
effect of linting. Dropping the $ passes the assignment to the shell.

Presence-only, with no upgrade, also keeps local behaviour aligned with CI,
which uses golangci-lint-action rather than brew.

Closes#1038

 make lint could not run at all on a machine that had never installed
golangci-lint: brew upgrade requires the formula to be present already, so
the target died with "Error: golangci-lint not installed" before the linter
ran. Checking for the formula and installing it when absent makes the target
idempotent.
The env var was also never reaching brew. Make expands $H (undefined) and
leaves the literal OMEBREW_NO_AUTO_UPDATE, so every make lint triggered a
full brew update, mutating the developer's brew installation as a side
effect of linting. Dropping the $ passes the assignment to the shell.
Presence-only, with no upgrade, also keeps local behaviour aligned with CI,
which uses golangci-lint-action rather than brew.
Closes#1038
@claude

claudeBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @JonJagger's task in 1m 16s —— View job


Review: PR #1041make lint bootstrap fix

  • Read CLAUDE.md and gather context
  • Inspect the Makefile diff vs origin/main
  • Static checks (build/vet — n/a, Makefile-only change; no Go touched)
  • Post review feedback

Summary

The actual code change on the current HEAD is a single character: $HOMEBREW_NO_AUTO_UPDATE=1HOMEBREW_NO_AUTO_UPDATE=1. This is a real, worthwhile fix — in a Make recipe $H expands the undefined Make variable H to empty, leaving the literal OMEBREW_NO_AUTO_UPDATE=1 brew upgrade …, so the env var never reached brew and every make lint silently triggered a full Homebrew auto-update. Nicely diagnosed. ✅

⚠️ One thing to reconcile: PR metadata vs. code

The branch history tells a story worth flagging:

  • 61335865 — switched to brew list … || brew install (the install-when-absent / fresh-machine bootstrap described in the PR body).
  • c2f232b3reverted that, restoring brew upgrade and keeping only the $ fix.

As a result the current diff no longer matches the PR's title and body:

  • Title: "let make lint bootstrap golangci-lint on a fresh machine"
  • Body: "Checking for the formula and installing it when absent makes the target idempotent" + Closes #1038

But brew upgrade golangci-lint still fails with Error: golangci-lint not installed on a machine that never installed it — the exact #1038 scenario. So this branch as it stands does not close #1038.

Recommendation: either

  1. re-add the self-bootstrapping form (see inline suggestion) so the title/body/Closes #1038 stay accurate, or
  2. keep the scope as the pure $-expansion bugfix and update the title/body and drop Closes #1038 (point it at a bug describing the auto-update side effect instead).

Right now the title and closing keyword promise more than the code delivers, which will auto-close #1038 without actually fixing it.

On @gsavage's review questions

  • "switched upgrade to install — mechanism for keeping it up-to-date?" — moot on current HEAD, since brew upgrade was kept; it does stay current.
  • "should we pin to a specific version?" — currently unpinned, which matches CI's golangci-lint-actionversion: latest. Pinning would be a deliberate separate change if you want local to track a fixed version.

Nothing blocking from a correctness standpoint on the one-line fix itself — it's good. The main ask is to make the PR description and issue linkage match what the code now does.

Comment threadMakefile Outdated
 The defect is the leading $: make reads $H (undefined) and leaves the
literal OMEBREW_NO_AUTO_UPDATE, so brew never sees the env var and every
make lint triggers a full brew update, mutating the developer's brew
installation as a side effect of linting. Dropping the $ passes the
assignment to the shell.
Replacing upgrade with a presence-only install went beyond that defect and
removed any way of keeping golangci-lint current, which is what review
flagged. brew upgrade keeps the local linter moving with CI, which runs
golangci-lint-action at version: latest.
Bootstrapping on a machine that has never installed golangci-lint is a
separate concern and stays out of scope here.
Comment threadMakefile

ensure_golangci-lint:
@$HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade golangci-lint
@HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade golangci-lint

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $ expansion fix here is correct and worth keeping. In a Make recipe $H expands the (undefined) Make variable H to empty, leaving the literal OMEBREW_NO_AUTO_UPDATE=1 brew upgrade …. That stray token never sets the env var, so every make lint was actually triggering a full Homebrew auto-update. Dropping the $ passes the assignment through to the shell. Good catch. 👍

One caveat now that commit c2f232b3 reverted back to brew upgrade: on a machine that has never installed golangci-lint, brew upgrade golangci-lint still fails with Error: golangci-lint not installed — which is exactly the fresh-machine scenario in #1038. So with the current diff this target is not idempotent on a clean machine.

If keeping brew upgrade is the intended scope, consider making it self-bootstrapping without losing the upgrade behaviour:

Suggested change
@HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade golangci-lint
@HOMEBREW_NO_AUTO_UPDATE=1 brew list golangci-lint >/dev/null 2>&1 \
&& HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade golangci-lint \
|| HOMEBREW_NO_AUTO_UPDATE=1 brew install golangci-lint

Re: @gsavage's questions — with brew upgrade kept, the linter does stay current (mechanism for keeping it up-to-date), and it's unpinned, which matches CI's golangci-lint-action at version: latest. Pinning to a specific version would be a deliberate separate change if you want local == a fixed CI version.

@JonJagger
JonJagger merged commit d6468dd into mainJul 28, 2026
20 checks passed
@JonJagger
JonJagger deleted the fix-lint-bootstrap-golangci-lint branch July 28, 2026 10:51
Sign up for freeto 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.

make lint cannot bootstrap golangci-lint, and its brew env var is misspelled by make expansion

3 participants

@JonJagger@gsavage@mbevc1