The Game Panel Design record
The Game Panel
ADR-0015 Accepted

Dependencies are locked and Composer is pinned

Created
Decided
Versions
History

Context

composer.lock is gitignored, and every CI job runs composer self-update && composer install && composer dump-autoload. Each run resolves dependencies fresh, against a Composer binary that also moves. A transitive release can turn the build red overnight with no local change, and PHPStan or php-cs-fixer can behave differently in CI than they do locally.

Committing the lock file is the standard, recommended practice for a project: everyone who sets up the project, CI included, then runs on exactly the same dependency versions.

Decision

composer.lock is committed, and CI installs from it with composer install --no-interaction --no-progress. CI runs a pinned Composer version, matching the one used locally, and the pin is changed deliberately.

Alternatives

Resolving dependencies fresh on every CI run, with the lock file ignored and Composer self-updated. It lets builds break with no local change, and lets tools behave differently in CI than locally.

No other arrangement was weighed.

Consequences

Easier:

  • Every CI job will install the dependency versions in the committed lock file, the same ones used locally, so a build will not break without a local change and tools will behave the same in CI as they do locally.
  • composer dump-autoload will no longer be needed in CI, since composer install generates the autoloader.

Harder:

  • Updating Composer will be a deliberate change to the pin. A vulnerable Composer will stay pinned until someone moves it, so Composer's security releases will need acting on.

Constrained:

  • Declared lower bounds will not be tested. A --prefer-lowest matrix leg, keeping them honest, will be a separate change.

Sources

  • PR #50, chore(engine): Tooling, CI and documentation cleanup, opened and merged , squashed as 54dcfb0: the problem, the decision, the alternative and the consequences other than Composer's security releases. Its commit message and diff record the lock file and pin changes. created is when it was opened and decided when it merged.
  • PR #75, chore: Rename package, add licence and patch Composer CVE, merged and squashed as 3372f20: the consequence for Composer's security releases, taken from what followed rather than anticipated. It moved the pin from 2.9.3 to 2.10.3 because 2.9.3 is inside the range affected by CVE-2026-84361, which had left CI running a Composer open to arbitrary command execution through a package's Perforce source URL.
  • Composer documentation, Basic usage, "Commit your composer.lock file to version control", read : committing the lock file as the standard practice for projects, and why.

Source adr/0015-dependencies-are-locked-and-composer-is-pinned.md · commit 072385a · exported