Skip to content

fix: lintroller not enforcing violations due to || true in Makefile#1636

Merged
aknysh merged 27 commits intomainfrom
fix-mkdirtemp-linting
Oct 17, 2025
Merged

fix: lintroller not enforcing violations due to || true in Makefile#1636
aknysh merged 27 commits intomainfrom
fix-mkdirtemp-linting

Conversation

@osterman
Copy link
Member

@osterman osterman commented Oct 15, 2025

what

  • Removed || true from the make lintroller target in Makefile to properly enforce linting violations
  • Updated lintroller comment to include os.MkdirTemp rule
  • Removed unnecessary grep -v "^#" filter
  • Integrated lintroller as a golangci-lint module plugin for CI workflows
  • Added lintroller configuration in .golangci.yml settings.custom section
  • Updated CodeQL workflow to build and use custom golangci-lint binary with lintroller
  • Added comprehensive test coverage for all lintroller rules (os-setenv-in-test, os-mkdirtemp-in-test)
  • Renamed testdata file to bad_test.go so lintroller rules properly apply

why

  • Makefile bug: The || true was causing lintroller to always exit with code 0 (success), even when violations were detected, so pre-commit hooks would pass
  • Plugin integration: Lintroller was only running as standalone binary, not integrated with golangci-lint CI workflow
  • GitHub Advanced Security: Plugin integration enables SARIF output for CodeQL integration, showing lintroller findings in GitHub's security dashboard alongside other linters
  • Unified linting: Custom golangci-lint binary with lintroller provides single tool for all linting (standard + custom rules)
  • PR fix: !exec returning executable not found - !exec should preserve PATH #1634 initially contained os.MkdirTemp violations that weren't caught because pre-commit lintroller had || true
  • The developer had to manually fix the violations in a second commit after realizing the issue
  • Test coverage was incomplete - only covered t.Setenv in defer, missing os.Setenv and os.MkdirTemp tests

references

Summary by CodeRabbit

  • Chores

    • CI and local tooling now build and run a custom lint binary (with the new plugin), ensure it’s executable, filter packages from scans, and upload SARIF results; workflows, pre-commit, and Makefile updated to use this custom lint flow. Linter config enables new env/temp-dir checks.
  • Tests

    • Test data refreshed with compliant/non-compliant examples; many tests refactored to use testing helpers and t.Setenv; benchmarks adjusted.
  • Documentation

    • README expanded with plugin/module guidance, build/run CI examples, and config templates.

osterman and others added 2 commits October 15, 2025 13:22
…ions

## what
- Removed `|| true` from the `make lintroller` target in Makefile
- Updated comment to include os.MkdirTemp in the list of rules
- Removed unnecessary `grep -v "^#"` filter that was suppressing output

## why
- The `|| true` caused lintroller to always exit with code 0, even when violations were found
- This meant pre-commit hooks would pass despite lintroller detecting issues
- PR #1634 initially contained os.MkdirTemp violations that weren't caught because of this bug
- The developer had to manually fix the violations in a second commit

## references
- Related to PR #1634 which had os.MkdirTemp violations that weren't caught
- The lintroller rule itself works correctly (added in PR #1630)
- The issue was only in the Makefile target that always returned success

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
## what
- Renamed testdata/src/a/bad.go to bad_test.go so rules properly apply
- Added test cases for os.Setenv in test files
- Added test cases for os.MkdirTemp in test files
- Added test cases for exceptions (benchmarks, defer blocks)
- Added comments documenting which rule each test validates

## why
- The original test file only covered t.Setenv in defer/cleanup
- Missing tests for os-setenv-in-test and os-mkdirtemp-in-test rules
- File needed _test.go suffix for lintroller rules to apply
- Comprehensive tests ensure all rules work as expected

## references
- All lintroller tests now pass with full coverage
- Validates the rules added in PR #1630

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@osterman osterman requested a review from a team as a code owner October 15, 2025 18:27
@github-actions github-actions bot added the size/s Small size PR label Oct 15, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 15, 2025

📝 Walkthrough

Walkthrough

Adds a custom golangci-lint build with a lintroller plugin, wires the custom binary into Makefile, pre-commit and GitHub Actions, updates linter configs and docs, replaces/extends lintroller testdata, and refactors tests to use t.Setenv / t.TempDir and an updated test helper signature.

Changes

Cohort / File(s) Summary
Makefile & custom golangci-lint
Makefile
Added custom-gcl target to build ./custom-gcl (golangci-lint + lintroller), set executable, verify, and made lint depend on it; lint runs ./custom-gcl with package filtering to exclude /testdata.
Lintroller testdata — removed
tools/lintroller/testdata/src/a/bad.go
Deleted legacy test file containing two tests that enforced t.Setenv disallowed in defer/Cleanup.
Lintroller testdata — added
tools/lintroller/testdata/src/a/bad_test.go
Added comprehensive testcases showing allowed/disallowed patterns for t.Setenv, os.Setenv, os.MkdirTemp, t.TempDir, and benchmarks; includes // want expectations for lintroller.
CI & GitHub Actions
.github/workflows/codeql.yml, .github/workflows/pre-commit.yml
CI workflow now builds the custom golangci-lint with lintroller, runs it (install-mode: none), emits SARIF and uploads results; pre-commit workflow updated to skip lintroller (noting execution via custom-gcl).
golangci & custom-gcl config
.golangci.yml, .custom-gcl.yml
Enabled lintroller in .golangci.yml with plugin settings; .custom-gcl.yml adjusted (removed module: for first plugin entry, added doc/template comments).
Pre-commit hook config
.pre-commit-config.yaml
golangci-lint hook changed to run make custom-gcl then execute ./custom-gcl, updated description to reflect lintroller usage.
Tests (refactors & helper signature)
pkg/config/load_test.go, pkg/list/list_vendor_test.go, pkg/utils/yaml_func_exec_test.go
Tests updated to use t.Setenv and t.TempDir; setupTestFiles signature changed to return (string, func()); callers adjusted and minor message text tweaks applied.
Docs
tools/lintroller/README.md
Expanded README describing plugin/module design, custom build process, CI integration, configuration, and multi-plugin guidance.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(200,230,255,0.12)
  participant Dev as Developer
  participant Make as Makefile
  participant CustomGCL as ./custom-gcl
  participant Lintroller as lintroller (plugin)
  end

  Dev->>Make: make custom-gcl
  Make->>CustomGCL: go build (golangci-lint + lintroller)
  CustomGCL-->>Make: ./custom-gcl (chmod +x, verify)
  Dev->>Make: make lint
  Make->>CustomGCL: run ./custom-gcl (pkgs filtered, excludes /testdata)
  CustomGCL->>Lintroller: invoke lintroller checks
  Lintroller-->>CustomGCL: diagnostics/results
  CustomGCL-->>Make: exit code/results

  rect rgba(230,255,217,0.12)
  participant CI as GitHub Actions
  CI->>CustomGCL: build custom golangci-lint (with plugins)
  CI->>CustomGCL: run (install-mode: none) -> produce SARIF
  CI->>CI: upload SARIF (always)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

patch

Suggested reviewers

  • aknysh

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "fix: lintroller not enforcing violations due to || true in Makefile" directly addresses the Makefile changes in this pull request, which removes the || true flag from the lintroller target to allow proper exit codes on violations. This fix is explicitly confirmed in the changeset and PR objectives. However, the title focuses on this specific Makefile correction while the PR encompasses a much broader scope including integration of lintroller as a golangci-lint module plugin, CodeQL workflow updates, comprehensive test data changes, configuration updates, and documentation expansion. The title captures a real and meaningful aspect of the change but doesn't convey the full scope of the comprehensive integration work being performed.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-mkdirtemp-linting

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f23388e and d9ed60b.

📒 Files selected for processing (1)
  • pkg/config/load_test.go (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/config/load_test.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mergify
Copy link

mergify bot commented Oct 15, 2025

Important

Cloud Posse Engineering Team Review Required

This pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes.

To expedite this process, reach out to us on Slack in the #pr-reviews channel.

@mergify mergify bot added the needs-cloudposse Needs Cloud Posse assistance label Oct 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
tools/lintroller/testdata/src/a/bad_test.go (3)

37-37: Add period to inline comment.

The inline comment doesn't end with a period, which violates the godot linter requirement.

As per coding guidelines.

Apply this diff:

-		os.Setenv("PATH", orig) // OK: os.Setenv is allowed in defer blocks
+		os.Setenv("PATH", orig) // OK: os.Setenv is allowed in defer blocks.

52-52: Add period to inline comment.

The inline comment doesn't end with a period, which violates the godot linter requirement.

As per coding guidelines.

Apply this diff:

-	tempDir, _ := os.MkdirTemp("", "bench-*") // OK: os.MkdirTemp is allowed in benchmarks
+	tempDir, _ := os.MkdirTemp("", "bench-*") // OK: os.MkdirTemp is allowed in benchmarks.

58-58: Add period to inline comment.

The inline comment doesn't end with a period, which violates the godot linter requirement.

As per coding guidelines.

Apply this diff:

-	os.Setenv("PATH", "/bench/path") // OK: os.Setenv is allowed in benchmarks
+	os.Setenv("PATH", "/bench/path") // OK: os.Setenv is allowed in benchmarks.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 82ff97a and 65ea585.

📒 Files selected for processing (3)
  • Makefile (1 hunks)
  • tools/lintroller/testdata/src/a/bad.go (0 hunks)
  • tools/lintroller/testdata/src/a/bad_test.go (1 hunks)
💤 Files with no reviewable changes (1)
  • tools/lintroller/testdata/src/a/bad.go
🧰 Additional context used
📓 Path-based instructions (3)
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Write unit tests as table-driven tests focused on behavior; prefer high coverage for pkg/ and internal/exec/; comments must end with periods.
Use t.Skipf with a reason instead of t.Skip; never skip without a reason.
Test files must mirror implementation file names (e.g., aws_ssm_store_test.go pairs with aws_ssm_store.go).

Files:

  • tools/lintroller/testdata/src/a/bad_test.go
**/testdata/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Use test fixtures for complex inputs under testdata

Files:

  • tools/lintroller/testdata/src/a/bad_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All comments must end with periods across all Go code (godot linter enforced).
Organize imports into three groups (stdlib, 3rd-party, Atmos) separated by blank lines and sorted alphabetically within groups; preserve existing aliases.
Add defer perf.Track(<atmosConfig|nil>, ".")() at the start of all public and critical private functions, followed by a blank line.
All errors must be wrapped using static errors from errors/errors.go; prefer errors.Join for multiple errors, fmt.Errorf with %w for context, and check with errors.Is; never use dynamic errors directly.
Use utils.PrintfMarkdown() to render embedded markdown examples for CLI help output.
Co-locate unit tests with implementation files; integration tests reside under tests/.
Distinguish UI output from logging: UI prompts/status/errors to stderr; data/results to stdout; logging for system/debug info only with structured fields.
Most text UI must go to stderr; only data/results to stdout. Prefer utils.PrintfMessageToTUI for UI messages.
Bind all environment variables with viper.BindEnv(); every env var must have an ATMOS_ alternative binding.
Favor cross-platform code: prefer SDKs over external binaries, use filepath/os/runtime, and handle OS-specific differences or use build tags.
For non-standard execution paths, capture telemetry using telemetry.CaptureCmd or telemetry.CaptureCmdString without collecting user data.
Search for existing methods and utilities (internal/exec, pkg/) before implementing new functionality; prefer reuse/refactoring over duplication.

Files:

  • tools/lintroller/testdata/src/a/bad_test.go
🧠 Learnings (1)
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
PR: cloudposse/atmos#1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.

Applied to files:

  • tools/lintroller/testdata/src/a/bad_test.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
🔇 Additional comments (2)
Makefile (2)

29-29: Comment accurately reflects linter capabilities.

The updated comment now includes os.MkdirTemp, matching the linter's actual rules.


33-33: Critical fix enables proper failure propagation.

Removing || true and the grep filter ensures lintroller violations now correctly fail CI/pre-commit hooks. This addresses the core issue where PR #1634's os.MkdirTemp violations went undetected.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 15, 2025
@codecov
Copy link

codecov bot commented Oct 15, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.97%. Comparing base (e237f52) to head (d9ed60b).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1636      +/-   ##
==========================================
- Coverage   64.97%   64.97%   -0.01%     
==========================================
  Files         338      338              
  Lines       37535    37535              
==========================================
- Hits        24388    24387       -1     
+ Misses      11201    11200       -1     
- Partials     1946     1948       +2     
Flag Coverage Δ
unittests 64.97% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

## what
- Enabled lintroller as a module plugin in .golangci.yml
- Added lintroller configuration in settings.custom section
- Updated CodeQL workflow to build custom golangci-lint with lintroller
- CI now runs lintroller as part of golangci-lint with SARIF output

## why
- Lintroller was only running standalone via pre-commit hooks
- Plugin system allows integration with golangci-lint for GitHub Advanced Security
- SARIF output enables CodeQL to display lintroller findings
- Custom plugin rules now integrated alongside standard golangci-lint linters
- Ensures os.MkdirTemp, os.Setenv violations are caught in CI with proper reporting

## references
- Lintroller plugin properly registers with golangci-lint v2 module plugin system
- Custom binary built via `golangci-lint custom` includes lintroller
- Tested and verified lintroller catches violations in custom-gcl binary

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions bot added size/m Medium size PR and removed size/s Small size PR labels Oct 15, 2025
## what
- Restored golangci-lint-action@v8 usage in CI
- Added install-mode: none to use pre-built custom binary
- Build custom-gcl and install as /usr/local/bin/golangci-lint
- Action now uses our custom binary with lintroller plugin

## why
- golangci-lint-action provides valuable features (annotations, caching, PR comments)
- install-mode: none allows using custom binary while keeping action benefits
- More maintainable than reimplementing action's functionality manually
- Leverages action's integration with GitHub's UI and workflows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 65ea585 and 0cbdd59.

📒 Files selected for processing (2)
  • .github/workflows/codeql.yml (1 hunks)
  • .golangci.yml (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
.golangci.yml

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled

Files:

  • .golangci.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
🔇 Additional comments (2)
.golangci.yml (1)

18-18: Enabling lintroller: good call.

This ensures the custom rules actually run under golangci-lint.

.github/workflows/codeql.yml (1)

93-101: Pinned install + custom build looks solid.

Using golangci-lint v2 and building the custom binary aligns with the new plugin model.

## what
- Added detailed comments to .custom-gcl.yml explaining plugin build process
- Added comments to .golangci.yml explaining custom linter configuration
- Added extensive inline comments to codeql.yml workflow explaining each step
- Documented how to add multiple custom linters to the system

## why
- Plugin system is complex and not immediately obvious
- Comments clarify that multiple custom linters compile into single binary
- Explains why we install golangci-lint v2 (for the build tool, not linters)
- Documents the relationship between .custom-gcl.yml and .golangci.yml
- Makes it clear how install-mode: none allows using custom binary with action

## references
- Addresses confusion about supporting multiple custom linters
- Clarifies build process and integration with golangci-lint-action
- Documents SARIF integration for GitHub Advanced Security

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.golangci.yml (1)

5-30: Enable required linters per project standards.

Please add the missing linters: gofmt, goimports, govet, staticcheck, errcheck, ineffassign. This aligns with our baseline.

As per coding guidelines

Suggested patch:

 linters:
   enable:
     - bodyclose
     - cyclop
     - dogsled
     - dupl
     - err113
     - forbidigo
     - funlen
     - gocognit
     - gocritic
     - godot
     - gosec
     - importas
+    - gofmt
+    - goimports
+    - govet
+    - staticcheck
+    - errcheck
+    - ineffassign
     - lintroller
     - loggercheck
     - misspell
     - nestif
     - nilerr
     - nolintlint
     - revive
     - rowserrcheck
     - tparallel
     - unconvert
     - unparam
     - unused
     - whitespace
🧹 Nitpick comments (1)
.github/workflows/codeql.yml (1)

104-112: Pin the action’s version to match the built binary.

You install/build v2.5.0 but set the action to “latest”. Pin it to the same version to avoid drift.

-          version: latest
+          version: v2.5.0
           install-mode: none  # Use the custom binary we built above
           only-new-issues: true
           args: >
             --out-format=sarif:golangci-lint.sarif
             --issues-exit-code=0
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 65ea585 and 8aaf911.

📒 Files selected for processing (2)
  • .github/workflows/codeql.yml (1 hunks)
  • .golangci.yml (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
.golangci.yml

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled

Files:

  • .golangci.yml
🧠 Learnings (1)
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled

Applied to files:

  • .golangci.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
🔇 Additional comments (3)
.golangci.yml (2)

18-18: LGTM: lintroller enabled.

Good to see lintroller integrated into the main linter set.


79-86: Ensure lintroller plugin loads and custom settings are valid
golangci-lint config verify -v reports plugin "lintroller" not found—confirm the plugin is installed, that type: module (or type: plugin) matches your integration method, and that the settings (tsetenv-in-defer, os-setenv-in-test, os-mkdirtemp-in-test) exactly match lintroller’s option names.

.github/workflows/codeql.yml (1)

97-103: Confirm custom-gcl output
Verified that golangci-lint custom produces ./custom-gcl (present in workspace), so the cp step will succeed.

## what
- Added comprehensive "How Module Plugins Work" section to README
- Documented single custom binary approach (not dynamic loading)
- Explained relationship between .custom-gcl.yml and .golangci.yml
- Added step-by-step guide for adding multiple custom linters
- Documented CI/CD integration with golangci-lint-action
- Clarified build process and install-mode: none usage

## why
- Module plugin system is non-obvious and differs from traditional .so plugins
- Users need to understand all plugins compile into single binary
- Important to document why we install golangci-lint v2 (build tool)
- Shows how to scale to multiple custom linters
- Explains SARIF integration and GitHub Security benefits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@osterman osterman requested a review from a team as a code owner October 15, 2025 20:08
@osterman osterman added the no-release Do not create a new release (wait for additional code changes) label Oct 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
tools/lintroller/README.md (3)

185-194: Pin plugin sources for reproducible builds

The .custom-gcl.yml example is clear. To avoid surprises, consider pinning plugins by tag/commit (module@vX.Y.Z) or via a replace directive, even when using local path.


247-266: Add SARIF upload step and avoid sudo cp in CI

  • Add an upload step so results reach GitHub Security.
  • Prefer placing ./custom-gcl earlier in PATH instead of sudo copying over system golangci-lint.

Apply these tweaks:

- - name: Build custom golangci-lint with plugins
-   run: |
-     golangci-lint custom
-     sudo cp ./custom-gcl /usr/local/bin/golangci-lint
+ - name: Build custom golangci-lint with plugins
+   run: |
+     golangci-lint custom
+     echo "$PWD" >> $GITHUB_PATH
+
+ - name: Verify custom binary
+   run: ./custom-gcl version

- - name: Run golangci-lint with plugins
+ - name: Run golangci-lint with plugins
    uses: golangci/golangci-lint-action@v8
    with:
-     install-mode: none  # Use our custom binary instead of action's binary
-     args: --out-format=sarif:golangci-lint.sarif
+     install-mode: none  # Use our custom binary instead of action's binary
+     args: --out-format=sarif:golangci-lint.sarif --timeout=5m
+     version: none       # Ensure action doesn't install its own binary

+ - name: Upload SARIF to GitHub Security
+   uses: github/codeql-action/upload-sarif@v3
+   with:
+     sarif_file: golangci-lint.sarif

267-272: Name consistency: “Lint Roller” vs “Lintroller”

Use one style throughout (prefer “Lint Roller” for prose, “lintroller” for the linter ID).

Apply:

-Benefits:
-- ✅ Lintroller findings appear in GitHub Security tab via SARIF
-- ✅ Inline PR annotations for violations
-- ✅ Unified linting output (standard + custom linters)
-- ✅ Supports `//nolint:lintroller` comments
+Benefits:
+- ✅ Lint Roller findings appear in GitHub Security tab via SARIF
+- ✅ Inline PR annotations for violations
+- ✅ Unified linting output (standard + custom linters)
+- ✅ Supports `//nolint:lintroller` comments
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b732580 and 3a19d19.

📒 Files selected for processing (1)
  • tools/lintroller/README.md (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*.go : All code must pass golangci-lint checks
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Before submitting PRs, ensure tests pass, coverage targets met, run golangci-lint, and update documentation
🪛 LanguageTool
tools/lintroller/README.md

[grammar] ~267-~267: There might be a mistake here.
Context: ...sarif:golangci-lint.sarif ``` Benefits: - ✅ Lintroller findings appear in GitHub S...

(QB_NEW_EN)


[grammar] ~268-~268: There might be a mistake here.
Context: ...enefits: - ✅ Lintroller findings appear in GitHub Security tab via SARIF - ✅ Inlin...

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
🔇 Additional comments (3)
tools/lintroller/README.md (3)

162-181: Module-plugin overview reads right; align versions across docs/CI

Looks good. Please ensure the golangci-lint version you install (e.g., v2.5.0) matches the version in .custom-gcl.yml to avoid schema/drift issues.


195-210: Enable/configure block looks correct; confirm linter name

The settings.custom.lintroller name must match the plugin’s registered name (register.Plugin("lintroller", …)). If that differs, golangci-lint won’t wire settings.


214-246: Multi-plugin guidance LGTM

Clear steps for adding more plugins. No issues.

osterman and others added 2 commits October 15, 2025 15:20
- Add periods to inline comments in test file (godot linter)
- Pin golangci-lint-action version to v2.5.0 to match built binary

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Change from `--out-format=sarif:file.sarif` (v1 syntax) to
`--output.sarif.path=file.sarif` (v2 syntax).

This fixes the CI error: "unknown flag: --out-format"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
.github/workflows/codeql.yml (1)

93-118: Comments are helpful but overly verbose.

The inline documentation is thorough, but the sheer volume makes the workflow harder to scan. Consider condensing these into a shorter explanation with a link to external docs if needed.

tools/lintroller/testdata/src/a/bad_test.go (1)

51-54: Consider handling the error even in benchmark test data.

Line 52 ignores the error from os.MkdirTemp. While this is test data meant to verify the linter detects os.MkdirTemp usage, ignoring errors—even in benchmarks—can make the test data misleading. Consider at least a panic or b.Fatal if the goal is to show that os.MkdirTemp itself (not error handling) is the issue.

Example:

 func BenchmarkGoodMkdirTemp(b *testing.B) {
-	tempDir, _ := os.MkdirTemp("", "bench-*") // OK: os.MkdirTemp is allowed in benchmarks.
+	tempDir, err := os.MkdirTemp("", "bench-*") // OK: os.MkdirTemp is allowed in benchmarks.
+	if err != nil {
+		b.Fatal(err)
+	}
 	defer os.RemoveAll(tempDir)
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3a19d19 and a6a3815.

📒 Files selected for processing (2)
  • .github/workflows/codeql.yml (1 hunks)
  • tools/lintroller/testdata/src/a/bad_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Write unit tests as table-driven tests focused on behavior; prefer high coverage for pkg/ and internal/exec/; comments must end with periods.
Use t.Skipf with a reason instead of t.Skip; never skip without a reason.
Test files must mirror implementation file names (e.g., aws_ssm_store_test.go pairs with aws_ssm_store.go).

Files:

  • tools/lintroller/testdata/src/a/bad_test.go
**/testdata/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Use test fixtures for complex inputs under testdata

Files:

  • tools/lintroller/testdata/src/a/bad_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All comments must end with periods across all Go code (godot linter enforced).
Organize imports into three groups (stdlib, 3rd-party, Atmos) separated by blank lines and sorted alphabetically within groups; preserve existing aliases.
Add defer perf.Track(<atmosConfig|nil>, ".")() at the start of all public and critical private functions, followed by a blank line.
All errors must be wrapped using static errors from errors/errors.go; prefer errors.Join for multiple errors, fmt.Errorf with %w for context, and check with errors.Is; never use dynamic errors directly.
Use utils.PrintfMarkdown() to render embedded markdown examples for CLI help output.
Co-locate unit tests with implementation files; integration tests reside under tests/.
Distinguish UI output from logging: UI prompts/status/errors to stderr; data/results to stdout; logging for system/debug info only with structured fields.
Most text UI must go to stderr; only data/results to stdout. Prefer utils.PrintfMessageToTUI for UI messages.
Bind all environment variables with viper.BindEnv(); every env var must have an ATMOS_ alternative binding.
Favor cross-platform code: prefer SDKs over external binaries, use filepath/os/runtime, and handle OS-specific differences or use build tags.
For non-standard execution paths, capture telemetry using telemetry.CaptureCmd or telemetry.CaptureCmdString without collecting user data.
Search for existing methods and utilities (internal/exec, pkg/) before implementing new functionality; prefer reuse/refactoring over duplication.

Files:

  • tools/lintroller/testdata/src/a/bad_test.go
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*.go : All code must pass golangci-lint checks
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Before submitting PRs, ensure tests pass, coverage targets met, run golangci-lint, and update documentation
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
PR: cloudposse/atmos#1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.

Applied to files:

  • tools/lintroller/testdata/src/a/bad_test.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: [mock-windows] tests/fixtures/scenarios/complete
  • GitHub Check: [localstack] demo-localstack
  • GitHub Check: Acceptance Tests (ubuntu-latest, linux)
  • GitHub Check: Acceptance Tests (windows-latest, windows)
  • GitHub Check: Acceptance Tests (macos-latest, macos)
  • GitHub Check: Summary
🔇 Additional comments (1)
tools/lintroller/testdata/src/a/bad_test.go (1)

1-59: Comprehensive test coverage for lintroller rules.

The test data covers all the key scenarios:

  • t.Setenv in defer/cleanup (should fail)
  • os.Setenv in tests (should fail)
  • os.MkdirTemp in tests (should fail)
  • Allowed usages in defer blocks and benchmarks

The // want comments correctly specify expected lint messages for each violation. Nice work setting up thorough test data.

osterman and others added 4 commits October 15, 2025 17:28
Add explicit chmod +x after go build to ensure the binary is executable
on all platforms, particularly in CI environments.

This fixes the pre-commit error: "Permission denied" when running lintroller

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The lintroller main package is in cmd/lintroller/, not the root.
This fixes the build to create a proper executable instead of an archive.

Also added:
- Explicit chmod +x after build for CI compatibility
- Verification that binary is executable after build
- Updated dependencies to include cmd/lintroller/*.go

This fixes: 'Permission denied' and 'syntax error' when running lintroller

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The lintroller/testdata contains intentional violations for testing.
Exclude all testdata directories using 'go list' with grep filter.

This fixes: lintroller reporting false positives on test fixtures

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…iles

Replace os.Setenv with t.Setenv in test files for automatic cleanup:
- pkg/config/load_test.go: 8 violations fixed
- pkg/list/list_vendor_test.go: 1 os.MkdirTemp violation fixed
- pkg/utils/yaml_func_exec_test.go: 3 violations fixed

This ensures environment variables and temp directories are automatically
cleaned up after tests without needing manual defer statements.

Fixes lintroller violations caught by custom linting rules.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@mergify
Copy link

mergify bot commented Oct 16, 2025

💥 This pull request now has conflicts. Could you fix it @osterman? 🙏

osterman and others added 2 commits October 16, 2025 08:50
When changing from os.MkdirTemp to t.TempDir(), the directory name
no longer contained 'atmos-test-vendor', which broke the test mode
detection in getVendorInfos. Fixed by creating an intermediate
directory with the expected name pattern.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add a Makefile target to build the custom golangci-lint binary
(custom-gcl) that includes the lintroller plugin. Update the
pre-commit hook to build and use this custom binary instead of
the system golangci-lint, ensuring lintroller rules are enforced
during pre-commit checks.

Changes:
- Add custom-gcl target to Makefile that builds the binary if missing
- Update lint target to depend on custom-gcl and use ./custom-gcl
- Update pre-commit golangci-lint hook to build and use custom-gcl

This ensures developers have the same linting experience locally
as in CI, catching violations before they're pushed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions bot added size/l Large size PR and removed size/m Medium size PR labels Oct 16, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6491214 and fa576be.

📒 Files selected for processing (2)
  • .pre-commit-config.yaml (1 hunks)
  • Makefile (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*.go : All code must pass golangci-lint checks
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled

Applied to files:

  • .pre-commit-config.yaml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Summary

osterman and others added 2 commits October 16, 2025 12:59
Fix CI failures by:
1. Skip lintroller hook in pre-commit.yml since it already runs
   in codeql.yml via the custom golangci-lint binary
2. Run go mod tidy on lintroller module before building custom
   golangci-lint to ensure dependencies are ready

This ensures:
- No duplicate linting runs between pre-commit and codeql workflows
- Custom binary build succeeds by having clean module state
- Lintroller enforcement happens once in codeql.yml

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Address remaining CodeRabbit review feedback:

1. Fix lintroller description in .golangci.yml
   - Changed from 't.TempDir checks' to 'os.MkdirTemp checks'
   - Accurately reflects the actual rule (os-mkdirtemp-in-test)

2. Remove stale-binary guard in Makefile custom-gcl target
   - Removed 'if [ ! -f ./custom-gcl ]' guard that prevented rebuilds
   - Added .custom-gcl.yml as a dependency
   - Ensures binary is rebuilt when inputs change

Note: The codeql.yml comment about || true was already addressed
in commit f9010b9 which added continue-on-error and if: always().

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fa576be and 2850654.

📒 Files selected for processing (4)
  • .github/workflows/codeql.yml (1 hunks)
  • .github/workflows/pre-commit.yml (1 hunks)
  • .golangci.yml (3 hunks)
  • Makefile (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .golangci.yml
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*.go : All code must pass golangci-lint checks
📚 Learning: 2025-10-16T15:18:00.319Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-16T15:18:00.319Z
Learning: Applies to **/*.go : Ensure Atmos remains portable across Linux, macOS, and Windows; use filepath.Join, os.PathSeparator, and build constraints when necessary.

Applied to files:

  • Makefile
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary

Fix two critical CI issues:

1. Windows test compilation failure
   - Remove duplicate TestShouldExcludePathForTesting_WindowsCaseInsensitive
   - Remove duplicate TestMergeDefaultImports_WindowsCaseInsensitive
   - These tests exist in load_windows_test.go with proper build constraints
   - Having them in both files caused redeclaration errors on Windows

2. golangci-lint action not using custom binary
   - Replace golangci-lint-action usage with direct binary execution
   - The action was finding system binary even with install-mode: none
   - Now directly runs: golangci-lint run with custom binary
   - Copy custom-gcl to both /usr/local/bin and ~/go/bin for coverage

This ensures:
- Windows tests compile without redeclaration errors
- lintroller plugin is available during CI linting
- Custom binary is used instead of system binary

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions bot added size/m Medium size PR and removed size/l Large size PR labels Oct 16, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
.github/workflows/codeql.yml (1)

144-156: Job won't fail when lint violations are found—enforce via re-fail step.

The continue-on-error: true on line 145 suppresses the lint step's exit code, so the job succeeds even when violations exist. The comments state "proper enforcement," but currently violations are uploaded to SARIF without blocking the PR. Add a step to re-fail after SARIF upload:

      - name: Run golangci-lint with lintroller plugin
        continue-on-error: true
+       id: lint
        run: |
          # Run the custom binary directly instead of via the action
          # The action was finding the system binary even with install-mode: none
          golangci-lint run \
            --new-from-rev=origin/${{ github.base_ref }} \
            --output.sarif.path=golangci-lint.sarif \
            --issues-exit-code=1 \
            --new=false

      - name: Upload filtered SARIF results
         if: always()
         uses: github/codeql-action/upload-sarif@v3
         with:
           sarif_file: golangci-lint.sarif
+
+      - name: Fail if lint violations found
+        if: failure() && steps.lint.outcome == 'failure'
+        run: exit 1

(The flags --new-from-rev and --new=false work together correctly; --new-from-rev enables diff-based checking independently and --new=false doesn't override it.)

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2850654 and e934db6.

📒 Files selected for processing (2)
  • .github/workflows/codeql.yml (1 hunks)
  • pkg/config/load_test.go (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/config/load_test.go
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*.go : All code must pass golangci-lint checks
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Summary
🔇 Additional comments (1)
.github/workflows/codeql.yml (1)

93-122: Build and installation approach is sound.

The multi-step workflow to compile lintroller into a custom golangci-lint binary and install it to the system PATH is a reasonable solution for including custom plugins. The detailed comments in the step (lines 100–111) clearly document the approach for future maintainers.

Revert the mistake of replacing the golangci-lint-action with raw
commands. The action provides critical features like PR annotations,
caching, and GitHub UI integration.

The real fix is to move the system binary out of the way BEFORE
copying our custom binary:
- mv ~/go/bin/golangci-lint ~/go/bin/golangci-lint.system
- cp ./custom-gcl ~/go/bin/golangci-lint

This ensures when the action runs with install-mode: none, it finds
our custom binary with the lintroller plugin in PATH.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/codeql.yml (1)

145-160: Add a step to verify the custom binary is being used by the action.

Currently, after replacing the binary, there's no confirmation that the action actually uses the custom binary. Add a verification step (e.g., which golangci-lint && golangci-lint --version) to detect if binary setup failed silently:

       chmod +x ~/go/bin/golangci-lint
       golangci-lint --version

+      - name: Verify custom golangci-lint is in PATH
+        run: |
+          which golangci-lint
+          golangci-lint --version
+          # Confirm lintroller is included (if possible)
+          golangci-lint help | grep -q "lintroller" || echo "WARNING: lintroller may not be compiled in"

       - name: Run golangci-lint with lintroller plugin
         continue-on-error: true
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e934db6 and be711d3.

📒 Files selected for processing (1)
  • .github/workflows/codeql.yml (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Summary
🔇 Additional comments (4)
.github/workflows/codeql.yml (4)

125-144: Documentation is thorough and correct.

The multi-step comments clearly explain the lintroller integration, the SARIF output flow, and the exit-code enforcement. The inline annotation about violations (os.MkdirTemp, os.Setenv, etc.) is helpful for maintainability. Well done on the documentation here.


146-160: Workflow configuration correctly balances enforcement with SARIF uploads.

The use of continue-on-error: true on the lint step, --issues-exit-code=1 in args, and if: always() on the upload ensures linter violations fail CI while SARIF results are always uploaded for security review. This aligns with the PR objective to enforce lintroller violations. The only-new-issues: true setting and --output.sarif.path are properly configured.


145-160: No action needed—install-mode: none is supported in v8.0.0.

The golangci-lint-action@v8.0.0 supports the install-mode input parameter with "none" as a valid value, which correctly skips binary installation and uses the preinstalled binary from PATH. The configuration is compatible and aligns with the documented behavior.


93-123: The original review comment identifies non-existent issues; the code is correct as-is.

Both tools/lintroller and .custom-gcl.yml are present and properly configured. The cd ../.. pattern works correctly because GitHub Actions runs the workflow from the repository root, so returning to the parent's parent directory lands exactly where needed. The binary replacement strategy is sound—installing to ~/go/bin/golangci-lint places it in PATH, and install-mode: none correctly uses the pre-built binary. Error handling is already in place: --issues-exit-code=1, continue-on-error: true, and if: always() on SARIF upload. The implementation is robust and well-documented.

Likely an incorrect or invalid review comment.

osterman and others added 2 commits October 16, 2025 16:50
Remove runtime and strings imports that were left over after
removing the Windows-specific test functions. These imports are
not needed in load_test.go since the Windows tests are now only
in load_windows_test.go.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…-error

Fix two critical issues in the golangci-lint workflow:

1. Add comprehensive error checking to custom binary build:
   - Set 'set -e' to exit on any error
   - Check if 'golangci-lint custom' succeeds
   - Verify ./custom-gcl exists and is executable
   - Check mv and cp commands succeed with error messages
   - Fail fast with clear error messages if any step fails

2. Remove 'continue-on-error: true' from golangci-lint step:
   - Step will now FAIL the job if linting issues are found
   - SARIF upload step keeps 'if: always()' to upload even on failure
   - Provides proper enforcement while preserving SARIF results

This ensures:
- Workflow stops immediately if custom binary build fails
- No stale or missing binaries are used
- Linting failures properly fail the CI check
- SARIF results are still uploaded for GitHub Security

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
pkg/config/load_test.go (1)

14-22: Simplify by removing the no-op cleanup closure.

Since t.TempDir() handles cleanup automatically, returning and deferring a no-op cleanup function adds unnecessary complexity. Similarly, t.Setenv auto-cleans, so the pattern throughout these tests doesn't need manual cleanup.

Apply this diff to simplify:

-func setupTestFiles(t *testing.T) (string, func()) {
+func setupTestFiles(t *testing.T) string {
 	tempDir := t.TempDir()
-
-	cleanup := func() {
-		// t.TempDir() handles cleanup automatically
-	}
-
-	return tempDir, cleanup
+	return tempDir
 }

Then update the single call site at line 78:

-		tempDir, cleanup := setupTestFiles(t)
-		defer cleanup()
+		tempDir := setupTestFiles(t)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between be711d3 and b7ef1b7.

📒 Files selected for processing (2)
  • .github/workflows/codeql.yml (1 hunks)
  • pkg/config/load_test.go (9 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/config/load_test.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Use table-driven unit tests for pure functions and focus on behavior; co-locate tests; target >80% coverage for pkg/ and internal/exec/.
Always use t.Skipf() with a clear reason; never use t.Skip() or t.Skipf without a reason.

Files:

  • pkg/config/load_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods; applies to single-line, multi-line, inline, and documentation comments (golangci-lint godot).
Group imports into three sections (stdlib, 3rd-party, Atmos), separated by blank lines; sort alphabetically within each group; preserve existing aliases.
Configuration loading must use Viper with precedence CLI → ENV → files → defaults; bind config name atmos and add path, AutomaticEnv, and ATMOS prefix.
All errors must be wrapped using static errors (defined in errors/errors.go); use errors.Join for multiple errors; fmt.Errorf with %w for context; use errors.Is for checks; never compare error strings.
Distinguish structured logging from UI output: UI prompts/status/errors to stderr; data/results to stdout; never use logging for UI.
Most text UI must go to stderr; only data/results to stdout; prefer utils.PrintfMessageToTUI for UI messages.
All new configurations must support Go templating using existing utilities and available template functions.
Prefer SDKs over external binaries for cross-platform support; use filepath/os/runtime for portability.
For non-standard execution paths, capture telemetry via telemetry.CaptureCmd or telemetry.CaptureCmdString without user data.
80% minimum coverage on new/changed lines and include unit tests for new features; add integration tests for CLI using tests/ fixtures.
Always bind environment variables with viper.BindEnv and provide ATMOS_ alternatives for every env var.
Use structured logging with levels (Fatal>Error>Warn>Debug>Trace); avoid string interpolation and ensure logging does not affect execution.
Prefer re...

Files:

  • pkg/config/load_test.go
pkg/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests for packages live under pkg/ alongside implementation files.

Files:

  • pkg/config/load_test.go
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to .golangci.yml : Configure golangci-lint with gofmt, goimports, govet, staticcheck, errcheck, ineffassign, misspell, unused, revive, gocritic enabled
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
PR: cloudposse/atmos#1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: The atmos codebase has a custom extension to *testing.T that provides a Chdir method, allowing test functions to call t.Chdir() to change working directories during tests. This is used consistently across test files in the codebase.

Applied to files:

  • pkg/config/load_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
PR: cloudposse/atmos#1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method that can be called on *testing.T objects. This functionality is implemented through custom testing framework extensions and is used consistently throughout the test suite for changing working directories during tests.

Applied to files:

  • pkg/config/load_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
PR: cloudposse/atmos#1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests. This is implemented through custom testing framework extensions and is used consistently throughout the test suite.

Applied to files:

  • pkg/config/load_test.go
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
PR: cloudposse/atmos#1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.

Applied to files:

  • pkg/config/load_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
PR: cloudposse/atmos#1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests.

Applied to files:

  • pkg/config/load_test.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
🔇 Additional comments (3)
.github/workflows/codeql.yml (3)

93-152: Excellent error handling and documentation in the custom binary build.

The build step now comprehensively checks for failures at each critical point—custom build, binary existence, executability, and move/copy operations—and fails fast with set -e and explicit guards. The inline documentation clearly explains the multi-step process and how additional plugins can be added via .custom-gcl.yml. This is a solid foundation for reliable custom binary management.


176-184: Lintroller violations now properly fail the workflow.

The lint step is configured to fail when violations are found (--issues-exit-code=1 with no continue-on-error), which enforces the PR objective. The only-new-issues: true setting handles diff-scoping for changed code. Assuming the action correctly maps this to the appropriate --new-from-* flag for your context, this should work reliably.

If you haven't already, verify that only-new-issues: true correctly reports only new issues in forked PRs. (The golangci-lint-action@v8 should handle this internally, but it's worth confirming if you see unexpected behavior.)


186-190: SARIF upload step correctly runs even when linting fails.

The if: always() condition ensures SARIF results are uploaded for CodeQL integration regardless of whether violations were found. Combined with the lint step's failure on violations, this achieves the desired outcome: enforcement + observability.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 16, 2025
Revert to main branch behavior where golangci-lint uses
--issues-exit-code=0 to always succeed and upload SARIF.

Main branch pattern:
- golangci-lint doesn't fail the CI job on linting issues
- SARIF results are uploaded to CodeQL/Security tab for visibility
- This allows the workflow to complete and show findings without blocking

The enforcement happens via:
- Pre-commit hooks (make lintroller) - now properly enforced without || true
- PR annotations from golangci-lint action
- CodeQL Security tab visibility via SARIF

This matches the existing CI pattern established in main branch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@aknysh aknysh merged commit 3ab014a into main Oct 17, 2025
53 checks passed
@aknysh aknysh deleted the fix-mkdirtemp-linting branch October 17, 2025 23:11
@mergify mergify bot removed the needs-cloudposse Needs Cloud Posse assistance label Oct 17, 2025
@github-actions
Copy link

These changes were released in v1.195.0-rc.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-release Do not create a new release (wait for additional code changes) size/m Medium size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants