Skip to content

Make tests independent of the machine they run on - #217

Merged
vertti merged 2 commits into
mainfrom
fix-test-hygiene
Aug 11, 2026
Merged

Make tests independent of the machine they run on#217
vertti merged 2 commits into
mainfrom
fix-test-hygiene

Conversation

@vertti

@vertti vertti commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Four tests depended on the developer's environment rather than on the code. After this, mise run test is green locally — it hasn't been on this machine.

A test could delete a contributor's files

TestFindFile_StopAtHome created and RemoveAll'd ~/test_preflight inside the real home directory. Anyone who happened to have that path lost it to go test ./....

It also failed outright for anyone with a global ~/.preflight — the config location this package exists to discover:

$ HOME=<tmp with .preflight> go test ./pkg/preflightfile/
--- FAIL: TestFindFile_StopAtHome
    expected error when .preflight not found

Now uses t.Setenv("HOME", t.TempDir()), plus a companion test that a .preflight above HOME isn't picked up.

A test that passed with the logic deleted

TestFindFile_StopAtGit wrote .preflight into the directory it searched from, so FindFile returned on its first iteration and never reached the .git boundary it claimed to test.

Verified by mutation — deleting the .git check from preflightfile.go:

old test new test
.git logic present pass pass
.git logic deleted pass fail

Added the mirror case (WalksUpWithoutGitBoundary) so the expected error is known to come from the boundary rather than from the walk failing generally.

git tests inherited ~/.gitconfig

commit.gpgsign = true — which plenty of people set globally — aborted the commit with exit 128:

$ GIT_CONFIG_GLOBAL=<gpgsign=true> go test ./pkg/gitcheck/
--- FAIL: TestRealGitRunner_TagsAtHead_WithTag
    Received unexpected error: exit status 128

A global core.hooksPath with a failing pre-commit hook did the same. Both now pass. Commands run through a helper setting GIT_CONFIG_GLOBAL=/dev/null, GIT_CONFIG_SYSTEM=/dev/null, GIT_TERMINAL_PROMPT=0, and it reports git's actual output on failure instead of a bare exit status 128.

The TCP flake

TestTCPCommand/unreachable_port assumed 127.0.0.1:1 refuses connections. On this machine lsof shows a process bound to the IPv6 wildcard *:1, which accepts IPv4-mapped connections there — so it passed in Linux CI and failed on macOS. It now binds and closes a port to get one that is genuinely free, which is what the adjacent subtest already did.

Two subtests that asserted nothing

  • clean flag asserted inside if err != nil with no else, and the string it matched was ErrCheckFailed's text — returned by every failing check of any type. It could not fail, its path depended on the developer's uncommitted files, and it printed their private file list into test output. pkg/gitcheck covers this against mocks, so it's removed rather than rewritten.
  • tag flag with nonexistent tag passed --tag, which doesn't exist. Cobra's parse error satisfied assert.Error, so no tag logic ran. Split into an explicit unknown-flag assertion and a real --tag-match test asserting ErrorIs(err, ErrCheckFailed).

Summary by CodeRabbit

  • Tests
    • Improved network and Git command tests for more reliable validation across environments.
    • Added coverage for unsupported tags and missing tag matches.
    • Strengthened repository setup and tag-creation test helpers.
    • Expanded preflight file discovery tests for Git boundaries, upward traversal, and home-directory limits.
    • Prevented tests from modifying a developer’s actual home directory.

Four tests depended on the developer's environment rather than the code.

TestFindFile_StopAtHome created and RemoveAll'd ~/test_preflight inside the
real home directory, so running the suite could delete a contributor's
files. It also failed outright for anyone with a global ~/.preflight — the
config location this very package exists to discover. Now uses a temporary
HOME, plus a companion test that a .preflight above HOME is not picked up.

TestFindFile_StopAtGit wrote .preflight into the directory it searched from,
so FindFile returned on the first iteration and never reached the .git
boundary it claimed to test. Confirmed by deleting that logic: the old test
still passed, the new one fails. Added the mirror case so the error is known
to come from the boundary rather than from the walk failing generally.

The gitcheck runner tests inherited ~/.gitconfig. commit.gpgsign=true, which
plenty of people set, aborted the commit with exit 128; a global
core.hooksPath with a failing pre-commit hook did the same. They now run
with GIT_CONFIG_GLOBAL and GIT_CONFIG_SYSTEM pointed at /dev/null, and
report git's output on failure instead of a bare exit status.

TestTCPCommand/unreachable_port assumed 127.0.0.1:1 refuses connections. A
process bound to the IPv6 wildcard accepts IPv4-mapped connections there, so
it passed in CI and failed on macOS. Binds and closes a port instead, which
is what the adjacent subtest already did.

Also removes two subtests that asserted nothing: "clean flag" asserted
inside `if err != nil` with no else and matched ErrCheckFailed's text, which
every failing check returns; and "tag flag" passed --tag, which does not
exist, so cobra's parse error satisfied assert.Error and no tag logic ran.
The real flag is --tag-match, now covered.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The tests now obtain an ephemeral localhost port for unreachable-port checks. Git command tests use isolated configuration and prompt settings. CLI tests validate unsupported options and nonexistent tag matches. Preflight file tests cover Git repository boundaries, upward traversal without Git, and HOME boundaries with temporary directories.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 4
✅ 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 clearly and concisely summarizes the main change: making tests independent of the execution machine and environment.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-test-hygiene

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.

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.10%. Comparing base (41213e0) to head (8b8c6ee).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #217      +/-   ##
==========================================
+ Coverage   93.00%   93.10%   +0.10%     
==========================================
  Files          49       49              
  Lines        1872     1872              
==========================================
+ Hits         1741     1743       +2     
+ Misses         94       93       -1     
+ Partials       37       36       -1     

see 1 file with indirect coverage changes

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

@vertti
vertti merged commit 6455c72 into main Aug 11, 2026
18 of 19 checks passed
@vertti
vertti deleted the fix-test-hygiene branch August 11, 2026 13:05

@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: 4

🤖 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 `@cmd/preflight/execute_test.go`:
- Around line 332-335: Update the “tag-match against a tag that cannot exist”
test around executeCommand so it creates a temporary repository with a tag on
HEAD before invoking the command, then uses a different --tag-match pattern to
exercise the tag-mismatch branch; alternatively, assert the command output
contains “no tag matches pattern” while preserving the existing ErrCheckFailed
assertion.

In `@pkg/gitcheck/runner_test.go`:
- Around line 48-49: Update the environment arguments in the relevant test setup
to use os.DevNull for both GIT_CONFIG_GLOBAL and GIT_CONFIG_SYSTEM instead of
the hardcoded "/dev/null" paths, preserving cross-platform test support without
adding build tags.
- Around line 47-50: Update TestRealGitRunner_TagsAtHead_WithTag and the
RealGitRunner command setup to build a controlled child environment from
os.Environ() that excludes GIT_DIR, GIT_WORK_TREE, and GIT_INDEX_FILE, then
apply it to both test commands and RealGitRunner’s exec.Cmd.Env while preserving
the existing Git configuration overrides.

In `@pkg/preflightfile/preflightfile_test.go`:
- Around line 102-108: Update the test setup around home and the .preflight
fixture so home is created as a child of a dedicated t.TempDir() directory, with
the parent .preflight written in that test-owned directory. Remove the manual
t.Cleanup removal, since the temporary directory lifecycle handles cleanup
safely.
🪄 Autofix

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: ASSERTIVE

Plan: Pro Plus

Run ID: 8ce26d9f-56ae-4d32-9c39-03ca3b636d7d

📥 Commits

Reviewing files that changed from the base of the PR and between 41213e0 and 8b8c6ee.

📒 Files selected for processing (3)
  • cmd/preflight/execute_test.go
  • pkg/gitcheck/runner_test.go
  • pkg/preflightfile/preflightfile_test.go

Comment on lines +332 to +335
t.Run("tag-match against a tag that cannot exist", func(t *testing.T) {
_, err := executeCommand("git", "--tag-match", "v999.999.999-nonexistent")
require.Error(t, err)
assert.ErrorIs(t, err, ErrCheckFailed)

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- test context ---'
sed -n '300,345p' cmd/preflight/execute_test.go

printf '%s\n' '--- git-check implementation ---'
sed -n '110,180p' pkg/gitcheck/check.go

printf '%s\n' '--- related test helpers and tag setup ---'
rg -n -C 4 'tag-match|executeCommand|git tag|no tag matches pattern|ErrCheckFailed' cmd/preflight pkg/gitcheck

Repository: vertti/preflight

Length of output: 40168


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- command helper and git runner construction ---'
sed -n '1,55p' cmd/preflight/execute_test.go
sed -n '1,100p' cmd/preflight/cmd_git.go
rg -n -C 5 'type .*GitRunner|TagsAtHead|New.*Git|gitRunner|RunGitCheck' pkg cmd

printf '%s\n' '--- repository tag state ---'
git tag --points-at HEAD
git rev-parse --show-toplevel
git status --short --branch

printf '%s\n' '--- deterministic branch probe from the implementation ---'
python3 - <<'PY'
from pathlib import Path
source = Path("pkg/gitcheck/check.go").read_text()
empty_branch = source.index("if len(tags) == 0")
match_branch = source.index("result.Failf(\"no tag matches pattern", empty_branch)
assert empty_branch < match_branch
print("TagsAtHead() == [] reaches the no-tags return before path.Match.")
print("A non-empty tag list is required to reach the no-matching-tag return.")
PY

Repository: vertti/preflight

Length of output: 12363


Ensure the test reaches the tag-mismatch branch.

Create a temporary repository with a tag at HEAD and a different --tag-match pattern, or assert no tag matches pattern in the command output. Without a tag at HEAD, the check returns earlier with no tags.

🤖 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 `@cmd/preflight/execute_test.go` around lines 332 - 335, Update the “tag-match
against a tag that cannot exist” test around executeCommand so it creates a
temporary repository with a tag on HEAD before invoking the command, then uses a
different --tag-match pattern to exercise the tag-mismatch branch;
alternatively, assert the command output contains “no tag matches pattern” while
preserving the existing ErrCheckFailed assertion.

Comment on lines +47 to +50
cmd.Env = append(os.Environ(),
"GIT_CONFIG_GLOBAL=/dev/null",
"GIT_CONFIG_SYSTEM=/dev/null",
"GIT_TERMINAL_PROMPT=0",

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.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

env | rg '^GIT_(DIR|WORK_TREE|INDEX_FILE|OBJECT_DIRECTORY|ALTERNATE_OBJECT_DIRECTORIES)=' || true
rg -n -C 3 'exec\.Command\("git"|cmd\.Env|GIT_(DIR|WORK_TREE|INDEX_FILE)' \
  pkg/gitcheck/runner_test.go pkg/gitcheck/runner.go || true

Repository: vertti/preflight

Length of output: 2213


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- runner_test.go outline ---'
ast-grep outline pkg/gitcheck/runner_test.go || true
printf '%s\n' '--- runner.go outline ---'
ast-grep outline pkg/gitcheck/runner.go || true
printf '%s\n' '--- runner_test.go relevant sections ---'
cat -n pkg/gitcheck/runner_test.go | sed -n '1,115p'
printf '%s\n' '--- runner.go relevant sections ---'
cat -n pkg/gitcheck/runner.go | sed -n '1,105p'
printf '%s\n' '--- build constraints and related environment setup ---'
rg -n -C 3 '//go:build|// \+build|t\.Setenv|os\.Setenv|GIT_(DIR|WORK_TREE|INDEX_FILE|OBJECT_DIRECTORY|ALTERNATE_OBJECT_DIRECTORIES)|Chdir|cmd\.Dir' \
  pkg/gitcheck .github 2>/dev/null || true

Repository: vertti/preflight

Length of output: 8820


🌐 Web query:

Git documentation GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE environment variables git repository selection

💡 Result:

Git uses the GIT_DIR, GIT_WORK_TREE, and GIT_INDEX_FILE environment variables to control how it locates and interacts with a repository [1][2]. GIT_DIR The GIT_DIR variable specifies the path to the repository, which is the directory containing the Git metadata (typically named.git) [3][1]. When GIT_DIR is set, Git bypasses its standard repository discovery process—which otherwise searches for a.git directory in the current working directory and its parent directories [3][1]. Setting this variable explicitly defines the base of the repository [1][4]. GIT_WORK_TREE The GIT_WORK_TREE variable specifies the root path of the working tree [1][2]. It is used in conjunction with GIT_DIR (or the --git-dir command-line option) to define where your project files are located [1][5]. If GIT_DIR is set but GIT_WORK_TREE (or the --work-tree command-line option and core.worktree configuration) is not, Git defaults to assuming that the current working directory is the root of the working tree [3][1]. GIT_INDEX_FILE The GIT_INDEX_FILE variable specifies the path to an alternate index file [1][2]. By default, Git uses the index file located at $GIT_DIR/index [1][2]. Setting this variable allows you to target a different index, which is often used in specialized operations or when manipulating multiple index states [1]. Summary of Repository Selection Under normal circumstances, Git performs repository discovery by walking up the directory tree to find a.git subdirectory, which identifies both the repository location and the top level of the working tree [3][1]. Setting GIT_DIR disables this automatic discovery [1][6]. If you provide a GIT_DIR path that is not at the top level of your project, you must also provide the correct path to the working tree via GIT_WORK_TREE to ensure Git operates on the intended files [1][7]. Command-line options like --git-dir and --work-tree serve as functional equivalents to these environment variables and take precedence over them [1][4].

Citations:


🌐 Web query:

Go os/exec Cmd.Env inherited environment when Env is nil duplicate environment variables

💡 Result:

In Go's os/exec package, the behavior of the Env field in the Cmd struct is as follows: 1. Inheritance Behavior: If the Env field is nil (its default value), the new process inherits the current process's environment [1][2]. 2. Duplicate Environment Variables: If you provide a non-nil slice to Env, and that slice contains duplicate keys (e.g., FOO=bar, FOO=baz), the system uses only the last value provided for each key [1][3]. This applies regardless of whether you are overriding the entire environment or appending to it [1][4]. 3. Combining with Current Environment: If you want to keep the current environment variables while adding or overriding specific ones, you must explicitly populate the Env slice, typically by appending to a copy of the current environment [4]: cmd:= exec.Command("prog") cmd.Env = append(os.Environ, "KEY=value") // Inherits current environment plus new/overridden values Because Go deduplicates these variables by keeping the last occurrence, placing your new or overridden values at the end of the slice ensures they take precedence over any inherited values [1][3]. Note: On Windows, there is a special case where the SYSTEMROOT variable is automatically added if it is missing and not explicitly set to an empty string [1][2]. Additionally, the Dir field may also influence the PWD environment variable on Unix systems [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import os
import subprocess
from pathlib import Path

source = Path("pkg/gitcheck/runner_test.go").read_text()
required = [
    '"GIT_CONFIG_GLOBAL=/dev/null"',
    '"GIT_CONFIG_SYSTEM=/dev/null"',
    '"GIT_TERMINAL_PROMPT=0"',
]
assert all(item in source for item in required)

inherited = dict(os.environ)
inherited.update({
    "GIT_DIR": "/external/repository/.git",
    "GIT_WORK_TREE": "/external/repository",
    "GIT_INDEX_FILE": "/external/repository/.git/index",
})
child_env = [f"{key}={value}" for key, value in inherited.items()]
child_env += [
    "GIT_CONFIG_GLOBAL=/dev/null",
    "GIT_CONFIG_SYSTEM=/dev/null",
    "GIT_TERMINAL_PROMPT=0",
]

result = subprocess.run(
    ["/usr/bin/env"],
    env=dict(item.split("=", 1) for item in child_env),
    text=True,
    capture_output=True,
    check=True,
)
child = dict(line.split("=", 1) for line in result.stdout.splitlines() if "=" in line)
for key in ("GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE"):
    assert child[key] == inherited[key]
print("constructed child environment preserves all three repository-selection variables")

root = subprocess.check_output(
    ["git", "rev-parse", "--show-toplevel"],
    text=True,
).strip()
probe_env = dict(os.environ)
probe_env["GIT_DIR"] = str(Path(root) / ".git")
probe_env.pop("GIT_WORK_TREE", None)
probe_env.pop("GIT_INDEX_FILE", None)
selected = subprocess.check_output(
    ["git", "rev-parse", "--show-toplevel"],
    cwd="/tmp",
    env=probe_env,
    text=True,
).strip()
assert selected == root
print(f"inherited GIT_DIR selects {selected} even when git runs from /tmp")
PY

Repository: vertti/preflight

Length of output: 324


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import os
import subprocess
from pathlib import Path

root = subprocess.check_output(
    ["git", "rev-parse", "--show-toplevel"],
    text=True,
).strip()
git_dir = subprocess.check_output(
    ["git", "rev-parse", "--git-dir"],
    text=True,
).strip()
if not os.path.isabs(git_dir):
    git_dir = str(Path(root, git_dir).resolve())

probe_env = dict(os.environ)
probe_env["GIT_DIR"] = git_dir
probe_env["GIT_WORK_TREE"] = root
probe_env.pop("GIT_INDEX_FILE", None)

selected = subprocess.check_output(
    ["git", "rev-parse", "--show-toplevel"],
    cwd="/tmp",
    env=probe_env,
    text=True,
).strip()

assert selected == root, (root, selected)
print(f"GIT_DIR and GIT_WORK_TREE select {selected} when git runs from /tmp")
PY

Repository: vertti/preflight

Length of output: 230


Isolate Git repository variables in test commands.

If the test process inherits GIT_DIR, GIT_WORK_TREE, or GIT_INDEX_FILE, the commands in TestRealGitRunner_TagsAtHead_WithTag can target repository metadata, the work tree, or the index outside t.TempDir(). RealGitRunner also inherits these variables because its exec.Cmd.Env is nil. Filter them from the child environment and use the same controlled environment for RealGitRunner.

🤖 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 `@pkg/gitcheck/runner_test.go` around lines 47 - 50, Update
TestRealGitRunner_TagsAtHead_WithTag and the RealGitRunner command setup to
build a controlled child environment from os.Environ() that excludes GIT_DIR,
GIT_WORK_TREE, and GIT_INDEX_FILE, then apply it to both test commands and
RealGitRunner’s exec.Cmd.Env while preserving the existing Git configuration
overrides.

Comment on lines +48 to +49
"GIT_CONFIG_GLOBAL=/dev/null",
"GIT_CONFIG_SYSTEM=/dev/null",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,20p' pkg/gitcheck/runner_test.go
rg -n --glob 'go.mod' --glob '*.yml' --glob '*.yaml' \
  '//go:build|GOOS|windows|darwin|linux|unix' . || true

Repository: vertti/preflight

Length of output: 491


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- pkg/gitcheck/runner_test.go ---'
cat -n pkg/gitcheck/runner_test.go

printf '%s\n' '--- module and nearby package files ---'
cat go.mod
git ls-files 'pkg/gitcheck/*'

printf '%s\n' '--- build constraints and platform references ---'
rg -n --glob '*.go' --glob 'go.mod' --glob '*.yml' --glob '*.yaml' \
  '//go:build|// \+build|GOOS|windows|darwin|linux|unix|os.DevNull|GIT_CONFIG_GLOBAL|GIT_CONFIG_SYSTEM|GIT_DIR|GIT_WORK_TREE|GIT_INDEX_FILE' .

Repository: vertti/preflight

Length of output: 8786


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

p = Path("pkg/gitcheck/runner_test.go")
text = p.read_text()
lines = text.splitlines()

print("package:", next((x for x in lines if x.startswith("package ")), "<none>")
print("leading build constraints:")
for line in lines[:12]:
    print(repr(line))
print("uses os.DevNull:", "os.DevNull" in text)
print("uses /dev/null:", "/dev/null" in text)
print("clears Git repository selectors:")
for name in ("GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE"):
    print(name, any(name in line for line in lines))
PY

Repository: vertti/preflight

Length of output: 253


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- pkg/gitcheck/runner.go ---'
cat -n pkg/gitcheck/runner.go

printf '%s\n' '--- gitcheck tests and call sites ---'
cat -n pkg/gitcheck/check_test.go
rg -n 'RealGitRunner|exec.Command|cmd\.Env|GIT_' pkg/gitcheck '*.go' 2>/dev/null || true

printf '%s\n' '--- repository test/build configuration ---'
rg -n --hidden --glob '!*.sum' --glob '!vendor/**' \
  'GOOS|go test|go vet|windows|unix' .github Makefile* README.md 2>/dev/null || true

Repository: vertti/preflight

Length of output: 13198


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

p = Path("pkg/gitcheck/runner_test.go")
lines = p.read_text().splitlines()
print("leading build constraints:")
for line in lines[:12]:
    print(repr(line))
print("uses os.DevNull:", any("os.DevNull" in line for line in lines))
print("uses /dev/null:", any("/dev/null" in line for line in lines))
for name in ("GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE"):
    print(f"{name} referenced:", any(name in line for line in lines))
PY

Repository: vertti/preflight

Length of output: 530


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read-only semantic probe for the proposed platform-neutral value.
cat > /tmp/probe.go <<'EOF'
package main

import (
	"fmt"
	"os"
	"runtime"
)

func main() {
	fmt.Printf("GOOS=%s os.DevNull=%q\n", runtime.GOOS, os.DevNull)
}
EOF

go run /tmp/probe.go

Repository: vertti/preflight

Length of output: 188


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cat > /tmp/probe.go <<'EOF'
package main

import (
	"fmt"
	"os"
	"runtime"
)

func main() {
	fmt.Printf("GOOS=%s os.DevNull=%q\n", runtime.GOOS, os.DevNull)
}
EOF

go run /tmp/probe.go

Repository: vertti/preflight

Length of output: 188


Use os.DevNull for both Git config paths. "/dev/null" is invalid on Windows, which is a supported build target. Keep this test cross-platform instead of adding a Unix-only build tag.

🤖 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 `@pkg/gitcheck/runner_test.go` around lines 48 - 49, Update the environment
arguments in the relevant test setup to use os.DevNull for both
GIT_CONFIG_GLOBAL and GIT_CONFIG_SYSTEM instead of the hardcoded "/dev/null"
paths, preserving cross-platform test support without adding build tags.

Source: Coding guidelines

Comment on lines +102 to +108
home := t.TempDir()
t.Setenv("HOME", home)
t.Setenv("USERPROFILE", home)

// A .preflight above HOME must not be picked up.
require.NoError(t, os.WriteFile(filepath.Join(filepath.Dir(home), ".preflight"), []byte("env HOME\n"), 0o600))
t.Cleanup(func() { _ = os.Remove(filepath.Join(filepath.Dir(home), ".preflight")) })

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep the fixture inside the test-owned temporary directory.

Line 107 writes .preflight to the parent of t.TempDir(). That parent can be a shared directory such as /tmp. The test can overwrite or delete another process's .preflight file.

Create home as a child of a dedicated t.TempDir() directory. Put the parent .preflight in that dedicated directory. Then remove the manual cleanup.

Proposed fix
-func TestFindFile_StopsBeforeLeavingHome(t *testing.T) {
-	home := t.TempDir()
+func TestFindFile_StopsBeforeLeavingHome(t *testing.T) {
+	root := t.TempDir()
+	home := filepath.Join(root, "home")
+	require.NoError(t, os.MkdirAll(home, 0o700))
 	t.Setenv("HOME", home)
 	t.Setenv("USERPROFILE", home)

 	// A .preflight above HOME must not be picked up.
-	require.NoError(t, os.WriteFile(filepath.Join(filepath.Dir(home), ".preflight"), []byte("env HOME\n"), 0o600))
-	t.Cleanup(func() { _ = os.Remove(filepath.Join(filepath.Dir(home), ".preflight")) })
+	require.NoError(t, os.WriteFile(filepath.Join(root, ".preflight"), []byte("env HOME\n"), 0o600))
🤖 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 `@pkg/preflightfile/preflightfile_test.go` around lines 102 - 108, Update the
test setup around home and the .preflight fixture so home is created as a child
of a dedicated t.TempDir() directory, with the parent .preflight written in that
test-owned directory. Remove the manual t.Cleanup removal, since the temporary
directory lifecycle handles cleanup safely.

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