diff --git a/.github/workflows/aws-cdk.yml b/.github/workflows/aws-cdk.yml index 601acb0..f609d10 100644 --- a/.github/workflows/aws-cdk.yml +++ b/.github/workflows/aws-cdk.yml @@ -412,6 +412,7 @@ jobs: permissions: id-token: write contents: read + pull-requests: write environment: ${{ inputs.github-environment }} outputs: stack-outputs: ${{ steps.deploy.outputs.stack-outputs }} @@ -584,6 +585,79 @@ jobs: path: deployment-diff.txt retention-days: 7 + - name: Post diff to PR comment + if: inputs.diff == true && github.event_name == 'pull_request' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 + env: + STACK_NAME: ${{ needs.prepare.outputs.stack-name }} + ENVIRONMENT: ${{ inputs.github-environment }} + HAS_CHANGES: ${{ steps.diff-analysis.outputs.has-changes }} + with: + script: | + const fs = require('fs'); + const stackName = process.env.STACK_NAME; + const environment = process.env.ENVIRONMENT; + const hasChanges = process.env.HAS_CHANGES === 'true'; + + const commentHeader = `CDK Diff: ${stackName}`; + const { owner, repo } = context.repo; + const issue_number = context.issue.number; + + let diffContent = ''; + try { + diffContent = fs.readFileSync('deployment-diff.txt', 'utf8').trim(); + } catch (e) { + diffContent = 'No diff output available'; + } + + const statusIcon = hasChanges ? '⚠️' : '✅'; + const statusText = hasChanges ? 'Infrastructure changes detected' : 'No infrastructure changes detected'; + + const lines = [ + `## ${commentHeader}`, + '', + `${statusIcon} **${statusText}**`, + '', + `**Stack:** \`${stackName}\``, + ]; + + if (environment) { + lines.push(`**Environment:** ${environment}`); + } + + lines.push( + '', + '
', + 'Full diff', + '', + '```', + diffContent, + '```', + '', + '
' + ); + + const commentBody = lines.join('\n'); + + const comments = await github.rest.issues.listComments({ + owner, repo, issue_number, + }); + + const botComment = comments.data.find(comment => + comment.user.type === 'Bot' && + comment.body.includes(commentHeader) + ); + + if (!botComment) { + await github.rest.issues.createComment({ + owner, repo, issue_number, body: commentBody + }); + } else { + await github.rest.issues.updateComment({ + owner, repo, comment_id: botComment.id, body: commentBody + }); + } + - name: Execute CDK deployment if: inputs.deploy == true id: deploy diff --git a/docs/aws-cdk.md b/docs/aws-cdk.md index 3ad094b..8fee7ce 100644 --- a/docs/aws-cdk.md +++ b/docs/aws-cdk.md @@ -7,6 +7,7 @@ A streamlined AWS CDK workflow supporting multi-environment infrastructure synth - **Multi-environment support**: development, staging, and production deployments - **Bootstrap validation**: Automatic CDK environment preparation and validation - **Changeset preview**: CloudFormation diff analysis before deployment +- **PR diff comments**: When running a diff on a pull request, the result is posted (or updated) as a PR comment - **Smart Node.js setup**: Automatic detection from .nvmrc file with dependency caching - **Package manager detection**: Automatic support for npm, yarn (classic/berry), and pnpm - **Debug support**: Verbose logging and debug output for troubleshooting @@ -80,12 +81,19 @@ jobs: ``` **PR Diff (No Environment):** + +> **Note:** `pull-requests: write` is required for the workflow to post diff comments on the PR. + ```yaml on: pull_request: branches: - '**' +permissions: + pull-requests: write + contents: read + jobs: diff: uses: aligent/workflows/.github/workflows/aws-cdk.yml@main @@ -97,8 +105,8 @@ jobs: **PR Diff (Multiple Environments):** - Each environment should have its own `STACK_NAME`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY` configured. - -- `github.base_ref` references the name of the target branch for staging and production +- `github.base_ref` references the name of the target branch for staging and production. +- Each environment posts its own comment keyed on the stack name, so multiple diffs can coexist on the same PR. ```yaml on: @@ -106,6 +114,10 @@ on: branches: - '**' +permissions: + pull-requests: write + contents: read + jobs: diff-staging: if: github.base_ref == 'staging'