Skip to content

fix(ci): look up only the owned ECR repo in the destroy cleanup - #484

Merged
cristim merged 1 commit into
mainfrom
fix/483-ecr-destroy-script
Oct 5, 2026
Merged

cristim merged 1 commit into
mainfrom
fix/483-ecr-destroy-script

Conversation

@cristim

@cristim cristim commented Oct 4, 2026

Copy link
Copy Markdown
Member

Summary

scripts/force-delete-owned-ecr-repo.sh now looks up only the owned ECR repository (describe-repositories --repository-names "$OWNED_REPO") instead of listing the whole account.

Why

A DescribeRepositories call without --repository-names is authorized against repository/*. The deploy role's ECR grant (terraform/environments/aws/ci-cd-permissions/policy_compute.tf, ECRRepositoryScoped) covers only arn:aws:ecr:*:*:repository/cudly-*, so destroy-fargate-dev.yml failed with AccessDeniedException on run 37244760348 before the filter ran.

Change

  • Look up the repository by name. RepositoryNotFoundException means it is already gone: the script prints a message and exits 0. Any other error prints the AWS message and exits with the AWS CLI's exit code. Nothing uses || true.
  • The response still goes through select-owned-name.sh, so the exact-name check is unchanged and the existing wiring and sweep assertions still apply. select-owned-name.sh itself is not modified; the RDS and Cloud SQL scripts also call it.
  • New behaviour tests in scripts/test-ecr-delete-selection.sh stub terraform and aws. The aws stub denies the list-all form the same way the role does, and covers these cases: repo found (exactly the owned repo is deleted), a different name returned (nothing deleted), RepositoryNotFoundException (exit 0), another error (non-zero, AWS message on stderr), and a failed delete (non-zero).

Tests

Pre-fix (new tests against the parent script): passed: 50, failed: 6, exit 1:

FAIL: behaviour: the owned repository is looked up by name, not by listing the account
      exit 254, stderr: An error occurred (AccessDeniedException) when calling the DescribeRepositories operation: ... not authorized to perform: ecr:DescribeRepositories on resource: arn:aws:ecr:us-east-1:111111111111:repository/*
FAIL: behaviour: exactly the owned repository is force-deleted
FAIL: behaviour: a returned name other than the owned one is not deleted
FAIL: behaviour: RepositoryNotFoundException exits 0 and deletes nothing
FAIL: behaviour: the already-deleted case says so
FAIL: behaviour: the lookup error's AWS message reaches stderr

Post-fix: bash scripts/test-ecr-delete-selection.sh -> passed: 56, failed: 0. bash scripts/test-rds-deletion-protection-scope.sh -> passed: 53, failed: 0.

Verification

  • shellcheck -x scripts/force-delete-owned-ecr-repo.sh: clean. The test file still has its one existing SC2016 info and no new findings.
  • Sibling pre-destroy steps:
    • disable-owned-rds-deletion-protection.sh also lists all instances (rds describe-db-instances), but rds:DescribeDBInstances is granted on * in policy_data.tf (RDSDescribeAccountWide), so that call is not denied. Left unchanged.
    • delete-owned-cloud-sql-instance.sh is GCP. Its permissions come from project-level IAM, not AWS ARN scoping. Left unchanged.
    • destroy-fargate-dev.yml and cleanup-staging.yml make no other AWS list calls.
  • No live destroy was run.

🤖 Generated with claude-flow

force-delete-owned-ecr-repo.sh listed every repository in the account and
filtered for the owned one. A list-all DescribeRepositories is authorized
against repository/*, and the deploy role's ECR grant covers only
repository/cudly-*, so every real destroy failed with AccessDenied before
the filter ran.

Ask for the owned repository by name instead. RepositoryNotFoundException
means it is already gone and exits 0; any other error fails with the AWS
CLI's exit code. The response still passes through select-owned-name.sh,
so only the owned repository can be deleted.

The new behaviour tests stub aws to deny the list-all form, as the role
does.

Closes #483
@coderabbitai

coderabbitai Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 2 billable files and costs up to $0.50.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Or wait 8 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 76 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: LeanerCloud/cloud-commitments-platform/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: a89cffad-d261-4298-9f50-809438f747a0
📥 Commits

Reviewing files that changed from the base of the PR and between cab5817 and 73de13a.

📒 Files selected for processing (2)
  • scripts/force-delete-owned-ecr-repo.sh
  • scripts/test-ecr-delete-selection.sh
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cristim cristim added type/bug Defect severity/medium Moderate harm urgency/this-sprint Within the current sprint impact/internal Team-internal only effort/xs Trivial / one-liner priority/p2 Backlog-worthy triaged Item has been triaged labels Oct 5, 2026
@cristim
cristim merged commit a11cacc into main Oct 5, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/xs Trivial / one-liner impact/internal Team-internal only priority/p2 Backlog-worthy severity/medium Moderate harm triaged Item has been triaged type/bug Defect urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant