From 5d4951a37308e3a4d31cff52ee995c903044f8ce Mon Sep 17 00:00:00 2001 From: Jeroen Soeters Date: Fri, 21 Aug 2026 13:19:52 -0700 Subject: [PATCH] fix(scripts): mutate a module-root package from its own directory When a changed package is itself a module root, such as pkg/plugin, the relative-path computation never matched: the prefix strip carries a trailing slash, so a path equal to the module root came through intact and gremlins was invoked on a doubled absolute path like ./home/runner/work/formae/formae/pkg/plugin, failing setup before coverage could run. The check then reported the package as producing no usable result. A package that equals its module root is now addressed as the current directory, so gremlins runs in that module on the module itself. --- scripts/mutation-test-changed.sh | 11 +++++-- scripts/tests/mutation-test-changed_test.sh | 32 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/scripts/mutation-test-changed.sh b/scripts/mutation-test-changed.sh index d1fc149c7..fd8b3c70a 100755 --- a/scripts/mutation-test-changed.sh +++ b/scripts/mutation-test-changed.sh @@ -307,9 +307,16 @@ main() { for pkg in "${testable_packages[@]}"; do pkg_index=$((pkg_index + 1)) module_root=$(find_module_root "$pkg") - # Compute relative package path from the module root + # Compute relative package path from the module root. A package that is + # itself the module root has nothing to strip — the prefix pattern below + # carries a trailing slash and would leave the absolute path intact — so + # it is addressed as the current directory instead. rel_pkg="${REPO_ROOT}/${pkg#/}" - rel_pkg="${rel_pkg#"$module_root"/}" + if [[ "$rel_pkg" == "$module_root" ]]; then + rel_pkg="." + else + rel_pkg="${rel_pkg#"$module_root"/}" + fi echo "" echo "=== $pkg (module: ${module_root#"$REPO_ROOT"/}) ===" diff --git a/scripts/tests/mutation-test-changed_test.sh b/scripts/tests/mutation-test-changed_test.sh index 55e3e53fe..ae021fe78 100755 --- a/scripts/tests/mutation-test-changed_test.sh +++ b/scripts/tests/mutation-test-changed_test.sh @@ -371,6 +371,37 @@ test_a_report_with_a_zero_exit_is_ok() { assert_status 0 "a completed run passes" } +# A changed package that is its own module root (it holds a go.mod) is invoked +# on itself: gremlins runs in that directory targeting the directory, not a +# path re-rooted below it. +test_a_module_root_package_is_invoked_on_itself() { + local work repo bin invocation + work=$(new_workdir) + repo="$work/repo" + bin="$work/bin" + invocation="$work/invocation" + + make_fixture_repo "$repo" + add_changed_package "$repo" "pkg/plugin" + printf 'module example/plugin\n\ngo 1.26\n' > "$repo/pkg/plugin/go.mod" + fixture_commit "$repo" "make pkg/plugin its own module" + + stub_gremlins "$bin" "pwd > '$invocation'; echo \"\$target\" >> '$invocation' +printf '%s' '$(mutation_report KILLED)' > \"\$report_path\"; exit 0" + + run_script "$repo" "$bin" + + assert_status 0 "a module-root package produces a usable result" + assert_output_matches '\| `pkg/plugin` \| ok \|' \ + "the module-root package row is ok" + if [[ "$(sed -n 1p "$invocation" 2>/dev/null)" != "$repo/pkg/plugin" ]]; then + fail "gremlins did not run in the package's own module root (got '$(sed -n 1p "$invocation" 2>/dev/null)')" + fi + if [[ "$(sed -n 2p "$invocation" 2>/dev/null)" != "./." ]]; then + fail "gremlins was not invoked on the module root itself (got '$(sed -n 2p "$invocation" 2>/dev/null)')" + fi +} + # Surviving mutants make gremlins exit non-zero: advisory content, not a crash. test_surviving_mutants_are_not_a_failure() { local work repo bin @@ -883,6 +914,7 @@ run_test() { main() { run_test test_exit_zero_without_report_is_a_failure run_test test_a_report_with_a_zero_exit_is_ok + run_test test_a_module_root_package_is_invoked_on_itself run_test test_surviving_mutants_are_not_a_failure run_test test_an_unknown_non_zero_exit_with_a_report_is_ok run_test test_a_zero_mutant_report_is_ok_without_a_score