Migrate the Terraform S3 backends off dynamodb_table onto use_lockfile and delete the lock tables
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 45/100
- Tipo de issue
- Refactorización
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- aws, terraform
- Área
- ci-cd, cloud, databases, devops, documentation, infrastructure
Línea de trabajo
Empieza con los archivos backend indicados en hackforla/incubator y hackforla/devops-security; después revisa tf-plan-scoped.json, CONTRIBUTING.md y la plantilla de issue de pre-work para encontrar todas las referencias a tablas de bloqueo. Ejecuta los planes de Terraform del repositorio e inspecciona los workflows de apply referenciados; detente si los cambios difieren de las expectativas indicadas. Se considera terminado cuando ambos apply no generan advertencias, la documentación y la policy están actualizadas, la plantilla se renderiza correctamente y ambas tablas de DynamoDB están registradas, eliminadas y se ha verificado que ya no existen.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Overview
We need to replace the deprecated dynamodb_table backend parameter with use_lockfile = true in hackforla/incubator and hackforla/devops-security, then delete the two now-unused DynamoDB lock tables, because HashiCorp deprecated DynamoDB-based state locking in Terraform 1.11 and will remove it in a future minor version. Both repos already run 1.16.1, so every plan and apply in both is printing the deprecation warning today.
Action Items
Facts verified 2026-09-07, so you do not have to re-derive them:
- The warning fires 3x per plan run and 4x per apply, in every run sampled in both repos back to 2026-08-08. It reads
Warning: Deprecated Parameter / The parameter "dynamodb_table" is deprecated. Use parameter "use_lockfile" instead.and points atbackend.tf line 7, which is misleading — that line is an emptybackend "s3" {}block. The parameter is interraform/prod.backend.tfvars, which the workflows pass asbackend_config_file. use_lockfilewent generally available in Terraform 1.11, in the same release that deprecated the DynamoDB arguments. Both repos resolverequired_version = "~> 1.16.0"to 1.16.1, so there is no version work.- No new IAM permission is needed. S3-native locking needs
s3:GetObject,s3:PutObjectands3:DeleteObjecton<key>.tflock. The apply roles (incubator-tf-apply,devops-security-tf-apply) holdAdministratorAccess. The plan roles never take a lock at all —dflook/terraform-planpasses-lock=falseunconditionally (image/entrypoints/plan.sh:15, checked at both the pinnedv1.49.0and atmain). That is also why the plan roles work today holding onlyReadOnlyAccessover DynamoDB. - Both state buckets (
hfla-incubator-terraform-state,hfla-ops-terraform-state) have versioning Enabled. - Both lock tables hold exactly one item and it is not a lock — it is the
…/terraform.tfstate-md5digest row. No lock is currently held in either. - Both tables have
DeletionProtectionEnabled: true, so deleting them is a two-call operation. Neither has point-in-time recovery. - These are the only two DynamoDB tables in account
035866691871. After step 3 the account has none.
1. hackforla/incubator — 1 PR, terraform/prod.backend.tfvars:
- Delete the
dynamodb_table = "hfla_incubator_terraform_table"line and adduse_lockfile = true. - Add a no-op comment line to any
.tffile in the same PR. Both workflows filter onpaths: ['**/*.tf', '**/*.yaml'], andprod.backend.tfvarsmatches neither pattern — so a PR that changes only the tfvars triggers no workflow at all, on the PR or on the merge. This is not optional: without it there is nothing to verify against and the merge produces no apply run. - Treat a non-empty plan as a hard gate. A backend change produces zero resource changes. If the plan shows any, stop and raise it rather than merging.
- After the PR merges, confirm the
Terraform apply (OIDC)run succeeds and that noDeprecated Parameterwarning appears anywhere in its log.
2. hackforla/devops-security — 1 PR. This one is bigger than incubator's, because three other things in this repo reference the lock table:
-
terraform/prod.backend.tfvars— deletedynamodb_table = "hfla_ops_terraform_table", adduse_lockfile = true. -
terraform/aws-custom-policies/tf-plan-scoped.json— delete the wholeAllowDynamoDBLockTableAccessForTerraformPlanstatement. This file is live:terraform/aws-custom-policies.tffeeds it tomodules/aws-policies, which deploys it as the IAM policyIncubatorTfPlanSecretsRead, currently attached to theincubator-tf-planrole. Leaving the statement would leave a live policy granting DynamoDB actions on a table that no longer exists.- Do not add
.tflockpermissions to replace it. The statement immediately above it already grantss3:PutObject/s3:DeleteObjectonarn:aws:s3:::hfla-ops-terraform-state/*, which covers the lock file — and the plan role does not lock anyway. - Do not "fix" the fact that a policy named
IncubatorTfPlanSecretsRead, attached to incubator's plan role, grants access to devops-security's backend. That cross-wiring predates this work. If it looks wrong to you, raise it as its own issue.
- Do not add
-
CONTRIBUTING.md— delete the#### Set up DynamoDB to store the backend statesection (lines 157–174, through the***afterBack to Top), and in the Creating Local tfvars file example (~line 251) swapdynamodb_table = "hfla_ops_terraform_table"foruse_lockfile = true. This is the section that tells every new member to create a lock table by hand. -
.github/ISSUE_TEMPLATE/pre-work-template-devops-security.md— delete the- [ ] Create the DynamoDB tablesub-item (line 40) and reword its parent (line 38) so it no longer promises a DynamoDB step. - Same no-op
.tfcomment requirement, and it is worse here: this repo's filter ispaths: ['**/*.tf']only, so.tfvars,.json,.mdand the issue template all fail to trigger it. - The plan gate is different in this repo. Expect exactly one change: an in-place update of
module.aws_custom_policies.aws_iam_policy.custom_policy["IncubatorTfPlanSecretsRead"], from the JSON edit. Anything else — any replacement, any second resource — is a stop-and-raise. - After the PR merges, confirm
Apply Terraform changes on mergesucceeds with noDeprecated Parameterwarning, and that the policy's new default version no longer contains the DynamoDB statement. - After the merge, re-open
/issues/new/chooseand confirm the pre-work template renders without the DynamoDB step. GitHub renders issue templates from the default branch only, so this genuinely cannot be checked from the branch.
3. Delete both tables — only after both PRs have merged and both apply runs are green:
-
Confirm no lock is held in either table.
aws dynamodb scan --table-name <table> --region us-west-2 --query 'Items[].LockID.S'must return only the-md5row. -
Record both table definitions in a comment on this issue before deleting, so the change is reversible without a PR trail to read. Capture
aws dynamodb describe-tableandaws dynamodb list-tags-of-resourcefor each. -
Disable deletion protection, then delete. Both calls need admin in
035866691871— if you do not have it, hand this step off rather than working around it.for t in hfla_incubator_terraform_table hfla_ops_terraform_table; do aws dynamodb update-table --table-name "$t" --region us-west-2 --no-deletion-protection-enabled aws dynamodb delete-table --table-name "$t" --region us-west-2 done -
Verify:
aws dynamodb list-tables --region us-west-2returns an empty list, and the next apply in each repo still succeeds. -
To reverse, recreate the table and re-enable protection. Terraform rewrites the
-md5digest row itself on the next apply, so the row does not need restoring.hfla_ops_terraform_tableadditionally carried tagsmanaged-by=exemptandproject=devops-security;hfla_incubator_terraform_tablecarried none.aws dynamodb create-table --table-name <table> --region us-west-2 \ --attribute-definitions AttributeName=LockID,AttributeType=S \ --key-schema AttributeName=LockID,KeyType=HASH \ --billing-mode PAY_PER_REQUEST aws dynamodb update-table --table-name <table> --region us-west-2 --deletion-protection-enabled
Do the backend swap in one step, not a two-phase migration — but know why:
- Terraform documents that
dynamodb_tableanduse_lockfilemay be set simultaneously, and that is the official migration path. Its only purpose is to keep two clients that disagree about the locking mechanism from both acquiring a lock. Since holding both keeps the deprecation warning firing, a phased migration means four PRs to clear a warning that two will clear. - The risk it covers is real but small here: while this is in flight, a
terraform applyfrom a local checkout that still hasdynamodb_tablewould not see a CI lock taken through S3, or vice versa. Mitigate by not running a local apply against either repo on the day the PRs merge, and by the lock check in step 3. - Note for anyone with an existing local checkout: CI initialises from a clean container every run, so there is no cached backend config and no migration prompt. A local
.terraform/directory will promptBackend configuration changedand needsterraform init -reconfigure.
Out of scope — do not do these here:
- Do not touch the action pins in these repos' workflows.
actions/checkout,aws-actions/configure-aws-credentialsanddflook/terraform-*belong to hackforla/devops#183, hackforla/incubator#158, hackforla/incubator#159 and hackforla/devops-security#170. - Do not tag or otherwise adopt the two state buckets.
hfla-incubator-terraform-stateis still untagged and still shows as unmanaged in the Terraform coverage report; that is separate work.
Resources/Instructions
- Files, all on
mainin both repos. Line numbers were accurate 2026-09-07 and may drift — locate each by its content rather than by position.hackforla/incubator:terraform/prod.backend.tfvarshackforla/devops-security:terraform/prod.backend.tfvars,terraform/aws-custom-policies/tf-plan-scoped.json,CONTRIBUTING.md,.github/ISSUE_TEMPLATE/pre-work-template-devops-security.md
- S3 backend documentation — the
use_lockfileargument, the statement that DynamoDB locking "is deprecated and will be removed in a future minor version", the simultaneous-configuration note, and the.tflockpermission list. - Terraform 1.11 CHANGELOG — "S3 native state locking is now generally available", the release that introduced the deprecation.
dflook/terraform-plan's-lock=falsebehaviour: image/entrypoints/plan.sh line 15.- Runs showing the warning, for comparison after the fix: incubator apply 34061802778, devops-security apply 34009820416.
- Lenguaje dominante
- PowerShell
- Estrellas
- 8
- Forks
- 10
- Merge medio
- 7 h 30 min
- PR fusionados (30 d)
- 22
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de hackforla/devops
-
Fix CONTRIBUTING.md's "Getting write access" section - it contradicts the fork bot and the wiki Abiertocomplexity: small feature: Onboarding good first issue role: DevOps Engineer size: 1pt
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
-
complexity: small feature: maintenance role: DevOps Engineer size: 1pt
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
-
complexity: small feature: maintenance role: DevOps Engineer size: 1pt
Dificultad 3/5 1-2 días Aptitud para principiantes 58/100
-
complexity: medium feature: security role: DevOps Engineer size: 3pt
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
-
complexity: large epic feature: project terraform setup role: DevOps Engineer size: 13+pt
Dificultad 5/5 Más de una semana Aptitud para principiantes 30/100
Todos los issues de hackforla/devops
Issues similares
-
task
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
vsanthanam/JBird#429 ·
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
alexgorbatchev/simple-ptt#14 ·
-
github-request
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
openedx/axim-engineering#1758 · 2 comentarios ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
components-web-app/docs#92 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100