Applying the change
Exact commands and workflow names for each platform. See SKILL.md for the checklist of where to make each change; this file is how to make it take effect.
Terraform
Two workflows in bewith-dev/IAC-Terraform, one per account. Both are workflow_dispatch only, with no push or pull_request trigger, so merging the PR applies nothing:
| Workflow | Root it prepends | Account / region | Serves |
|---|---|---|---|
Terraform - Dev - Infrastructure (terraform-dev-infrastructure.yaml) | environments/dev/infrastructure/ | 440238706581 / eu-west-1 | IR staging |
Terraform - Prod - Infrastructure (terraform-prod-infrastructure.yaml) | environments/production/infrastructure/ | 890742586475 / us-east-1 | US production |
Two inputs, identical in both:
| Input | Type | Meaning |
|---|---|---|
project_path | string, required | Path relative to that workflow's root — 9.sqs/9.13.app-push, never the full path. One project per run; there is no "apply everything". |
apply | boolean, default false | false runs terraform plan and stops. true runs plan then terraform apply -auto-approve. |
gh workflow run "Terraform - Dev - Infrastructure" --repo bewith-dev/IAC-Terraform \
--ref <branch-or-main> -f project_path=9.sqs/9.13.app-push -f apply=false
gh run list --repo bewith-dev/IAC-Terraform --limit 1 # then: gh run watch <id> --exit-status
--ref accepts a feature branch, and with apply=false the run is read-only — so plan before the PR is even reviewed and paste the result in. Expect Plan: 1 to add, 0 to change, 0 to destroy; re-plan on main after merge to confirm nothing drifted, then dispatch again with apply=true and look for Apply complete! Resources: 1 added. The queue URL appears in the apply log as the resource id.
The run name encodes what you asked for — Terraform dev infra - 9.sqs/9.13.app-push , Apply - true — so check it before assuming a run applied anything. A production apply is Hard-Floor: a human dispatches it.
Both workflows guard the path before running: a nonexistent project_path, a directory with no .tf files, or a missing variables file fails early. Those guard steps echo their own ❌ Error: text into the collapsed ##[group]Run block as part of the script source, cyan-highlighted, whether or not they fire — a real failure repeats the message after ##[endgroup] and the step goes red.
EKS env var
Merging the values is not enough. The shared config reaches pods through envFrom: configMapRef with no checksum annotation, so ArgoCD updates the ConfigMap and the running pods keep their old environment until a rollout restart: kubectl rollout restart deployment/<service> -n <namespace> against the affected cluster, once ArgoCD reports Synced.
ECS
No IaC, so the queue's shape is not written down anywhere. Copy a live sibling instead of composing attributes from scratch:
aws sqs list-queues --region eu-central-1 # what the siblings are really called
aws sqs get-queue-attributes --region eu-central-1 --attribute-names All \
--queue-url $(aws sqs get-queue-url --region eu-central-1 --queue-name smsQueueDEV.fifo --query QueueUrl --output text)
Mirror that attribute set, changing only the name. Two traps: All also returns read-only attributes (QueueArn, CreatedTimestamp, LastModifiedTimestamp, ApproximateNumberOf*) that create-queue rejects — and create-queue today defaults to MaximumMessageSize 1MB with SqsManagedSseEnabled on, while every sibling predates those defaults and sits at 256KB with SSE off. Pass both explicitly or the new queue silently differs:
aws sqs create-queue --region eu-central-1 --queue-name appPushQueueDEV.fifo \
--attributes '{"FifoQueue":"true","ContentBasedDeduplication":"true","MessageRetentionPeriod":"1209600","MaximumMessageSize":"262144","SqsManagedSseEnabled":"false"}'
Then diff the result against the sibling, excluding QueueArn, the timestamps, the ApproximateNumberOf* counters and Policy. Anything left is drift you introduced.
The env files live in s3://coing-ecs-files/, referenced from each task definition's containerDefinitions[0].environmentFiles. A queue URL belongs in two files per environment, because the producer and the consumer are separate services:
| File | Read by |
|---|---|
backend-service-libs/{dev,prod}/services/.env | every backend-services service — this is where the AWS_*_QUEUE_URL block lives |
backend-service-libs/{dev,prod}/hosts/.env | the same services' RPC hostnames — no queue URLs here |
sqs-consumer/{dev,prod}/.env | the consumer that polls the queue; it keeps its own copy of every queue URL |
superco-consumer/{dev,prod}/.env, service-*/{dev,prod}/.env | one-off per-service files, frontends mostly; queues rarely reach them |
dev is FR staging, prod is FR production. Overwriting an env file is a click-ops edit to a live environment with no review and no PR, so back it up first — the convention already in the bucket is a sibling .env.bak-<YYYYMMDDHHMMSS>:
aws s3 cp s3://coing-ecs-files/sqs-consumer/dev/.env "s3://coing-ecs-files/sqs-consumer/dev/.env.bak-$(date +%Y%m%d%H%M%S)"
aws s3 cp s3://coing-ecs-files/sqs-consumer/dev/.env ./x.env # edit, keeping the AWS_*_QUEUE_URL block together
aws s3 cp ./x.env s3://coing-ecs-files/sqs-consumer/dev/.env
aws s3 cp s3://coing-ecs-files/sqs-consumer/dev/.env - | diff ./x.env - # confirm the upload
Env files are read when a task starts, so a new variable costs nothing until the next deploy. Force one only when running code already needs it:
aws ecs update-service --cluster <cluster> --service service-sqs-consumer --force-new-deployment --region eu-central-1
One account (356419207885) holds both FR environments, told apart only by a -prod suffix on the family, container and log group. One aws login reaches production, and one forgotten suffix changes it. Do staging first, verify, then production.