Skip to main content
A run that fails in CI is a red check and a log to open. @e2edev/github is a reporter that turns it into one pull request comment: the counts, every test that did not pass with its error and evidence, and links to the source lines and to the workflow run holding the screenshots, traces, and recordings. A rerun edits the same comment. The same text goes to the job summary, so it is there on a push too.

Setup

e2e.config.ts
Two lines in the workflow: the job may write pull request comments, and the step that runs e2e gets the token.
.github/workflows/e2e.yml
Upload the artifacts on every non-cancelled outcome. The comment links to the workflow run as the place to fetch them, and a flaky test that passed on its second attempt can still leave evidence worth inspecting.

The comment

Failed tests first, then flaky, then skipped; passed tests are folded away. The test column links to the source line at the pull request’s head commit. A run-level error such as APP_UNREACHABLE appears above the table. Titles and error messages are escaped and clipped, and the body stays under GitHub’s size limit: past fifty rows the table says how many more there are. The comment carries a hidden marker naming the config’s projectId, the workflow, and the job, so two configs or two jobs on one pull request each keep their own comment. Matrix replicas of one job share all three, so give each its own key:
with MATRIX_BROWSER: ${{ matrix.browser }} in the step’s env. Never use the run id as the key: a rerun has a new one and would post a second comment.

When nothing is posted

The reporter never changes the run’s status or exit code. When it cannot post, it says why in one row under the summary:
The reporter reads the token and the event payload when the run finishes, never when the config loads, and the token never enters the report. GitHub Enterprise Server works through GITHUB_SERVER_URL and GITHUB_API_URL.

Rendering the comment elsewhere

renderComment(report, { marker, artifactsUrl, sourceUrl }) is exported. It takes a report document and returns the comment body, so a service that receives the report can post the same comment under its own identity. A marker longer than 1024 characters or an artifactsUrl longer than 2048 is rejected rather than posted incomplete.