Skip to content

mutation-cargo: caller checkout omits submodules, breaking builds with vendored git submodule deps #363

Description

@leynos

Summary

The mutation-cargo.yml reusable workflow checks out the caller
repository without submodules, so any caller with a git submodule
dependency (a vendored crate pulled in via [submodule] in
.gitmodules) fails its unmutated baseline build immediately, before
any mutant is tested. The job aborts in about a minute with cargo build failed in an unmutated tree, so no mutants were tested.

Observed

leynos/zamburak's scheduled mutation-testing workflow has failed on
this on at least two occasions:

Both runs fail in the mutants job's "Run mutation testing" step
after roughly a minute, with an identical error:

Found 24 mutants to test
ERROR cargo build failed in an unmutated tree, so no mutants were tested
FAILED   Unmutated baseline in 0s build

*** baseline

*** /home/runner/.rustup/toolchains/.../cargo test --no-run --verbose --package=zamburak@0.1.0 --all-features
error: failed to get `monty` as a dependency of package `zamburak-monty v0.1.0 (.../crates/zamburak-monty)`

Caused by:
  failed to load source for dependency `monty`

Caused by:
  Unable to update /home/runner/work/zamburak/zamburak/third_party/full-monty/crates/monty

Caused by:
  failed to read `/home/runner/work/zamburak/zamburak/third_party/full-monty/crates/monty/Cargo.toml`

Caused by:
  No such file or directory (os error 2)

mutation_cargo_exit_code=4
mutation_cargo_outcome=baseline tests failing
##[error]Process completed with exit code 4.

Root cause

zamburak vendors third_party/full-monty as a git submodule (see
.gitmodules), and crates/zamburak-monty's Cargo.toml has a path
dependency on third_party/full-monty/crates/monty. The workspace
member is in scope for cargo test --all-features even though the
mutation paths/exclude-globs inputs keep third_party/ out of the
mutated file set — the submodule directory still has to exist for the
crate to build at all.

mutation-cargo.yml's "Checkout caller repository" step
(actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0) does not
set submodules, so it defaults to false and the submodule
directory is left empty. By contrast, zamburak's own ci.yml checks
out with submodules: recursive and builds fine — this is specific to
the mutation workflow's checkout step.

Impact

Any caller with a git submodule dependency (vendored crate, fixture
repo, etc.) that participates in the build graph will fail the
unmutated baseline on every scheduled and dispatched mutation run,
without ever exercising a single mutant. The failure is fast (~1
minute) and easy to mistake for an unrelated CI blip.

Suggested fix

Either:

  • Check out the caller repository with submodules: recursive (or
    submodules: true) unconditionally in mutation-cargo.yml, matching
    the behaviour callers already rely on on their own CI checkouts; or
  • Add a submodules input to mutation-cargo.yml (default false to
    preserve current behaviour) that callers with submodule dependencies
    can opt into, and document it in
    docs/mutation-cargo-workflow.md.

The former is simpler and has no known downside for callers without
submodules (actions/checkout is a no-op for repos with no
.gitmodules).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghighHigh criticality issuetesting

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions