Files
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

283 lines
11 KiB
YAML

name: terraform-bench (plan)
# Runs terraform fmt + init + validate + plan against tests/benchmarks/cloudopsbench/infra/ on every PR
# that touches the bench infra. Posts the plan output as a sticky PR comment so
# reviewers can see what would change before approving.
#
# Never applies — apply is developer-local in v1 (see tests/benchmarks/cloudopsbench/infra/README.md).
# When apply-from-CI is desirable later, add a separate workflow that runs on
# merge-to-main with a different (higher-privileged) AWS role.
on:
pull_request:
paths:
- "tests/benchmarks/cloudopsbench/infra/**"
- ".github/workflows/terraform-bench.yml"
workflow_dispatch:
permissions:
contents: read
pull-requests: write
id-token: write # required for AWS OIDC role assumption
concurrency:
group: terraform-bench-${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
plan:
name: terraform plan
if: github.repository == 'Tracer-Cloud/opensre' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
runs-on: ubuntu-latest
defaults:
run:
working-directory: tests/benchmarks/cloudopsbench/infra
env:
AWS_REGION: us-east-1
# tfplan + plan.txt artifacts are not uploaded; plan output goes into the
# PR comment. If you want a downloadable plan binary, add an
# actions/upload-artifact step after `terraform show`.
TF_IN_AUTOMATION: "true"
TF_INPUT: "0"
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.7.5"
# Wrapper MUST stay enabled (default) — it's what populates
# `steps.<id>.outputs.stdout` for the `terraform show` step that
# feeds the sticky PR comment. Disabling it makes the comment
# render with a blank plan body. See greptile review on initial
# PR for details.
- name: Configure AWS credentials (OIDC role assumption)
# No long-lived AWS keys. The role is provisioned by tests/benchmarks/cloudopsbench/infra/
# Terraform; ARN is hardcoded here because Terraform outputs aren't
# available before the workflow can run. Account ID is the
# tracer-cloud account.
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/opensre-bench-terraform-plan
role-session-name: github-actions-terraform-plan-${{ github.run_id }}
aws-region: us-east-1
- name: terraform fmt
id: fmt
run: terraform fmt -check -recursive -no-color
continue-on-error: true
- name: terraform init
id: init
run: terraform init -no-color
- name: terraform validate
id: validate
run: terraform validate -no-color
- name: terraform plan
id: plan
run: terraform plan -no-color -input=false -lock=false -out=tfplan
continue-on-error: true
- name: terraform show
id: show
if: steps.plan.outcome == 'success'
run: terraform show -no-color tfplan
- name: Post plan to PR
if: github.event_name == 'pull_request' && always()
uses: actions/github-script@v7
env:
PLAN_STDOUT: ${{ steps.show.outputs.stdout }}
FMT_OUTCOME: ${{ steps.fmt.outcome }}
INIT_OUTCOME: ${{ steps.init.outcome }}
VALIDATE_OUTCOME: ${{ steps.validate.outcome }}
PLAN_OUTCOME: ${{ steps.plan.outcome }}
WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
with:
script: |
const fs = require('fs');
const MARKER = '<!-- terraform-bench-plan-comment -->';
const fmt = process.env.FMT_OUTCOME;
const init = process.env.INIT_OUTCOME;
const validate = process.env.VALIDATE_OUTCOME;
const plan = process.env.PLAN_OUTCOME;
const url = process.env.WORKFLOW_URL;
const icon = (outcome) => outcome === 'success' ? '✅' :
outcome === 'failure' ? '❌' :
outcome === 'skipped' ? '⏭️' : '⚠️';
let planBody = process.env.PLAN_STDOUT || '';
// GitHub PR comments cap at 65536 chars. Reserve ~1000 for surrounding text.
const MAX = 60000;
let truncated = false;
if (planBody.length > MAX) {
planBody = planBody.slice(-MAX);
truncated = true;
}
const body = [
MARKER,
'### terraform-bench plan',
'',
'| step | outcome |',
'| --- | --- |',
`| fmt | ${icon(fmt)} \`${fmt}\` |`,
`| init | ${icon(init)} \`${init}\` |`,
`| validate | ${icon(validate)} \`${validate}\` |`,
`| plan | ${icon(plan)} \`${plan}\` |`,
'',
fmt !== 'success' ? '> Run `terraform fmt -recursive` in `tests/benchmarks/cloudopsbench/infra/` to fix formatting.' : '',
'',
plan === 'success'
? `<details><summary>Plan output${truncated ? ' (truncated — see <a href="' + url + '">workflow logs</a> for full output)' : ''}</summary>\n\n\`\`\`hcl\n${planBody}\n\`\`\`\n\n</details>`
: `Plan did not run successfully — see [workflow logs](${url}) for details.`,
'',
`_Updated by [\`terraform-bench.yml\`](${url})._`,
].join('\n');
// Find an existing comment to update, else create a new one.
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body && c.body.includes(MARKER));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}
- name: Fail if any step errored
if: |
steps.fmt.outcome == 'failure' ||
steps.init.outcome == 'failure' ||
steps.validate.outcome == 'failure' ||
steps.plan.outcome == 'failure'
run: |
echo "::error::One or more terraform steps failed. See PR comment + workflow logs."
exit 1
# ---------------------------------------------------------------------- #
# Security + lint scanners — run in parallel with plan. #
# #
# Suppression policy (intentional skips) is defined per-tool: #
# - checkov: tests/benchmarks/cloudopsbench/infra/.checkov.yaml #
# - tfsec: tests/benchmarks/cloudopsbench/infra/.tfsec/config.yml #
# - tflint: tests/benchmarks/cloudopsbench/infra/.tflint.hcl #
# Each suppression includes a justification at the source. Day-one #
# findings should be REAL findings — change configs, not the workflow, #
# if a rule needs to be skipped. #
# #
# checkov + tfsec hard-fail (security blocks PRs). tflint soft-fails #
# because its rules cover code quality / deprecations, not security — #
# we want visibility without blocking. #
# ---------------------------------------------------------------------- #
tflint:
name: tflint
runs-on: ubuntu-latest
defaults:
run:
working-directory: tests/benchmarks/cloudopsbench/infra
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup tflint
uses: terraform-linters/setup-tflint@v4
with:
tflint_version: latest
- name: tflint --init (download plugins)
run: tflint --init
- name: tflint
id: tflint
run: tflint --recursive --format compact
continue-on-error: true
- name: Surface tflint findings (non-blocking)
if: steps.tflint.outcome == 'failure'
run: |
echo "::warning::tflint reported findings. Code-quality only — does not block PR. Review in workflow logs."
tfsec:
name: tfsec
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
# tfsec via Docker, bypassing aquasecurity/tfsec-action.
#
# Why direct Docker run: the action shells out to api.github.com to
# resolve the latest release binary, and the aquasecurity org has an
# IP allow list that blocks GitHub Actions runner IPs — making the
# action effectively unusable from CI. The aquasec/tfsec image on
# Docker Hub has no such restriction.
#
# Migration path (v2): tfsec is in maintenance mode; rule set lives on
# in Trivy. Replace with `aquasec/trivy:latest config /src` when
# ready — same .tfsec/config.yml is recognized.
#
# Suppressions: tests/benchmarks/cloudopsbench/infra/.tfsec/config.yml. tfsec exits 1 on any
# finding by default, which fails the step — exactly the hard-fail
# behavior we want. Add a justified exclude to the config rather
# than disabling the step.
- name: tfsec scan (via Docker)
run: |
docker run --rm \
-v "${{ github.workspace }}/tests/benchmarks/cloudopsbench/infra:/src" \
aquasec/tfsec:latest \
/src \
--config-file=/src/.tfsec/config.yml \
--no-color
checkov:
name: checkov
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
# Suppressions live in tests/benchmarks/cloudopsbench/infra/.checkov.yaml. soft_fail is
# FALSE — real findings block the PR. Add a justified skip-check
# to the config rather than disabling here.
- name: checkov scan
uses: bridgecrewio/checkov-action@v12
with:
directory: tests/benchmarks/cloudopsbench/infra
framework: terraform
config_file: tests/benchmarks/cloudopsbench/infra/.checkov.yaml
quiet: true
soft_fail: false
# Re-enable SARIF upload when CodeQL alerts are wanted:
# output_format: cli,sarif
# output_file_path: console,checkov-results.sarif