name: Publish Test Results on: workflow_run: workflows: ["tests 1", "tests 2"] types: - completed jobs: merge-reports: permissions: pull-requests: write checks: write if: ${{ github.event.workflow_run.event == 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 18 - run: npm ci env: DEBUG: pw:install PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - run: npm run build - name: Download blob report artifact uses: ./.github/actions/download-artifact with: namePrefix: 'blob-report' path: 'all-blob-reports' - name: Merge reports run: | npx playwright merge-reports --config .github/workflows/merge.config.ts ./all-blob-reports env: NODE_OPTIONS: --max-old-space-size=4096 - name: Upload HTML report to Azure run: | REPORT_DIR='run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}' azcopy cp --recursive "./playwright-report/*" "https://mspwblobreport.blob.core.windows.net/\$web/$REPORT_DIR" echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/index.html" env: AZCOPY_AUTO_LOGIN_TYPE: SPN AZCOPY_SPA_APPLICATION_ID: '${{ secrets.AZCOPY_SPA_APPLICATION_ID }}' AZCOPY_SPA_CLIENT_SECRET: '${{ secrets.AZCOPY_SPA_CLIENT_SECRET }}' AZCOPY_TENANT_ID: '${{ secrets.AZCOPY_TENANT_ID }}' - name: Read pull request number uses: ./.github/actions/download-artifact with: namePrefix: 'pull-request' path: '.' - name: Comment on PR uses: actions/github-script@v6 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const fs = require('fs'); let prNumber; if (context.payload.workflow_run.event === 'pull_request') { const prs = context.payload.workflow_run.pull_requests; if (prs.length) { prNumber = prs[0].number; } else { prNumber = parseInt(fs.readFileSync('pull_request_number.txt').toString()); console.log('Read pull request number from file: ' + prNumber); } } else { core.error('Unsupported workflow trigger event: ' + context.payload.workflow_run.event); return; } if (!prNumber) { core.error('No pull request found for commit ' + context.sha + ' and workflow triggered by: ' + context.payload.workflow_run.event); return; } { // Mark previous comments as outdated by minimizing them. const { data: comments } = await github.rest.issues.listComments({ ...context.repo, issue_number: prNumber, }); for (const comment of comments) { if (comment.user.login === 'github-actions[bot]' && /\[Test results\]\(https:\/\/.+?\) for "${{ github.event.workflow_run.name }}"/.test(comment.body)) { await github.graphql(` mutation { minimizeComment(input: {subjectId: "${comment.node_id}", classifier: OUTDATED}) { clientMutationId } } `); } } } const reportDir = 'run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}'; const reportUrl = `https://mspwblobreport.z1.web.core.windows.net/${reportDir}/index.html#?q=s%3Afailed%20s%3Aflaky`; core.notice('Report url: ' + reportUrl); const mergeWorkflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; const reportMd = await fs.promises.readFile('report.md', 'utf8'); function formatComment(lines) { let body = lines.join('\n'); if (body.length > 65535) body = body.substring(0, 65000) + `... ${body.length - 65000} more characters`; return body; } const { data: response } = await github.rest.issues.createComment({ ...context.repo, issue_number: prNumber, body: formatComment([ `### [Test results](${reportUrl}) for "${{ github.event.workflow_run.name }}"`, reportMd, '', `Merge [workflow run](${mergeWorkflowUrl}).` ]), }); core.info('Posted comment: ' + response.html_url); const check = await github.rest.checks.create({ ...context.repo, name: 'Merge report (${{ github.event.workflow_run.name }})', head_sha: '${{ github.event.workflow_run.head_sha }}', status: 'completed', conclusion: 'success', details_url: reportUrl, output: { title: 'Test results for "${{ github.event.workflow_run.name }}"', summary: [ reportMd, '', '---', `Full [HTML report](${reportUrl}). Merge [workflow run](${mergeWorkflowUrl}).` ].join('\n'), } });