How do Laravel Pint's --test, --bail and --repair options differ in what they change and in their exit codes?
answer
- write or not, and pass or fail
- --test: dry run, fails on drift
- --bail: stops at the first bad file
- --repair: writes fixes, still fails
- parse errors fail every mode
basics
~20 s--test writes nothing and exits 1 if any file would change; --bail does the same but stops at the first offending file; --repair writes the fixes yet still exits 1 when it changed anything. Plain pint fixes and exits 0.
solid answer
~40 sPlain `./vendor/bin/pint` rewrites files and exits 0 even after fixing dozens of them, so it cannot gate a build. `--test` is a dry run: nothing is written, the summary lists the offending files, and the exit code is 1 when any file would change. `--bail` is a dry run that stops at the first file with a violation, which gives faster feedback but an incomplete list. `--repair` writes the fixes like a normal run and then exits 1 if it changed anything, which suits a hook or bot that should correct the code yet still stop the commit so a person re-stages and reviews the result. In every mode, a file Pint cannot parse also makes it exit non-zero.
code
bash · 4 lines./vendor/bin/pint --test; echo "exit: $?" # 1 if any file would change, nothing written
./vendor/bin/pint --bail; echo "exit: $?" # stops at the first offending file
./vendor/bin/pint --repair; echo "exit: $?" # files fixed, still 1 if anything changed
./vendor/bin/pint --test --output-to-file=pint.xml --output-format=junitgo deeper
Recall that --test checks without writing and fails when something is wrong, while plain pint fixes files and succeeds.
Explain each mode as two answers, write or not and pass or fail, including that --repair writes and still exits 1 and that parse errors fail every mode.
Choose the mode per context: --test with a machine-readable report in CI, --repair in hooks, --parallel and a persisted cache for speed, and never plain pint as a gate.
Decide whether style is enforced by failing builds or by automatic fixes, and make that choice consistent across hooks, CI and bots so developers get one clear signal.
## Two questions every Pint run answers Every run of **Laravel Pint** makes two separate decisions: 1. **Does it write the fixes to disk?** Fix mode rewrites files; a *dry run* only calculates what would change. 2. **Does it exit with success or failure?** Build tools, Git hooks and Composer scripts only read the **exit code**: 0 means success, anything else means failure. The options `--test`, `--bail` and `--repair` exist because the default answers to those two questions, *write* and *succeed*, are right for a developer at a keyboard and wrong for an automated gate. ## The four modes compared | Command | Writes files | Exits 1 when | Typical use | |---|---|---|---| | `pint` | yes | a file cannot be parsed or fixed | formatting locally | | `pint --test` | no | any file would change | CI gate, full report | | `pint --bail` | no | the first file that would change | fast fail on huge trees | | `pint --repair` | yes | any file was changed | hooks and bots that fix and stop | A few details behind the table: - **Plain `pint` succeeds after fixing.** If it rewrote fifty files, it did its job, so the exit code is 0. Running it in CI therefore proves nothing about the pushed commit: it formats the CI checkout and passes. - **`--test`** turns the run into a dry run. The summary names every file with a violation and the rules involved; adding `-v` prints the diff for each file as well. The exit code is 1 when anything would change. - **`--bail`** is a dry run that also stops at the **first** violation. It is quicker on a very large tree, but you learn about one file at a time. - **`--repair`** keeps fix mode, so files are rewritten, but flips the exit code to 1 when at least one file changed. A clean tree exits 0. - **Errors fail every mode.** A file with a syntax error that Pint cannot parse, or a fixer that throws, produces a non-zero exit even in plain fix mode. ## Choosing one for a pipeline For a CI job, `--test` is the usual choice: the job fails, the log lists every offending file, and nothing is written into a checkout that nobody will commit. `--bail` trades the full list for speed. `--repair` fits a different workflow: a pre-commit hook or a formatting bot that should fix the code *and* stop, so that a person looks at the result before it goes further. Plain `pint` belongs on a developer's machine. The Laravel starter kits wire this up in `composer.json`: ```json "lint": ["pint --parallel"], "lint:check": ["pint --parallel --test"] ``` Their `composer test` script calls `@lint:check` before running the test suite, so a style failure stops the suite from running. ## Reporting and speed in CI A CI log is easier to consume when it is machine-readable: - `--format` switches the console output to a reporter such as `json`, `junit`, `checkstyle`, `xml` or `txt`, which a CI system can turn into annotations or test results. - `--output-to-file` together with `--output-format` writes a report to a file while the console keeps the normal summary. - `--parallel` (short `-p`), marked experimental in Pint 1.32, spreads files across worker processes and uses every available core unless `--max-processes` caps it. Pint also uses a **cache file** that records what it has already checked. Pointing `--cache-file` (or a `cache-file` key in `pint.json`) at a path the CI job keeps between runs lets later runs skip files that have not changed. ## Common mistakes 1. Running plain `pint` in CI and treating green as proof of formatting. 2. Using `--repair` in CI without committing the result, so the job fails yet the fix is thrown away with the checkout. 3. Expecting `--bail` to list every problem. 4. Forgetting that the exit code also reflects parse errors, and blaming style when a file simply does not compile. 5. Reading a failed `--test` log and guessing at the fix. The summary names each file and the rules that fired; adding `-v` prints the exact diff, and running plain `pint` locally applies it. Each option answers the two questions differently, and naming both answers is the clearest way to explain them in an interview.
- Why might a team choose --repair over --test in a pre-commit hook?`--test` only reports, so the developer must run Pint again by hand. `--repair` fixes the files and still exits 1, which aborts the commit; the developer inspects the changes, re-stages them and commits again. The fix is automatic, but nothing slips into a commit unreviewed.
- How do you make Pint faster on a large codebase in CI?Pass `--parallel` (experimental in Pint 1.32), which spreads files across worker processes and uses every core unless `--max-processes` limits it, and point `--cache-file` (or `cache-file` in `pint.json`) at a path the job keeps between runs, so unchanged files are skipped.
- What does --output-to-file add over --format?`--format=junit` replaces the console output with the report. `--output-to-file=pint.xml` plus `--output-format=junit` writes the report to a file and leaves the normal human-readable summary on the console, so the log stays readable and the CI system still gets a parseable report.
saying these in an interview costs you the question
- --test fixes the files first and then reports what it changed.
- Plain pint exits 1 whenever it had to fix a file.
- --repair is a dry run that only suggests fixes.
- --bail still reports every violation, just more tersely.
- A green plain pint step in CI proves the pushed commit was formatted.