erun pin
Re-pin every place an environment records its erun version — in one motion.
Why this exists
One erun version is written down in several places, and they only work when they agree:
| Site | Where |
|---|---|
| Terraform module ref | ?ref=v<version> on every github.com/sophium/erun.git//… module source |
| Helm chart dependencies | each <tenant>-<component> umbrella's Chart.yaml erun dependency version: |
| Build-env image | FROM …/erun-devops:<version> in a custom runtime image |
| Terraform variable image reference | an erun image reference a tenant's own Terraform sets directly, e.g. the cluster-edge module's dns01_webhook_image |
| Environment runtime image | the env's runtimeimage, when it names erun's own stock erun-devops image |
| Environment runtime version | the env's runtimeversion, when the environment's own runtime image is erun's |
| Environment runtime chart | the env's runtimechart, when it names erun's own stock erun-devops chart |
Nothing kept them in step, so they drifted. One repo was found with Terraform on 1.0.102, its charts on 1.0.106, and the running binary on 1.0.115 — realigning it by hand meant editing seven files.
Synopsis
erun pin [TENANT] [ENVIRONMENT] [flags]
What it does
- Resolves the target:
--version,--revert, or (by default) the latest published stable release. - Verifies the target is published before writing anything. Pinning to a version that does not exist produces a tree that only fails much later, at
terraform initor a chart pull, far from the cause. - Resolves a plan — every site, its current value, and what it would become.
- Records the version you were on, so a revert is one motion.
- Rewrites the pins, and nothing else.
It is idempotent: running it against an already-aligned tree reports no changes and writes nothing.
Which tree it rewrites
Every environment of a tenant shares one repo. pin finds it in this order: the target environment's own local checkout, then a sibling environment of the same tenant that has one, and only as a last resort the directory you ran erun pin from — which may not be the tenant's repo at all. When it falls back that far, the plan names that tree's current commit and warns if the tree's own pins disagree with what the environment has deployed, so the plan is never mistaken for a statement about the environment's real drift.
What it does not do
It edits the source of truth and stops there. Realizing the new version — erun terraform apply, erun deploy — stays a separate explicit step, so changing a pin is never a rollout by accident.
Flags
| Flag | Description |
|---|---|
--version | Pin to this erun version. Refused if it is not published. |
--latest | Pin to the latest published stable release (the default when no version is given). |
--revert | Pin back to the version recorded before the last re-pin. |
--list | List the published erun versions available to pin to. |
--dry-run | Resolve and print the full plan — every site, old → new — without writing. |
--tenant, --environment | Target a specific tenant/environment. |
Examples
erun pin --list # what can I pin to?
erun pin my-tenant dev --dry-run # what would change?
erun pin my-tenant dev --version 1.0.174 # pin every reference
erun pin my-tenant dev --revert # back to where you were
Error behaviour
| Failure | Behaviour |
|---|---|
| The environment is a host env. | Refused before anything is written: a host env has no pod and no runtime version to pin. |
| The environment has no local checkout of its repo on this machine, and no other environment of the tenant does either. | Refused before anything is written, naming the tenant and environment. |
| The target version is not published. | Refused before anything is written, naming the registry it checked. |
| The registry cannot be read and a version was given. | Pins it anyway, tracing that it could not be verified — "I could not check" is not "it is not there". |
| The registry cannot be read and no version was given. | Errors: resolving the latest needs the registry. |
--revert with no recorded previous pin. | Errors — there is nowhere to revert to. |
| Already pinned to the target. | Reports no changes and writes nothing. |
What it leaves alone
Only erun's own references move. A tenant's own Terraform module sources, its own chart dependencies, and the umbrella chart's own version: are not erun version pins and are never rewritten. Vendored charts under charts/ are skipped too — those are regenerated by helm dependency update, not pinned.
A tagged runtimeimage is only a pin site when it names the stock erun-devops image. A tenant's own <tenant>-devops image rides the tenant's own release line, not erun's, so its tag is left alone — rewriting it to the erun target version would name a tag that line never publishes. The dry-run plan says so explicitly (skipped: runtimeimage <image> is not the stock erun-devops image; …) rather than leaving you to assume it was covered.
The same reasoning applies to the environment's own runtimeversion: it is only a pin site when the environment runs erun's own runtime image. An environment running a tenant-owned image has its runtimeversion alone too, for the same reason and with the same explicit skipped: line in the plan. The line is read from every statement the environment's config makes about that image — its runtimeimage, the image its last deploy confirmed running, and the image its own runtimechart publishes — so an environment whose runtimeimage is missing or stale is not mistaken for one on erun's line. An environment that records none of them is not assumed onto erun's line either: with no runtimeimage, a deploy installs the tenant's own <tenant>-devops image and records the version it deployed as runtimeversion, so that number belongs to the tenant's build, not to erun's release. The skipped: line names what the decision read.
A stated runtimechart (an OCI reference, set by --runtime-chart or directly in config) is classified the same way, by its own chart name rather than its version number: only a reference naming erun's own stock erun-devops chart is a pin site. A tenant's own umbrella chart — exactly what --runtime-chart exists to let an environment run on its own release line, separate from the image — is left alone, with the same explicit skipped: line. A stated chart with no version rides the deploy version already, so there is nothing to move.
erun list shows the same thing without needing to run a pin first: it names which release line each environment's runtime-version belongs to, right beside the number.
After a re-pin, run helm dependency update on each umbrella to refresh its Chart.lock, then erun terraform apply and erun deploy to realize the version.