diff --git a/.github/workflows/.reusable-docker-e2e-tests.yml b/.github/workflows/.reusable-docker-e2e-tests.yml
index b6fd246285fa..c75c3d50b8f5 100644
--- a/.github/workflows/.reusable-docker-e2e-tests.yml
+++ b/.github/workflows/.reusable-docker-e2e-tests.yml
@@ -193,14 +193,63 @@ jobs:
**๐ฆ Artifacts:** [View test results and HTML report](${{ steps.artifact-url.outputs.url }})
**๐ Run:** [#${{ github.run_number }} (attempt ${{ github.run_attempt }})](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
+ # Keeps a single sticky comment at constant height: the newest result stays
+ # expanded on top, and every earlier result is folded into one collapsed
+ # "Previous results" block. Each job rewrites the comment, prepending its
+ # entry and collapsing the rest.
- name: Comment PR with test results
if: always() && github.event_name == 'pull_request' && (steps.report-summary-success.outputs.summary || steps.report-summary-failure.outputs.summary)
continue-on-error: true
- uses: marocchino/sticky-pull-request-comment@v2
+ uses: actions/github-script@v7
+ env:
+ SUMMARY: ${{ steps.report-summary-success.outputs.summary || steps.report-summary-failure.outputs.summary }}
+ PASSED: ${{ steps.report-summary-success.outputs.summary && 'true' || 'false' }}
+ LABEL: ${{ steps.test-type.outputs.label }} ยท ${{ inputs.runs-on }}
+ RUN_NUMBER: ${{ github.run_number }}
+ RUN_ATTEMPT: ${{ github.run_attempt }}
with:
- header: playwright-e2e-results
- append: true
- message: ${{ steps.report-summary-success.outputs.summary || steps.report-summary-failure.outputs.summary }}
+ script: |
+ const MARKER = ''
+ const HISTORY = '๐๏ธ Previous results
\n'
+ const ENTRY = ''
+ const MAX_ENTRIES = 12 // keeps the comment body well under GitHub's 65536-char limit
+
+ const { SUMMARY, PASSED, LABEL, RUN_NUMBER, RUN_ATTEMPT } = process.env
+ const emoji = PASSED === 'true' ? 'โ
' : 'โ'
+ const repo = { owner: context.repo.owner, repo: context.repo.repo }
+ const newest = `${emoji} ${LABEL} โ run #${RUN_NUMBER} (attempt ${RUN_ATTEMPT})
\n\n${SUMMARY}\n\n `
+
+ // Recover earlier entries (collapsed) from the existing comment body.
+ // Entries are split on the ENTRY sentinel (each entry has its own
+ // ); the last chunk also carries the wrapper's closing tag.
+ const parse = (body) => {
+ if (!body) return []
+ const [top, rest = ''] = body.split(HISTORY)
+ const previousTop = (top.split(MARKER)[1] || '').trim()
+ const older = rest.split(ENTRY).map((s) => s.trim()).filter(Boolean)
+ if (older.length) older[older.length - 1] = older.at(-1).replace(/<\/details>\s*$/, '').trim()
+ if (previousTop) older.unshift(previousTop.replace('', ''))
+ return older
+ }
+
+ const comments = await github.paginate(github.rest.issues.listComments, {
+ ...repo,
+ issue_number: context.issue.number,
+ per_page: 100,
+ })
+ const previous = comments.find((comment) => comment.body && comment.body.includes(MARKER))
+
+ const [current, ...older] = [newest, ...parse(previous?.body)].slice(0, MAX_ENTRIES)
+ let body = `${MARKER}\n\n${current.replace('', '')}`
+ if (older.length) {
+ body += `\n\n${HISTORY}\n${older.map((entry) => `${ENTRY}\n${entry}`).join('\n')}\n `
+ }
+
+ if (previous) {
+ await github.rest.issues.updateComment({ ...repo, comment_id: previous.id, body })
+ } else {
+ await github.rest.issues.createComment({ ...repo, issue_number: context.issue.number, body })
+ }
# Visual regression: after all E2E retries, run comparison and upload results
- name: Upload visual regression baselines (main branch)