Skip to content

Terraform — Scaleway cluster #33

Terraform — Scaleway cluster

Terraform — Scaleway cluster #33

Workflow file for this run

name: Terraform — Scaleway cluster
# Drives 02-cluster/scaleway through the .github/actions/terraform composite action:
# - pull_request → plan
# - push to main → apply
# - schedule (daily 18h) → destroy (cost-control teardown of the homelab)
# - workflow_dispatch → up/down on demand (plan | apply | destroy)
#
# State R/W + lock uses the org state role (vars.AWS_TF_STATE_ROLE_ARN —
# AmazonS3FullAccess, see 01-iam/ci-managed/aws-state-access). Scaleway cluster
# lifecycle uses the CI API key from the `scaleway` environment (Kubernetes/VPC/
# PrivateNetwork FullAccess, see 01-iam/bootstrap/scaleway). Provider creds are set as job env (read by the
# action) — never passed as plain action inputs. No static AWS keys.
on:
pull_request:
paths:
- '02-cluster/scaleway/**'
- '.github/actions/terraform/**'
- '.github/workflows/scaleway.yml'
push:
branches: [main]
paths:
- '02-cluster/scaleway/**'
- '.github/actions/terraform/**'
- '.github/workflows/scaleway.yml'
schedule:
# 16:00 UTC = 18:00 Europe/Paris in summer (CEST). GitHub cron is UTC and does
# NOT follow DST, so in winter (CET) this fires at 17:00 Paris.
- cron: '0 16 * * *'
workflow_dispatch:
inputs:
command:
description: 'Terraform command (apply = up, destroy = down).'
type: choice
options: [plan, apply, destroy]
default: plan
concurrency:
# Serialize everything that writes this root's state (apply/destroy never cancel
# mid-flight); only cancel superseded PR plans. schedule/push share ref=main.
group: scaleway-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
terraform:
runs-on: ubuntu-latest
timeout-minutes: 20
# The `scaleway` environment carries SCW_ACCESS_KEY / SCW_SECRET_KEY (and
# satisfies zizmor's secrets-in-environment audit). It currently has no
# protection rule, so the daily scheduled destroy runs unattended — keep it
# that way (a required-reviewer rule would block the cron).
environment: scaleway
permissions:
id-token: write # mint OIDC tokens for AWS + Infisical
contents: read
# Provider creds exposed to the composite action via the job env (not inputs).
env:
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 }}
INFISICAL_MACHINE_IDENTITY_ID: ${{ vars.INFISICAL_MACHINE_IDENTITY_ID }}
steps:
- name: Assert state role ARN is present
env:
ROLE_ARN: ${{ vars.AWS_TF_STATE_ROLE_ARN }}
run: |
if [ -z "$ROLE_ARN" ]; then
echo "::error::vars.AWS_TF_STATE_ROLE_ARN is not set (provisioned by 01-iam/ci-managed/aws-state-access)."
exit 1
fi
- name: Resolve terraform command
id: cmd
env:
EVENT: ${{ github.event_name }}
DISPATCH_CMD: ${{ github.event.inputs.command }}
run: |
case "$EVENT" in
schedule) cmd=destroy ;;
push) cmd=apply ;;
workflow_dispatch) cmd="${DISPATCH_CMD:-plan}" ;;
*) cmd=plan ;;
esac
echo "command=$cmd" >> "$GITHUB_OUTPUT"
echo "Resolved terraform command: $cmd (event: $EVENT)"
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 1
- uses: ./.github/actions/terraform
with:
root: 02-cluster/scaleway
tfvars-file: 02-cluster-staging.tfvars
command: ${{ steps.cmd.outputs.command }}
aws-role-arn: ${{ vars.AWS_TF_STATE_ROLE_ARN }}