Skip to content

Release build isn't reproducible: no lockfile lets transitive deps drift between local and CI builds #157

Description

@BorisTyshkevich

Cutting v0.3.0 surfaced a real gap: the GitHub Release asset (sql.html, built by release.yml's fresh npm install) is not byte-identical to the artifact built locally and deployed to the three demo clusters, despite both being built from the exact same commit (3cab9fd) and carrying the same build stamp (v0.3.0 (3cab9fd)).

Root cause: package-lock.json is gitignored by project convention, so every npm install re-resolves the full dependency tree fresh. The four bundled runtime deps (CodeMirror 6, Chart.js, dagre, signals-core) were identical in both builds (checked via npm ls), but a transitive dependency — @kurkle/color (a Chart.js dependency) — resolved to 0.3.4 in the local install and 0.4.0 in the CI install (registry latest as of the release), because Chart.js's own declared range apparently allows both and nothing pins it. Confirmed via npm view @kurkle/color version.

Impact: low for this specific case (isolated to Chart.js's internal color-parsing helper — diff was 4 tiny hunks inside one minified <script> block, nothing in the app's own logic or the other three deps). But the general problem stands: the "GitHub Release asset == what's deployed == what a local build reproduces" invariant that's been relied on for release verification since v0.1.5 (see the deploy-sql-browser-demo-clusters memory notes) can silently break whenever any transitive dependency ships a new version between two npm install runs, with no warning.

Options to consider (not resolved in this pass — deployed clusters and local build are internally consistent with each other, just diverged from the newly cut GitHub Release asset for v0.3.0):

  1. Commit package-lock.json (reverses the current no-lockfile convention — trades drift risk for the usual lockfile-staleness tradeoffs).
  2. Accept the drift as a known limitation of intentionally always picking up the latest transitive-dep patches, and drop/soften the "byte-identical" release-verification claim in docs/memory.
  3. Pin @kurkle/color (and audit other transitive deps of the four approved runtime deps) explicitly in package.json overrides.

Filed as inbox — deferred rather than fixed now since it doesn't block v0.3.0 (the three clusters are correctly in sync with each other and with main), and the fix is a deliberate call on the no-lockfile convention that's out of scope for a routine release cut.

Metadata

Metadata

Assignees

No one assigned

    Labels

    inboxFiled mid-task; not yet triaged into the roadmap

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions