diff --git a/.github/workflows/plan-review.yml b/.github/workflows/plan-review.yml index bd0da40..f6ba776 100644 --- a/.github/workflows/plan-review.yml +++ b/.github/workflows/plan-review.yml @@ -66,38 +66,10 @@ jobs: - name: Post review to PR if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - let review = ''; - try { - review = fs.readFileSync('review-output.txt', 'utf8'); - } catch (e) { - review = 'LLM review output not available.'; - } - let resultJson = {}; - try { - resultJson = JSON.parse(fs.readFileSync('review-result.json', 'utf8')); - } catch (e) { - resultJson = {risk: 'FAILED'}; - } - const riskEmoji = {LOW: '\u{1F7E2}', MEDIUM: '\u{1F7E1}', HIGH: '\u{1F534}', FAILED: '\u26AA'}[resultJson.risk] || '\u26AA'; - - const body = [ - '## LLM Plan Review', - '', - `**Risk: ${riskEmoji} ${resultJson.risk}**`, - '', - review - ].join('\n'); - - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body - }); + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: sh platform/scripts/post-review-comment.sh - 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/.github/workflows/platform-ci.yml b/.github/workflows/platform-ci.yml index c897032..f32a518 100644 --- a/.github/workflows/platform-ci.yml +++ b/.github/workflows/platform-ci.yml @@ -90,43 +90,10 @@ jobs: - name: Post plan to PR if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - const planPath = '${{ env.TF_ROOT }}/plan-output.txt'; - let plan = ''; - try { - plan = fs.readFileSync(planPath, 'utf8'); - } catch (e) { - plan = 'Plan output not available.'; - } - // Truncate to fit GitHub comment limits - if (plan.length > 60000) { - plan = plan.substring(0, 60000) + '\n\n... (truncated)'; - } - const hasChanges = '${{ steps.plan.outputs.has_changes }}' === 'true'; - const status = hasChanges ? '**Changes detected** — review required.' : '**No changes** — infrastructure is up to date.'; - const body = [ - '## Terraform Plan', - '', - status, - '', - '
Plan output', - '', - '```', - plan, - '```', - '', - '
' - ].join('\n'); - - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body - }); + 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 }}" # -------------------------------------------------------------------------- # Review — LLM risk analysis via Bedrock @@ -158,38 +125,10 @@ jobs: - name: Post review to PR if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - let review = ''; - try { - review = fs.readFileSync('review-output.txt', 'utf8'); - } catch (e) { - review = 'LLM review output not available.'; - } - let resultJson = {}; - try { - resultJson = JSON.parse(fs.readFileSync('review-result.json', 'utf8')); - } catch (e) { - resultJson = {risk: 'FAILED'}; - } - const riskEmoji = {LOW: '🟢', MEDIUM: '🟡', HIGH: '🔴', FAILED: '⚪'}[resultJson.risk] || '⚪'; - - const body = [ - '## 🧠 LLM Plan Review', - '', - `**Risk: ${riskEmoji} ${resultJson.risk}**`, - '', - review - ].join('\n'); - - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body - }); + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: sh scripts/post-review-comment.sh - 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 4a0264d..5e24654 100644 --- a/.github/workflows/tf-plan.yml +++ b/.github/workflows/tf-plan.yml @@ -106,41 +106,7 @@ jobs: - name: Post plan to PR if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - const planPath = '${{ inputs.tf_root }}/plan-output.txt'; - let plan = ''; - try { - plan = fs.readFileSync(planPath, 'utf8'); - } catch (e) { - plan = 'Plan output not available.'; - } - if (plan.length > 60000) { - plan = plan.substring(0, 60000) + '\n\n... (truncated)'; - } - const hasChanges = '${{ steps.plan.outputs.has_changes }}' === 'true'; - const status = hasChanges - ? '**Changes detected** — review required.' - : '**No changes** — infrastructure is up to date.'; - const body = [ - '## Terraform Plan', - '', - status, - '', - '
Plan output', - '', - '```', - plan, - '```', - '', - '
' - ].join('\n'); - - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body - }); + 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 }}" diff --git a/scripts/post-plan-comment.sh b/scripts/post-plan-comment.sh new file mode 100644 index 0000000..70580d3 --- /dev/null +++ b/scripts/post-plan-comment.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# Post terraform plan output as a PR comment. +# +# Usage: post-plan-comment.sh +# +# Env: GH_TOKEN (or gh auth), GITHUB_REPOSITORY, PR_NUMBER + +set -e + +PLAN_FILE="$1" +HAS_CHANGES="$2" + +if [ "$HAS_CHANGES" = "true" ]; then + STATUS="**Changes detected** — review required." +else + STATUS="**No changes** — infrastructure is up to date." +fi + +PLAN=$(head -c 60000 "$PLAN_FILE" 2>/dev/null || echo "Plan output not available.") + +cat > /tmp/plan-comment.md <Plan output + +\`\`\` +${PLAN} +\`\`\` + + +EOF + +gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --body-file /tmp/plan-comment.md diff --git a/scripts/post-review-comment.sh b/scripts/post-review-comment.sh new file mode 100644 index 0000000..605ab7e --- /dev/null +++ b/scripts/post-review-comment.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# Post LLM review result as a PR comment. +# +# Usage: post-review-comment.sh +# +# Reads review-result.json and review-output.txt from current directory. +# Env: GH_TOKEN (or gh auth), GITHUB_REPOSITORY, PR_NUMBER + +set -e + +RISK=$(jq -r '.risk // "FAILED"' review-result.json 2>/dev/null || echo "FAILED") +REVIEW=$(cat review-output.txt 2>/dev/null || echo "LLM review output not available.") + +case "$RISK" in + LOW) EMOJI="🟢" ;; + MEDIUM) EMOJI="🟡" ;; + HIGH) EMOJI="🔴" ;; + *) EMOJI="⚪" ;; +esac + +cat > /tmp/review-comment.md <