Skip to content

perf(test): release_sandbox_test copies the full 21MB repo 6 times (~5.8s) — use a tiny fixture dir #825

Description

@Chemaclass

Problem

tests/unit/release_sandbox_test.sh is the slowest unit test file: ~5.8s (next slowest is 3.3s; average unit file is ~400ms).

Measured cause: it calls release::sandbox::create 6 times, and each call tar-copies the entire working repo into a temp dir:

  • release::sandbox::create (release.sh:374) runs tar -cf - . from $(pwd) with excludes for .git, node_modules, .release-state, .tasks, tmp
  • From the repo root that payload is ~21MB (measured: tar ... | wc -c = 20,951,040 bytes; tar-side alone takes ~0.46s, plus extraction and a 21MB rm -rf per test)
  • Two tests additionally run release::sandbox::setup_git, which does git init && git add . && git commit over the full 21MB tree

None of the 11 tests need real repo content. They assert:

  1. a temp dir is created (SANDBOX_DIR set, dir exists)
  2. key files are copied (bashunit, build.sh, CHANGELOG.md)
  3. .git and .release-state are excluded
  4. setup_git initializes a repo with exactly 1 commit
  5. mock_gh / mock_git_push behavior (no sandbox copy involved at all)

Proposed fix

Run release::sandbox::create from a tiny fixture directory instead of the repo root:

  • In set_up_before_script (or a helper), build a throwaway dir (use temp_dir from bashunit's API) containing:
    • fake bashunit, build.sh, CHANGELOG.md files (one line each — the copy test only checks existence)
    • a fake .git/ dir and .release-state/ dir (so the exclusion tests prove exclusion self-contained, instead of depending on the real repo's .git)
  • Each test that calls release::sandbox::create first cds into the fixture dir (the function tars $(pwd)), restoring cwd after — same pattern the tests already use with RELEASE_SCRIPT_DIR
  • release::sandbox::setup_git works unchanged on the fixture (it is a plain git init/add/commit in $SANDBOX_DIR, release.sh:405)
  • The mock_gh/mock_git_push tests need no change

No production code changes. release.sh stays untouched — this is test-only.

Expected result: ~5.8s → well under 1s (copy payload drops from 21MB to a few KB).

Files

  • tests/unit/release_sandbox_test.sh — the only file to change
  • release.sh:374-413release::sandbox::create / release::sandbox::setup_git (read-only reference)

Constraints

  • Bash 3.0+ compatible test code — but note the file already gates itself to Bash 3.1+ at the top (release.sh uses +=), so [[ ]] present in this file is tolerated; prefer [ ] for new code per .claude/rules/bash-style.md
  • TDD: adjust one test at a time, keep the suite green after each step
  • Tests must stay safe under ./bashunit --parallel tests/(unique temp dirs per test — temp_dir handles this)
  • Keep cleaning up $SANDBOX_DIR after each test (the tests already rm -rf it)

Acceptance criteria

  • time ./bashunit tests/unit/release_sandbox_test.sh < 1s (baseline: ~5.8s)
  • All 11 tests still pass and still verify the same behaviors (copy, .git/.release-state exclusion, git init + 1 commit, gh/git-push mocks)
  • Exclusion tests create their own .git/.release-state in the fixture (no dependency on repo state)
  • No changes to release.sh
  • ./bashunit tests/ and ./bashunit --parallel tests/ green
  • make sa, make lint pass; shfmt -w . produces no diff

Verification commands

time ./bashunit tests/unit/release_sandbox_test.sh
./bashunit tests/ && ./bashunit --parallel tests/
make sa && make lint && shfmt -d .

Metadata

Metadata

Assignees

Labels

pure testingPure testing relatedrefactoringRefactoring or cleaning related

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions