From eb86c30e2e58f1874e2cfbcf8523f809028e0097 Mon Sep 17 00:00:00 2001 From: Alexander Amiri Date: Mon, 16 Mar 2026 20:49:39 +0100 Subject: [PATCH] Reduce CI plan output verbosity and merge PR comments - run-plan.sh: Filter state refresh/read noise from CI log, write clean output to plan-clean.txt alongside the full plan-output.txt - post-plan-comment.sh: Use filtered output for PR comment, extract Plan summary line as header, append LLM review into the same comment - Remove post-review-comment.sh (merged into plan comment) - Reorder workflow steps: run LLM review before posting PR comment so both plan and review appear in a single notification --- .github/workflows/platform-ci.yml | 15 ++++-------- .github/workflows/tf-plan.yml | 15 ++++-------- scripts/post-plan-comment.sh | 40 ++++++++++++++++++++++++++----- scripts/post-review-comment.sh | 19 --------------- scripts/run-plan.sh | 7 +++++- 5 files changed, 48 insertions(+), 48 deletions(-) delete mode 100644 scripts/post-review-comment.sh diff --git a/.github/workflows/platform-ci.yml b/.github/workflows/platform-ci.yml index fa22973..60d177d 100644 --- a/.github/workflows/platform-ci.yml +++ b/.github/workflows/platform-ci.yml @@ -104,15 +104,8 @@ jobs: path: ${{ env.TF_ROOT }}/lambdas/builds/ retention-days: 1 - - name: Post plan to PR - if: github.event_name == 'pull_request' && steps.changes.outputs.has_infra_changes == 'true' - env: - GH_TOKEN: ${{ github.token }} - PR_NUMBER: ${{ github.event.pull_request.number }} - run: sh scripts/post-plan-comment.sh "${{ env.TF_ROOT }}/plan-output.txt" "${{ steps.plan.outputs.has_changes }}" - # ---------------------------------------------------------------- - # LLM Plan Review (inline — plan-output.txt already in workspace) + # LLM Plan Review (runs before PR comment so both are combined) # ---------------------------------------------------------------- - name: Run LLM review id: review @@ -121,12 +114,12 @@ jobs: REVIEW_RESULT_PATH: review-result.json run: sh scripts/extract-review-risk.sh scripts/review-plan.py "${{ env.TF_ROOT }}/plan-output.txt" - - name: Post review to PR - if: github.event_name == 'pull_request' && steps.plan.outputs.has_changes == 'true' + - name: Post plan + review to PR + if: github.event_name == 'pull_request' && steps.changes.outputs.has_infra_changes == 'true' env: GH_TOKEN: ${{ github.token }} PR_NUMBER: ${{ github.event.pull_request.number }} - run: sh scripts/post-review-comment.sh + run: sh scripts/post-plan-comment.sh "${{ env.TF_ROOT }}/plan-output.txt" "${{ steps.plan.outputs.has_changes }}" - name: Post HIGH risk to Slack if: steps.review.outputs.risk_level == 'HIGH' && github.ref == 'refs/heads/main' diff --git a/.github/workflows/tf-plan.yml b/.github/workflows/tf-plan.yml index cb27b6c..7eb0ccd 100644 --- a/.github/workflows/tf-plan.yml +++ b/.github/workflows/tf-plan.yml @@ -98,15 +98,8 @@ jobs: if: steps.plan.outputs.has_changes == 'true' run: .platform/scripts/upload-plan.sh "${{ inputs.tf_root }}" - - name: Post plan to PR - if: github.event_name == 'pull_request' - env: - GH_TOKEN: ${{ github.token }} - PR_NUMBER: ${{ github.event.pull_request.number }} - run: sh .platform/scripts/post-plan-comment.sh "${{ inputs.tf_root }}/plan-output.txt" "${{ steps.plan.outputs.has_changes }}" - # ---------------------------------------------------------------- - # LLM Plan Review (runs in same job — plan-output.txt already here) + # LLM Plan Review (runs before PR comment so both are combined) # ---------------------------------------------------------------- - name: Run LLM review id: review @@ -122,12 +115,12 @@ jobs: echo '{"level":"${{ steps.review.outputs.risk_level }}","reviewed_at":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}' | \ aws s3 cp - "s3://${PLAN_BUCKET}/${PLAN_DIR}/risk.json" --content-type application/json - - name: Post review to PR - if: github.event_name == 'pull_request' && steps.plan.outputs.has_changes == 'true' + - name: Post plan + review to PR + if: github.event_name == 'pull_request' env: GH_TOKEN: ${{ github.token }} PR_NUMBER: ${{ github.event.pull_request.number }} - run: sh .platform/scripts/post-review-comment.sh + run: sh .platform/scripts/post-plan-comment.sh "${{ inputs.tf_root }}/plan-output.txt" "${{ steps.plan.outputs.has_changes }}" - name: Alert Slack on HIGH risk if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.review.outputs.risk_level == 'HIGH' diff --git a/scripts/post-plan-comment.sh b/scripts/post-plan-comment.sh index 70580d3..424844f 100644 --- a/scripts/post-plan-comment.sh +++ b/scripts/post-plan-comment.sh @@ -1,8 +1,11 @@ #!/bin/sh -# Post terraform plan output as a PR comment. +# Post terraform plan + LLM review as a single PR comment. # # Usage: post-plan-comment.sh # +# If review-output.txt exists in the current directory, it is appended +# to the comment. This avoids posting two separate comments. +# # Env: GH_TOKEN (or gh auth), GITHUB_REPOSITORY, PR_NUMBER set -e @@ -10,15 +13,27 @@ set -e PLAN_FILE="$1" HAS_CHANGES="$2" +# --- Extract plan summary line (e.g. "Plan: 5 to add, 2 to change, 0 to destroy") --- +SUMMARY=$(grep -E '^(Plan:|No changes\.)' "$PLAN_FILE" 2>/dev/null | head -1) +[ -z "$SUMMARY" ] && SUMMARY="See plan output below." + if [ "$HAS_CHANGES" = "true" ]; then - STATUS="**Changes detected** — review required." + STATUS=":construction: **Changes detected** — ${SUMMARY}" else - STATUS="**No changes** — infrastructure is up to date." + STATUS=":white_check_mark: **No changes** — infrastructure is up to date." fi -PLAN=$(head -c 60000 "$PLAN_FILE" 2>/dev/null || echo "Plan output not available.") +# --- Filter plan: strip refresh/read noise, keep only the meaningful diff --- +PLAN_CLEAN_FILE="$(dirname "$PLAN_FILE")/plan-clean.txt" +if [ -f "$PLAN_CLEAN_FILE" ]; then + PLAN=$(head -c 60000 "$PLAN_CLEAN_FILE") +else + # Fallback: filter inline + PLAN=$(grep -v -E '^(module\.|data\.|\s+#).*: (Refreshing state|Reading|Read complete)' "$PLAN_FILE" 2>/dev/null | head -c 60000) +fi -cat > /tmp/plan-comment.md < /tmp/plan-comment.md < -EOF +ENDOFCOMMENT + +# --- Append LLM review if available --- +if [ -f review-output.txt ]; then + REVIEW=$(cat review-output.txt) + cat >> /tmp/plan-comment.md </dev/null || echo "LLM review output not available.") - -cat > /tmp/review-comment.md </tfplan # Human-readable output is written to /plan-output.txt +# A filtered version (no refresh noise) is written to /plan-clean.txt set -uo pipefail @@ -28,7 +29,11 @@ terraform plan -out=tfplan -detailed-exitcode -no-color "${EXTRA_ARGS[@]}" > pla PLAN_EXIT=$? set -e -cat plan-output.txt +# Create filtered output: strip state refresh and data source read lines +grep -v -E '^(module\.|data\.|\s+#).*: (Refreshing state|Reading|Read complete)' plan-output.txt > plan-clean.txt || true + +# Print only the clean output to the CI log (not hundreds of refresh lines) +cat plan-clean.txt if [ "$PLAN_EXIT" = "1" ]; then echo "Terraform plan failed"