Context / Problem
Terraform for cluster/scaleway is currently applied and destroyed exclusively from a developer's
local machine via mise tasks. Moving apply/destroy into GitHub Actions enables repeatable, audited
operations — in particular an automatic nightly destroy at 16:00 UTC (18:00 CEST) to avoid idle
Scaleway billing, and a gated manual apply for controlled cluster startup.
Scope & Non-Goals
In scope:
terraform-apply.yml — manual only, gated behind a required-reviewer environment
terraform-destroy-manual.yml — manual, no gate
terraform-destroy-scheduled.yml — cron 0 16 * * *, fully automated, no gate
Non-goals: plan-only workflow, PR speculative plans, automatic re-apply after nightly destroy.
Acceptance Criteria
Design Notes
Gate only on apply: the scaleway GitHub Environment (with required reviewers) is referenced
exclusively by the apply workflow. Both destroy workflows are ungated — they pull credentials from
repo-level secrets (TF_SCW_ACCESS_KEY, TF_SCW_SECRET_KEY, TF_VAR_infisical_client_id,
TF_VAR_infisical_client_secret) so no environment protection rule can block them.
Credential naming: The existing SCW_ACCESS_KEY / SCW_SECRET_KEY (read-only, from
github-ci/) must NOT be reused here. The Terraform CI workflows use TF_SCW_ACCESS_KEY /
TF_SCW_SECRET_KEY (from the terraform-ci/ module — see dependency below). Both credential
pairs coexist in secrets but serve different purposes.
S3 backend in CI: AWS_DEFAULT_REGION=fr-par and
AWS_ENDPOINT_URL_S3=https://s3.fr-par.scw.cloud must be set explicitly — mise.toml injects
these locally but CI gets nothing for free.
Required-reviewer gate: requires GitHub paid plan (or public repo) for private repos. Without
it, the apply workflow still runs but the gate won't pause execution.
Cron timezone: 0 16 * * * UTC = 18:00 CEST (summer) / 17:00 CET (winter). GitHub Actions
cron does not support local timezones.
Tasks
1. Prerequisites (manual, before code)
2. Apply workflow
3. Manual destroy workflow
4. Scheduled destroy workflow
5. Validation
Dependencies
Requires #28 to be completed and secrets set before any workflow
can successfully authenticate to Scaleway and the S3 state backend.
Context / Problem
Terraform for
cluster/scalewayis currently applied and destroyed exclusively from a developer'slocal machine via
misetasks. Moving apply/destroy into GitHub Actions enables repeatable, auditedoperations — in particular an automatic nightly destroy at 16:00 UTC (18:00 CEST) to avoid idle
Scaleway billing, and a gated manual apply for controlled cluster startup.
Scope & Non-Goals
In scope:
terraform-apply.yml— manual only, gated behind a required-reviewer environmentterraform-destroy-manual.yml— manual, no gateterraform-destroy-scheduled.yml— cron0 16 * * *, fully automated, no gateNon-goals: plan-only workflow, PR speculative plans, automatic re-apply after nightly destroy.
Acceptance Criteria
.github/workflows/terraform-apply.yml—workflow_dispatchonly;environment: scaleway(with required reviewers configured on that environment); exposesnode_count(default1) andbootstrap_argocd(defaulttrue) as dispatch inputs; runsterraform init+terraform apply -auto-approveincluster/scaleway.github/workflows/terraform-destroy-manual.yml—workflow_dispatchonly, no environment gate; runsterraform init+terraform destroy -auto-approve; credentials from repo-level secrets.github/workflows/terraform-destroy-scheduled.yml—schedule: cron: '0 16 * * *'only (no dispatch), no gate; same credentials and commands as manual destroy; includes comment# 16:00 UTC = 18:00 CEST (summer) / 17:00 CET (winter)TF_SCW_ACCESS_KEY→SCW_ACCESS_KEY+AWS_ACCESS_KEY_ID;TF_SCW_SECRET_KEY→SCW_SECRET_KEY+AWS_SECRET_ACCESS_KEY;AWS_DEFAULT_REGION=fr-par;AWS_ENDPOINT_URL_S3=https://s3.fr-par.scw.cloudTF_VAR_infisical_client_id/TF_VAR_infisical_client_secretinjected for all three (needed whenbootstrap_argocd=true)hashicorp/setup-terraform@v3atterraform_version: "1.14"(matchingterraform-lock.yml)actionlintpasses on all three workflow filesDesign Notes
Gate only on apply: the
scalewayGitHub Environment (with required reviewers) is referencedexclusively by the apply workflow. Both destroy workflows are ungated — they pull credentials from
repo-level secrets (
TF_SCW_ACCESS_KEY,TF_SCW_SECRET_KEY,TF_VAR_infisical_client_id,TF_VAR_infisical_client_secret) so no environment protection rule can block them.Credential naming: The existing
SCW_ACCESS_KEY/SCW_SECRET_KEY(read-only, fromgithub-ci/) must NOT be reused here. The Terraform CI workflows useTF_SCW_ACCESS_KEY/TF_SCW_SECRET_KEY(from theterraform-ci/module — see dependency below). Both credentialpairs coexist in secrets but serve different purposes.
S3 backend in CI:
AWS_DEFAULT_REGION=fr-parandAWS_ENDPOINT_URL_S3=https://s3.fr-par.scw.cloudmust be set explicitly —mise.tomlinjectsthese locally but CI gets nothing for free.
Required-reviewer gate: requires GitHub paid plan (or public repo) for private repos. Without
it, the apply workflow still runs but the gate won't pause execution.
Cron timezone:
0 16 * * *UTC = 18:00 CEST (summer) / 17:00 CET (winter). GitHub Actionscron does not support local timezones.
Tasks
1. Prerequisites (manual, before code)
scalewayGitHub Environment with at least one required reviewer (for the apply gate)TF_SCW_ACCESS_KEY,TF_SCW_SECRET_KEY,TF_VAR_infisical_client_id,TF_VAR_infisical_client_secret(used by ungated destroy workflows); also setTF_SCW_ACCESS_KEY/TF_SCW_SECRET_KEYin thescalewayenvironment for the gated apply2. Apply workflow
.github/workflows/terraform-apply.ymlwithworkflow_dispatch+ inputsnode_count(default1),bootstrap_argocd(defaulttrue)environment: scalewayto the jobhashicorp/setup-terraform@v3step (pinned SHA,terraform_version: "1.14")terraform init+terraform apply -auto-approve -var node_count=... -var bootstrap_argocd=...permissions: contents: read; pin all action SHAs3. Manual destroy workflow
.github/workflows/terraform-destroy-manual.yml(workflow_dispatchonly, no environment block)terraform init+terraform destroy -auto-approvepermissions: contents: read; pin action SHAs4. Scheduled destroy workflow
.github/workflows/terraform-destroy-scheduled.yml(schedule: cron: '0 16 * * *'only)terraform init+terraform destroy -auto-approve5. Validation
actionlinton all three workflowsgh workflow run terraform-destroy-scheduled.yml)Dependencies
Requires #28 to be completed and secrets set before any workflow
can successfully authenticate to Scaleway and the S3 state backend.