Repository navigation
Install with a frozen lockfile in every workflow - #149
Merged
Merged
Conversation
`bun install` treats a lockfile that disagrees with a `package.json` as something to silently repair: it exits 0, rewrites `bun.lock` in the runner, and the job proceeds against a dependency graph nobody committed. Nothing then reports the drift, because from the outside a resolved install and a locked install look identical. They were not identical. `bun.lock` recorded the extension at 0.4.1 and a peer range of `>=17.0.7 <18` while `packages/extension/package.json` said 0.6.0 and `<19`, through an unknown number of green pipelines, because no job ever asked. It was noticed only when a plain `bun install` in a fresh worktree rewrote the file as a side effect of running the gate. Measured both ways against the same introduced drift, on this tree: `bun install` exits 0 and modifies `bun.lock`; `bun install --frozen-lockfile` exits 1 with "lockfile had changes, but lockfile is frozen" and names the fix. So the flag is a real check and not a no-op, which is the only reason it is worth adding. Applied to all nine install sites -- the six in ci.yml, plus release.yml, auto-commit-dist.yml and refresh-bundle.yml. The last two build the committed bundle, and freezing them is the point rather than an oversight: a bundle built from a dependency graph the lockfile does not describe is the artifact this rule exists to prevent, and blocking that build until the lockfile is committed is the correct outcome. The manual command in refresh-bundle.yml's header comment is left alone; it is a local invocation, not a pipeline. CONTRIBUTING.md says what to do when it fails, which is the same thing bun's own error says: run `bun install` locally and commit `bun.lock` alongside the dependency change that moved it.
The previous commit left this one plain and justified it as "a local invocation, not a pipeline". That justification was wrong. The command is the documented *substitute* for the refresh-bundle workflow, for use before that workflow exists on the default branch, and its output is the committed extension bundle -- the same artifact, reached by a different route. A bundle built from a dependency graph the lockfile does not describe is what this rule exists to prevent, and it does not stop being that because a human typed the command. The discriminator is whether the output is committed or verified, not whether a human or a runner starts it. By that test `scripts/setup.sh` stays plain and deliberately so: it bootstraps a developer's own environment, commits nothing, and is the normal path by which a lockfile gets legitimately updated after a dependency change. Freezing it would block the repair the other nine sites tell you to perform. Found by a reviewer's wider grep. Mine was scoped to `run:` lines under .github/, which is the same narrowing this repository keeps relearning: the scan reported "none" because of where it was pointed, not because there was nothing there.
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.
bun installtreats a lockfile that disagrees with apackage.jsonas something to silently repair: it exits 0, rewritesbun.lockin the runner, and the job proceeds against a dependency graph nobody committed. Nothing reports the drift, because from outside a resolved install and a locked install look identical.They were not identical here.
bun.lockrecorded the extension at0.4.1and a peer range of>=17.0.7 <18, whilepackages/extension/package.jsonsaid0.6.0and<19— through an unknown number of green pipelines, because no job ever asked. It surfaced only when a plainbun installin a fresh worktree rewrote the file as a side effect of running the gate. (Main has since caught up; the missing check is the durable half.)The flag is a real check, measured both ways
Against the same introduced drift, on this tree:
and on the clean tree,
--frozen-lockfileexits 0. A guard that cannot fail is worth nothing, so this was checked before it was adopted rather than after.Scope: all nine install sites
The six in
ci.yml, plusrelease.yml,auto-commit-dist.ymlandrefresh-bundle.yml.Freezing the last two is the point rather than an oversight. They build the committed bundle, and a bundle built from a dependency graph the lockfile does not describe is precisely the artifact this rule exists to prevent; blocking that build until the lockfile is committed is the correct outcome, and it fails with a message that names the fix. A release built from an unlocked graph is the same argument, harder.
The documented docker equivalent in
refresh-bundle.yml's header comment is frozen too. It was left plain in the first commit and justified as "a local invocation, not a pipeline"; that was wrong, and a reviewer's wider grep caught it. The command is the documented substitute for that workflow and produces the same committed bundle — a different route to the artifact the rule exists to protect. My own grep had been scoped torun:lines under.github/, so it reported "none" because of where it was pointed.scripts/setup.shstays plain, deliberately. The discriminator is whether the output is committed or verified, not whether a human or a runner starts it: setup bootstraps a developer's own environment, commits nothing, and is the normal path by which a lockfile gets legitimately updated after a dependency change. Freezing it would block the very repair the other ten sites instruct you to perform.Why this belongs with the last two changes
Same shape, third surface. The marker guard existed and no job ran it;
CREW_LIVE_CLAUDEwas documented and no code read it; the lockfile was committed and no job compared it. In each case the absence of a check and the absence of a problem produce identical output, and the only thing that distinguishes them is going and looking.CONTRIBUTING.mdgains the one thing a contributor hitting a red pipeline needs: runbun installlocally and commitbun.lockalongside the dependency change that moved it — the same instruction bun's own error gives.Gate
bun install --frozen-lockfileexit 0 on this tree ·check:markers428 scanned, 0 findings ·format:check·typecheck· all four workflow files parse as YAML ·check-trailersclean.