diff --git a/.github/scripts/post-danger-comment.js b/.github/scripts/post-danger-comment.js new file mode 100644 index 000000000..382e1126c --- /dev/null +++ b/.github/scripts/post-danger-comment.js @@ -0,0 +1,82 @@ +const fs = require('fs'); +const core = require('@actions/core'); + +module.exports = async ({ github, context }) => { + const hasItems = (arr) => Array.isArray(arr) && arr.length > 0; + + let report; + try { + report = JSON.parse(fs.readFileSync('danger_report.json', 'utf8')); + } catch (e) { + console.log('No danger report found, skipping comment'); + return; + } + + if (!report.pr_number) { + console.log('No PR number found in report, skipping comment'); + return; + } + + let body = '## Danger Report\n\n'; + + if (hasItems(report.errors)) { + body += '### ❌ Errors\n'; + report.errors.forEach(e => body += `- ${e}\n`); + body += '\n'; + } + + if (hasItems(report.warnings)) { + body += '### ⚠️ Warnings\n'; + report.warnings.forEach(w => body += `- ${w}\n`); + body += '\n'; + } + + if (hasItems(report.messages)) { + body += '### ℹ️ Messages\n'; + report.messages.forEach(m => body += `- ${m}\n`); + body += '\n'; + } + + if (hasItems(report.markdowns)) { + report.markdowns.forEach(md => body += `${md}\n\n`); + } + + if (!hasItems(report.errors) && + !hasItems(report.warnings) && + !hasItems(report.messages) && + !hasItems(report.markdowns)) { + body += '✅ All checks passed!'; + } + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: report.pr_number + }); + + const botComment = comments.find(c => + c.user.login === 'github-actions[bot]' && + c.body.includes('## Danger Report') + ); + + if (botComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: body + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: report.pr_number, + body: body + }); + } + + // Fail if there are errors + if (report.errors && report.errors.length > 0) { + core.setFailed('Danger found errors'); + } +}; diff --git a/.github/workflows/danger-comment.yml b/.github/workflows/danger-comment.yml new file mode 100644 index 000000000..d5556f0f8 --- /dev/null +++ b/.github/workflows/danger-comment.yml @@ -0,0 +1,30 @@ +name: Danger Comment +on: + workflow_run: + workflows: [Danger] + types: [completed] + +permissions: + actions: read + contents: read + issues: write + pull-requests: write + +jobs: + comment: + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: Download Danger Report + uses: actions/download-artifact@v4 + with: + name: danger-report + run-id: ${{ github.event.workflow_run.id }} + - name: Post or Update PR Comment + uses: actions/github-script@v7 + with: + script-file: .github/scripts/post-danger-comment.js diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 12372470c..6cde03850 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -1,21 +1,30 @@ ---- -name: danger -on: pull_request - +name: Danger +on: + pull_request: + types: [ opened, reopened, edited, synchronize ] jobs: danger: + name: Danger runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 100 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 3.4 - bundler-cache: true - - name: Run Danger - run: | - # the token is public, has public_repo scope and belongs to the grape-bot user owned by @dblock, this is ok - TOKEN=$(echo -n Z2hwX2lYb0dPNXNyejYzOFJyaTV3QUxUdkNiS1dtblFwZTFuRXpmMwo= | base64 --decode) - DANGER_GITHUB_API_TOKEN=$TOKEN bundle exec danger --verbose + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + bundler-cache: true + - name: Run Danger + run: bundle exec danger dry_run --verbose + env: + DANGER_REPORT_PATH: danger_report.json + - name: Upload Danger Report + if: always() + uses: actions/upload-artifact@v4 + with: + name: danger-report + path: danger_report.json + retention-days: 1 + if-no-files-found: ignore