Orchestration specification

Offline Validation

Networked setup hydrates the workspace once; validation then runs with OFFLINE=1 and never quietly re-downloads anything.

Applies at
scripts/build/
Status
Stable

01 Defines

A split between a networked prepare phase that installs, restores, and downloads, and a validation phase that only reads what is already present, switched by a single OFFLINE make variable.

02 Applies when

  • A validation step would otherwise fetch something — Terraform providers, TFLint plugins, package dependencies.
  • CI hydrates the workspace in one phase and validates in a later one.
  • A developer needs make validate to work without network access.

03 Boundaries

  • OFFLINE=1 skips network steps; it does not provide what they would have fetched.
  • Dependency installation itself belongs to the dev container and the prepare phase, not to validation targets or ad hoc scripts.
  • Offline mode never turns a real validation failure into a pass.

Expected behaviour

  1. 01
    OFFLINE defaults to 0 in 00-config.mk, so a plain make validate behaves normally on a connected machine.
  2. 02
    Every step that needs the network checks OFFLINE and, when it is 1, prints a skip: line instead of downloading.
  3. 03
    Steps that need no network still run under OFFLINE=1 against whatever the prepare phase left behind.
  4. 04
    Validation initialises Terraform with -backend=false, so it needs no credentials either way.

Behaviour#

Validation is most useful when it is reproducible: the same inputs give the same result, and nothing changes underneath it mid-run. A target that re-runs terraform init or tflint --init as a side effect quietly depends on the network and on whatever the registry serves that minute.

The repository separates the two concerns. Getting dependencies onto the machine is setup — the dev container’s lifecycle hooks locally, a prepare phase in CI. Validation then runs against the hydrated workspace, and OFFLINE=1 tells every module that the network is off-limits.

FlowPrepare once, validate offline
  1. 01 Prepare Lockfile restores, provider and plugin downloads; network allowed Update-Content Phase
  2. 02 Hydrated .terraform/, .cache/tflint, and node_modules/ are on disk
  3. 03 Validate make validate OFFLINE=1 — network steps print skip: and the checks run Explicit Skips

The default is OFFLINE=0. In that mode the Terraform module clears each root’s .terraform/ and re-initialises it before validating, which is what a fresh checkout wants. The 00-config.mk comment describes the CI intent: OFFLINE is set once the prepare phase has hydrated the workspace, “so validation never silently re-downloads dependencies”.

What the switch changes#

StepOFFLINE=0OFFLINE=1
check.terraform.validateRemove .terraform/, init -backend=false, validateskip: offline Terraform init (<dir>), then validate
check.terraform.linttflint --init, then lint each rootskip: offline TFLint plugin init, then lint
check.terraform.fmtFormat checkUnchanged — needs no network
check.hugo, check.linksBuild and checkUnchanged

Keeping setup out of validation#

The scripts standard keeps “networked setup separate from offline validation” and keeps “dependency installation and long-running setup out of ad hoc scripts”. Make targets use the environment rather than create it: the Node tooling is restored by an update-content.d/ hook, CI tools by scripts/ci/setup-ci-toolchain.sh, and validation targets only consume them.

Examples#

The validate recipe, reflowed from its single line for reading:

scripts/build/53-terraform.mk
if [ "$(OFFLINE)" = "1" ]; then
  printf 'skip: offline Terraform init (%s)\n' "$$dir"
else
  rm -rf -- "$$dir/.terraform"
  terraform -chdir="$$dir" init -backend=false -reconfigure
fi
terraform -chdir="$$dir" validate

Locally, the switch is a make variable like any other:

make validate             # downloads providers and plugins as needed
make validate OFFLINE=1   # uses what is already on disk