Skip to content

feat: add --strict to report failed repositories in the exit status - #6

Merged
magicdrive merged 1 commit into
mainfrom
feat/strict-mode
Oct 27, 2026
Merged

magicdrive merged 1 commit into
mainfrom
feat/strict-mode

Conversation

@magicdrive

Copy link
Copy Markdown
Owner

Problem

git-parallel always exits with 0, even when the command fails in some or all repositories. This is documented as historical behavior (test_error_propagation), so scripts cannot rely on the exit status to detect a failed pull/fetch.

Root Cause

Each batch is waited for with a bare wait, which returns 0 whatever the jobs returned, and each job (git::parallel::execute) ends with echo, so the command's own status is lost as well.

Solution

Add an opt-in --strict; the default is unchanged.

  • Every job is waited for with wait "$pid" (in both modes) and, with --strict, its status is collected. execute now returns the command's status; a frozen repository returns 0.
  • Decisions:
    • Default: unchanged, exit 0 (historical behavior).
    • Exit status: 0 when every repository succeeded (frozen ones and "no repository" count as success); 1 when at least one failed. Usage errors also exit 1 but happen before anything runs.
    • Partial failure / multiple repositories: all repositories still run (no fail-fast); stdout is the same as without --strict; stderr lists the failed repositories in order with their own status, also under --silent:
      git-parallel: the command failed in 2 of 5 repositories:
        /src/api (exit 1)
        /src/web (exit 128)
      
    • Cancellation: a failure does not cancel other repositories; only signals cancel.
    • SIGINT/SIGTERM (and HUP/QUIT): running commands are killed, temp files removed, git-parallel: interrupted by SIG<NAME> on stderr, exit 128 + signal (130/143/129/131). Without --strict the old handler (SIGKILL of the whole tree, git-parallel included) is kept.
    • JSON: git-parallel has no JSON output; none added.
  • Help, man page and README document the exit status.

Security Impact

None. No new input is evaluated; command handling is unchanged.

Compatibility

Default behavior, output and exit status are unchanged; the existing 20 tests are untouched and pass. --strict is a new long option only.

Tests

8 new tests in tests/run.sh: success, partial failure with --jobs 3/2/1 (failure in every batch position), all fail (128) and command not found (127), distinct statuses per repository across batches (3, 42) and the last job of the last batch, frozen repositories, --silent, no repositories, SIGTERM (143) and SIGINT (130) with commands killed and temp files removed, --help.

  • GREEN: make check (bash 5.3) and TEST_BASH=/bin/bash tests/run.sh (bash 3.2): 28 passed, 0 failed.
  • RED: the new tests fail against main's script (43 assertion failures), and against this branch with the per-PID wait replaced by a bare wait (partial failure, statuses and frozen/silent tests fail).

CI

The existing matrix (Linux/macOS, bash 3.2/4/5) runs the new tests.

Migration

None. Use git parallel --strict -- ... where the exit status matters.

Risks

Low. The default path now waits per PID instead of a bare wait, which waits for the same set of jobs.

https://claude.ai/code/session_01RbGbwRHvCEhsKLZfbvbbRg

By default git-parallel exits with 0 even when the command fails in some
or all repositories: the batches are waited for with a bare `wait`, and
each job ends with `echo`, so the command's status is lost twice. The
default is documented as historical behavior and stays unchanged.

--strict (opt-in):
- every job is waited for by its PID and its exit status is collected
  (the job now returns the command's status; frozen repositories return 0)
- all repositories still run; the exit status is 1 when the command failed
  in at least one, and the failed repositories are listed on stderr with
  their own status, also with --silent
- SIGHUP/SIGINT/SIGQUIT/SIGTERM kill the running commands, remove the
  temporary files and exit with 128 + the signal number

The help, the man page and the README describe the exit status. New tests
cover success, partial and total failure, per-repository statuses across
batches, frozen repositories, --silent, no repositories, SIGTERM and SIGINT.
Existing tests are unchanged.

Claude-Session: https://claude.ai/code/session_01RbGbwRHvCEhsKLZfbvbbRg
@magicdrive
magicdrive merged commit 6087a01 into main Oct 27, 2026
9 checks passed
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