ReviewOS

pantry-pm/pantry

pantry install writes .env-inferred services into pantry.lock, so the committed lock depends on the local .env

#253
Closed glennmichael123 opened this 5 days ago ·
5 days ago

Problem

A non-frozen pantry install writes the services it infers from the project's .env (#36, env_deps.zig) into pantry.lock as if the workspace declared them. So the committed lockfile depends on whichever database the developer who last ran pantry install has in their local .env.

The Stacks release refreshes pantry.lock with pantry install --ignore-scripts --quiet on the machine cutting the release. Cut from a checkout whose .env says DB_CONNECTION=postgres, v0.75.335's lock gained:

  • "postgresql.org": "latest" in the root workspace's dependencies
  • postgresql.org@18.4, gnome.org/libxslt@1.1.45 and unicode.org@73.2.0 in packages

CI has no such .env, so its install removed them again, and the lockfile check failed with "Installing changed pantry.lock in a way no platform difference explains (removed: gnome.org/libxslt@1.1.45, postgresql.org@18.4, unicode.org@73.2.0)". The release never published (stacksjs/stacks Releaser run 40665558792, CI run 40665557398).

Reproduction (pantry 0.11.144)

In a Stacks checkout whose config/deps.ts declares sqlite and whose committed pantry.lock has no postgres:

  1. Set DB_CONNECTION=postgres in .env and run pantry install --ignore-scripts --quiet. pantry.lock gains the four entries above.
  2. Set DB_CONNECTION=sqlite and run it again. They're removed (19 lines).
  3. With DB_CONNECTION=postgres still in .env, PANTRY_ENV_DEPS=0 pantry install --ignore-scripts --quiet leaves them out, matching CI.

A process-level DB_CONNECTION doesn't change the result; the file is read directly.

Expected

Inferring services from .env is right for installing what a checkout needs to run. Recording them in the lockfile's declared dependencies is not: the lock should describe the workspace's declared dependencies, the same on every machine. Options:

  • install inferred services without writing them into pantry.lock; or
  • record them apart from the workspace's declared dependencies, so a lock check can tell local inference from declarations; or
  • skip .env inference when the purpose of the run is maintaining the lockfile.

The --frozen-lockfile rule in env_deps.zig already treats the lockfile as the contract. This is the same principle applied to the run that writes it.

What Stacks does on its side

stacksjs/stacks passes PANTRY_ENV_DEPS=0 when its release refreshes pantry.lock, so a release cut on a Postgres machine stops producing a lock CI rejects. Other projects that commit pantry.lock and choose their database in .env have the same exposure without it.

Sign in to comment on this issue.