actions icon indicating copy to clipboard operation
actions copied to clipboard

Add summary to PR comments

Open justinvp opened this issue 1 year ago • 1 comments

Hello!

  • Vote on this issue by adding a 👍 reaction
  • If you want to implement this feature, comment to let us know (we'll work with you on design, scheduling, etc.)

Issue details

It would be useful to have a brief summary in PR comments just before the Pulumi output, including a URL to view the details in Pulumi Cloud along with a summary of the changes, to see an overall view without having to expand the full output and scroll to the bottom.

Affected area/feature

PR comments

justinvp avatar Jun 23 '23 18:06 justinvp

If someone wants a working code snippet for GitHub yaml:

      - name: Run pulumi preview
        env:
          GITHUB_TOKEN: ${{ secrets.PULUMI_PAT }}
        working-directory: ${{ env.WORK_DIR }}
        shell: bash -e -o pipefail {0}
        run: |
          pulumi preview -s ${{ env.STACK_NAME }} --diff --save-plan plan.json $PULUMI_ARGS | \
            tee ${{ runner.temp }}/preview.out

      - name: Upload plan
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.PULUMI_PLAN_ARTIFACT }}
          path: ${{ env.WORK_DIR }}/plan.json

      - name: Handle plan output
        id: plan
        shell: python
        working-directory: ${{ env.WORK_DIR }}
        run: |
          import collections
          import json
          import os

          with open('plan.json') as f:
            plan = json.load(f, object_pairs_hook=collections.OrderedDict)

          table = [('', 'Name', 'Type', 'Operation')]
          any_changed = False
          longest_name_len = 0
          longest_typ_len = 0

          resource_plans = plan.get('resourcePlans', collections.OrderedDict())
          for urn, resource_plan in resource_plans.items():
            changed = False
            steps = resource_plan.get('steps', [])
            goal = resource_plan.get('goal', {})
            name = goal.get('name', '?')
            typ = goal.get('type', '?')
            op = 'unset-fixme'
            diff_op = ''
            if steps != ['same']:
              changed = True
              if 'create-replacement' in steps:
                op = 'create-replacement'
                diff_op = '+-'
              elif 'replace' in steps:
                op = 'replace'
                diff_op = '+-'
              elif 'create' in steps:
                op = 'create'
                diff_op = '+'
              elif 'delete' in steps:
                op = 'delete'
                diff_op = '-'
                # special case, no goal is set
                _, _, typ, name  = urn.split('::')
                typ = typ.split('$')[-1]
              elif 'update' in steps:
                op = 'update'
                diff_op = '!~'
              else:
                op = 'unknown-fixme'
                diff_op = ''
            if goal.get('inputDiff', {}) != {}:
              if not changed:
                op = 'refresh'
                diff_op = ''
              changed = True
            if goal.get('outputDiff', {}) != {}:
              if not changed:
                op = 'refresh'
                diff_op = ''
              changed = True
            if changed:
              any_changed = True
              longest_name_len = max(longest_name_len, len(name))
              longest_typ_len = max(longest_typ_len, len(typ))
              table.append((diff_op, name, typ, op))

          diff_op_len = 2
          colspace = ' ' * 2

          output = ''

          if any_changed:
            output += '## Resource Changes (${{ inputs.app_name }}/${{ inputs.stack_name }})\n'
            output += '```diff\n'
            for row in table:
              diff_op, name, typ, op = row
              output += f'{diff_op:2}{colspace}{name:{longest_name_len}}{colspace}{typ:{longest_typ_len}}{colspace}{op}\n'
            output += '```\n'
          else:
            output += '## No Resource Changes (${{ inputs.app_name }}/${{ inputs.stack_name }})\n'
            print('No changes to apply. Update job will be skipped.')
          with open(os.environ['GITHUB_STEP_SUMMARY'], 'a') as f:
            f.write(output)
          with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
            f.write(f'plan-has-changes={any_changed}\n')

This python snippet currently prints the diff in diff format to the Summary section. Could be worked around a little to print to PR as well.

same-id avatar Dec 05 '23 10:12 same-id