Skip to content

fix(release): deno.lock on main lacks the plugin-vite dependency closure, failing deno ci --prod and blocking canary.3 #1571

Description

@rickylabs

Summary

deno.lock on main is out of date: packages/fresh/deno.json declares a direct dependency on @fresh/plugin-vite@^1.1.2, but the lock contains only the workspace-member dependency line and none of that declaration's resolution closure. deno ci --prod therefore fails frozen, which blocks the release path.

This is a release blocker. It failed v0.0.6-canary.3 before any tag or publish.

Evidence

release-canary.yml run 31600415045, step 6 "Cut ephemeral canary branch and tag":

error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it.
error: Uncaught (in promise) Error: deno ci --prod failed with exit 1.

Steps 7–19 were skipped, so no canary version was minted, nothing was published, and no JSR publish attempt was consumed. Step 4 (JSR budget) had already passed. Only v0.0.6-canary.1 and .2 exist, and no ephemeral release/canary-* branch remains.

Root cause

main@5705aeb19 carries exactly one lock line for the new dependency:

"jsr:@fresh/plugin-vite@^1.1.2",     # under the packages/fresh workspace member

but no top-level specifier resolution. Regenerating with the repo-pinned Deno 2.9.5 produces the deterministic closure — 386 insertions, 9 deletions — including the direct specifiers jsr:@fresh/plugin-vite@^1.1.2, npm:@babel/core, npm:@prefresh/vite, npm:@remix-run/node-fetch-server, npm:@types/babel__core, npm:rollup, npm:vite, plus jsr:@fresh/core@2, jsr:@deno/loader@0.4, @std/dotenv, @std/fmt, @std/media-types, and the derived Babel/Vite transitive graph. With that closure, deno ci --prod passes.

How it happened — recorded so the rule is right next time

During #1459 the same closure appeared as uncommitted churn (+385/-9) written by a new client-bundle test fixture's real vite build. It was diagnosed as incidental harness churn because its composition (Babel/Vite/Rollup/Preact resolver entries) looks exactly like build-toolchain noise, and it was reduced to the single workspace-member line as the "exact minimal delta".

That diagnosis was wrong in substance. The churn was not a side effect of running a build — it was the required closure of the newly declared packages/fresh dependency, which the build happened to trigger. Adding --no-lock to the fixture then stopped the regeneration, so the incomplete lock reached main and looked settled.

The generalisable lesson: when a manifest gains a direct dependency, the lock delta is whatever deno install deterministically produces for it — "minimal" is not a target to hand-tune toward, and a one-line delta under a workspace member is a symptom of an incomplete lock, not evidence of a clean one.

Acceptance criteria

  • deno.lock on main contains the complete deterministic closure of packages/fresh's declared @fresh/plugin-vite@^1.1.2 dependency, generated with the repo-pinned Deno 2.9.5
  • The lock delta is solely that closure — no unrelated dependency movement
  • deno ci --prod passes frozen
  • Release-preparation gates pass, and a second run leaves the lock byte-identical (lock neutrality)
  • v0.0.6-canary.3 is re-dispatched from the corrected main SHA and reaches terminal green

Provenance

0.0.6 runtime lane, 2026-08-12. Canary.3 run 31600415045; source main@5705aeb19 (#1558).

Refs #1459.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions