Skip to main content

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:

SiteWhere
Terraform module ref?ref=v<version> on every github.com/sophium/erun.git//… module source
Helm chart dependencieseach <tenant>-<component> umbrella's Chart.yaml erun dependency version:
Build-env imageFROM …/erun-devops:<version> in a custom runtime image
Terraform variable image referencean erun image reference a tenant's own Terraform sets directly, e.g. the cluster-edge module's dns01_webhook_image
Environment runtime imagethe env's runtimeimage, when it names erun's own stock erun-devops image
Environment runtime versionthe env's runtimeversion, when the environment's own runtime image is erun's
Environment runtime chartthe 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

  1. Resolves the target: --version, --revert, or (by default) the latest published stable release.
  2. 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 init or a chart pull, far from the cause.
  3. Resolves a plan — every site, its current value, and what it would become.
  4. Records the version you were on, so a revert is one motion.
  5. 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

FlagDescription
--versionPin to this erun version. Refused if it is not published.
--latestPin to the latest published stable release (the default when no version is given).
--revertPin back to the version recorded before the last re-pin.
--listList the published erun versions available to pin to.
--dry-runResolve and print the full plan — every site, old → new — without writing.
--tenant, --environmentTarget 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

FailureBehaviour
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.