Skip to content

fix: test the declared Terraform floor, and document it (ENG-8760) - #7

Merged
johnsca merged 8 commits into
mainfrom
johnsca/fix/ENG-8760/min-terraform-version
Oct 13, 2026
Merged

johnsca merged 8 commits into
mainfrom
johnsca/fix/ENG-8760/min-terraform-version

Conversation

@johnsca

@johnsca johnsca commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

ENG-8760

what

Adds a CI job that validates this module at the floor it declares, raises that floor to a supported Terraform line, restores the README's generated tables, and adds the terraform-docs tooling the sibling repos already carry. Also stops the repo un-ignoring its provider lock file, and gives zizmor a token. The docs job also reads .terraform-docs.yml, which the action ignores by default.

why

The ticket is about a sibling that declared a floor it could not run on. This module's floor was not wrong, but it was equally untested, so the job goes everywhere rather than only where the bug happened to surface.

The floor moves from 1.13.5 to 1.14 because 1.13 no longer receives security fixes. Previously the floor was simply the pinned toolchain version, which made the new job repeat what lint already does. The CI pin moves to 1.16.5 at the same time, so the two ends are now distinct and the job covers something lint does not.

The README is the substantive fix. Its tables claimed the module has no requirements at all, while the constraints have been in provider.tf since CI was first set up here. Nothing caught it because this is the one repo of the set with no terraform-docs config, no pin, no just target and no docs job, so CI was about to start enforcing a floor the module's public documentation denied existed. Regenerating alone would not hold, which is why the tooling comes with it.

The lock file matters for the same reason. Every sibling ignores it deliberately, because committing one in a published module pins consumers to its provider versions, and this repo did the opposite. The new job runs init, which makes producing that file routine, so an un-ignore that was previously harmless is now one careless git add from doing real damage.

The job itself lives in stacklet/github-tooling, because five module repositories need the same check and it carries enough shell to be worth one copy rather than five. This PR references that action by commit SHA, naming the commit on github-tooling's main.

testing

  • Sandbox deploy. Planned from a root module against the sandbox dev account at the declared floor of 1.14.0, and again at 1.16.4. Both produce the same 6 resources, and no resource, variable or output changed.
  • The README regenerated with the pinned terraform-docs and confirmed stable on a second run, so the new docs job passes on arrival rather than going red.
  • The extraction checked against a module carrying three constraints at once, one of them in a .tf.json and one split across lines. It returns all three, and Terraform's own init agrees on which one binds. The action it replaces returns an empty string for that module.
  • The docs job confirmed to load .terraform-docs.yml, which it was silently ignoring.
  • just lint clean at the new pin, and zizmor re-run with a token to confirm its five online audits schedule rather than skip. The prek release that job installs now comes from .tool-versions rather than being resolved at run time, so CI and a local run agree on it.
  • Repointed the uses: pin at 3865043, the commit github-tooling's main carries now that feat: add the validate-min-terraform action (ENG-8760) github-tooling#1 merged. The action resolves there, so this job runs for the first time on this PR.
  • Refreshed the pinned tools and re-ran just lint at them: terraform 1.16.5, tflint 0.64.0, just 1.58.0, uv 0.12.23. terraform-docs stays at 0.20.0, the version terraform-docs/gh-actions v1.4.1 bundles, so the docs job and just docs keep rendering with the same binary. The plans above ran at 1.16.4, the pin at the time.

docs

The README's Requirements and Providers tables now match provider.tf, and the tooling added alongside is what keeps them matching.

one thing to know before reading the diff

Planning this module surfaces two deprecation warnings that predate this change and are left alone here. data.aws_region.current.name is deprecated in AWS provider 6.x in favour of .region, and the empty provider "aws" {} block is the old proxy-provider form that no sibling uses. Both are worth a follow-up ticket rather than a drive-by fix inside a change about version floors.

@johnsca

johnsca commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai please review this PR.

Filed by Claude on Cory's behalf.

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 30, 2026

Copy link
Copy Markdown

@cubic-dev-ai please review this PR.

Filed by Claude on Cory's behalf.

@johnsca I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files

Architecture diagram
sequenceDiagram
    participant Dev as Developer
    participant GH as GitHub Actions
    participant TF as Terraform CLI
    participant TFMin as terraform-min-max
    participant TFDocs as terraform-docs
    participant Ziz as Zizmor
    participant README as README.md

    Note over Dev,README: CI Pipeline for Module Validation

    Dev->>GH: Push to PR
    GH->>GH: Trigger lint-docs job
    GH->>TFDocs: Run terraform-docs check
    TFDocs->>README: Compare generated docs
    alt Docs out of date
        TFDocs-->>GH: Fail pipeline
    else Docs current
        TFDocs-->>GH: Pass
    end

    GH->>GH: Trigger validate-min-terraform job
    GH->>GH: Assert single required_version in provider.tf
    GH->>TFMin: Read minimum Terraform version
    TFMin->>TFMin: Parse required_version constraint
    TFMin-->>GH: minVersion (e.g., 1.14.0)
    GH->>TF: Setup Terraform at declared floor
    TF->>TF: terraform init -backend=false
    TF->>TF: terraform validate
    alt Validation fails
        TF-->>GH: Error
        GH-->>Dev: CI failure
    else Validation passes
        TF-->>GH: Success
    end

    Dev->>GH: Run lint job with GH_TOKEN
    GH->>Ziz: Run pre-commit checks
    Ziz->>Ziz: NEW: Perform online supply-chain audits
    Ziz-->>GH: Audit results
    GH-->>Dev: Lint status

    Dev->>Dev: Run just docs
    Dev->>TFDocs: terraform-docs .
    TFDocs->>README: Regenerate Requirements/Providers tables
    TFDocs-->>Dev: Updated docs

    Note over TF,README: Module Configuration Summary
    Note over TF: required_version >= 1.14.0
    Note over TF: aws provider ~> 6.0
    Note over README: Now documents declared floor and provider versions
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/workflows/ci.yml
johnsca and others added 3 commits October 5, 2026 15:36
[ENG-8760](https://stacklet.atlassian.net/browse/ENG-8760)

### what

Adds a CI job that validates this module at the floor it declares, restores the
README's Requirements table, and adds the terraform-docs tooling the other four
module repos already carry.

### why

ENG-8760 found `terraform-aws-onboarding-account` declaring a floor it could
not run on. This repo's floor is correct, but it was never tested: the job runs
in all five module repos so an incorrect floor cannot sit in `main` the way the
original one did.

The floor here equals the `.tool-versions` pin today, so the job duplicates what
the lint job already covers. That is the point at which it stops being free and
starts being insurance: the moment the two diverge, the bottom of the constraint
is covered without anyone remembering to add a job.

The README is the substantive fix. Its Requirements table said `No requirements.`
and `| aws | n/a |`, while `provider.tf` declares `>= 1.13.5` and `aws ~> 6.0`.
The constraints arrived in a20d594, which never touched the README, and nothing
here would have caught that: alone among the five repos, this one has no
terraform-docs config, no terraform-docs pin, no `just docs` target and no
`lint-docs` job. So CI was about to start enforcing a floor that the module's
own public documentation denied existed. Adding the tooling is what stops it
drifting again.

`.gitignore` also stops un-ignoring `.terraform.lock.hcl`. The other four ignore
it deliberately, because committing a lock file in a published module pins every
consumer to its provider versions. The new job runs `terraform init`, which
makes producing that file routine, so the un-ignore was one `git add -A` away
from doing real damage.

The lint job now passes a token to zizmor. Its five online audits skip silently
without one, and the summary line reads identically either way.

### testing

- [x] Ran the version-resolution action locally against this `provider.tf`:
      resolves `>= 1.13.5` to `1.13.5`, the version CI will install, and the
      module validates there.
- [x] Regenerated the README with the pinned terraform-docs 0.20.0 and confirmed
      the result is stable on a second run, so the new `lint-docs` job passes.
- [x] The guard step exercised both ways under bash and GNU grep: passes as-is,
      and fails when a second `required_version` is planted in another file.
- [x] `just lint` clean, and zizmor re-run with a token to confirm the five
      online audits schedule rather than skip.
- [ ] Sandbox deploy. Expect a no-op: no resource, variable or output changed.

### docs

The README's Requirements and Providers tables now match `provider.tf`. The
tooling added alongside is what keeps them matching.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The old floor was the oldest release that could run the module, which meant
standing behind Terraform lines that no longer receive security fixes. Declare
1.14 instead, and move the CI pin to the current 1.16.4 so the floor and the
pin stay distinct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
terraform-min-max finds the constraint by regex, takes the first match per
file, ignores .tf.json, and picks a file by shortest path. The guard step
added to compensate was the same regex with the same blind spots, so it could
never be more correct than the thing it was guarding. On a required_version
split across lines the action extracts an empty string, which semver reads as
"any version", so the floor resolves to the oldest Terraform ever released.

terraform-docs parses the configuration and reports every required_version in
the module, which removes the question of which file holds the real one. The
floor is then the highest declared lower bound, which is what Terraform
applies. Pinned by digest because terraform-docs publishes no immutable
releases, so neither a tag nor a release checksum is fixed.

Also point the docs job at .terraform-docs.yml, which it was ignoring, and
settle on that spelling in the two repos that used .terraform-docs.yaml.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@johnsca
johnsca force-pushed the johnsca/fix/ENG-8760/min-terraform-version branch from 241a244 to 042cf7b Compare October 5, 2026 15:50
@johnsca

johnsca commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai please review this PR.

Filed by Claude on Cory's behalf.

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown

@cubic-dev-ai please review this PR.

Filed by Claude on Cory's behalf.

@johnsca I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 7 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant CI as CI Pipeline
    participant Docs as terraform-docs
    participant TF as Terraform
    participant REG as Terraform Registry
    participant ZM as Zizmor
    participant GH as GitHub API

    Note over CI: Three independent CI jobs validate the module

    CI->>ZM: Run pre-commit checks
    ZM->>GH: NEW: Supply-chain audits with GH_TOKEN
    GH-->>ZM: Audit results
    ZM-->>CI: Validation results

    CI->>Docs: Check docs job (terraform-docs action)
    Docs->>Docs: Parse .terraform-docs.yml config
    Docs->>Docs: Generate markdown from Terraform config
    alt Docs match README
        Docs-->>CI: Pass (no diff)
    else Docs differ
        Docs-->>CI: Fail (diff detected)
    end

    CI->>CI: Validate min Terraform job
    CI->>Docs: Extract required_version from provider.tf
    Docs-->>CI: Constraint ">= 1.14.0"
    CI->>CI: Parse floor version "1.14.0"
    CI->>TF: Setup Terraform 1.14.0
    TF->>REG: Check provider availability
    REG-->>TF: Providers compatible
    TF->>TF: init -backend=false
    TF->>TF: validate
    alt Validation passes
        TF-->>CI: Success
    else Validation fails
        TF-->>CI: Failure - floor not supported
    end

    Note over TF: Provider lock file intentionally gitignored<br/>to avoid pinning consumers
Loading

Re-trigger cubic

@johnsca
johnsca force-pushed the johnsca/fix/ENG-8760/min-terraform-version branch from eaae510 to 3e36376 Compare October 6, 2026 20:04
@johnsca

johnsca commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai please review this PR.

Filed by Claude on Cory's behalf.

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 6, 2026

Copy link
Copy Markdown

@cubic-dev-ai please review this PR.

Filed by Claude on Cory's behalf.

@johnsca I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 7 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant CI as GitHub Actions CI
    participant Job1 as Lint (pre-commit)
    participant Ziz as zizmor
    participant Job2 as docs job
    participant TFD as terraform-docs
    participant Job3 as validation job
    participant ACT as validate-min-terraform action
    participant TF as Terraform CLI

    Note over CI,TF: CI pipeline for module validation and documentation

    CI->>Job1: Run lint job
    Job1->>Ziz: Run zizmor supply-chain audit
    Ziz->>Ziz: Check GH_TOKEN
    alt GH_TOKEN present
        Ziz->>Ziz: Run online audits (5)
    else GH_TOKEN missing
        Ziz->>Ziz: Skip online audits silently
    end

    CI->>Job2: Run docs job
    Job2->>TFD: terraform-docs gh-action
    TFD->>TFD: Load .terraform-docs.yml
    TFD->>TFD: Compare generated docs vs README.md
    alt Docs match
        TFD-->>Job2: Pass
    else Docs differ
        TFD-->>Job2: Fail
    end

    CI->>Job3: Run validate-min-terraform job
    Job3->>ACT: Checkout + invoke shared action
    ACT->>ACT: Extract required_version from provider.tf
    ACT->>TF: Run terraform init + validate
    TF-->>ACT: Validation result
    ACT-->>Job3: Pass/fail
Loading

Re-trigger cubic

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@johnsca
johnsca force-pushed the johnsca/fix/ENG-8760/min-terraform-version branch from 3e36376 to a20d66d Compare October 6, 2026 20:47
@johnsca
johnsca marked this pull request as ready for review October 6, 2026 21:03
@johnsca
johnsca requested a review from a team as a code owner October 6, 2026 21:03

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 7 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant CI as GitHub Actions CI
    participant Checkout as actions/checkout
    participant Lint as pre-commit (prek-action)
    participant Zizmor as zizmor (in pre-commit)
    participant GHAPI as GitHub API
    participant Docs as terraform-docs action
    participant TFDocs as terraform-docs (pinned 0.20.0)
    participant Config as .terraform-docs.yml
    participant README as README.md
    participant Tooling as stacklet/github-tooling action
    participant Terraform as Terraform (floor 1.14.0)
    participant ProviderTF as provider.tf constraint

    Note over CI,ProviderTF: CI Pipeline for Terraform Module

    CI->>Checkout: job: lint-docs & validate-min-terraform
    Checkout->>Checkout: persist-credentials: false

    Note over CI,Zizmor: Lint Job (existing, with NEW env)
    CI->>Lint: Run pre-commit checks
    Lint->>Zizmor: Execute zizmor online audits
    Zizmor->>GHAPI: NEW: Authenticated calls with GH_TOKEN
    GHAPI-->>Zizmor: Audit results (scheduled, not skipped)
    Zizmor-->>Lint: Summary (confirmed audits ran)
    Lint-->>CI: Lint pass/fail

    Note over CI,README: Documentation Job (NEW)
    CI->>Docs: Check documentation
    Docs->>Config: NEW: Read .terraform-docs.yml (explicit config-file)
    Config-->>Docs: Formatter: markdown, output: README.md, lockfile: false
    Docs->>TFDocs: Invoke terraform-docs (pinned via .tool-versions)
    TFDocs->>ProviderTF: Read required_version and provider constraints
    ProviderTF-->>TFDocs: terraform >= 1.14.0, aws ~> 6.0
    TFDocs->>README: Generate Requirements & Providers tables
    Note over Docs,README: fail-on-diff: true - checks tables match
    README-->>Docs: Diff comparison
    Docs-->>CI: Docs check pass/fail

    Note over CI,Terraform: Validation Job (NEW)
    CI->>Tooling: Validate at declared Terraform floor
    Tooling->>ProviderTF: Extract required_version constraint
    ProviderTF-->>Tooling: ">= 1.14.0"
    Tooling->>Terraform: Run terraform init/plan at floor 1.14.0
    Terraform-->>Tooling: Plan result (6 resources, no diff expected)
    Tooling-->>CI: Validation pass/fail

    Note over CI,ProviderTF: Floor vs Pin (distinct lines)
    Note over ProviderTF: required_version = ">= 1.14.0" (supported line)
    Note over Tooling: .tool-versions pins 1.16.4 (toolchain)
Loading

Re-trigger cubic

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@johnsca
johnsca force-pushed the johnsca/fix/ENG-8760/min-terraform-version branch from bdc8849 to 148a1be Compare October 6, 2026 22:13

@jtroup jtroup left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as mentioned in the t-azure-s-relay PR. Thanks @johnsca

@johnsca
johnsca force-pushed the johnsca/fix/ENG-8760/min-terraform-version branch from 413a90d to 804ffd9 Compare October 8, 2026 16:13
terraform-docs stays at 0.20.0: terraform-docs/gh-actions v1.4.1, which the
docs job runs, bundles that exact version, so moving it here would have CI
check the README against a different renderer than `just docs` uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@johnsca
johnsca force-pushed the johnsca/fix/ENG-8760/min-terraform-version branch from 804ffd9 to 2776feb Compare October 9, 2026 21:16
johnsca and others added 2 commits October 13, 2026 14:12
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@johnsca
johnsca merged commit ccf17f0 into main Oct 13, 2026
5 checks passed
@johnsca
johnsca deleted the johnsca/fix/ENG-8760/min-terraform-version branch October 13, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants