chore(ci): commit composer.lock for deterministic CI resolution#21
chore(ci): commit composer.lock for deterministic CI resolution#21Goosterhof wants to merge 1 commit into
Conversation
The package gitignored composer.lock while CI runs `composer install --prefer-dist`, which with no committed lock silently degrades to a full fresh resolve every run — CI never tests the same dependency graph twice, and any transitive major (illuminate/* ^11||^12||^13, testbench ^9||^10||^11, pest ^3||^4) can land unbidden with no source change. Un-gitignore /composer.lock and commit a freshly resolved lock so CI installs a pinned graph; Dependabot (composer, weekly) bumps it via reviewed PRs. Published client library — consumers resolve against their own constraints, so this lock is never consumed downstream (zero consumer impact). Sister fix to phpstan-warroom-rules PR #55 (merged). Simple case here: no Infection/mutation gate and no symfony/console pin, so nothing to drop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129qYnTu3C5qVK2yNcqHELD
Goosterhof
left a comment
There was a problem hiding this comment.
✅ Approve-worthy
0 blockers · 0 majors · 0 minors · 0 nits · 1 praise · 0 inline
Two-file chore: .gitignore:4 drops the /composer.lock ignore rule, composer.lock (10000 additions) is added tracked. Source, tests, and composer.json are untouched — the diff matches the PR body's stated scope exactly.
Verified independently rather than taking the body's claims on faith:
composer.lockcontent-hashis7d55dc6a8d42f695b96074287c22e4f4, consistent with thecomposer.jsonshipped at this head (require/require-devuntouched) — not a stale lock generated against a different manifest.- All 4 checks green at head
294ddbe, includingcheck (8.4)/check (8.5)(composer install→composer audit→composer format:check→composer phpstan→composer test) and theci-passedrollup — so the committed lock is the one CI already resolved and exercised, not an untested snapshot. .github/dependabot.ymlconfirms the weekly composer schedule the body cites, so lock staleness has a standing remediation path once this merges.
This closes the fresh-resolve-every-run gap Principle-adjacent to the phpstan-warroom-rules #55 fix — a gitignored lock meant composer install re-resolved the full graph on every CI run, so a permissive illuminate/* ^11||^12||^13 transitive could shift the tested graph with zero source change. Committing the lock pins CI to one deterministic graph; correctly scoped as consumer-inert since downstream consumers resolve against their own constraints, not this package's lock.
No residual findings — this is exactly the mechanical fix it claims to be.
Automated war-room agent review — posted because this PR carries the Agent Review Requested label.
What
Un-gitignore
composer.lockand commit it (now tracked). Two-file change:.gitignore+composer.lock.Why
CI runs
composer installagainst a gitignored lock. With no committed lock,installsilently degrades to a full fresh resolve every run — CI never tests the same dependency graph twice, and any transitive major in the permissiveilluminate/* ^11||^12||^13/orchestra/testbench/pestranges can land unbidden with no source change.Committing the lock pins CI to one deterministic graph. This is a published client library — consumers resolve against their own constraints, so our lock is never consumed downstream and there is zero consumer impact. Dependabot composer is already wired weekly to keep the lock fresh via reviewed PRs.
Sister to phpstan-warroom-rules #55 (merged) — the F-2 fresh-resolve-determinism fix, applied to the shared PHP-package family.
Verified
All gates green from the tracked lock:
composer install✓ ·composer test(Pest, 67 passed/143 assertions) ✓ ·composer phpstan(max) ✓ ·pint --test✓ ·composer auditno advisories ✓.The fresh lock pins the current-latest coherent graph (testbench v11.1.0, pest v4.7.5) — the same majors CI was already silently resolving; committing the lock makes that graph reproducible, not different (gates confirm green).
Scope
.gitignore+composer.lockonly — nocomposer.json, source, tests, or fixtures touched. Non-consumer-facing dev-tooling, so no CHANGELOG entry.🤖 Generated with Claude Code