Skip to content

feat: Inject AHOY_CMD and AHOY_COMMAND_NAME environment variables into subprocesses#170

Merged
ocean merged 16 commits into
ahoy-cli:v3-candidatefrom
ocean:master
Jun 16, 2026
Merged

feat: Inject AHOY_CMD and AHOY_COMMAND_NAME environment variables into subprocesses#170
ocean merged 16 commits into
ahoy-cli:v3-candidatefrom
ocean:master

Conversation

@ocean

@ocean ocean commented May 12, 2026

Copy link
Copy Markdown
Member

Sets AHOY_CMD to the resolved path of the running ahoy binary and AHOY_COMMAND_NAME to the name of the invoked command, making both available to every subprocess ahoy runs.

Adds a testdata fixture and BATS integration tests to verify the behaviour.

This is a fix for #165

Summary by CodeRabbit

Release Notes

  • New Features

    • Commands now get AHOY_COMMAND_NAME (current command name) and AHOY_CMD (binary path) in the execution environment.
  • Improvements

    • Configuration parsing now more consistently follows the ahoy.yml schema.
    • Validation reports all detected command/config issues together (instead of stopping early).
    • Circular-import handling is more robust, with clearer detection.
    • Bash completion is generated consistently.
  • Bug Fixes

    • Subprocess execution failures are now surfaced as proper command errors.

…o subprocesses

Sets AHOY_CMD to the resolved path of the running ahoy binary and
AHOY_COMMAND_NAME to the name of the invoked command, making both
available to every subprocess ahoy runs.

Adds a testdata fixture and BATS integration tests to verify the
behaviour.
@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5204386d-5ee2-46d8-bc3a-ef9cd556e742

📥 Commits

Reviewing files that changed from the base of the PR and between 40cee88 and eee4425.

📒 Files selected for processing (1)
  • ahoy_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • ahoy_test.go

Walkthrough

Adds AHOY_CMD and AHOY_COMMAND_NAME environment variable injection into executed subprocesses. Refactors circular import detection into a processImport helper using an importVisited map. Switches config validation to accumulate errors before a single fatal report, and command execution from Run to RunE for proper error propagation. GitHub Actions workflows are hardened with commit-pinned actions, per-job permissions, and a new zizmor security scan.

Changes

Environment variable injection, error handling, and circular import detection

Layer / File(s) Summary
Config/Command struct YAML tags and package state
ahoy.go
Config and Command struct fields gain explicit yaml:"..." tags. Package-level ahoyExecutable and importVisited variables are declared.
Circular import detection and normalizePath helper
ahoy.go
normalizePath converts a path to a cleaned absolute form. processImport centralises include path expansion, checks importVisited to skip repeated imports, and logs "Circular import detected" when a cycle is found. getSubCommands delegates to processImport. setupApp initialises and seeds importVisited with the primary config path.
Configuration validation error accumulation
ahoy.go
getCommands validation accumulates invalid-command reasons into a configErrors slice. After command construction all entries are logged and a single fatal message is issued.
Executable capture, env injection, and RunE error propagation
ahoy.go
main() captures the binary path into ahoyExecutable. Each Cobra command switches from Run to RunE. AHOY_COMMAND_NAME and AHOY_CMD are appended to the subprocess environment. Subprocess errors propagate through RunE. Bash completion generation is made unconditional.
Test YAML and Bats tests for env variable injection
testdata/ahoy-self-env.ahoy.yml, tests/environment-variables.bats
Test YAML defines commands that echo and validate AHOY_CMD and AHOY_COMMAND_NAME. Bats tests assert both variables are non-empty, resolve to the actual binary, point to an executable, and are accessible together in the same subprocess.
Unit tests for circular imports and state isolation
ahoy_test.go
TestGetSubCommand resets importVisited to prevent test pollution. appRun capture logic is refactored with explicit pipe error handling and deferred stream restoration. TestMultiBranchAndCircularImports exercises multi-branch import merging and verifies "Circular import detected" appears in log output for circular configs.
missing-cmd.bats: regex assertions and circular import test
tests/missing-cmd.bats
Existing fatal-output assertions switch from exact string matching to regex matching. A new test writes circular import YAML fixtures and asserts non-zero exit, no panic, and "Circular import detected" in output.

GitHub Actions hardening and linting configuration

Layer / File(s) Summary
Build and test workflow action pinning and lint fix
.github/workflows/build_and_test.yml
actions/checkout and actions/setup-go are pinned to newer commit SHAs. Lint step working-directory changes from hardcoded v2 to ${{ matrix.directory }}. Both upload-artifact steps are pinned to a newer SHA.
Release workflow permissions and tooling pinning
.github/workflows/release.yml
Global permissions: {} replaced with per-job permissions. Actions and Syft are pinned by commit SHA (Syft from latest to v1.45.1). "Determine release mode" uses EVENT_NAME/DRY_RUN env variables. post-release adds REF_NAME env var.
CodeQL checkout pinning and zizmor security scan workflow
.github/workflows/codeql.yml, .github/workflows/zizmor.yml
CodeQL workflow pins checkout to v6.0.2 commit SHA. New zizmor.yml runs security scanning on master pushes and all pull requests with least-privilege permissions and pinned action versions.
golangci-lint v2 configuration migration
v2/.golangci.yml
Migrates to version: "2" schema, switches from disable-all to default: none, restructures exclusions under linters.exclusions with presets and path rules, and adds a formatters section for gofmt/goimports.

Sequence Diagram(s)

sequenceDiagram
  participant main
  participant osExec as os.Executable()
  participant setupApp
  participant processImport
  participant RunE as cobra RunE handler
  participant subprocess as exec.Command.Run()

  main->>osExec: capture binary path
  osExec-->>main: ahoyExecutable
  main->>setupApp: initialise importVisited, seed primary config path
  setupApp->>processImport: process each import path
  processImport->>processImport: check importVisited for cycle
  processImport-->>setupApp: merged command map or "Circular import detected" log
  setupApp->>RunE: build command with RunE
  RunE->>subprocess: os.Environ() + AHOY_COMMAND_NAME + AHOY_CMD
  subprocess-->>RunE: error or nil
  RunE-->>setupApp: return error to cobra
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hoppity-hop through the import tree,
No circles shall trap me, I run free!
AHOY_CMD set, my path made clear,
Errors collected, then logged — oh dear!
RunE returns what once just died,
This rabbit reviewed it, satisfied! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: injecting two environment variables (AHOY_CMD and AHOY_COMMAND_NAME) into subprocesses, which is the main feature delivered across ahoy.go, test fixtures, and integration tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@ocean

ocean commented May 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai There should be a configuration change to include you doing code reviews on the v3-candidate branch, please check your configuration

@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@ocean, let me check the current CodeRabbit configuration for this repository to verify the branch settings.


🛠 Debug Information Gathered


@ocean — I've found the issue. The current configuration has base_branches set to an empty array, which means CodeRabbit only automatically reviews PRs targeting the default branch. The v3-candidate branch is not included.

To fix this, add v3-candidate to the base_branches list in your .coderabbit.yaml file:

reviews:
  auto_review:
    base_branches:
      - v3-candidate

This field accepts regex patterns too, so if you want to cover all non-default branches you could use .*, but scoping it to v3-candidate specifically is the more targeted approach.

Once that change is merged into the default branch, CodeRabbit will automatically review PRs that target v3-candidate as well.

@ocean

ocean commented May 13, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai help

@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai rate limit to show your current review rate limit status.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
  • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
  • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve merge conflict to automatically resolve merge conflicts.
  • @coderabbitai autofix to automatically fix issues identified in unresolved review comments.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit configuration file (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@ocean

ocean commented May 14, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ocean

ocean commented May 14, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@v2/ahoy.go`:
- Line 321: The current assignment to command.Env appends ahoyEnvVars before
envVars so user-provided environment entries can override injected values;
change the append order so envVars are appended first and ahoyEnvVars are
appended last (so injected AHOY_CMD / AHOY_COMMAND_NAME override any
duplicates), i.e., update the expression that builds command.Env which uses
command.Environ(), ahoyEnvVars and envVars to append envVars then ahoyEnvVars.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 850910d1-4739-42ea-8472-a116e8914154

📥 Commits

Reviewing files that changed from the base of the PR and between aa7f6e7 and 1f78216.

📒 Files selected for processing (3)
  • v2/ahoy.go
  • v2/testdata/ahoy-self-env.ahoy.yml
  • v2/tests/environment-variables.bats

Comment thread v2/ahoy.go Outdated
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

❌ Failed to create PR with unit tests: AGENT_CHAT: Failed to open pull request

ocean added 10 commits May 17, 2026 13:40
- $AHOY_CMD contains a path to the actual ahoy executable
so it can be used for substitution for running ahoy-driven
subcommands with the exact same binary.
- $AHOY_COMMAND_NAME contains the name of the ahoy command (within
the .ahoy.yml file) that is being run, and therefore allows the
subprocess to know it is being run by an ahoy parent process.

Signed-off-by: Drew Robinson <drew.robinson@gmail.com>
… files...

... don't override the injected runtime values. In Go's os/exec, the
last occurrence of a duplicate environment variable key
takes precedence, and we want that to be the ones set by ahoy
itself.

Signed-off-by: Drew Robinson <drew.robinson@gmail.com>
yaml.v2 uses case-insensitive field matching as a fallback when no tags
are present, but yaml.v3 (the current maintained version) requires exact
matches. Without tags, migrating to yaml.v3 would silently leave AhoyAPI
empty on every config file, causing spurious "unsupported API version"
errors for all users. Add explicit yaml:"..." tags to every field on both
Config and Command to make the structs safe for a future yaml.v3 migration.
…os.Exit

os.Exit inside rootCmd.Execute() bypasses the pipe-drain cleanup in main(),
which can cause in-flight subprocess stderr output to be silently truncated.
Switching the command closure from Run to RunE and returning the subprocess
error lets main() close the write-end of the pipe and wait for the drain
goroutine to flush before exiting.
The block logged the sourcefile path and called os.Exit(0) whenever
sourcefile was set, which in normal usage is always. This meant shell
completion was printing the config file path instead of command names
and exiting without running the pipe-drain cleanup in main(). Removing
it lets the correct completion logic below run and avoids the os.Exit
inside Execute().
… first

Previously getCommands() called logger("fatal") on the first invalid
command definition, meaning users had to fix errors one at a time with
no indication others existed. Each validation failure now logs as
[error] and continues, with a single [fatal] summary after all commands
are checked. Update BATS assertions to match the new output format.
getSubCommands() and getCommands() mutually recurse when processing
imports. A circular reference (A imports B imports A) caused infinite
recursion until the Go runtime panicked with a stack overflow.

Track visited file paths in a package-level map reset by setupApp() at
startup. The root config file is marked visited immediately so imports
cannot loop back to it. When a circular reference is detected, a [warn]
message is emitted and the file is skipped. Add a BATS test to verify
no crash occurs and the warning is present. Also reset the map in the
unit test that calls getSubCommands() directly.
os.Pipe() errors were silently discarded with _, leaving w as nil and
causing a panic on the subsequent os.Stdout assignment. Add proper error
handling that returns early and cleans up any partially created pipes.
Add a deferred restore of os.Stdout/os.Stderr so they are recovered even
if cmd.Execute() panics, preventing file descriptor leaks between tests.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
ahoy.go (1)

385-387: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

RunE currently suppresses actionable execution errors.

With SilenceErrors=true, this path returns an error but only prints a blank line. Failures like “executable not found” can become effectively silent. Print the actual error (or at least non-exit errors) before returning.

Suggested fix
-                if err := command.Run(); err != nil {
-                    fmt.Fprintln(os.Stderr)
-                    return err
-                }
+                if err := command.Run(); err != nil {
+                    var exitErr *exec.ExitError
+                    if !errors.As(err, &exitErr) {
+                        fmt.Fprintln(os.Stderr, err.Error())
+                    }
+                    return err
+                }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ahoy.go` around lines 385 - 387, In the RunE function's error handling block
where command.Run() is checked, the current code prints only a blank line to
stderr instead of the actual error message. Replace the fmt.Fprintln(os.Stderr)
call with a proper error print statement that outputs the error content (e.g.,
using fmt.Fprintf or fmt.Fprintln with the err variable) to ensure actionable
execution errors like "executable not found" are visible to users before
returning the error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/zizmor.yml:
- Around line 14-20: The zizmor job currently grants only security-events: write
permission in its job-level permissions block, but the actions/checkout action
requires contents: read permission to access the repository. Since job-level
permissions override the workflow-level permissions rather than extending them,
add contents: read to the permissions block alongside the existing
security-events: write permission.

In `@ahoy.go`:
- Around line 188-196: The importVisited map persists as monotonic state across
the entire app run, causing files legitimately imported from different recursion
branches to be incorrectly flagged as circular imports. Replace this global
persistent map with stack-style tracking that marks imports as visited only for
the current recursion path: mark them as visited on function entry and unmark
them on function exit. Additionally, normalize all seeded and imported paths
consistently before checking or storing them in the tracking map to ensure
reliable comparison. This approach will prevent false positives for valid
multi-branch imports while still catching genuine circular dependencies within a
single path.

---

Outside diff comments:
In `@ahoy.go`:
- Around line 385-387: In the RunE function's error handling block where
command.Run() is checked, the current code prints only a blank line to stderr
instead of the actual error message. Replace the fmt.Fprintln(os.Stderr) call
with a proper error print statement that outputs the error content (e.g., using
fmt.Fprintf or fmt.Fprintln with the err variable) to ensure actionable
execution errors like "executable not found" are visible to users before
returning the error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 07aebd8e-3f65-41a9-bbe8-88437928ff27

📥 Commits

Reviewing files that changed from the base of the PR and between b13edf2 and 3861510.

📒 Files selected for processing (11)
  • .circleci/config.yml
  • .coderabbit.yaml
  • .github/dependabot.yml
  • .github/workflows/build_and_test.yml
  • .github/workflows/codeql.yml
  • .github/workflows/release.yml
  • .github/workflows/zizmor.yml
  • .golangci.yml
  • ahoy.go
  • ahoy_test.go
  • tests/missing-cmd.bats
💤 Files with no reviewable changes (1)
  • .circleci/config.yml

Comment thread .github/workflows/zizmor.yml
Comment thread ahoy.go Outdated
ocean added 4 commits June 15, 2026 16:36
…versions and enable Zizmor scanning

Signed-off-by: Drew Robinson <drew.robinson@gmail.com>
Signed-off-by: Drew Robinson <drew.robinson@gmail.com>
Signed-off-by: Drew Robinson <drew.robinson@gmail.com>

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
ahoy_test.go (1)

247-256: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Close pipe readers to avoid descriptor leaks in test helper.

r and rErr are not closed, so repeated appRun calls can leak file descriptors and destabilise long test runs.

Suggested patch
 r, w, pipeErr := os.Pipe()
 if pipeErr != nil {
 	return "", fmt.Errorf("failed to create stdout pipe: %w", pipeErr)
 }
+defer r.Close()
 rErr, wErr, pipeErr := os.Pipe()
 if pipeErr != nil {
 	w.Close()
 	r.Close()
 	return "", fmt.Errorf("failed to create stderr pipe: %w", pipeErr)
 }
+defer rErr.Close()

Also applies to: 292-295

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ahoy_test.go` around lines 247 - 256, The pipe readers r and rErr created by
os.Pipe() calls are never closed, causing file descriptor leaks in the appRun
test helper function when called repeatedly. Add cleanup code to close both r
and rErr before the function returns successfully. This should typically be done
via defer statements immediately after each os.Pipe() call, or by ensuring both
readers are closed in all code paths that lead to the function returning (both
success and error paths). The defer approach is preferred to guarantee cleanup
even if the function exits early through multiple return statements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ahoy_test.go`:
- Around line 404-409: This test mutates global state including AhoyConf.srcDir
and the importVisited global variable without restoring them, which causes test
isolation issues. Save the original values of AhoyConf.srcDir, importVisited,
and any global logger output at the beginning of the test, then use defer or
t.Cleanup() to restore all these values after the test completes. Apply this
cleanup pattern to all locations in the test where these globals are modified,
ensuring that both the initial setup around line 404-409 and the modifications
around line 439-445 are properly cleaned up.

---

Outside diff comments:
In `@ahoy_test.go`:
- Around line 247-256: The pipe readers r and rErr created by os.Pipe() calls
are never closed, causing file descriptor leaks in the appRun test helper
function when called repeatedly. Add cleanup code to close both r and rErr
before the function returns successfully. This should typically be done via
defer statements immediately after each os.Pipe() call, or by ensuring both
readers are closed in all code paths that lead to the function returning (both
success and error paths). The defer approach is preferred to guarantee cleanup
even if the function exits early through multiple return statements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 62ab644e-801d-4cea-9e5f-5e265db1e099

📥 Commits

Reviewing files that changed from the base of the PR and between 3861510 and 40cee88.

📒 Files selected for processing (7)
  • .github/workflows/build_and_test.yml
  • .github/workflows/codeql.yml
  • .github/workflows/release.yml
  • .github/workflows/zizmor.yml
  • ahoy.go
  • ahoy_test.go
  • v2/.golangci.yml
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/zizmor.yml
  • ahoy.go
  • .github/workflows/release.yml

Comment thread ahoy_test.go
…bust

Signed-off-by: Drew Robinson <drew.robinson@gmail.com>
@ocean ocean merged commit cac253d into ahoy-cli:v3-candidate Jun 16, 2026
5 checks passed
Sign up for free to 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.

1 participant