Repository navigation
chore(cleanup): delete cmd/cleanup-lambda and its unused deploy modules - #1591
Conversation
cmd/cleanup-lambda deleted purchase_executions rows only when expires_at had lapsed, and no production path sets PurchaseExecution.TTL (the only writer of expires_at), so it never deleted an execution. None of its three deploy modules (compute/aws/cleanup-lambda, compute/gcp/cleanup-function, compute/azure/cleanup-function) is instantiated by any environment root, and no Dockerfile builds the binary the AWS module points at. The server's cleanup scheduled task (CleanupOldExecutions plus CleanupExpiredSessions) already covers retention with the live-status and health-score guards. Delete the command, its integration test, the three modules and the GCP module's source test; drop the module-specific cases from the Azure Key Vault and GCP Secret Manager guard tests, the three .trivyignore entries whose only source was those modules, and the .gitignore binary entry; repoint the docs, known_issues, CI and Terraform comments. Add TestPurchaseExecutionsDeletedOnlyByConfigStore, which fails if any non-test Go file outside internal/config deletes from or truncates purchase_executions, so retention cannot fork into a second job again. expires_at and its index stay; no migration. Closes LeanerCloud#357 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale:
Reviewer: rQ1. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale: none Reviewer: rQ2. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
|
Local verification at |
|
Merged by IAmJSD's agent at IAmJSD's request (IAmJSD is acting owner while the maintainers are away), under the bar IAmJSD set: 2 approving independent review(s) on |
Summary
Acting-owner decision on #357 (IAmJSD, 2026-10-29): delete
cmd/cleanup-lambdaand everything that exists only to build or deploy it.Root cause
cmd/cleanup-lambdadeletedpurchase_executionsrows only whenexpires_at < now(plus the terminal-status guard from #1173). The only writer ofexpires_atisSavePurchaseExecution, viatimeFromTTL(execution.TTL), and no production code path setsPurchaseExecution.TTL. So the column is NULL on every row current code writes, and the job never deleted an execution. It was also never deployed:compute/aws/cleanup-lambda,compute/gcp/cleanup-function,compute/azure/cleanup-function) is instantiated by any environment root.git grepfinds nomoduleblock that sources them./app/cleanup-lambdabinary the AWS module'simage_config.commandpoints at. The Dockerfile builds only./cmd/serverandmigrate.entry_point = "cleanupExpiredRecords"on ago121Cloud Function, and the Azure module POSTs{"dryRun": false}to a custom-handler Function App.cmd/cleanup-lambdais apackage mainthat callslambda.Start, so it could serve neither one.The in-app
cleanupscheduled task (handleCleanupExpiredRecords, which callsCleanupExpiredSessionsandCleanupOldExecutions(DefaultExecutionTTLDays)) already handles session and execution retention with the live-status and health-score guards. Every platform schedules it (see "Database Cleanup Jobs" indocs/DEPLOYMENT.md).What changed
Deleted:
cmd/cleanup-lambda/(main.go,main_integration_test.go)terraform/modules/compute/aws/cleanup-lambda/terraform/modules/compute/gcp/cleanup-function/: nothing consumes it, and it deploys the same dead job (the same{"dryRun": false}body andcleanupExpiredRecordsentry point), so it goes too.terraform/modules/compute/azure/cleanup-function/: the brief did not name this one. It is the Azure copy of the same dead path: no consumer, and it POSTs the same{"dryRun": false}CleanupEventbody to/api/cleanup. It is deleted on the same reasoning. If you want it kept, the module deletion reverts cleanly on its own.terraform/modules/compute/gcp/cleanup_function_source_test.go(it only read the deleted GCP module)References removed or repointed:
scripts/test-azure-kv-access-policy.shandscripts/test-gcp-secret-scope.sh: removed the cases that scanned the deleted modules. The AKS case and the default-scan-root cases still pin the #1621 and #1614 regressions. History comments inscripts/check-azure-kv-access-policy.sh,scripts/check-gcp-secret-scope.shand the access-policy fixture now say the module was deleted..trivyignore: removedAVD-AZU-0004,AVD-AZU-0012andGCP-0001. Each justification named only the deleted modules, andgit grepfinds no otherazurerm_*function_app,azurerm_storage_accountorgoogle_storage_bucketresource underterraform/oriac/..gitignore: removed thecleanup-lambdabinary entry.docs/DEPLOYMENT.md: removed the module from the tree and the two "not consumed by any environment" notes.known_issues/33_*.mdandknown_issues/35_*.md: added chore(pkg/cmd): medium/low findings from the 2026-07-28 full review [platform part] #357 amendment/update notes. Neither file moves toresolved/, because 35 still has the open feat(plans): settle a failed-with-submission row so a managed plan can be deleted #999 entry and 33 tracks fix(iac): several scheduled tasks are not scheduled; delayed purchases never fire on GCP/Azure #712.internal/config/store_postgres.go(CleanupOldExecutionsdoc comment) andstore_postgres_retention_integration_test.go: comments only..github/workflows/ci.yml(shard-timing comment) andterraform/environments/aws/ci-cd-permissions/policy_boundary.tf: comments only. The role list in the boundary comment no longer names the cleanup Lambda role. It now says five EventBridge invoker roles, which matches the module tree, so the total stays twelve.CHANGELOG.md: added an entry under Unreleased "Removed".Added:
internal/config/purchase_executions_delete_guard_test.go:TestPurchaseExecutionsDeletedOnlyByConfigStorefails if any non-test Go file underinternal/orcmd/outsideinternal/confighas a string literal that deletes from or truncatespurchase_executions. Retention can't drift into a second job again.TestPurchaseExecutionsDeletesMatcherpins what the matcher flags, so a broken matcher can't turn the guard into a silent pass. Like the existingTestNoUnscopedRecommendationsDelete, it checks one literal at a time.Kept: everything in
internal/that the in-app task uses.CleanupOldExecutionsis unchanged.expires_at(column kept, no migration)purchase_executions.expires_atandidx_purchase_executions_expires_atstay. Code that still reads it:CleanupOldExecutionsbranch 3 (expires_at IS NOT NULL AND expires_at < NOW() - retention, with the status allowlist)GetPendingExecutions(AND (expires_at IS NULL OR expires_at > NOW()))exec.TTL = ttlFromTime(expiresAt.Time)) and every executionSELECTcolumn listSavePurchaseExecutionfromPurchaseExecution.TTL, which no production path setsLegacy or imported rows can still carry non-NULL values, which is why these readers stay. Dropping the column or the
TTLfield would be a separate decision with its own migration.Terraform: what the next apply destroys
No environment root in this repo instantiates any of the three modules, so applying
terraform/environments/{aws,gcp,azure}destroys nothing and plans are unchanged. Only an out-of-tree root that sourced one of these module paths directly would lose resources on its nextinit/apply. For completeness:compute/aws/cleanup-lambda:aws_iam_role.cleanup(<stack>-cleanup-lambda),aws_iam_role_policy_attachment.cleanup_basic,aws_iam_role_policy_attachment.cleanup_vpc,aws_iam_role_policy.cleanup_secrets,aws_cloudwatch_log_group.cleanup(/aws/lambda/<stack>-cleanup),aws_lambda_function.cleanup,aws_cloudwatch_event_rule.cleanup_schedule,aws_cloudwatch_event_target.cleanup,aws_lambda_permission.cleanup_eventbridge,aws_cloudwatch_metric_alarm.cleanup_errorscompute/gcp/cleanup-function:google_service_account.cleanup,google_secret_manager_secret_iam_member.cleanup_db_password,google_cloudfunctions2_function.cleanup,google_storage_bucket.function_source(force_destroy = false, so a destroy fails until the bucket is emptied),google_cloud_scheduler_job.cleanup,google_cloudfunctions2_function_iam_member.cleanup_invokercompute/azure/cleanup-function:azurerm_storage_account.cleanup,azurerm_service_plan.cleanup,azurerm_user_assigned_identity.cleanup,azurerm_role_assignment.cleanup_kv_secrets_user,azurerm_linux_function_app.cleanup,azurerm_logic_app_workflow.cleanup_trigger,azurerm_logic_app_trigger_recurrence.cleanup,azurerm_logic_app_action_http.cleanupCloses #357
Verification
All of the following is local unit, guard-script and Terraform-static evidence. Nothing was planned, applied or deployed.
Fail-before (guard test added on an untouched tree, before any deletion):
Pass-after (same command after the deletion): both PASS, as does
TestNoUnscopedRecommendationsDelete.Mutation probe: with the
internal/configskip removed from the walk, the guard flagsinternal/config/store_postgres.go:2391(the real multi-lineCleanupOldExecutionsDELETE). That shows the scanner sees real store SQL and that the skip is what scopes it. The probe was reverted.Other commands (with
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null AWS_EC2_METADATA_DISABLED=true):go build ./...,go vet ./...,go vet -tags integration ./...: all OKgo mod tidy -diff: no diff (aws-lambda-gois still used bycmd/lambda)go test -count=1on./internal/config/,./terraform/modules/compute/{aws,gcp,azure}/,./terraform/environments/aws/ci-cd-permissions/(boundary/policy guards that walk every AWS module) and./internal/mocks/: all okgo test -tags integration -count=1 -run 'TestRampRetention_OldCleanupWritersPreserveHeldRows' ./internal/config/(only its comment changed): PASS on real Postgres (testcontainers)golangci-lint run --allow-parallel-runners ./internal/config/with and without--build-tags integration: 0 issuesgocyclo -over 10 -ignore "_test\.go" internal/config/store_postgres.go: no findings (comment-only change)shellcheckon the four touched scripts: clean.bash scripts/test-azure-kv-access-policy.sh: 25 passed, 0 failed.bash scripts/test-gcp-secret-scope.sh: 59 passed, 0 failed. Bothcheck-*.shexit 0 on the default scan roots.terraform fmt -checkplusterraform init -backend=falseandterraform validateonterraform/environments/aws/ci-cd-permissions(comment change): valid.terraform fmt -check -recursive terraform/modules/compute: clean.Not run locally:
actionlint(not installed; theci.ymlchange is a YAML comment) andtrivy config(not installed). The three removed.trivyignoreIDs have no remaining source resource bygit grep, but the pre-commit Trivy hook is the real check.Combined-tree verification. Tested on a local, never-pushed tree:
queue/platform@594ac3ec= origin/mainae6854b3plus:Linux, Go 1.26.9,
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null AWS_EC2_METADATA_DISABLED=true; Docker Postgres via testcontainers.go build ./...,go vet ./...,go vet -tags integration ./...and the fullgo test -race -short -count=1 ./....--build-tags integration.gocyclo -over 10is silent on the changed non-test files.-tags integration -count=1, one package at a time):internal/api,internal/auth,internal/config,internal/scheduler,internal/serverandinternal/testutilpass.scripts/test-git-secrets-allowlist.shpasses.Out of scope
expires_at, its index andPurchaseExecution.TTLstay (see above).CleanupOldExecutionsis unchanged.docs/audits/codebase-audit-2026-09-02.mdstill mentions the modules. It is a verbatim historical audit record and is left as is.RATE_LIMIT_DOMAINLIKE wildcards) was already handled by fix(clear-rate-limit): match RATE_LIMIT_DOMAIN literally in the LIKE pattern #1272, and the terminal-status guard landed in fix(cleanup): only delete settled executions when their TTL lapses #1173. This PR finishes the remaining MEDIUM item.Maintainers: please mirror the issue's triage labels onto this PR:
impact/internal,effort/l,type/chore,triaged,priority/p3,severity/low,urgency/eventually.🤖 Generated with Claude Code