@@ -24,7 +24,6 @@ permissions:
2424 contents : read
2525
2626env :
27- GO_VERSION : ' 1.21'
2827 MISE_VERSION : ' 2025.12.10'
2928 COMMON_EXCLUDES : >-
3029 --exclude-resource-type iam
4039 --exclude-resource-type config-rules
4140 --exclude-resource-type nat-gateway
4241 --exclude-resource-type ec2-subnet
43- ALL_REGIONS : >-
44- ap-northeast-1 ap-northeast-2 ap-northeast-3
45- ap-south-1 ap-southeast-1 ap-southeast-2
46- ca-central-1 eu-central-1 eu-north-1
47- eu-west-1 eu-west-2 eu-west-3
48- me-central-1 sa-east-1
49- us-east-1 us-east-2 us-west-1 us-west-2
5042
5143jobs :
5244 # ============================================
5648 name : " PhxDevOps: Global"
5749 runs-on : ubuntu-latest
5850 timeout-minutes : 30
51+ outputs :
52+ deleted_count : ${{ steps.nuke.outputs.deleted_count }}
53+ error_count : ${{ steps.nuke.outputs.error_count }}
5954 if : |
6055 github.event_name == 'push' ||
6156 github.event_name == 'workflow_dispatch' && (inputs.account == 'phxdevops' || inputs.account == '') ||
@@ -81,16 +76,30 @@ jobs:
8176 restore-keys : ${{ runner.os }}-go-
8277 - run : go mod download
8378 - name : Nuke global resources
79+ id : nuke
8480 run : |
81+ set +e
8582 go run -ldflags="-X 'main.VERSION=${{ github.sha }}'" main.go aws \
8683 --older-than 2h --force --config ./.github/nuke_config.yml \
8784 --region global ${{ env.COMMON_EXCLUDES }} \
88- --delete-unaliased-kms-keys --log-level info
85+ --delete-unaliased-kms-keys --log-level info 2>&1 | tee /tmp/nuke.log
86+ EXIT_CODE=${PIPESTATUS[0]}
87+
88+ # Parse output for counts
89+ DELETED=$(grep -c "^\s*INFO\s*\[Deleted\]" /tmp/nuke.log || echo "0")
90+ ERRORS=$(grep -c "^\s*ERROR\s*\[Failed\]" /tmp/nuke.log || echo "0")
91+ echo "deleted_count=${DELETED}" >> $GITHUB_OUTPUT
92+ echo "error_count=${ERRORS}" >> $GITHUB_OUTPUT
93+
94+ exit $EXIT_CODE
8995
9096 phxdevops_regional :
9197 name : " PhxDevOps: ${{ matrix.region }}"
9298 runs-on : ubuntu-latest
9399 timeout-minutes : 20
100+ outputs :
101+ deleted_count : ${{ steps.nuke.outputs.deleted_count }}
102+ error_count : ${{ steps.nuke.outputs.error_count }}
94103 if : |
95104 github.event_name == 'push' ||
96105 github.event_name == 'workflow_dispatch' && (inputs.account == 'phxdevops' || inputs.account == '') ||
@@ -120,11 +129,28 @@ jobs:
120129 restore-keys : ${{ runner.os }}-go-
121130 - run : go mod download
122131 - name : Nuke ${{ matrix.region }}
132+ id : nuke
123133 run : |
134+ set +e
124135 go run -ldflags="-X 'main.VERSION=${{ github.sha }}'" main.go aws \
125136 --older-than 2h --force --config ./.github/nuke_config.yml \
126137 --region ${{ matrix.region }} ${{ env.COMMON_EXCLUDES }} \
127- --delete-unaliased-kms-keys --log-level info
138+ --delete-unaliased-kms-keys --log-level info 2>&1 | tee /tmp/nuke.log
139+ EXIT_CODE=${PIPESTATUS[0]}
140+
141+ DELETED=$(grep -c "^\s*INFO\s*\[Deleted\]" /tmp/nuke.log || echo "0")
142+ ERRORS=$(grep -c "^\s*ERROR\s*\[Failed\]" /tmp/nuke.log || echo "0")
143+ echo "deleted_count=${DELETED}" >> $GITHUB_OUTPUT
144+ echo "error_count=${ERRORS}" >> $GITHUB_OUTPUT
145+
146+ exit $EXIT_CODE
147+ - name : Upload results
148+ if : always()
149+ uses : actions/upload-artifact@v4
150+ with :
151+ name : phxdevops-${{ matrix.region }}
152+ path : /tmp/nuke.log
153+ retention-days : 7
128154
129155 phxdevops_notify :
130156 name : " PhxDevOps: Notify"
@@ -141,12 +167,32 @@ jobs:
141167 with :
142168 role-to-assume : arn:aws:iam::087285199408:role/cloud-nuke-gha
143169 aws-region : us-east-1
144- - name : Send Slack notification
170+ - name : Download all artifacts
171+ uses : actions/download-artifact@v4
172+ with :
173+ pattern : phxdevops-*
174+ path : /tmp/logs
175+ merge-multiple : true
176+ continue-on-error : true
177+ - name : Aggregate and notify
145178 run : |
146179 WEBHOOK_URL=$(aws secretsmanager get-secret-value \
147180 --secret-id cloud-nuke/slack-webhook \
148181 --query SecretString --output text)
149182
183+ # Aggregate counts from all logs
184+ TOTAL_DELETED=0
185+ TOTAL_ERRORS=0
186+ if [ -d /tmp/logs ]; then
187+ TOTAL_DELETED=$(grep -rh "^\s*INFO\s*\[Deleted\]" /tmp/logs 2>/dev/null | wc -l || echo "0")
188+ TOTAL_ERRORS=$(grep -rh "^\s*ERROR\s*\[Failed\]" /tmp/logs 2>/dev/null | wc -l || echo "0")
189+ fi
190+ # Add global counts
191+ GLOBAL_DELETED="${{ needs.phxdevops_global.outputs.deleted_count }}"
192+ GLOBAL_ERRORS="${{ needs.phxdevops_global.outputs.error_count }}"
193+ TOTAL_DELETED=$((TOTAL_DELETED + ${GLOBAL_DELETED:-0}))
194+ TOTAL_ERRORS=$((TOTAL_ERRORS + ${GLOBAL_ERRORS:-0}))
195+
150196 if [ "${{ needs.phxdevops_global.result }}" == "success" ] && \
151197 [ "${{ needs.phxdevops_regional.result }}" == "success" ]; then
152198 STATUS="✅ Success"
@@ -156,6 +202,14 @@ jobs:
156202 COLOR="danger"
157203 fi
158204
205+ # Build message
206+ MSG="*PhxDevOps Nuke*: ${STATUS}"
207+ MSG="${MSG}\nDeleted: ${TOTAL_DELETED} resources"
208+ if [ "$TOTAL_ERRORS" -gt 0 ]; then
209+ MSG="${MSG} | Errors: ${TOTAL_ERRORS}"
210+ fi
211+ MSG="${MSG}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>"
212+
159213 curl -sS -X POST "$WEBHOOK_URL" -H "Content-Type: application/json" -d @- <<EOF
160214 {
161215 "attachments": [{
@@ -164,7 +218,7 @@ jobs:
164218 "type": "section",
165219 "text": {
166220 "type": "mrkdwn",
167- "text": "*PhxDevOps Nuke*: ${STATUS}\nGlobal: ${{ needs.phxdevops_global.result }} | Regional: ${{ needs.phxdevops_regional.result }}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run> "
221+ "text": "${MSG} "
168222 }
169223 }]
170224 }]
@@ -178,6 +232,9 @@ jobs:
178232 name : " ConfigTests: Global"
179233 runs-on : ubuntu-latest
180234 timeout-minutes : 30
235+ outputs :
236+ deleted_count : ${{ steps.nuke.outputs.deleted_count }}
237+ error_count : ${{ steps.nuke.outputs.error_count }}
181238 if : |
182239 github.event_name == 'workflow_dispatch' && (inputs.account == 'configtests' || inputs.account == '') ||
183240 github.event_name == 'schedule' && github.event.schedule == '0 */3 * * *'
@@ -202,12 +259,22 @@ jobs:
202259 restore-keys : ${{ runner.os }}-go-
203260 - run : go mod download
204261 - name : Nuke global resources
262+ id : nuke
205263 run : |
264+ set +e
206265 go run -ldflags="-X 'main.VERSION=${{ github.sha }}'" main.go aws \
207266 --older-than 2h --force --config ./.github/nuke_config.yml \
208267 --region global ${{ env.COMMON_EXCLUDES }} \
209268 --exclude-resource-type internet-gateway \
210- --delete-unaliased-kms-keys --log-level info
269+ --delete-unaliased-kms-keys --log-level info 2>&1 | tee /tmp/nuke.log
270+ EXIT_CODE=${PIPESTATUS[0]}
271+
272+ DELETED=$(grep -c "^\s*INFO\s*\[Deleted\]" /tmp/nuke.log || echo "0")
273+ ERRORS=$(grep -c "^\s*ERROR\s*\[Failed\]" /tmp/nuke.log || echo "0")
274+ echo "deleted_count=${DELETED}" >> $GITHUB_OUTPUT
275+ echo "error_count=${ERRORS}" >> $GITHUB_OUTPUT
276+
277+ exit $EXIT_CODE
211278
212279 configtests_regional :
213280 name : " ConfigTests: ${{ matrix.region }}"
@@ -241,12 +308,29 @@ jobs:
241308 restore-keys : ${{ runner.os }}-go-
242309 - run : go mod download
243310 - name : Nuke ${{ matrix.region }}
311+ id : nuke
244312 run : |
313+ set +e
245314 go run -ldflags="-X 'main.VERSION=${{ github.sha }}'" main.go aws \
246315 --older-than 2h --force --config ./.github/nuke_config.yml \
247316 --region ${{ matrix.region }} ${{ env.COMMON_EXCLUDES }} \
248317 --exclude-resource-type internet-gateway \
249- --delete-unaliased-kms-keys --log-level info
318+ --delete-unaliased-kms-keys --log-level info 2>&1 | tee /tmp/nuke.log
319+ EXIT_CODE=${PIPESTATUS[0]}
320+
321+ DELETED=$(grep -c "^\s*INFO\s*\[Deleted\]" /tmp/nuke.log || echo "0")
322+ ERRORS=$(grep -c "^\s*ERROR\s*\[Failed\]" /tmp/nuke.log || echo "0")
323+ echo "deleted_count=${DELETED}" >> $GITHUB_OUTPUT
324+ echo "error_count=${ERRORS}" >> $GITHUB_OUTPUT
325+
326+ exit $EXIT_CODE
327+ - name : Upload results
328+ if : always()
329+ uses : actions/upload-artifact@v4
330+ with :
331+ name : configtests-${{ matrix.region }}
332+ path : /tmp/nuke.log
333+ retention-days : 7
250334
251335 configtests_notify :
252336 name : " ConfigTests: Notify"
@@ -262,12 +346,30 @@ jobs:
262346 with :
263347 role-to-assume : arn:aws:iam::087285199408:role/cloud-nuke-gha
264348 aws-region : us-east-1
265- - name : Send Slack notification
349+ - name : Download all artifacts
350+ uses : actions/download-artifact@v4
351+ with :
352+ pattern : configtests-*
353+ path : /tmp/logs
354+ merge-multiple : true
355+ continue-on-error : true
356+ - name : Aggregate and notify
266357 run : |
267358 WEBHOOK_URL=$(aws secretsmanager get-secret-value \
268359 --secret-id cloud-nuke/slack-webhook \
269360 --query SecretString --output text)
270361
362+ TOTAL_DELETED=0
363+ TOTAL_ERRORS=0
364+ if [ -d /tmp/logs ]; then
365+ TOTAL_DELETED=$(grep -rh "^\s*INFO\s*\[Deleted\]" /tmp/logs 2>/dev/null | wc -l || echo "0")
366+ TOTAL_ERRORS=$(grep -rh "^\s*ERROR\s*\[Failed\]" /tmp/logs 2>/dev/null | wc -l || echo "0")
367+ fi
368+ GLOBAL_DELETED="${{ needs.configtests_global.outputs.deleted_count }}"
369+ GLOBAL_ERRORS="${{ needs.configtests_global.outputs.error_count }}"
370+ TOTAL_DELETED=$((TOTAL_DELETED + ${GLOBAL_DELETED:-0}))
371+ TOTAL_ERRORS=$((TOTAL_ERRORS + ${GLOBAL_ERRORS:-0}))
372+
271373 if [ "${{ needs.configtests_global.result }}" == "success" ] && \
272374 [ "${{ needs.configtests_regional.result }}" == "success" ]; then
273375 STATUS="✅ Success"
@@ -277,6 +379,13 @@ jobs:
277379 COLOR="danger"
278380 fi
279381
382+ MSG="*ConfigTests Nuke*: ${STATUS}"
383+ MSG="${MSG}\nDeleted: ${TOTAL_DELETED} resources"
384+ if [ "$TOTAL_ERRORS" -gt 0 ]; then
385+ MSG="${MSG} | Errors: ${TOTAL_ERRORS}"
386+ fi
387+ MSG="${MSG}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>"
388+
280389 curl -sS -X POST "$WEBHOOK_URL" -H "Content-Type: application/json" -d @- <<EOF
281390 {
282391 "attachments": [{
@@ -285,7 +394,7 @@ jobs:
285394 "type": "section",
286395 "text": {
287396 "type": "mrkdwn",
288- "text": "*ConfigTests Nuke*: ${STATUS}\nGlobal: ${{ needs.configtests_global.result }} | Regional: ${{ needs.configtests_regional.result }}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run> "
397+ "text": "${MSG} "
289398 }
290399 }]
291400 }]
@@ -299,6 +408,9 @@ jobs:
299408 name : " Sandbox: Global"
300409 runs-on : ubuntu-latest
301410 timeout-minutes : 30
411+ outputs :
412+ deleted_count : ${{ steps.nuke.outputs.deleted_count }}
413+ error_count : ${{ steps.nuke.outputs.error_count }}
302414 if : |
303415 github.event_name == 'workflow_dispatch' && (inputs.account == 'sandbox' || inputs.account == '') ||
304416 github.event_name == 'schedule' && github.event.schedule == '0 0 * * *'
@@ -323,12 +435,22 @@ jobs:
323435 restore-keys : ${{ runner.os }}-go-
324436 - run : go mod download
325437 - name : Nuke global resources
438+ id : nuke
326439 run : |
440+ set +e
327441 go run -ldflags="-X 'main.VERSION=${{ github.sha }}'" main.go aws \
328442 --older-than 24h --force --config ./.github/nuke_config.yml \
329443 --region global ${{ env.COMMON_EXCLUDES }} \
330444 --exclude-resource-type eip \
331- --delete-unaliased-kms-keys --log-level info
445+ --delete-unaliased-kms-keys --log-level info 2>&1 | tee /tmp/nuke.log
446+ EXIT_CODE=${PIPESTATUS[0]}
447+
448+ DELETED=$(grep -c "^\s*INFO\s*\[Deleted\]" /tmp/nuke.log || echo "0")
449+ ERRORS=$(grep -c "^\s*ERROR\s*\[Failed\]" /tmp/nuke.log || echo "0")
450+ echo "deleted_count=${DELETED}" >> $GITHUB_OUTPUT
451+ echo "error_count=${ERRORS}" >> $GITHUB_OUTPUT
452+
453+ exit $EXIT_CODE
332454
333455 sandbox_regional :
334456 name : " Sandbox: ${{ matrix.region }}"
@@ -362,12 +484,29 @@ jobs:
362484 restore-keys : ${{ runner.os }}-go-
363485 - run : go mod download
364486 - name : Nuke ${{ matrix.region }}
487+ id : nuke
365488 run : |
489+ set +e
366490 go run -ldflags="-X 'main.VERSION=${{ github.sha }}'" main.go aws \
367491 --older-than 24h --force --config ./.github/nuke_config.yml \
368492 --region ${{ matrix.region }} ${{ env.COMMON_EXCLUDES }} \
369493 --exclude-resource-type eip \
370- --delete-unaliased-kms-keys --log-level info
494+ --delete-unaliased-kms-keys --log-level info 2>&1 | tee /tmp/nuke.log
495+ EXIT_CODE=${PIPESTATUS[0]}
496+
497+ DELETED=$(grep -c "^\s*INFO\s*\[Deleted\]" /tmp/nuke.log || echo "0")
498+ ERRORS=$(grep -c "^\s*ERROR\s*\[Failed\]" /tmp/nuke.log || echo "0")
499+ echo "deleted_count=${DELETED}" >> $GITHUB_OUTPUT
500+ echo "error_count=${ERRORS}" >> $GITHUB_OUTPUT
501+
502+ exit $EXIT_CODE
503+ - name : Upload results
504+ if : always()
505+ uses : actions/upload-artifact@v4
506+ with :
507+ name : sandbox-${{ matrix.region }}
508+ path : /tmp/nuke.log
509+ retention-days : 7
371510
372511 sandbox_notify :
373512 name : " Sandbox: Notify"
@@ -383,12 +522,30 @@ jobs:
383522 with :
384523 role-to-assume : arn:aws:iam::087285199408:role/cloud-nuke-gha
385524 aws-region : us-east-1
386- - name : Send Slack notification
525+ - name : Download all artifacts
526+ uses : actions/download-artifact@v4
527+ with :
528+ pattern : sandbox-*
529+ path : /tmp/logs
530+ merge-multiple : true
531+ continue-on-error : true
532+ - name : Aggregate and notify
387533 run : |
388534 WEBHOOK_URL=$(aws secretsmanager get-secret-value \
389535 --secret-id cloud-nuke/slack-webhook \
390536 --query SecretString --output text)
391537
538+ TOTAL_DELETED=0
539+ TOTAL_ERRORS=0
540+ if [ -d /tmp/logs ]; then
541+ TOTAL_DELETED=$(grep -rh "^\s*INFO\s*\[Deleted\]" /tmp/logs 2>/dev/null | wc -l || echo "0")
542+ TOTAL_ERRORS=$(grep -rh "^\s*ERROR\s*\[Failed\]" /tmp/logs 2>/dev/null | wc -l || echo "0")
543+ fi
544+ GLOBAL_DELETED="${{ needs.sandbox_global.outputs.deleted_count }}"
545+ GLOBAL_ERRORS="${{ needs.sandbox_global.outputs.error_count }}"
546+ TOTAL_DELETED=$((TOTAL_DELETED + ${GLOBAL_DELETED:-0}))
547+ TOTAL_ERRORS=$((TOTAL_ERRORS + ${GLOBAL_ERRORS:-0}))
548+
392549 if [ "${{ needs.sandbox_global.result }}" == "success" ] && \
393550 [ "${{ needs.sandbox_regional.result }}" == "success" ]; then
394551 STATUS="✅ Success"
@@ -398,6 +555,13 @@ jobs:
398555 COLOR="danger"
399556 fi
400557
558+ MSG="*Sandbox Nuke*: ${STATUS}"
559+ MSG="${MSG}\nDeleted: ${TOTAL_DELETED} resources"
560+ if [ "$TOTAL_ERRORS" -gt 0 ]; then
561+ MSG="${MSG} | Errors: ${TOTAL_ERRORS}"
562+ fi
563+ MSG="${MSG}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>"
564+
401565 curl -sS -X POST "$WEBHOOK_URL" -H "Content-Type: application/json" -d @- <<EOF
402566 {
403567 "attachments": [{
@@ -406,7 +570,7 @@ jobs:
406570 "type": "section",
407571 "text": {
408572 "type": "mrkdwn",
409- "text": "*Sandbox Nuke*: ${STATUS}\nGlobal: ${{ needs.sandbox_global.result }} | Regional: ${{ needs.sandbox_regional.result }}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run> "
573+ "text": "${MSG} "
410574 }
411575 }]
412576 }]
0 commit comments