name: Levitate / Report breaking changes on: workflow_run: workflows: ["Levitate / Detect breaking changes"] types: [completed] permissions: pull-requests: write jobs: notify: name: Report runs-on: ubuntu-latest env: ARTIFACT_NAME: 'levitate' # The name of the artifact that we would like to download ARTIFACT_FOLDER: '${{ github.workspace }}/tmp' # The name of the folder where we will download the artifact to permissions: contents: write issues: write pull-requests: write artifacts: read steps: - uses: actions/checkout@v3 # Download artifact (as a .zip archive) - name: 'Download artifact' uses: actions/github-script@v6 env: RUN_ID: ${{ github.event.workflow_run.id }} with: script: | const fs = require('fs'); const { owner, repo } = context.repo; const runId = process.env.RUN_ID; const artifactName = process.env.ARTIFACT_NAME; const artifactFolder = process.env.ARTIFACT_FOLDER; const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner, repo, run_id: runId, }); const artifact = artifacts.data.artifacts.find(a => a.name === artifactName); if (!artifact) { throw new Error(`Could not find artifact ${ artifactName } in workflow (${ runId })`); } const download = await github.rest.actions.downloadArtifact({ owner, repo, artifact_id: artifact.id, archive_format: 'zip', }); fs.mkdirSync(artifactFolder, { recursive: true }); fs.writeFileSync(`${ artifactFolder }/${ artifactName }.zip`, Buffer.from(download.data)); # Unzip artifact - name: Unzip artifact run: unzip "${ARTIFACT_FOLDER}/${ARTIFACT_NAME}.zip" -d "${ARTIFACT_FOLDER}" # Parse the artifact and register fields as step output variables # (All fields in the JSON will be available as ${{ steps.levitate-run.outputs. }} - name: Parsing levitate result uses: actions/github-script@v6 id: levitate-run with: script: | const filePath = `${ process.env.ARTIFACT_FOLDER }/result.json`; const script = require('./.github/workflows/scripts/json-file-to-job-output.js'); await script({ core, filePath }); # Skip - print a message if the "Detect" workflow was skipped - name: Check if the workflow should be skipped if: steps.levitate-run.outputs.shouldSkip == 'true' run: echo "Skipping." # Check if label exists - name: Check if "levitate breaking change" label exists id: does-label-exist if: steps.levitate-run.outputs.shouldSkip != 'true' uses: actions/github-script@v6 env: PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} with: script: | const { data } = await github.rest.issues.listLabelsOnIssue({ issue_number: process.env.PR_NUMBER, owner: context.repo.owner, repo: context.repo.repo, }); const labels = data.map(({ name }) => name); const doesExist = labels.includes('levitate breaking change'); return doesExist ? 1 : 0; # Comment on the PR - name: Comment on PR if: steps.levitate-run.outputs.exit_code == 1 && steps.levitate-run.outputs.shouldSkip != 'true' uses: marocchino/sticky-pull-request-comment@v2 with: number: ${{ steps.levitate-run.outputs.pr_number }} message: | ⚠️   **Possible breaking changes** _(Open the links below in a new tab to go to the correct steps)_ ${{ steps.levitate-run.outputs.message }} [Console output](${{ steps.levitate-run.outputs.job_link }}) [Read our guideline](https://github.com/grafana/grafana/blob/main/contribute/breaking-changes-guide.md) # Remove comment from the PR (no more breaking changes) - name: Remove comment from PR if: steps.levitate-run.outputs.exit_code == 0 && steps.levitate-run.outputs.shouldSkip != 'true' uses: marocchino/sticky-pull-request-comment@v2 with: number: ${{ steps.levitate-run.outputs.pr_number }} delete: true # Posts a notification to Slack if a PR has a breaking change and it did not have a breaking change before - name: Post to Slack id: slack if: steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0 && steps.levitate-run.outputs.shouldSkip != 'true' && env.HAS_SECRETS uses: slackapi/slack-github-action@v1.24.0 with: payload: | { "pr_link": "https://github.com/grafana/grafana/pull/${{ steps.levitate-run.outputs.pr_number }}", "pr_number": "${{ steps.levitate-run.outputs.pr_number }}", "job_link": "${{ steps.levitate-run.outputs.job_link }}", "reporting_job_link": "${{ github.event.workflow_run.html_url }}", "message": "${{ steps.levitate-run.outputs.message }}" } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_LEVITATE_WEBHOOK_URL }} HAS_SECRETS: ${{ (github.repository == "grafana/grafana" || secrets.SLACK_LEVITATE_WEBHOOK_URL != '') || '' }} # Add the label - name: Add "levitate breaking change" label if: steps.levitate-run.outputs.exit_code == 1 && steps.does-label-exist.outputs.result == 0 && steps.levitate-run.outputs.shouldSkip != 'true' && env.HAS_SECRETS uses: actions/github-script@v6 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} HAS_SECRETS: ${{ (secrets.GH_BOT_ACCESS_TOKEN != '') || '' }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | await github.rest.issues.addLabels({ issue_number: process.env.PR_NUMBER, owner: context.repo.owner, repo: context.repo.repo, labels: ['levitate breaking change'] }) # Remove label (no more breaking changes) - name: Remove "levitate breaking change" label if: steps.levitate-run.outputs.exit_code == 0 && steps.does-label-exist.outputs.result == 1 && steps.levitate-run.outputs.shouldSkip != 'true' && env.HAS_SECRETS uses: actions/github-script@v6 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} HAS_SECRETS: ${{ (secrets.GH_BOT_ACCESS_TOKEN != '') || '' }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | await github.rest.issues.removeLabel({ issue_number: process.env.PR_NUMBER, owner: context.repo.owner, repo: context.repo.repo, name: 'levitate breaking change' }) # Add reviewers # This is very weird, the actual request goes through (comes back with a 201), but does not assign the team. # Related issue: https://github.com/renovatebot/renovate/issues/1908 - name: Add "grafana/plugins-platform-frontend" as a reviewer if: steps.levitate-run.outputs.exit_code && steps.levitate-run.outputs.shouldSkip != 'true' && env.HAS_SECRETS uses: actions/github-script@v6 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} HAS_SECRETS: ${{ (secrets.GH_BOT_ACCESS_TOKEN != '') || '' }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | await github.rest.pulls.requestReviewers({ pull_number: process.env.PR_NUMBER, owner: context.repo.owner, repo: context.repo.repo, reviewers: [], team_reviewers: ['grafana/plugins-platform-frontend'] }); # Remove reviewers (no more breaking changes) - name: Remove "grafana/plugins-platform-frontend" from the list of reviewers if: steps.levitate-run.outputs.exit_code == 0 && steps.levitate-run.outputs.shouldSkip != 'true' && env.HAS_SECRETS uses: actions/github-script@v6 env: PR_NUMBER: ${{ steps.levitate-run.outputs.pr_number }} HAS_SECRETS: ${{ (secrets.GH_BOT_ACCESS_TOKEN != '') || '' }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | await github.rest.pulls.removeRequestedReviewers({ pull_number: process.env.PR_NUMBER, owner: context.repo.owner, repo: context.repo.repo, reviewers: [], team_reviewers: ['grafana/plugins-platform-frontend'] });