Repository navigation
fix: test the declared Terraform floor in CI (ENG-8760) - #7
Conversation
|
@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. |
There was a problem hiding this comment.
No issues found across 4 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant GH as GitHub Actions Runner
participant CI as CI Workflow
participant Lint as Lint Job
participant Docs as Docs Job (NEW)
participant Validate as Validate at Declared Floor (NEW)
participant TF as Terraform CLI
participant TFMin as terraform-min-max Action
participant Providers as Terraform Providers (azurerm, random, time)
participant README as README Generator
Note over GH,README: CI/CD Pipeline for Terraform Module
CI->>GH: Trigger workflow (push/PR)
GH-->>CI: Start jobs
CI->>Lint: Run pre-commit checks
Lint->>Lint: Execute checks (incl. zizmor)
Note over Lint: GH_TOKEN now passed to zizmor<br/>for online audits
CI->>Docs: NEW: Check documentation job
Docs->>README: terraform-docs action
README-->>Docs: Generated README tables
alt README out of date
Docs-->>CI: Fail (fail-on-diff)
else README current
Docs-->>CI: Pass
end
CI->>Validate: NEW: Validate at declared floor job
Validate->>Validate: Assert single required_version in provider.tf
Validate->>TFMin: Read declared floor
TFMin-->>Validate: minVersion (1.14.0)
Validate->>TF: Setup Terraform at floor version
TF-->>Validate: Terraform 1.14.0 ready
Validate->>TF: terraform init -backend=false
TF->>Providers: Resolve providers
Providers-->>TF: Provider versions
Validate->>TF: terraform validate
TF-->>Validate: Validation result
Validate-->>CI: Pass/fail
Note over CI: Existing validate-min-providers job<br/>still runs unchanged<br/>(pins providers, uses pinned TF 1.16.4)
[ENG-8760](https://stacklet.atlassian.net/browse/ENG-8760) ### what Adds a CI job that validates this module at the Terraform floor it declares, and a `lint-docs` job to keep the README's generated tables honest. ### why ENG-8760 found `terraform-aws-onboarding-account` declaring a floor it could not run on, undetected because `.tool-versions` pins a version far above it. This repo's floor is correct, but it was equally untested, so the job goes into all five module repos rather than only the one that was broken. This repo already had half the idea. `validate-min-providers` pins the *providers* to their declared minimums and validates against the pinned Terraform; the new job pins *Terraform* to its declared minimum and validates against whatever providers resolve. Between them, the combination a consumer honoring both advertised floors actually runs is still uncovered. Closing that needs a third run and its own verification, so it is left for a follow-up rather than bolted on here. A guard step ahead of the new job asserts exactly one `required_version`, in `provider.tf`. The action that resolves the floor picks its source file by shortest filename rather than by a canonical name. `lint-docs` is unrelated to the floor but adjacent: this repo generates its README tables with terraform-docs and had nothing checking they stayed current. `terraform-aws-stacklet-cur-setup` was in that state and its table had silently drifted to claim the module has no requirements at all. 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, so CI reported success while the supply-chain audits never ran. ### testing - [x] Ran the version-resolution action locally against this `provider.tf`: resolves `>= 1.9.0, < 2.0.0` to `1.9.0`, and the module validates there against current providers. - [x] Confirmed the README is already byte-identical to freshly regenerated terraform-docs 0.20.0 output, so the new `lint-docs` job passes on arrival. - [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 No documentation change. The new `lint-docs` job enforces the existing terraform-docs output rather than altering it. The pre-existing `resource_manager_id` deprecation warning from azurerm is untouched and unrelated; it is already explained in the `provider.tf` header. 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>
e8238f6 to
b399ac3
Compare
|
@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. |
There was a problem hiding this comment.
No issues found across 5 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant GH as GitHub Actions
participant WF as CI Workflow
participant Lint as Lint Job
participant Docs as Docs Job
participant MinTF as Validate Min Terraform Job
participant MinProv as Validate Min Providers Job
participant TFD as terraform-docs Container
participant TF as Terraform CLI
participant Repo as Repo Context
Note over GH,Repo: CI Pipeline for Terraform Module
GH->>WF: Trigger workflow
WF->>Lint: Run lint job
Lint->>Lint: pre-commit checks incl. zizmor
Lint->>GH: GH_TOKEN injection
GH-->>Lint: github.token
WF->>Docs: Run docs job
Docs->>Repo: Checkout with persist-credentials: false
Docs->>TFD: Run terraform-docs action
TFD->>Repo: Read .terraform-docs.yml config
TFD->>Repo: Generate README tables
alt Docs up to date
TFD-->>Docs: No diff
Docs-->>WF: Pass
else Docs outdated
TFD-->>Docs: Diff detected
Docs-->>WF: Fail
end
WF->>MinTF: Run validate-min-terraform job
MinTF->>Repo: Checkout with persist-credentials: false
MinTF->>TFD: Run terraform-docs image (json output)
TFD->>Repo: Parse all required_version constraints
TFD-->>MinTF: Constraints list
MinTF->>MinTF: Extract highest lower bound (>= or ~>)
alt Constraints valid
MinTF->>MinTF: Compute floor version
MinTF->>TF: setup-terraform with floor version
TF->>Repo: terraform init -backend=false
TF->>Repo: terraform validate
TF-->>MinTF: Validation result
MinTF-->>WF: Pass
else No required_version or unparseable
MinTF-->>WF: Fail with clear error
end
WF->>MinProv: Run validate-min-providers job
MinProv->>Repo: Checkout
MinProv->>TF: Pin providers to minimums
MinProv->>Repo: Validate against pinned Terraform version
MinProv-->>WF: Pass/Fail
e3a3327 to
88320f6
Compare
|
@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. |
There was a problem hiding this comment.
No issues found across 5 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant GH as GitHub Actions
participant Lint as Lint Job
participant Zizmor as zizmor
participant Docs as Docs Job
participant TFDocs as terraform-docs
participant MinTerra as Min-Terraform Job
participant Action as validate-min-terraform Action
participant Terraform as Terraform CLI
participant Validator as terraform validate
participant Repo as Module Repo
Note over GH,Repo: CI Pipeline for Terraform Module
GH->>Lint: Trigger on push/PR
Lint->>Zizmor: pre-commit checks with GH_TOKEN
Note over Lint,Zizmor: CHANGED: Supply GH_TOKEN so online audits run
Zizmor-->>Lint: Supply-chain audit results
GH->>Docs: Run docs job
Docs->>TFDocs: Check documentation with config-file
Note over Docs,TFDocs: NEW: Explicitly load .terraform-docs.yml
TFDocs->>Repo: Read .terraform-docs.yml + module files
Repo-->>TFDocs: Configuration and source
TFDocs->>TFDocs: Generate README tables
TFDocs-->>Docs: Diff result
alt README out of date
Docs-->>GH: Fail job
else README current
Docs-->>GH: Pass job
end
GH->>MinTerra: Run min-terraform job
MinTerra->>Action: Invoke validate-min-terraform action
Note over MinTerra,Action: NEW: Pin Terraform to declared floor
Action->>Repo: Read required_version constraint
Repo-->>Action: ">= 1.14.0, < 2.0.0"
Action->>Action: Extract minimum version (1.14.0)
Action->>Terraform: Execute init with Terraform 1.14.0
Terraform->>Terraform: Resolve providers at minimum
Terraform->>Validator: Run terraform validate
Validator-->>Terraform: Validation results
Terraform-->>Action: Plan/validate output
alt Validation succeeds
Action-->>MinTerra: Success
MinTerra-->>GH: Pass job
else Validation fails
Action-->>MinTerra: Error
MinTerra-->>GH: Fail job
end
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
88320f6 to
e98ac08
Compare
There was a problem hiding this comment.
1 issue found across 5 files
Confidence score: 2/5
- In
.github/workflows/ci.yml, a pull request can add a pre-commit hook that exfiltrates the inheritedcontents: readtoken. KeepGH_TOKENout of hook environments and scope it only to the command that needs it.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/ci.yml">
<violation number="1" location=".github/workflows/ci.yml:45">
P2: `GH_TOKEN` is inherited by every pre-commit hook, including commands defined by the PR's `.pre-commit-config.yaml`. A malicious pull request can add a hook that exfiltrates the `contents: read` token; run online zizmor separately with the token instead.</violation>
</file>
Architecture diagram
sequenceDiagram
participant GH as GitHub Actions
participant Lint as Lint Job
participant Ziz as zizmor
participant Docs as Docs Job
participant TD as terraform-docs
participant MinT as Min Terraform Job
participant TA as Toolchain Action
participant TF as Terraform CLI
Note over GH: CI Pipeline
GH->>Lint: Run lint job
Lint->>Ziz: pre-commit checks
Ziz->>Ziz: Online supply-chain audits
Note over Ziz: GH_TOKEN: ${{ github.token }}<br/>NEW: Enables 5 online audits that<br/>previously skipped silently
Ziz-->>Lint: Results
GH->>Docs: Run lint-docs job
Docs->>TD: terraform-docs/gh-actions
TD->>TD: Read .terraform-docs.yml config<br/>NEW: Explicit config-file path
TD->>TD: Generate README tables
alt README matches generated docs
TD-->>Docs: Pass (no diff)
else README out of date
TD-->>Docs: Fail (diff detected)
end
Docs-->>GH: Status
GH->>MinT: Run validate-min-terraform job
MinT->>TA: stacklet/github-tooling/validate-min-terraform
Note over TA: Pinned by commit SHA
TA->>TA: Extract required_version from provider.tf
TA->>TA: CHANGED: Parse constraint ">= 1.14.0, < 2.0.0"
TA->>TF: Install Terraform at floor (1.14.0)
TA->>TF: terraform init -backend=false
TA->>TF: terraform validate
Note over TF: CHANGED: Validates against<br/>declared minimum (1.14.0) instead of<br/>pin (.tool-versions: 1.16.4)
TF-->>TA: Validation results
TA-->>MinT: Pass/Fail
MinT-->>GH: Status
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
|
@cubic-dev-ai please re-review |
@johnsca I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
No issues found across 5 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant Dev as Developer
participant CI as GitHub Actions CI
participant Pre as pre-commit / prek
participant Docs as terraform-docs
participant TF as Terraform CLI
participant GH as GitHub API
Note over Dev,CI: PR Validation Pipeline
Dev->>CI: Push / PR to module repo
CI->>CI: Dispatch workflows
par Lint Job
CI->>Pre: prek-action with pinned version 0.5.5
Pre->>GH: Read write token (GH_TOKEN)
alt Token available
GH-->>Pre: Schedule & run 5 online zizmor audits
else Token missing
Pre->>Pre: Skip audits silently
end
Pre-->>CI: Lint results
and Docs Job
CI->>Docs: terraform-docs/gh-actions
Docs->>Docs: Load .terraform-docs.yml config
Docs->>Docs: Generate README tables
alt Docs current
Docs-->>CI: Pass (no diff)
else Docs stale
Docs-->>CI: Fail (diff detected)
end
and Provider Validation
CI->>TF: terraform init (pinned providers)
TF-->>CI: Provider state
CI->>TF: terraform validate
TF-->>CI: Validation results
and Floor Validation Job
CI->>TF: github-tooling/validate-min-terraform
TF->>TF: Read required_version from provider.tf
TF->>TF: Resolve floor = 1.14.0
TF->>TF: Install Terraform 1.14.0
TF->>TF: terraform init + validate
alt Floor passes
TF-->>CI: Success
else Floor fails
TF-->>CI: Failure (floor not tested)
end
end
CI-->>Dev: Aggregate status check
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7c8cf10 to
08e9ddf
Compare
35481a5 to
1cf5378
Compare
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>
1cf5378 to
883ad04
Compare
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ENG-8760
what
Adds a CI job that validates this module at the Terraform floor it declares, raises that floor to a supported line, and adds a docs job to keep the generated README tables honest. The lint job also gains a token for zizmor. The docs job reads
.terraform-docs.yml, which the action ignores by default, and the config file is renamed from.terraform-docs.yamlso all five repos spell it the same way.why
The ticket is about a sibling that declared a floor it could not run on, undetected because the pinned toolchain sat far above it. 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.9 to 1.14. The 1.9 was accurate, since the cross-variable validations here need it, but accurate is not the same as worth supporting: 1.13 and everything below it no longer receives security fixes. The CI pin moves to 1.16.5 at the same time, so the floor and the pin stay distinct and the new job covers an end that lint does not.
This repo already had half the idea. The existing job pins providers to their declared minimums and validates against the pinned Terraform. The new one pins Terraform to its declared minimum and validates against whatever providers resolve. The combination a consumer honoring both advertised floors actually runs is still covered by neither. Closing that needs a third run and its own verification, so it is left as a follow-up rather than bolted on here.
The docs job is unrelated to floors but adjacent. This repo generates its README tables and had nothing checking they stayed current, which is precisely the state a sibling was already in, with its tables claiming the module had no requirements at all.
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'smain.testing
.tf.jsonand one split across lines. It returns all three, and Terraform's owninitagrees on which one binds. The action it replaces returns an empty string for that module..terraform-docs.yml, which it was silently ignoring.just lintclean 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-versionsrather than being resolved at run time, so CI and a local run agree on it.uses:pin at3865043, the commit github-tooling'smaincarries 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.just lintat 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 versionterraform-docs/gh-actionsv1.4.1 bundles, so the docs job andjust docskeep rendering with the same binary. The plans above ran at 1.16.4, the pin at the time.docs
No documentation change. The new job enforces the existing generated output rather than altering it.
The azurerm deprecation warning visible in a local
validatehere is pre-existing and unrelated, and theprovider.tfheader already explains it.