Skip to content

Make pixi lockfile updates predictable and auditable #2298

Description

@rwgk

Problem statement

The repository currently checks in several pixi.lock files, but the process for updating them is not explicit enough. In practice, lockfile updates appear to happen organically when someone touches a related pixi.toml, fixes a CI issue, or refreshes an environment for a specific task.

That makes lockfile changes harder to reason about in review. A PR may include large dependency-solver churn without a clear indication of whether the churn is intentional, incidental, or required. Conversely, a PR may update a pixi.toml without updating the corresponding pixi.lock, leaving the next developer or CI job to discover the mismatch.

We should make lockfile maintenance predictable, auditable, and easy for contributors to follow.

Current situation

The repo has multiple pixi manifests and lockfiles, including the root environment, package-specific environments, and benchmark environments:

  • pixi.toml / pixi.lock
  • cuda_pathfinder/pixi.toml / cuda_pathfinder/pixi.lock
  • cuda_bindings/pixi.toml / cuda_bindings/pixi.lock
  • cuda_core/pixi.toml / cuda_core/pixi.lock
  • benchmarks/cuda_bindings/pixi.toml / benchmarks/cuda_bindings/pixi.lock
  • benchmarks/cuda_core/pixi.toml / benchmarks/cuda_core/pixi.lock

These lockfiles are useful because they pin the solved dependency graph used by the pixi developer and CI workflows. They help keep source builds and test environments reproducible across machines, platforms, CUDA variants, and solver state.

The current process is less clear than the purpose:

  • When a pixi.toml changes, it is not obvious whether the corresponding pixi.lock must always be updated in the same PR.
  • When pixi run is used without strict lockfile options, pixi may refresh the lockfile implicitly if it determines the lock is stale.
  • CI can therefore test an environment that was refreshed during the job, rather than enforcing that the committed lockfile was already current.
  • Large lockfile diffs can show up in feature PRs, making it difficult to separate intentional dependency updates from incidental solver churn.
  • If lockfiles are not refreshed regularly, a future unrelated PR may become the place where accumulated dependency churn appears.
  • Metadata-only changes can be easy to miss. For example, changing package metadata in a pixi.toml may leave old package metadata in the corresponding lockfile unless the lockfile is regenerated.

Recent history suggests that lockfiles have continued to be updated by several contributors, but not on an obvious schedule or through a single documented workflow. That is workable while the team remembers the expected behavior, but it is brittle as ownership changes.

Ideas and recommendations

Add a lockfile freshness check in CI

Add a small CI job that checks whether every committed pixi lockfile is current with respect to its manifest:

pixi lock --check --manifest-path .
pixi lock --check --manifest-path cuda_pathfinder
pixi lock --check --manifest-path cuda_bindings
pixi lock --check --manifest-path cuda_core
pixi lock --check --manifest-path benchmarks/cuda_bindings
pixi lock --check --manifest-path benchmarks/cuda_core

This would make stale lockfiles fail clearly in CI, with a direct remediation: regenerate and commit the affected lockfile.

Run pixi CI against committed lockfiles

Where CI is intended to validate the committed environment, use strict lockfile
behavior:

pixi run --locked ...

or set:

PIXI_LOCKED=1

This prevents CI from silently updating a lockfile during a test run. If a manifest and lockfile are out of sync, the job should fail and ask for the lockfile update to be committed.

Define contributor expectations

Document a simple policy near the pixi developer docs or in the contributor workflow:

  • If a PR changes a pixi.toml, it should update the corresponding pixi.lock in the same PR.
  • If a PR does not intentionally change pixi dependencies or metadata, it should not include unrelated lockfile churn.
  • If a lockfile changes, the PR description should briefly say why.
  • Large dependency refreshes should be isolated from feature work where possible.

Add scheduled lockfile refresh PRs

Add a scheduled workflow, for example weekly or monthly, that runs:

pixi update --no-install --manifest-path .
pixi update --no-install --manifest-path cuda_pathfinder
pixi update --no-install --manifest-path cuda_bindings
pixi update --no-install --manifest-path cuda_core
pixi update --no-install --manifest-path benchmarks/cuda_bindings
pixi update --no-install --manifest-path benchmarks/cuda_core

If this produces a diff, the workflow can open a dedicated PR. That makes broad dependency churn predictable and reviewable as dependency maintenance, rather than letting it accumulate until an unrelated PR happens to refresh the locks.

Consider scope and cadence

The scheduled refresh does not need to update everything aggressively. Some possible policies:

  • Weekly freshness check, monthly dependency refresh PR.
  • Refresh only default/test environments on a schedule, and refresh docs or benchmark environments when needed.
  • Refresh package lockfiles independently so a benchmark environment does not force unrelated core/bindings churn.

The key point is not the exact cadence, but that the repo has an explicit cadence and CI enforces the contract.

Expected outcome

After this change, lockfile updates should have clear intent:

  • Manifest changes require corresponding lockfile changes.
  • CI fails when committed lockfiles are stale.
  • CI does not silently mutate the environment under test.
  • Broad dependency churn appears in dedicated maintenance PRs.
  • Reviewers can tell whether a lockfile diff is required, incidental, or a scheduled refresh.

Related open issue:

Metadata

Metadata

Assignees

No one assigned

    Labels

    CI/CDCI/CD infrastructureP1Medium priority - Should do

    Fields

    No fields configured for Enhancement.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions