Repository navigation
Description
Two separate bugs found while wiring a production environment onto this shared workflow. Both are reproducible; evidence for each is below.
1. smurf stf format is not a real subcommand (on master)
.github/workflows/smurf-tf-workflow.yml line 277:
- name: 🧹 Terraform Format
run: |
smurf stf formatstf format does not exist in any smurf release I can find. The command is stf fmt. smurf stf --help on both v1.1.9 and v1.2.0 lists:
fmt Format the Terraform Infrastructure
and no format.
Why it only surfaced now. smurf changed how it handles an unknown subcommand:
| smurf | smurf stf format |
files touched |
|---|---|---|
| v1.1.9 | prints help, exit 0 | 0 |
| v1.2.0 (2026-09-07) | prints usage, exit 1 | 0 |
Verified by downloading both darwin-arm64 release binaries and running them against a clean git worktree of a repo that consumes this workflow.
So the step passed for as long as it has existed while formatting and checking nothing. v1.2.0's stricter handling is correct and simply exposed it. Every caller that does not pin smurf_version (it defaults to latest) went red on 2026-09-07 with no change in their own repositories.
Fix: smurf stf format → smurf stf fmt.
Second, smaller point on the same step: it is the only step in the job that runs without --dir. init, validate and the rest all pass --dir=${{ inputs.terraform_directory }}. So format operates on the whole checkout rather than the target root, which is why every root in a matrix fails together rather than just the one at fault. Worth passing --dir for consistency.
2. plan_only is declared and never read at v2.1.6
At tag v2.1.6 (the latest release) the reusable workflow is .github/workflows/tf-smurf.yml. It declares:
plan_only:
description: "Set this to `true` to run `smurf stf plan` only"
required: false
type: boolean
default: falseand then never references plan_only again. The apply and destroy jobs gate on inputs.terraform_destroy:
- name: ⏳ Approval Before Apply
if: inputs.terraform_destroy != 'true'
- name: 🚀 Terraform Apply
if: inputs.terraform_destroy != 'true'terraform_destroy is not a declared input at that tag — the declared name is destroy. An undeclared input evaluates to empty, so inputs.terraform_destroy != 'true' is always true and the apply path always runs, while terraform-destroy's inputs.terraform_destroy == 'true' is always false and never runs.
A caller passing plan_only: true therefore gets no protection from it. There is a trstringer/manual-approval@v1 gate in front, so this is not an unattended apply, but the input a caller uses to say "never apply" has no effect.
master's smurf-tf-workflow.yml has the correct gate (if: ${{ !inputs.plan_only }} on the apply job), so this is fixed there but not in any release.
3. Consequence for callers: no usable semver tag
CLAUDE.md in our repo requires callers to pin an exact semver tag. That is currently impossible:
- At
v2.1.6the file is namedtf-smurf.yml, notsmurf-tf-workflow.yml. A caller naming the latter fails at startup with zero jobs, which noif:can skip. tf-smurf.yml@v2.1.6has bug 2 above.- Only
masterhas the correctplan_onlygate, andmasteris not a pin.
We have had to pin callers to a commit SHA, which is exact but not semver. A release cut from master, after fixing stf format, would let every caller move back to a tag.
Suggested order
stf format→stf fmtonmaster(one word, unblocks everyone whosesmurf_versionfloats).- Optionally pass
--dirto that step for consistency with the others. - Cut a release from
masterso callers get theplan_onlyfix and a taggable version.
Activity
clouddrove-ci commentedon Sep 9, 2026
One addition, so the fix does not land as a second no-op.
stf fmtis non-recursive by default and takes--dir:The step currently runs bare, with no
--dir, so its working directory is the repo root. In a typical consumer that root holds no.tffiles at all (they live under something like_infra/), so simply changingformattofmtwould give a command that exits 0 while still checking nothing. Green, and still not doing the job.Suggested:
which also makes it consistent with
init,validateand the other steps, all of which already pass--dir=${{ inputs.terraform_directory }}. That has the useful side effect of scoping a failure to the root that caused it, instead of failing every root in a matrix together.Worth a note in the release description too: for callers whose roots have never actually been format-checked, the first run after this fix may legitimately go red. That is the check starting to work, not a regression.
clouddrove-ci commentedon Sep 9, 2026
Confirmed all three, thanks. The
stf formatdiagnosis is exactly right, including the cause:cmd/stf/stf.gogainedArgs: cobra.NoArgs, so what used to fall through to the group'sRunand exit 0 now exits 1.One correction to point 2 of section 1: passing
--dirto that step is not possible today.stf fmthas no--dirflag in any released smurf — it is the only stf subcommand without one, andinternal/terraform/format.gohardcodesos.Getwd(). So that needs a smurf change before the workflow can use it.PRs:
--dirtostf fmt, and acceptsformatas an alias forfmt. The alias un-breaks every caller on a floatingsmurf_versionas soon as it releases, without them touching their repos. TheNoArgsguard stays; it is correct.smurf stf format->smurf stf fmthere. Safe on every smurf version.--diris left as a comment on the step, to be added after the smurf release, since passing it sooner would break anyone pinning an oldersmurf_version.That leaves points 2 and 3 for you:
masteralready has the rightplan_onlygate, so a release cut frommasterafter #448 merges closes both, and gets callers back onto a tag instead of a SHA.fix(stf): give fmt a --dir flag and accept the format alias (#550)
clouddrove-ci commentedon Sep 9, 2026
All three points are shipped.
smurf v1.2.1 —
stf fmtgained--dir, andformatis now accepted as an alias. Verified against the published darwin-arm64 binary, running the exact call this workflow was making:Post-release smoke is green on all published assets, the ghcr image and the action on ubuntu and macOS.
github-shared-workflows v2.1.7 — https://github.com/clouddrove/github-shared-workflows/releases/tag/v2.1.7
smurf stf format->smurf stf fmt(fix(smurf-tf): call stf fmt, the subcommand that exists #448).plan_onlyis honoured: this is the first tag carryingif: ${{ !inputs.plan_only }}.Read the release notes before bumping. Four workflow files were renamed between v2.1.6 and this tag, so the
uses:line has to change too:tf-smurf.ymlsmurf-tf-workflow.ymldocker-smurf.ymlsmurf-docker.ymlhelm-smurf.ymlsmurf-helm-deploy.ymlstf-checks.ymlsmurf-tf-checks.ymlDeliberately left out: passing
--dirto the Terraform Format step. It now exists in smurf, but adding it to the shared workflow would break any caller pinningsmurf_versionolder than v1.2.1, since they would hit an unknown flag. The step carries a comment for whoever picks it up once v1.2.1 has propagated. Worth a separate issue if you want it tracked.Closing. Thanks for the write-up, the reproduction and the version table made this quick.