ci: validate composer manifests against their lock files - #197
Merged
Conversation
Nothing in .github/ ran `composer validate`, so a manifest and its lock disagreeing surfaced only once the multi-arch build reached `composer install` — roughly ninety seconds in, as a bare `exit code: 4` whose real message sat four lines earlier in the log. Renovate raised a guzzle constraint without regenerating the lock and four runs went on it. Adds composer-validate.yml, running `composer validate --check-lock` over every tracked composer.json (app/ and app/full/ today, discovered via git ls-files so a third variant needs no edit here). It fails in about half a second and names the package and both versions: Required package "guzzlehttp/guzzle" is in the lock file as "7.15.2" but that does not satisfy your constraint "^8.0". No setup-php step: the check compares the lock's content hash and recorded versions against the manifest's constraints, which does not depend on the platform PHP — verified on PHP 8.3/composer 2.7 and PHP 8.5/composer 2.9 against manifests requiring php>=8.5. CONTRIBUTING gains the local command and the distinction the fix turns on: `composer update --lock` refreshes the content hash but leaves a named version mismatch in place, which needs `composer update <package>`. This is a diagnosis-speed gate, not a replacement for the build. Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
|
There was a problem hiding this comment.
Automated approval for maintainer PR
All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Files
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



There is no
composer validate --check-lockanywhere in.github/, so a manifest and its lock disagreeing surfaces only once the multi-arch build reachescomposer install— roughly ninety seconds in, as a bareexit code: 4whose real message sits four lines earlier in the log. That has already happened: Renovate raised a guzzle constraint without regenerating the lock, and four CI runs went on it.This adds
.github/workflows/composer-validate.yml, runningcomposer validate --check-lock --no-check-publish --strictover every trackedcomposer.json. There are two, not one —app/composer.jsonandapp/full/composer.json— and both are discovered viagit ls-files '*composer.json'rather than named, so a third variant is covered without editing the workflow, andvendor/or untracked leftovers on the runner cannot widen the set. It runs on pull requests and on pushes tomain, matchingtest.yml.No
setup-phpstep. The check compares the lock's content hash and its recorded versions against the manifest's constraints, which does not depend on the platform PHP — verified on PHP 8.3 with composer 2.7 and on PHP 8.5 with composer 2.9, against manifests that requirephp >=8.5; both report./composer.json is valid. That avoids adding a third-party action and a SHA to keep current, and the job printsphp --versionandcomposer --versionso a change in the runner image is visible in the log.This is a diagnosis-speed gate, not a replacement for
build.ymlortest.yml: it proves the manifests and locks agree, never that the image builds.Verification
Against the current tree, which is self-consistent —
app/full/composer.jsonsays^7.5and the lock has 7.15.2:0.54s for both manifests, and it completes with
--network none.Against a copy of the same tree in a scratch directory with
guzzlehttp/guzzleraised to^8.0and the lock left alone — the exact shape of the incident:Composer names the package and both versions itself. For reference,
composer install --dry-runon that same tree exits 4 — the code the build was reporting.The missing-lock branch was exercised too: deleting
app/composer.lockfails that manifest with the explicit annotation whileapp/full/still validates, so one bad manifest does not mask the others.actionlintexits 0 on the new file and on all ten workflows together.One correction worth flagging
The first version of the error annotation told you to run
composer update --lock. That is wrong for the case where a package is named:--lockrefreshes the content hash and leaves the version mismatch in place, sovalidatestill fails afterwards — measured, guzzle stayed at 7.15.2 against^8.0. It is the right fix only when the hash alone drifted, which was also measured. The annotation and the CONTRIBUTING section now distinguish the two.Out of scope, noticed while reading
README.mdcarries aSecurity Scanbadge pointing at.github/workflows/security.yml, which no longer exists —ci.ymlrecords it as subsumed. The badge renders as a permanent failure. Left alone here.