Add Terraform dependency updates to the update-deps command - #97
Open
mattmenefee wants to merge 1 commit into
Open
Add Terraform dependency updates to the update-deps command#97mattmenefee wants to merge 1 commit into
mattmenefee wants to merge 1 commit into
Conversation
mattmenefee
force-pushed
the
update-deps-terraform-init-upgrade
branch
2 times, most recently
from
August 10, 2026 17:53
8c08241 to
df0d40b
Compare
mattmenefee
force-pushed
the
update-deps-terraform-init-upgrade
branch
3 times, most recently
from
August 10, 2026 20:18
d76573f to
fd67eb4
Compare
The /update-deps workflow covered Ruby and JavaScript dependencies but skipped Terraform entirely, so provider pins drifted until a plan failed. Nothing surfaces an available release on its own: Terraform has no bundle outdated equivalent, and terraform init -upgrade only re-resolves versions within the existing constraints, so against an exact pin it never finds anything newer. Add two steps. The first locates the providers and modules pinned in the .tf files, queries the registry for each one's latest version, and decides what to edit from the constraint's form — an exact pin always, a range only when the new release falls outside it, a root-module bare source never, since nothing governs it and init -upgrade will take the newest release published. The second re-resolves every root module's lock file and verifies the result. Splitting them keeps the stop condition at the top of its own step rather than buried at the end of a long one, and the failure it guards against is the reason it exists: a failed init leaves the lock file untouched while the .tf edits stand, and staging that pair produces a commit that can neither init nor plan. The commands are written so that every failure is loud and every result is trustworthy, because an absence is otherwise indistinguishable from a negative answer. The registry lookup ignores the response's .version field, which reports the highest semver version including prereleases and would pin infrastructure to a beta. The Git tag lookup strips the tag prefix and sorts numerically rather than trusting --sort=-v:refname, which ranks every v-prefixed tag above every bare one and every prerelease above its own release, and it captures ls-remote's status instead of piping into head, where an unreachable repository would exit 0 and read as "no newer tag". curl runs with -fsS and jq with -e for the same reason. init and plan both take -input=false so they error rather than blocking on a prompt with no TTY. Writing of the lock file is confirmed with git status rather than git diff alone, since a brand-new root module's lock file is untracked and invisible to diff. The lock-file refresh iterates every root module rather than only those whose .tf files changed, since a range constraint updates with no .tf edit at all; root modules are identified as the directories owning a lock file, which excludes child modules on its own. The provider baseline captured beforehand keeps versions and filenames, because providers that arrive transitively through child modules never appear in a required_providers block and can only be seen moving in the lock file. Terraform version changes flow through to the commit message and to the PR labels and summary alongside the gems and npm packages. Background on why the commands take the flags they do lives in a Terraform Update Notes reference section. Most repos this command runs against have no Terraform at all, so the first step opens with how to recognize that case and skip both. Renumbering the later steps and their cross-references follows from inserting the new ones.
mattmenefee
force-pushed
the
update-deps-terraform-init-upgrade
branch
from
August 10, 2026 20:47
fd67eb4 to
43ebb29
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Terraform to the
/update-depsworkflow as two steps:.tffiles, query the registry for each one's latest version, and decide what to edit based on the constraint's form: an exact pin always, a range only when the new release falls outside it, a child-module baresourcenever, and a root-module baresourcenever but watch it — nothing governs it, soinit -upgradetakes the newest release published.terraform init -upgrade -input=falsein every root module and verify the outcome. Opens with the stop condition, because a failedinitleaves the lock file untouched while the.tfedits stand, producing a commit that can neitherinitnorplan.Terraform Update Notesreference section, matching the existingVersion-Locked PackagespatternCorrectness of the prescribed commands
This is a command file an agent executes unsupervised, so every command is written so that a failure is loud and an absence is never mistaken for a negative answer. Each behavior below was verified by running it, including against Terraform 1.15.8 and the live registry:
inithalts the workflow. Across five distinct failure modes (unreachable private registry, nonexistent version, malformed HCL, no build for the platform, missing module repo)initexited non-zero and wrote nothing to the lock file — even where the output saidInstalled …first. The step distinguishes self-inflicted failures worth fixing in place from ones worth stopping over..version, which reports the highest semver version including prereleases —5.5.0-pre.1forheroku/herokuwhile stable is5.4.0.--sort=-v:refnameranks everyv-prefixed tag above every bare-numeric one, so a repo that dropped the prefix at2.0.0reports the olderv1.10.0, and it ranks prereleases and floating tags likestableabove real releases.ls-remoteoutput is captured, not piped intohead. A pipeline's status is the last command's, so an unreachable repository would exit 0 and read as "no newer tag" — the same trap-fsS/jq -eguard against for curl.git status, notgit diffalone. A brand-new root module's lock file is untracked and invisible todiff, sodiffalone would report a successful write as a failure and trigger a needless revert..tffiles — a range constraint updates with no.tfedit at all. Root modules are identified as the directories owning a lock file, which excludes child modules automatically.required_providersblock and can only be observed moving in the lock file.~>bounds are exact. Verified against Terraform's own resolver:~> 2.99selects2.100.0,~> 2.99.0selects2.99.1,>= 2.5drifts to3.1.0.git addcalls, since git validates every pathspec before staging anything and one matching nothing aborts the whole invocation. Both exclude the modulesterraform initvendors into.terraform/— verified against a run that vendored 110.tffiles.Test plan
/update-depsin a repo with Terraform configuration and confirm the registry lookup reports the latest stable version, not a prereleaseterraform init -upgrade -input=falserewrites.terraform.lock.hclterraform plansucceeds afterward instead of reporting an inconsistent dependency lock fileinit -upgraderun, despite no.tffile changinginithalts the workflow rather than staging a.tf/lock-file pair that cannot be plannedterraformlabel/update-depsin a repo with no.tffiles and confirm both steps are skipped without breaking staging