Skip to content

gstack-pregate: .bats tests are never recognised, so lanes always fails in bats repos #3161

Closed

Description

@mujtaba3B

What happens

In a repository whose tests are bats files (*.bats), gstack-pregate stage 2 fails every /ship with PREGATE_NO_LANE: each touched file "has no test lane", including the .bats file itself. No .gstack/pregate.json can fix it, because the pre-gate never treats a .bats file as a test:

  • lib/pregate/import-graph.ts: TEST_FILE_RE matches *.test|spec.[cm]?[jt]sx?, test_*.py, _test.(py|go|rb) and _spec.rb only. A dependencies entry pointing a source glob at tests/foo.bats therefore selects nothing.
  • lib/pregate/lane-selection.ts: a selection manifest's output is parsed with a similar pattern, so a manifest that prints every .bats file yields 0 files.

lanes cannot be downgraded via warn, so the only way to get past it is declaring the files [] ("no lane needed"), which makes the check pass without exercising anything.

Repro

  1. A repo with scripts/foo.sh and tests/foo.bats that runs it, and a CI job that runs bats.
  2. .gstack/pregate.json with "runner": "bats {files}" and "dependencies": {"scripts/**": ["tests/foo.bats"]}.
  3. Touch scripts/foo.sh and run gstack-pregate --allow-repo-commands --policy-from head --explain.

Observed: FAIL lanes - scripts/foo.sh has no test lane, and with a selection manifest that prints tests/foo.bats, lane <id>: 0 files from manifest.

Suggested fix

Recognise .bats (and probably *_test.sh / test_*.sh) in TEST_FILE_RE and in the selection-output pattern, judged by the bats TAP summary (1..N, ok/not ok) for the zero-run rule.

gstack 1.91.93.0, macOS.

Activity

  1. yolo-jared commented on Oct 17, 2026

    @yolo-jared
    Contributor

    +1, with a second real repo hitting this, and a test of #3177 against real bats-core.

    Repo: a private agent-config repo (shell scripts, hooks, bootstrap installers). Its tests are 14 bats files, 426 tests, on Bats 1.13.0. There are also some node --test files.

    What we see today:

    • With no .gstack/pregate.json, 290 of 361 tracked files fail lanes with PREGATE_NO_LANE.
    • The only way through is the workaround described here: map every shell and bats path to []. The pre-gate then passes without running a single bats test.
    • A whole-suite guards entry is no substitute. The suite takes 377 s, and the slowest file takes 97 s.
    • A guard that buffers its output so it can check the test count prints nothing for that long. That runs into the 300 s stall_timeout_s default added in v1.91.107.

    #3177 on real bats.

    Case Before (0bf9d508) After (#3177, 444f4e76)
    script mapped to its real 40-test .bats file fail PREGATE_NO_LANE pass: 40 tests ran in 1 file(s), exit 0 (25.7 s)
    same, with one test broken (false) fail PREGATE_NO_LANE fail: local lane exited 1 (1 failed of 40 ran; 1 files; pipefail)
    script mapped to a .bats file with no @test fail PREGATE_NO_LANE fail: ZERO-RUN: the runner reported 0 tests for 1 selected file(s)
    no dependencies entry fail PREGATE_NO_LANE fail PREGATE_NO_LANE (the bats file reaches the script through $BATS_TEST_DIRNAME/../scripts/tool, which the literal scan doesn't follow, so the mapping must be declared)

    The pass, fail and zero-run paths all behave as the PR describes on a real suite. We haven't tried a lane long enough to test the stall supervisor.

    One question for the design: runner is a single command, so in a repo with both bats and node --test tests, every selected file goes to that one command.

    • One way to handle that is a wrapper runner that sends .bats files to bats and .test.mjs files to node --test. With a wrapper, though, parseSummary no longer sees bats in the runner name, so it tries the other runners' summary formats first and treats bats as a last resort.
    • Is a wrapper the intended shape for mixed repos, or would a per-extension runner (for example {".bats": "bats {files}", ".mjs": "node --test {files}"}) fit better?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions