Skip to content

E2E Report

E2E Report #190

Workflow file for this run

name: E2E Report
on:
workflow_run:
workflows: ["PR Update"]
types:
- completed
workflow_dispatch:
inputs:
pr_number:
description: 'The PR number to generate report for'
required: true
type: string
jobs:
get-pr-info:
name: Get PR Info
runs-on: ubuntu-latest
# For workflow_run: only run if the triggering workflow failed
# For workflow_dispatch: always run (inputs are provided manually)
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'failure' }}
permissions:
actions: read
pull-requests: read
outputs:
pr-number: ${{ steps.get-info.outputs.pr-number }}
head-branch: ${{ steps.get-info.outputs.head-branch }}
has-blob-reports: ${{ steps.get-info.outputs.has-blob-reports }}
source-run-id: ${{ steps.get-info.outputs.source-run-id }}
source-run-number: ${{ steps.get-info.outputs.source-run-number }}
source-run-attempt: ${{ steps.get-info.outputs.source-run-attempt }}
source-head-sha: ${{ steps.get-info.outputs.source-head-sha }}
steps:
- name: Get PR and run info
id: get-info
uses: actions/github-script@v7
with:
script: |
const isDispatch = context.eventName === 'workflow_dispatch';
if (isDispatch) {
// For workflow_dispatch: look up everything from PR number
const prNumber = context.payload.inputs.pr_number;
console.log('Looking up PR:', prNumber);
// Get PR details
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: parseInt(prNumber)
});
const headSha = pr.head.sha;
const headBranch = pr.head.ref;
console.log('PR head SHA:', headSha);
console.log('PR head branch:', headBranch);
// Find the "PR Update" workflow
const { data: workflows } = await github.rest.actions.listRepoWorkflows({
owner: context.repo.owner,
repo: context.repo.repo
});
const prUpdateWorkflow = workflows.workflows.find(w => w.name === 'PR Update');
if (!prUpdateWorkflow) {
core.setFailed('Could not find "PR Update" workflow');
return;
}
console.log('Found PR Update workflow ID:', prUpdateWorkflow.id);
// Find the most recent completed run for this branch with blob-report artifacts
// We search by branch instead of SHA to handle cases where:
// 1. The PR was updated after E2E tests ran (artifacts exist for older SHA)
// 2. The current run for the SHA is still queued/in-progress
const { data: runs } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: prUpdateWorkflow.id,
branch: headBranch,
status: 'completed',
per_page: 20
});
console.log('Found', runs.workflow_runs.length, 'completed runs for branch', headBranch);
// Find a run with blob-report artifacts
let selectedRun = null;
let hasBlobReports = false;
for (const run of runs.workflow_runs) {
console.log('Checking run', run.id, 'conclusion:', run.conclusion);
const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: run.id
});
const blobReports = artifacts.artifacts.filter(a => a.name.startsWith('blob-report-'));
if (blobReports.length > 0) {
console.log('Found run with blob reports:', run.id, 'artifacts:', blobReports.map(a => a.name));
selectedRun = run;
hasBlobReports = true;
break;
}
}
if (!selectedRun) {
console.log('No runs found with blob-report artifacts');
core.setOutput('pr-number', prNumber);
core.setOutput('head-branch', headBranch);
core.setOutput('source-head-sha', headSha);
core.setOutput('has-blob-reports', 'false');
core.setOutput('source-run-id', '');
core.setOutput('source-run-number', '');
core.setOutput('source-run-attempt', '');
return;
}
core.setOutput('pr-number', prNumber);
core.setOutput('head-branch', headBranch);
core.setOutput('source-head-sha', headSha);
core.setOutput('source-run-id', selectedRun.id.toString());
core.setOutput('source-run-number', selectedRun.run_number.toString());
core.setOutput('source-run-attempt', selectedRun.run_attempt.toString());
core.setOutput('has-blob-reports', 'true');
return;
}
// For workflow_run: extract from payload
const workflowRun = context.payload.workflow_run;
const headSha = workflowRun.head_sha;
const headBranch = workflowRun.head_branch;
console.log('Head SHA:', headSha);
console.log('Head Branch:', headBranch);
// Set source run info
core.setOutput('source-run-id', workflowRun.id.toString());
core.setOutput('source-run-number', workflowRun.run_number.toString());
core.setOutput('source-run-attempt', workflowRun.run_attempt.toString());
core.setOutput('source-head-sha', headSha);
// Check for blob report artifacts
const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: workflowRun.id
});
const blobReports = artifacts.artifacts.filter(a => a.name.startsWith('blob-report-'));
console.log('Found blob reports:', blobReports.map(a => a.name));
core.setOutput('has-blob-reports', blobReports.length > 0 ? 'true' : 'false');
// Try to get PR number from workflow_run payload first
if (workflowRun.pull_requests && workflowRun.pull_requests.length > 0) {
const prNumber = workflowRun.pull_requests[0].number;
console.log('PR number from payload:', prNumber);
core.setOutput('pr-number', prNumber.toString());
core.setOutput('head-branch', headBranch);
return;
}
// Fall back to API lookup
try {
const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
owner: context.repo.owner,
repo: context.repo.repo,
commit_sha: headSha
});
if (prs.length === 0) {
console.log('No PRs found for commit');
core.setOutput('pr-number', '');
core.setOutput('head-branch', headBranch);
return;
}
// Find open PR or use first one
const openPr = prs.find(pr => pr.state === 'open') || prs[0];
console.log('PR number from API:', openPr.number);
core.setOutput('pr-number', openPr.number.toString());
core.setOutput('head-branch', openPr.head.ref);
} catch (e) {
console.log('Error fetching PR:', e);
core.setOutput('pr-number', '');
core.setOutput('head-branch', headBranch);
}
merge-reports:
name: Merge reports
needs: [get-pr-info]
if: ${{ needs.get-pr-info.outputs.has-blob-reports == 'true' && needs.get-pr-info.outputs.pr-number != '' }}
uses: ./.github/workflows/merge-reports.yml
with:
source_run_id: ${{ needs.get-pr-info.outputs.source-run-id }}
source_run_number: ${{ needs.get-pr-info.outputs.source-run-number }}
source_run_attempt: ${{ needs.get-pr-info.outputs.source-run-attempt }}
source_head_sha: ${{ needs.get-pr-info.outputs.source-head-sha }}
# No secrets: inherit - merge-reports only needs the default GITHUB_TOKEN for artifact download
publish-report:
name: Publish HTML report
needs: [get-pr-info, merge-reports]
if: ${{ needs.get-pr-info.outputs.pr-number != '' }}
uses: ./.github/workflows/publish-report.yml
with:
head_branch: ${{ needs.get-pr-info.outputs.head-branch }}
source_run_id: ${{ needs.get-pr-info.outputs.source-run-id }}
source_run_number: ${{ needs.get-pr-info.outputs.source-run-number }}
source_run_attempt: ${{ needs.get-pr-info.outputs.source-run-attempt }}
pr_number: ${{ needs.get-pr-info.outputs.pr-number }}
secrets: inherit