Skip to content

September 2026 Upgrade Notes

Between mid-August and mid-September 2026 Zenfra shipped changes that alter existing behaviour or need action from operators. This page lists only those; each item says who is affected and what to do. It is a one-time page, not a changelog.

If you run a private worker pool

Do these in order once, then keep the worker on the public image.

  1. Drain the old workers. Stop starting new runs on the pool and wait until no worker holds a run.
  2. Discard runs that are waiting for approval, and approved runs still queued to apply, on stacks with a project root. The new worker runs the tool in <repository>/<project root> instead of the repository root, and a plan made by an old worker bakes the old paths in. Applying such a plan on a new worker applies the wrong paths, so do not approve them and do not let a queued apply reach a new worker; discard and re-trigger after the upgrade. Runs on stacks without a project root are unaffected.
  3. Switch to the public image and give the worker disk for the log spool. The image is now ghcr.io/zenfracloud/zenfra-worker:latest. The worker spools run output to disk before uploading it, with defaults of 1 GiB per run, 8 GiB in total and a 512 MiB free-space floor; see Run logs and disk space.
  4. Give the worker an AWS identity if any integration uses worker mode. See the AWS item below.
  5. Start the new workers and re-trigger the runs you discarded.

Until the pool runs the new image: runs of stacks with customer-managed state stay Queued (they need a worker with the external-state-v1 capability), no-changes runs still wait for approval, and run logs from the old worker are not integrity-checked.

Breaking changes for every stack

Reserved variables are refused

Affected: any stack, bundle or run variable named TF_DATA_DIR, HOME, TF_CLI_CONFIG_FILE, TF_PLUGIN_CACHE_DIR, TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE, TF_CLI_ARGS, TF_CLI_ARGS_<subcommand>, TERRAFORM_CONFIG or TF_REATTACH_PROVIDERS. The run now fails before execution with ENV_POLICY_REFUSED, naming the variables.

What to do: remove them. The worker owns the tool's data directory, home directory and CLI configuration per run, so custom CLI configuration and provider mirrors are no longer supported, and host-level HOME tricks on private workers (for example ~/.ssh for Git module sources) no longer reach the tool. TF_VAR_* and TF_WORKSPACE still pass. See Reserved variables.

Push triggers follow the project root

Affected: stacks with Push Trigger on. A push now runs a stack only when a changed file is under the stack's project root or matches one of its Project globs. A stack with a project root and no globs stops running on pushes outside its root. A stack with no project root and some globs stops filtering: every push to the branch triggers it.

What to do: for stacks that depend on files outside their project root, add Project globs for those paths (for example modules/**). Pull-request runs are not affected. See Triggers.

Triggering a run can fail immediately

Affected: anything that creates runs, including CI scripts and the Terraform provider. Because every run on a VCS-backed stack is now pinned to a commit at creation, creating a run resolves the branch first and can be refused: 422 (ref_unresolvable, source_config_invalid, connector_offline, connector_deleted, vcs_auth_failed, vcs_scope_insufficient), 429 (rate_limited), 499 (client_closed_request), 500 (internal), 502 (provider_unavailable, provider_error) or 504 (provider_timeout). Previously the run was created and failed later during download.

What to do: treat these responses as retryable or as configuration errors as their code says. See Source commit.

Behaviour changes to know about

Worker-mode AWS integrations use the worker's identity

Affected: AWS integrations that had Generate credentials in worker enabled before 2026-09-15. From that date the private worker's own AWS identity assumes your role; Zenfra's role is no longer in the trust chain.

What to do: change the role's trust policy to name the worker principal instead of Zenfra's role, run every stack that uses the integration on a private pool, remove static keys from the worker's environment if you rely on an instance profile or IRSA, then validate with a Plan Only run (read) followed by a Plan & Apply run (write). See AWS Integration.

Run logs are complete or the run fails

Affected: every run planned by a worker on the new image. Zenfra now verifies that every byte of tool output arrived. If output was lost, the run is marked Failed with log_upload_incomplete even when the apply itself succeeded.

What to do: on such a failure, check your cloud before re-running. On private pools, make sure the spool has disk (item 3 above). See Logs.

No-changes runs finish without approval

Affected: tracked runs whose plan has no changes. They now finish right after planning instead of waiting for approval. Plans that change only outputs or contain moved or import changes still wait. Private pools see this once they run the new image. See No changes.

Customer-managed state needs a capable worker

Affected: stacks created with Customer-managed S3 state. Their runs are dispatched only to workers advertising external-state-v1; on a private pool that has not been upgraded, the run stays Queued. See Terraform State.