diff --git a/.github/workflows/cleanup-staging.yml b/.github/workflows/cleanup-staging.yml index 52f4e641b..1b43786ad 100644 --- a/.github/workflows/cleanup-staging.yml +++ b/.github/workflows/cleanup-staging.yml @@ -77,8 +77,18 @@ jobs: - name: Force-delete all staging ECR repos run: | for REPO in $(aws ecr describe-repositories \ - --query "repositories[?starts_with(repositoryName,'cudly-staging') || repositoryName=='cudly'].repositoryName" \ + --query "repositories[?starts_with(repositoryName,'cudly-staging')].repositoryName" \ --output text 2>/dev/null); do + # Defense in depth: refuse anything outside the staging naming + # pattern (in particular the bare 'cudly' prod-adjacent repo) + # even if the query filter above is ever loosened. + case "$REPO" in + cudly-staging*) ;; + *) + echo "Refusing to delete non-staging ECR repo '$REPO'; staging cleanup only deletes cudly-staging* repos" + exit 1 + ;; + esac echo "Force-deleting ECR repo $REPO..." aws ecr delete-repository --repository-name "$REPO" --force 2>/dev/null \ || echo " Failed to delete $REPO (may already be gone)" @@ -137,8 +147,18 @@ jobs: - name: Force-delete all staging ECR repos run: | for REPO in $(aws ecr describe-repositories \ - --query "repositories[?starts_with(repositoryName,'cudly-staging') || repositoryName=='cudly'].repositoryName" \ + --query "repositories[?starts_with(repositoryName,'cudly-staging')].repositoryName" \ --output text 2>/dev/null); do + # Defense in depth: refuse anything outside the staging naming + # pattern (in particular the bare 'cudly' prod-adjacent repo) + # even if the query filter above is ever loosened. + case "$REPO" in + cudly-staging*) ;; + *) + echo "Refusing to delete non-staging ECR repo '$REPO'; staging cleanup only deletes cudly-staging* repos" + exit 1 + ;; + esac echo "Force-deleting ECR repo $REPO..." aws ecr delete-repository --repository-name "$REPO" --force 2>/dev/null \ || echo " Failed to delete $REPO (may already be gone)" diff --git a/.github/workflows/rollback.yml b/.github/workflows/rollback.yml index 500a47263..73066541a 100644 --- a/.github/workflows/rollback.yml +++ b/.github/workflows/rollback.yml @@ -58,6 +58,8 @@ jobs: - name: Validate inputs id: check + env: + ECR_REPOSITORY: ${{ vars.ECR_REPOSITORY }} run: | IS_VALID=true IMAGE_URI="" @@ -71,7 +73,12 @@ jobs: # Construct image URI based on cloud provider case "${{ inputs.cloud }}" in aws-lambda|aws-fargate) - IMAGE_URI="${{ vars.AWS_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION || 'us-east-1' }}.amazonaws.com/${{ vars.ECR_REPOSITORY || 'cudly' }}:${{ inputs.image_tag }}" + if [ -z "$ECR_REPOSITORY" ]; then + echo "❌ ECR_REPOSITORY repository variable is not set; refusing to guess the repo name" + IS_VALID=false + else + IMAGE_URI="${{ vars.AWS_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION || 'us-east-1' }}.amazonaws.com/${ECR_REPOSITORY}:${{ inputs.image_tag }}" + fi ;; gcp) IMAGE_URI="${{ vars.GCP_REGION || 'us-central1' }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/${{ vars.ARTIFACT_REGISTRY_REPO || 'cudly' }}/cudly:${{ inputs.image_tag }}" @@ -127,7 +134,12 @@ jobs: if: startsWith(inputs.cloud, 'aws') run: | IMAGE_TAG="${{ inputs.image_tag }}" - REPO="${{ vars.ECR_REPOSITORY || 'cudly' }}" + REPO="${{ vars.ECR_REPOSITORY }}" + + if [ -z "$REPO" ]; then + echo "❌ ECR_REPOSITORY repository variable is not set" + exit 1 + fi echo "Checking if image exists: $REPO:$IMAGE_TAG"