Skip to content

refactor: reorganize terraform roots by domain (strata-prefixed) #43

refactor: reorganize terraform roots by domain (strata-prefixed)

refactor: reorganize terraform roots by domain (strata-prefixed) #43

Workflow file for this run

name: Scaleway Plan (via s3-lister role)
# Plans cluster/scaleway using the org-wide s3-lister IAM role, assumed DIRECTLY
# via GitHub OIDC — no static AWS keys, and no routing through the bootstrap CI
# role (that role exists only to create/update roles, not to power pipelines).
#
# The s3-lister role is READ-ONLY on S3, which shapes the whole job:
# - state is read but never written -> plan only, never apply
# - the S3-native lock can't be written -> -lock=false
# - the workspace already exists in S3 -> select it via TF_WORKSPACE;
# never `terraform workspace new` (a write the read-only role can't do)
# - bootstrap_argocd=false -> skip the Infisical data source
# and the in-cluster helm/kubernetes providers (no cluster, no secrets in CI)
#
# Scaleway API access for the refresh still uses the static SCW key from secrets
# (Scaleway is not an OIDC relying party) — same creds as scaleway-auth-check.yml.
on:
pull_request:
paths:
- '02-cluster/scaleway/**'
- '01-iam/aws/**'
- '.github/workflows/scaleway-plan.yml'
workflow_dispatch:
permissions:
contents: read
id-token: write # This is required for requesting the JWT
jobs:
plan:
runs-on: ubuntu-latest
# Scope SCW secret usage to a dedicated environment (matches
# scaleway-auth-check.yml; satisfies zizmor's secrets-outside-env audit).
environment: scaleway
permissions:
id-token: write # mint the OIDC token exchanged for temporary AWS creds
contents: read
env:
INFISICAL_MACHINE_IDENTITY_ID: ${{ vars.INFISICAL_MACHINE_IDENTITY_ID }}
# Scaleway provider creds for the refresh. Keys are secrets; the public
# org/project IDs are repo variables (not secrets).
SCW_ACCESS_KEY: ${{ secrets.SCW_ACCESS_KEY }}
SCW_SECRET_KEY: ${{ secrets.SCW_SECRET_KEY }}
SCW_DEFAULT_ORGANIZATION_ID: ${{ vars.SCW_DEFAULT_ORGANIZATION_ID }}
SCW_DEFAULT_PROJECT_ID: ${{ vars.SCW_DEFAULT_PROJECT_ID }}
# The infisical provider authenticates eagerly even with bootstrap_argocd
# off (the gated data source still pulls the provider into the graph), so
# it needs to configure successfully — here via keyless GitHub-OIDC (see
# the "Mint Infisical OIDC token" step). With bootstrap_argocd=false no
# secret is actually read.
steps:
# Fail fast and clearly if creds/vars aren't set, instead of letting the
# tooling emit a confusing assume-role or provider auth error.
- name: Assert credentials are present
env:
ROLE_ARN: ${{ vars.AWS_S3_LISTER_ROLE_ARN }}
run: |
if [ -z "$ROLE_ARN" ]; then
echo "::error::vars.AWS_S3_LISTER_ROLE_ARN is not set. Set it to the s3-lister role ARN (provisioned by state/10-access)."
exit 1
fi
if [ -z "$SCW_ACCESS_KEY" ] || [ -z "$SCW_SECRET_KEY" ]; then
echo "::error::SCW_ACCESS_KEY and/or SCW_SECRET_KEY are not set (see ci/10-scaleway/README.md)."
exit 1
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
with:
# Keep in sync with mise.toml [tools] terraform version.
terraform_version: "1.14"
# Direct OIDC -> s3-lister. Works because the role's trust now includes a
# GitHub-OIDC statement scoped org-wide (repo:IntegratedDynamic/*).
- name: Assume the s3-lister role via OIDC
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1
with:
role-to-assume: ${{ vars.AWS_S3_LISTER_ROLE_ARN }}
aws-region: eu-west-3
# Mint a GitHub OIDC JWT for the Infisical machine identity and stash it in
# $INFISICAL_AUTH_JWT (the provider's default token env var). audience must
# match the identity's boundAudiences. This is the keyless counterpart to
# the universal-auth client_id/secret used locally — no static Infisical
# secret in CI. core.getIDToken is the official @actions/core way to mint
# the token (it masks the value automatically).
- name: Mint Infisical OIDC token
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const jwt = await core.getIDToken('https://github.com/IntegratedDynamic')
core.exportVariable('INFISICAL_AUTH_JWT', jwt)
- name: Terraform plan (read-only role -> no lock, no apply)
env:
TF_CHDIR: "02-cluster/scaleway/"
TF_ENVIRONMENT: "02-cluster-staging.tfvars"
run: |
set -euo pipefail
terraform -chdir="${TF_CHDIR}" init -input=false
terraform -chdir="${TF_CHDIR}" workspace select "${TF_ENVIRONMENT%.*}"
terraform -chdir="${TF_CHDIR}" destroy -auto-approve -input=false -var-file="env/${TF_ENVIRONMENT}"