-
Notifications
You must be signed in to change notification settings - Fork 0
Lock Files and Reproducibility
A profile says what you want. A lock file records exactly what that resolved to β versions, URLs, redirect chains, sizes and digests β so a later apply either reproduces it or refuses.
binstaller lock
binstaller lock --output /tmp/binstaller.lock.json
binstaller lock --only helm --only kubectlDefault output path: binstaller.lock.json. Nothing is installed.
wrote lock file: /path/to/binstaller.lock.json
profile: demo
manifest fingerprint: 93554ed0c1409e233aeeb2bc3ea68cbd0310469c92d32cbdd780aa7271e55452
tools: 2
checksums: configured 2, discovered 0, inspected 0, missing 0
That last line is the one to read in CI. missing 0 is the goal.
{
"schemaVersion": 1,
"profileName": "demo",
"manifestFingerprint": "93554ed0c140β¦e55452",
"tools": [
{
"name": "dotbot",
"resolvedVersion": "v0.3.0",
"versionProvenance": null,
"downloadProvenance": {
"initialUrl": "https://github.com/worxbend/dotbot-go/releases/download/v0.3.0/dotbot-linux-amd64.tar.gz",
"finalUrl": "https://release-assets.githubusercontent.com/β¦",
"redirects": [
{ "from": "https://github.com/β¦", "to": "https://release-assets.githubusercontent.com/β¦", "statusCode": 302 }
]
},
"sizeBytes": 2148359,
"checksum": {
"algorithm": "sha256",
"value": "45d49e064d8684926fed97ad051c6ecebbf796a3c709edaa7a4a166b2978633d",
"source": "configured",
"discoveryUrl": null,
"discoveryFile": null,
"discoveryProvenance": null
},
"dynamicSource": false
}
]
}| Field | Why it's there |
|---|---|
manifestFingerprint |
Ties the lock to the exact manifest content it was generated from. |
downloadProvenance.redirects |
Records every hop, so a changed CDN path is visible in review. |
sizeBytes |
Cross-checked against upstream metadata at locked-apply time. |
checksum.source |
configured, discovered, or absent β provenance of the digest itself. |
dynamicSource |
Marks tools whose version is intentionally resolved by a latest-URL. |
β οΈ finalUrlvalues for GitHub release assets contain signed, expiring query parameters. They are recorded as provenance, not as a fetch target you should reuse by hand.
binstaller apply --locked --lock-file binstaller.lock.json
binstaller plan --locked # same gate, without installingThe gate refuses the run β before anything downloads β when any of these is true:
| Check | Refusal message |
|---|---|
| Lock file absent |
lock file <path> is missing; run \binstaller lock --config ` first or omit --locked`
|
| Schema mismatch | expected schema version 1, found N |
| Different profile | expected profile 'X', found 'Y' |
| Manifest edited |
manifest fingerprint changed: β¦; rerun \binstaller lock --config ``
|
| Duplicate lock entry | duplicate lock entry for tool 'X' |
| Tool not in lock | missing lock entry for tool 'X' |
| Digest absent from lock | tool 'X' has no locked sha256 digest; regenerate the lock file |
| Version drifted | tool 'X' version changed: lock has 'A', resolved 'B' |
| Provenance incomplete | tool 'X' has incomplete download provenance |
All refusals are rendered as locked apply refused by <lock path>: <reason>.
# once, when you change the profile
binstaller lock
git add config.yaml binstaller.lock.json
git commit -m "pin toolchain"
# everywhere else, forever after
binstaller apply --lockedEditing config.yaml changes the manifest fingerprint, so --locked will refuse until you
re-run binstaller lock. That's the point: the lock file and the profile move together, in the
same commit, visible in the same diff.
- name: Verify the toolchain still resolves to the locked state
run: binstaller plan --locked --lock-file binstaller.lock.jsonplan --locked runs the entire gate without installing anything β a cheap drift alarm on a
schedule.
- π§± Pair lock files with
policy.mode: strictso unpinned versions can't get in to begin with. - π Prefer pinned
versions:entries overdynamic.latest-urlβ a dynamic source can only ever be locked as "this was dynamic", not as a specific artifact. - π Give every tool a checksum (configured or discovered). A tool with no digest is refused under
--lockedanyway. - π Run
binstaller versionson a schedule to see upstream drift, then bump and re-lock deliberately.
- π Home
- π Getting Started
- ποΈ CLI Reference
- π³ Manifest Cookbook
- π§ Lock Files
- π Security Model
- π©Ί Troubleshooting
- β FAQ
- π οΈ Development