From 7ef9ec6de7d7de5ab7ed8d9c89d3c35c0ca0f0ac Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 08:35:37 -0500 Subject: [PATCH 01/25] Update e2e job names to avoid confustion and fix updating check status --- .github/workflows/e2e-tests.yml | 2 +- .github/workflows/test-e2e-fork.yml | 8 +++++++- .github/workflows/test-e2e.yml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index da71477..41bd5d8 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -1,4 +1,4 @@ -name: E2E Tests +name: E2E Tests [reusable] on: workflow_call: diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index e0ceb08..a55ed50 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -44,7 +44,13 @@ jobs: ref: process.env.ref }); - const check = checks.check_runs.filter(c => c.name === 'e2e-test'); + const check = checks.check_runs.filter(c => c.name === 'E2E Tests'); + + if (check.length === 0) { + console.log('No check run found with name "E2E Tests"'); + console.log('Available check runs:', checks.check_runs.map(c => c.name)); + throw new Error('No matching check run found'); + } const { data: result } = await github.rest.checks.update({ ...context.repo, diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index cc5897f..511d917 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -1,4 +1,4 @@ -name: E2E Tests +name: E2E Tests [triggered by maintainer] on: pull_request: From 6cf52a7bfccb804dbfcff4b25fbce1148ba65671 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 11:29:31 -0500 Subject: [PATCH 02/25] Use `process.env.job` instead of hardcoding job name --- .github/workflows/test-e2e-fork.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index a55ed50..994b650 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -44,10 +44,10 @@ jobs: ref: process.env.ref }); - const check = checks.check_runs.filter(c => c.name === 'E2E Tests'); + const check = checks.check_runs.filter(c => c.name === process.env.job); if (check.length === 0) { - console.log('No check run found with name "E2E Tests"'); + console.log('No check run found with name "E2E Tests [reusable]"'); console.log('Available check runs:', checks.check_runs.map(c => c.name)); throw new Error('No matching check run found'); } From 8d4908fb7258267a15982d7257344dcf004aad77 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 11:50:15 -0500 Subject: [PATCH 03/25] Updated comment to mention `sha=` portion to dispatch the event --- .github/workflows/ok-to-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ok-to-test.yml b/.github/workflows/ok-to-test.yml index 304afca..e2f8584 100644 --- a/.github/workflows/ok-to-test.yml +++ b/.github/workflows/ok-to-test.yml @@ -1,4 +1,4 @@ -# Write comments "/ok-to-test " on a pull request. This will emit a repository_dispatch event. +# Write comments "/ok-to-test sha=" on a pull request. This will emit a repository_dispatch event. name: Ok To Test on: From 4b5d3c5f1ab4e4c0e27396b930ea13977a706f76 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 12:34:10 -0500 Subject: [PATCH 04/25] Use propper job name e2e-tests --- .github/workflows/test-e2e-fork.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 994b650..6ac515e 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -44,10 +44,10 @@ jobs: ref: process.env.ref }); - const check = checks.check_runs.filter(c => c.name === process.env.job); + const check = checks.check_runs.filter(c => c.name === 'e2e-tests'); if (check.length === 0) { - console.log('No check run found with name "E2E Tests [reusable]"'); + console.log('No check run found with name "e2e-tests"'); console.log('Available check runs:', checks.check_runs.map(c => c.name)); throw new Error('No matching check run found'); } From 1a40b4fb95e96892ca38b08029fa60357ddbb4df Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 12:35:06 -0500 Subject: [PATCH 05/25] Pass jobm name as env --- .github/workflows/test-e2e-fork.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 6ac515e..fb06b21 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -36,6 +36,7 @@ jobs: env: ref: ${{ github.event.client_payload.pull_request.head.sha }} conclusion: ${{ needs.e2e-tests.result }} + job: e2e-tests with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -44,13 +45,7 @@ jobs: ref: process.env.ref }); - const check = checks.check_runs.filter(c => c.name === 'e2e-tests'); - - if (check.length === 0) { - console.log('No check run found with name "e2e-tests"'); - console.log('Available check runs:', checks.check_runs.map(c => c.name)); - throw new Error('No matching check run found'); - } + const check = checks.check_runs.filter(c => c.name === process.env.job); const { data: result } = await github.rest.checks.update({ ...context.repo, From 878b38deac8b43a0c7f12f96c40fcaf3bed2e1ba Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 12:36:27 -0500 Subject: [PATCH 06/25] Update status check to 'success' only if e2e tests are passed --- .github/workflows/test-e2e-fork.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index fb06b21..9e90ef8 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -30,7 +30,7 @@ jobs: update-check-status: needs: e2e-tests runs-on: ubuntu-latest - if: always() && github.event_name == 'repository_dispatch' + if: needs.e2e-tests.result == 'success' && github.event_name == 'repository_dispatch' steps: - uses: actions/github-script@v6 env: From 5199e9f350c13ce516b09255d29cba48ef74cb68 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 12:37:04 -0500 Subject: [PATCH 07/25] Revert "Update status check to 'success' only if e2e tests are passed" This reverts commit 878b38deac8b43a0c7f12f96c40fcaf3bed2e1ba. --- .github/workflows/test-e2e-fork.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 9e90ef8..fb06b21 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -30,7 +30,7 @@ jobs: update-check-status: needs: e2e-tests runs-on: ubuntu-latest - if: needs.e2e-tests.result == 'success' && github.event_name == 'repository_dispatch' + if: always() && github.event_name == 'repository_dispatch' steps: - uses: actions/github-script@v6 env: From e967f7ce1e63f7665560966fd42ed59cc0ed91a4 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 12:40:35 -0500 Subject: [PATCH 08/25] Revert job name --- .github/workflows/test-e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 511d917..cc5897f 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -1,4 +1,4 @@ -name: E2E Tests [triggered by maintainer] +name: E2E Tests on: pull_request: From 625297c1fb16c862123b121c0b601eaa4a1500c6 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 12:41:01 -0500 Subject: [PATCH 09/25] Add doc explaining how to test forked PR --- docs/fork-pr-testing.md | 111 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 docs/fork-pr-testing.md diff --git a/docs/fork-pr-testing.md b/docs/fork-pr-testing.md new file mode 100644 index 0000000..1cf1b93 --- /dev/null +++ b/docs/fork-pr-testing.md @@ -0,0 +1,111 @@ +# Fork PR Testing Guide + +This document explains how to test external pull requests using the dispatch action workflow system. + +## Overview + +The testing system consists of three main workflows: + +1. **E2E Tests [triggered by maintainer]** (`test-e2e.yml`) - Runs automatically for internal PRs, requires approval for external PRs +2. **Ok To Test** (`ok-to-test.yml`) - Processes slash commands to trigger fork testing +3. **E2E tests [fork]** (`test-e2e-fork.yml`) - Triggered manually via slash commands for external PRs + +## How It Works + +### 1. Initial PR State +When a PR is created or updated: +- The `test-e2e.yml` workflow automatically runs +- For **external PRs**: The `check-external-pr` job detects it's from a fork and **fails intentionally** +- For **internal PRs**: The workflow proceeds normally with e2e tests +- External PRs show ❌ for the check-external-pr job with a message asking for maintainer approval + +### 2. Manual Approval Required +**Important**: External PRs require manual approval before workflows can run. + +**Steps for maintainers:** +1. Go to the PR page +2. Click **"Approve workflow to run"** button +3. The workflow will then execute + +**Note**: The `test-e2e.yml` workflow will still fail for external PRs even after approval, as it's designed to prevent automatic execution. Need to use the slash command instead. + +### 3. Testing External PRs +Once the initial checks have run (and failed), maintainers can test the PR using slash commands: + +#### Step-by-Step Process: + +1. **Navigate to the PR** + - Go to the pull request you want to test + +2. **Add a comment with slash command** + ``` + /ok-to-test sha= + ``` + Replace `` with the actual commit SHA from the PR. + + **Note**: Use the short SHA. + +3. **Dispatch Action Triggers** + - The `ok-to-test.yml` workflow processes the slash command + - It triggers a `repository_dispatch` event with type `ok-to-test-command` + - The `test-e2e-fork.yml` workflow starts + +4. **Workflow Execution** + The fork workflow runs two jobs: + + **a) `e2e-tests` job** (conditional) + - Only runs if: + - Event is `repository_dispatch` + - SHA parameter is not empty + - PR head SHA contains the provided SHA + - Calls the reusable `e2e-tests.yml` workflow + - Runs the actual E2E tests if conditions are met + + **b) `update-check-status` job** (conditional) + - Runs after `e2e-tests` completes + - Updates the existing check for job named "e2e-tests" + - Sets the conclusion based on `e2e-tests` result: + - ✅ **Success** if tests pass + - ❌ **Failure** if tests fail + - ⏭️ **Skipped** if e2e-tests was skipped + +## Troubleshooting + +### Workflow Not Running +- **Check**: Ensure you've approved the workflow to run +- **Action**: Click "Approve workflow to run" in the PR checks tab + +### SHA Not Found +- **Check**: Verify the SHA exists in the PR commits +- **Action**: Use `git log --oneline` to find valid commit SHAs + +### Dispatch Not Triggering +- **Check**: Ensure the slash command format is correct +- **Action**: Use exact format: `/ok-to-test sha=` + +### Check Runs Not Updating +- **Note**: The fork workflow updates the existing "E2E Tests [reusable]" check run +- **Behavior**: The same check run is updated with new results rather than creating a new one + +## Security Notes + +- Only users with **write** permissions can trigger dispatch commands +- The fork workflow runs in the main repository context, allowing it to update check runs +- Manual approval is required for external PR workflows +- External PRs are automatically detected and prevented from running tests automatically + +## Workflow Files + +- **`.github/workflows/ok-to-test.yml`** - Ok To Test - Slash command processor +- **`.github/workflows/test-e2e.yml`** - E2E Tests [triggered by maintainer] - Initial PR checks +- **`.github/workflows/test-e2e-fork.yml`** - E2E tests [fork] - Dispatch action handler +- **`.github/workflows/e2e-tests.yml`** - E2E Tests [reusable] - Reusable workflow for actual testing + +## Testing Checklist + +- [ ] PR created with failing check-external-pr check (for external PRs) +- [ ] Workflow approved to run (if required) +- [ ] Slash command posted with valid SHA +- [ ] Dispatch action triggered successfully +- [ ] E2E Tests [reusable] check run updated with correct conclusion +- [ ] PR shows both original and updated check runs From 7135f439a512750975079f8d553b7bc762dd5958 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 13:14:04 -0500 Subject: [PATCH 10/25] Update check-external-pr check when e2e test success --- .github/workflows/test-e2e-fork.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index fb06b21..fad6b2e 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -36,7 +36,7 @@ jobs: env: ref: ${{ github.event.client_payload.pull_request.head.sha }} conclusion: ${{ needs.e2e-tests.result }} - job: e2e-tests + job: check-external-pr with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | From 316f6056801d7b24c38e5cdbb2de843dddcd0424 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 13:18:05 -0500 Subject: [PATCH 11/25] Update docs --- docs/fork-pr-testing.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/fork-pr-testing.md b/docs/fork-pr-testing.md index 1cf1b93..4aef835 100644 --- a/docs/fork-pr-testing.md +++ b/docs/fork-pr-testing.md @@ -67,7 +67,6 @@ Once the initial checks have run (and failed), maintainers can test the PR using - Sets the conclusion based on `e2e-tests` result: - ✅ **Success** if tests pass - ❌ **Failure** if tests fail - - ⏭️ **Skipped** if e2e-tests was skipped ## Troubleshooting @@ -107,5 +106,4 @@ Once the initial checks have run (and failed), maintainers can test the PR using - [ ] Workflow approved to run (if required) - [ ] Slash command posted with valid SHA - [ ] Dispatch action triggered successfully -- [ ] E2E Tests [reusable] check run updated with correct conclusion -- [ ] PR shows both original and updated check runs +- [ ] `check-external-pr` check run updated with correct conclusion From db2053fde4000c831cd5f345dcdf18ea9f91951c Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 15:28:48 -0500 Subject: [PATCH 12/25] Update status for e2e-test check as well --- .github/workflows/test-e2e-fork.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index fad6b2e..5732ff0 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -36,7 +36,6 @@ jobs: env: ref: ${{ github.event.client_payload.pull_request.head.sha }} conclusion: ${{ needs.e2e-tests.result }} - job: check-external-pr with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -45,7 +44,8 @@ jobs: ref: process.env.ref }); - const check = checks.check_runs.filter(c => c.name === process.env.job); + // update the check-external-pr check run + const check = checks.check_runs.filter(c => c.name === 'check-external-pr'); const { data: result } = await github.rest.checks.update({ ...context.repo, @@ -54,4 +54,14 @@ jobs: conclusion: process.env.conclusion }); - return result; + // update the 'e2e-test' check run + const check = checks.check_runs.filter(c => c.name === 'e2e-test'); + + const { data: result } = await github.rest.checks.update({ + ...context.repo, + check_run_id: check[0].id, + status: 'completed', + conclusion: process.env.conclusion + }); + + return null; From d30ed0b9d703c4110de200b1060cab1b4f7f10e1 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 15:31:23 -0500 Subject: [PATCH 13/25] Name the jobs 'run-e2e-tests' --- .github/workflows/test-e2e-fork.yml | 12 ++++++------ .github/workflows/test-e2e.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 5732ff0..1b3dc7c 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -13,7 +13,7 @@ concurrency: cancel-in-progress: true # cancel previous job runs for the same branch jobs: - e2e-tests: + run-e2e-tests: uses: ./.github/workflows/e2e-tests.yml if: | github.event_name == 'repository_dispatch' && @@ -28,14 +28,14 @@ jobs: OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} update-check-status: - needs: e2e-tests + needs: run-e2e-tests runs-on: ubuntu-latest if: always() && github.event_name == 'repository_dispatch' steps: - uses: actions/github-script@v6 env: ref: ${{ github.event.client_payload.pull_request.head.sha }} - conclusion: ${{ needs.e2e-tests.result }} + conclusion: ${{ needs.run-e2e-tests.result }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -44,7 +44,7 @@ jobs: ref: process.env.ref }); - // update the check-external-pr check run + // update the 'check-external-pr' check run const check = checks.check_runs.filter(c => c.name === 'check-external-pr'); const { data: result } = await github.rest.checks.update({ @@ -54,8 +54,8 @@ jobs: conclusion: process.env.conclusion }); - // update the 'e2e-test' check run - const check = checks.check_runs.filter(c => c.name === 'e2e-test'); + // update the 'run-e2e-tests' check run from 'test-e2e.yml' workflow + const check = checks.check_runs.filter(c => c.name === 'run-e2e-tests'); const { data: result } = await github.rest.checks.update({ ...context.repo, diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index cc5897f..e1333a1 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -33,7 +33,7 @@ jobs: fi echo "✅ Internal PR detected. Proceeding with tests." - e2e-test: + run-e2e-tests: needs: check-external-pr if: always() && (needs.check-external-pr.result == 'success' || github.event_name != 'pull_request') uses: ./.github/workflows/e2e-tests.yml From d403a29fdce28869f70fa1914d0bfb62987b0df1 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Thu, 2 Oct 2025 15:34:51 -0500 Subject: [PATCH 14/25] Update documentation --- docs/fork-pr-testing.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/fork-pr-testing.md b/docs/fork-pr-testing.md index 4aef835..303ac73 100644 --- a/docs/fork-pr-testing.md +++ b/docs/fork-pr-testing.md @@ -6,7 +6,7 @@ This document explains how to test external pull requests using the dispatch act The testing system consists of three main workflows: -1. **E2E Tests [triggered by maintainer]** (`test-e2e.yml`) - Runs automatically for internal PRs, requires approval for external PRs +1. **E2E Tests** (`test-e2e.yml`) - Runs automatically for internal PRs, requires approval for external PRs 2. **Ok To Test** (`ok-to-test.yml`) - Processes slash commands to trigger fork testing 3. **E2E tests [fork]** (`test-e2e-fork.yml`) - Triggered manually via slash commands for external PRs @@ -53,18 +53,18 @@ Once the initial checks have run (and failed), maintainers can test the PR using 4. **Workflow Execution** The fork workflow runs two jobs: - **a) `e2e-tests` job** (conditional) + **a) `run-e2e-tests` job** (conditional) - Only runs if: - Event is `repository_dispatch` - SHA parameter is not empty - PR head SHA contains the provided SHA - - Calls the reusable `e2e-tests.yml` workflow + - Calls the reusable `run-e2e-tests.yml` workflow - Runs the actual E2E tests if conditions are met **b) `update-check-status` job** (conditional) - Runs after `e2e-tests` completes - - Updates the existing check for job named "e2e-tests" - - Sets the conclusion based on `e2e-tests` result: + - Updates the existing check for job named "run-e2e-tests" from 'test-e2e.yml' workflow + - Sets the conclusion based on `run-e2e-tests` result: - ✅ **Success** if tests pass - ❌ **Failure** if tests fail @@ -96,7 +96,7 @@ Once the initial checks have run (and failed), maintainers can test the PR using ## Workflow Files - **`.github/workflows/ok-to-test.yml`** - Ok To Test - Slash command processor -- **`.github/workflows/test-e2e.yml`** - E2E Tests [triggered by maintainer] - Initial PR checks +- **`.github/workflows/test-e2e.yml`** - E2E Tests - Initial PR checks - **`.github/workflows/test-e2e-fork.yml`** - E2E tests [fork] - Dispatch action handler - **`.github/workflows/e2e-tests.yml`** - E2E Tests [reusable] - Reusable workflow for actual testing From bb4f5bdcb048d66e190465256901c131d850fa9c Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Wed, 22 Oct 2025 10:54:33 -0500 Subject: [PATCH 15/25] Update docs --- docs/fork-pr-testing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fork-pr-testing.md b/docs/fork-pr-testing.md index 303ac73..560133e 100644 --- a/docs/fork-pr-testing.md +++ b/docs/fork-pr-testing.md @@ -24,7 +24,7 @@ When a PR is created or updated: **Steps for maintainers:** 1. Go to the PR page -2. Click **"Approve workflow to run"** button +2. Click **"Approve workflow to run"** button. For contributors who have made more than one contribution, workflows will start automatically after approval. 3. The workflow will then execute **Note**: The `test-e2e.yml` workflow will still fail for external PRs even after approval, as it's designed to prevent automatic execution. Need to use the slash command instead. @@ -41,7 +41,7 @@ Once the initial checks have run (and failed), maintainers can test the PR using ``` /ok-to-test sha= ``` - Replace `` with the actual commit SHA from the PR. + Replace `` with the latest commit SHA from the PR. **Note**: Use the short SHA. From 04edd4dbfadfe7dee2f134ea0e96bffef787d324 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Wed, 22 Oct 2025 11:06:48 -0500 Subject: [PATCH 16/25] Always set status for check as succesfull as we were able to start a job Which means it passed hash check and e2e tests passed, so we can update those 2 checks to 'success' --- .github/workflows/test-e2e-fork.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 1b3dc7c..7e8aa68 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -35,7 +35,6 @@ jobs: - uses: actions/github-script@v6 env: ref: ${{ github.event.client_payload.pull_request.head.sha }} - conclusion: ${{ needs.run-e2e-tests.result }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -45,23 +44,23 @@ jobs: }); // update the 'check-external-pr' check run - const check = checks.check_runs.filter(c => c.name === 'check-external-pr'); + const externalCheck = checks.check_runs.filter(c => c.name === 'check-external-pr'); const { data: result } = await github.rest.checks.update({ ...context.repo, - check_run_id: check[0].id, + check_run_id: externalCheck[0].id, status: 'completed', - conclusion: process.env.conclusion + conclusion: 'success' }); // update the 'run-e2e-tests' check run from 'test-e2e.yml' workflow - const check = checks.check_runs.filter(c => c.name === 'run-e2e-tests'); + const e2eTestCheck = checks.check_runs.filter(c => c.name === 'run-e2e-tests'); const { data: result } = await github.rest.checks.update({ ...context.repo, - check_run_id: check[0].id, + check_run_id: e2eTestCheck[0].id, status: 'completed', - conclusion: process.env.conclusion + conclusion: 'success' }); return null; From 3eae7f3e7e25a53c7812c2f627cbf74132ab7d87 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Wed, 22 Oct 2025 11:08:20 -0500 Subject: [PATCH 17/25] Return a list of update results if successfully updated --- .github/workflows/test-e2e-fork.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 7e8aa68..568b651 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -46,7 +46,7 @@ jobs: // update the 'check-external-pr' check run const externalCheck = checks.check_runs.filter(c => c.name === 'check-external-pr'); - const { data: result } = await github.rest.checks.update({ + const { data: externalCheckUpdateResult } = await github.rest.checks.update({ ...context.repo, check_run_id: externalCheck[0].id, status: 'completed', @@ -56,11 +56,11 @@ jobs: // update the 'run-e2e-tests' check run from 'test-e2e.yml' workflow const e2eTestCheck = checks.check_runs.filter(c => c.name === 'run-e2e-tests'); - const { data: result } = await github.rest.checks.update({ + const { data: e2eTestCheckResult } = await github.rest.checks.update({ ...context.repo, check_run_id: e2eTestCheck[0].id, status: 'completed', conclusion: 'success' }); - return null; + return [externalCheckUpdateResult, e2eTestCheckResult]; From 5fb44ba7eb0f20428df94e9d7b5dcb4dd42b2c3f Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Wed, 22 Oct 2025 12:35:44 -0500 Subject: [PATCH 18/25] Update fork tests job name so we can update status for the correct 'run-e2e-tests' check --- .github/workflows/test-e2e-fork.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 568b651..0cb172b 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -13,7 +13,7 @@ concurrency: cancel-in-progress: true # cancel previous job runs for the same branch jobs: - run-e2e-tests: + run-e2e-tests-fork: uses: ./.github/workflows/e2e-tests.yml if: | github.event_name == 'repository_dispatch' && @@ -28,7 +28,7 @@ jobs: OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} update-check-status: - needs: run-e2e-tests + needs: run-e2e-tests-fork runs-on: ubuntu-latest if: always() && github.event_name == 'repository_dispatch' steps: From 8d16fccdbc65bf6b9b10b6b1d65e2d475c9b963a Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Fri, 24 Oct 2025 12:38:04 -0500 Subject: [PATCH 19/25] Update e2e status check based on result of run-e2e-tests-fork step --- .github/workflows/test-e2e-fork.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml index 0cb172b..993c5b8 100644 --- a/.github/workflows/test-e2e-fork.yml +++ b/.github/workflows/test-e2e-fork.yml @@ -35,6 +35,7 @@ jobs: - uses: actions/github-script@v6 env: ref: ${{ github.event.client_payload.pull_request.head.sha }} + conclusion: ${{ needs.run-e2e-tests-fork.result }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | @@ -60,7 +61,7 @@ jobs: ...context.repo, check_run_id: e2eTestCheck[0].id, status: 'completed', - conclusion: 'success' + conclusion: process.env.conclusion }); return [externalCheckUpdateResult, e2eTestCheckResult]; From 78ec743a6dab2d354075fce7e856912dd9235ed6 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Tue, 28 Oct 2025 10:51:49 -0500 Subject: [PATCH 20/25] Remove test-e2e-fork workflow --- .github/workflows/test-e2e-fork.yml | 67 ----------------------------- 1 file changed, 67 deletions(-) delete mode 100644 .github/workflows/test-e2e-fork.yml diff --git a/.github/workflows/test-e2e-fork.yml b/.github/workflows/test-e2e-fork.yml deleted file mode 100644 index 993c5b8..0000000 --- a/.github/workflows/test-e2e-fork.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: E2E tests [fork] - -on: - repository_dispatch: - types: [ ok-to-test-command ] - -permissions: - contents: read - checks: write - -concurrency: - group: e2e-fork-${{ github.event.client_payload.pull_request.number || github.run_id }} - cancel-in-progress: true # cancel previous job runs for the same branch - -jobs: - run-e2e-tests-fork: - uses: ./.github/workflows/e2e-tests.yml - if: | - github.event_name == 'repository_dispatch' && - github.event.client_payload.slash_command.args.named.sha != '' && - contains( - github.event.client_payload.pull_request.head.sha, - github.event.client_payload.slash_command.args.named.sha - ) - secrets: - OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }} - OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }} - OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} - - update-check-status: - needs: run-e2e-tests-fork - runs-on: ubuntu-latest - if: always() && github.event_name == 'repository_dispatch' - steps: - - uses: actions/github-script@v6 - env: - ref: ${{ github.event.client_payload.pull_request.head.sha }} - conclusion: ${{ needs.run-e2e-tests-fork.result }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { data: checks } = await github.rest.checks.listForRef({ - ...context.repo, - ref: process.env.ref - }); - - // update the 'check-external-pr' check run - const externalCheck = checks.check_runs.filter(c => c.name === 'check-external-pr'); - - const { data: externalCheckUpdateResult } = await github.rest.checks.update({ - ...context.repo, - check_run_id: externalCheck[0].id, - status: 'completed', - conclusion: 'success' - }); - - // update the 'run-e2e-tests' check run from 'test-e2e.yml' workflow - const e2eTestCheck = checks.check_runs.filter(c => c.name === 'run-e2e-tests'); - - const { data: e2eTestCheckResult } = await github.rest.checks.update({ - ...context.repo, - check_run_id: e2eTestCheck[0].id, - status: 'completed', - conclusion: process.env.conclusion - }); - - return [externalCheckUpdateResult, e2eTestCheckResult]; From 56288bc0af3f9e39a0467b9ac3135a681cf89708 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Tue, 28 Oct 2025 10:52:18 -0500 Subject: [PATCH 21/25] Trigger e2e tests on both maintainer creates PR and dispatch event --- .github/workflows/test-e2e.yml | 78 ++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index e1333a1..7911043 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -14,30 +14,90 @@ on: push: branches: [main] paths-ignore: *ignore_paths + repository_dispatch: + types: [ ok-to-test-command ] concurrency: - group: e2e-${{ github.event.pull_request.head.ref }} + group: ${{ github.event_name == 'pull_request' && format('e2e-{0}', github.event.pull_request.head.ref) || format('e2e-{0}', github.event.client_payload.pull_request.head.ref) }} cancel-in-progress: true # cancel previous job runs for the same branch jobs: check-external-pr: runs-on: ubuntu-latest - if: github.event_name == 'pull_request' + outputs: + condition: ${{ steps.check.outputs.condition }} steps: - name: Check if PR is from external contributor + id: check run: | - if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then - echo "❌ External PR detected. This workflow requires approval from a maintainer." - echo "Please ask a maintainer to run '/ok-to-test' command to trigger the fork workflow." - exit 1 + echo "Event name: ${{ github.event_name }}" + echo "Repository: ${{ github.repository }}" + + if [ "${{ github.event_name }}" == "pull_request" ]; then + # For pull_request events, check if PR is from external fork + echo "PR head repo: ${{ github.event.pull_request.head.repo.full_name }}" + if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then + echo "condition=skip" >> $GITHUB_OUTPUT + echo "Setting condition=skip (external fork PR creation)" + else + echo "condition=pr-creation-maintainer" >> $GITHUB_OUTPUT + echo "Setting condition=pr-creation-maintainer (internal PR creation)" + fi + elif [ "${{ github.event_name }}" == "repository_dispatch" ]; then + # For repository_dispatch events (ok-to-test), check if sha matches + SHA_PARAM="${{ github.event.client_payload.slash_command.args.named.sha }}" + PR_HEAD_SHA="${{ github.event.client_payload.pull_request.head.sha }}" + + echo "Checking dispatch event conditions..." + echo "SHA from command: $SHA_PARAM" + echo "PR head SHA: $PR_HEAD_SHA" + + if [ -n "$SHA_PARAM" ] && [[ "$PR_HEAD_SHA" == *"$SHA_PARAM"* ]]; then + echo "condition=dispatch-event" >> $GITHUB_OUTPUT + echo "Setting condition=dispatch-event (sha matches)" + else + echo "condition=skip" >> $GITHUB_OUTPUT + echo "Setting condition=skip (sha does not match or empty)" + fi + else + # Unknown event type + echo "condition=skip" >> $GITHUB_OUTPUT + echo "Setting condition=skip (unknown event type: ${{ github.event_name }})" fi - echo "✅ Internal PR detected. Proceeding with tests." - run-e2e-tests: + # Run tests for: + # 1. Internal PRs on pull_request events + # 2. External PRs on repository_dispatch (ok-to-test) events + e2e-test: needs: check-external-pr - if: always() && (needs.check-external-pr.result == 'success' || github.event_name != 'pull_request') + if: | + (needs.check-external-pr.outputs.condition == 'pr-creation-maintainer') + || + (needs.check-external-pr.outputs.condition == 'dispatch-event') uses: ./.github/workflows/e2e-tests.yml secrets: OP_CONNECT_CREDENTIALS: ${{ secrets.OP_CONNECT_CREDENTIALS }} OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }} OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + + comment-pr: + needs: [check-external-pr, e2e-test] + runs-on: ubuntu-latest + if: always() && needs.check-external-pr.outputs.condition == 'dispatch-event' + permissions: + pull-requests: write + steps: + - name: Create URL to the run output + id: vars + run: echo "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT + + - name: Create comment on PR + uses: peter-evans/create-or-update-comment@v5 + with: + issue-number: ${{ github.event.client_payload.pull_request.number }} + body: | + ${{ needs.e2e-test.result == 'success' && '✅ E2E tests passed.' || needs.e2e-test.result == 'failure' && '❌ E2E tests failed.' || '⚠️ E2E tests completed.' }} + + [View test run output][1] + + [1]: ${{ steps.vars.outputs.run-url }} From 2a931cd782f2d31f0b239dd8111bf0b075ded7e0 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Tue, 28 Oct 2025 11:14:56 -0500 Subject: [PATCH 22/25] Update fork-pr-testing doc --- docs/fork-pr-testing.md | 111 ++++++---------------------------------- 1 file changed, 17 insertions(+), 94 deletions(-) diff --git a/docs/fork-pr-testing.md b/docs/fork-pr-testing.md index 560133e..0c9cb8c 100644 --- a/docs/fork-pr-testing.md +++ b/docs/fork-pr-testing.md @@ -1,109 +1,32 @@ # Fork PR Testing Guide -This document explains how to test external pull requests using the dispatch action workflow system. +This document explains how testing works for external pull requests from forks. ## Overview -The testing system consists of three main workflows: +The testing system consists of two main workflows: -1. **E2E Tests** (`test-e2e.yml`) - Runs automatically for internal PRs, requires approval for external PRs -2. **Ok To Test** (`ok-to-test.yml`) - Processes slash commands to trigger fork testing -3. **E2E tests [fork]** (`test-e2e-fork.yml`) - Triggered manually via slash commands for external PRs +1. **E2E Tests** (`test-e2e.yml`) - Runs automatically for internal PRs, need manual trigger on external PRs. +2. **Ok To Test** (`ok-to-test.yml`) - Dispatches `repository_dispatch` event when maintainer put's `/ok-to-test sha=` comment in the forked PR thread. ## How It Works -### 1. Initial PR State -When a PR is created or updated: -- The `test-e2e.yml` workflow automatically runs -- For **external PRs**: The `check-external-pr` job detects it's from a fork and **fails intentionally** -- For **internal PRs**: The workflow proceeds normally with e2e tests -- External PRs show ❌ for the check-external-pr job with a message asking for maintainer approval +### 1. PR is created by maintainer: -### 2. Manual Approval Required -**Important**: External PRs require manual approval before workflows can run. +For the PR created by maintainer `E2E Test` workflow starts automatically. The PR check will reflect the status of the job. -**Steps for maintainers:** -1. Go to the PR page -2. Click **"Approve workflow to run"** button. For contributors who have made more than one contribution, workflows will start automatically after approval. -3. The workflow will then execute +### 2. PR is created by external contributor: -**Note**: The `test-e2e.yml` workflow will still fail for external PRs even after approval, as it's designed to prevent automatic execution. Need to use the slash command instead. +For the PR created by external contributor `E2E Test` workflow **won't** start automatically. +Maintainer should make a sanity check of the changes and run it manually by: +1. Putting a comment `/ok-to-test sha=` in the PR thread. +2. `E2E Test` workflow starts. +3. After `E2E Test` workflow finishes, the commit with a link and workflow status will appear in the thread. +4. Maintainer can merge PR or request the changes based on the `E2E Test` results. -### 3. Testing External PRs -Once the initial checks have run (and failed), maintainers can test the PR using slash commands: -#### Step-by-Step Process: +## Notes -1. **Navigate to the PR** - - Go to the pull request you want to test - -2. **Add a comment with slash command** - ``` - /ok-to-test sha= - ``` - Replace `` with the latest commit SHA from the PR. - - **Note**: Use the short SHA. - -3. **Dispatch Action Triggers** - - The `ok-to-test.yml` workflow processes the slash command - - It triggers a `repository_dispatch` event with type `ok-to-test-command` - - The `test-e2e-fork.yml` workflow starts - -4. **Workflow Execution** - The fork workflow runs two jobs: - - **a) `run-e2e-tests` job** (conditional) - - Only runs if: - - Event is `repository_dispatch` - - SHA parameter is not empty - - PR head SHA contains the provided SHA - - Calls the reusable `run-e2e-tests.yml` workflow - - Runs the actual E2E tests if conditions are met - - **b) `update-check-status` job** (conditional) - - Runs after `e2e-tests` completes - - Updates the existing check for job named "run-e2e-tests" from 'test-e2e.yml' workflow - - Sets the conclusion based on `run-e2e-tests` result: - - ✅ **Success** if tests pass - - ❌ **Failure** if tests fail - -## Troubleshooting - -### Workflow Not Running -- **Check**: Ensure you've approved the workflow to run -- **Action**: Click "Approve workflow to run" in the PR checks tab - -### SHA Not Found -- **Check**: Verify the SHA exists in the PR commits -- **Action**: Use `git log --oneline` to find valid commit SHAs - -### Dispatch Not Triggering -- **Check**: Ensure the slash command format is correct -- **Action**: Use exact format: `/ok-to-test sha=` - -### Check Runs Not Updating -- **Note**: The fork workflow updates the existing "E2E Tests [reusable]" check run -- **Behavior**: The same check run is updated with new results rather than creating a new one - -## Security Notes - -- Only users with **write** permissions can trigger dispatch commands -- The fork workflow runs in the main repository context, allowing it to update check runs -- Manual approval is required for external PR workflows -- External PRs are automatically detected and prevented from running tests automatically - -## Workflow Files - -- **`.github/workflows/ok-to-test.yml`** - Ok To Test - Slash command processor -- **`.github/workflows/test-e2e.yml`** - E2E Tests - Initial PR checks -- **`.github/workflows/test-e2e-fork.yml`** - E2E tests [fork] - Dispatch action handler -- **`.github/workflows/e2e-tests.yml`** - E2E Tests [reusable] - Reusable workflow for actual testing - -## Testing Checklist - -- [ ] PR created with failing check-external-pr check (for external PRs) -- [ ] Workflow approved to run (if required) -- [ ] Slash command posted with valid SHA -- [ ] Dispatch action triggered successfully -- [ ] `check-external-pr` check run updated with correct conclusion +- Only users with **write** permissions can trigger the `/ok-to-test` command. +- External PRs are automatically detected and prevented from running e2e tests automatically. +- Running e2e test on the external PR is optional. Maintainer can merge PR without running it. Maintainer decides whether it's needed to run an E2E test. From 31a8ccfcf55b6884c147f1e9cd414a401e1f5893 Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Fri, 31 Oct 2025 09:57:11 -0500 Subject: [PATCH 23/25] Update docs --- docs/fork-pr-testing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fork-pr-testing.md b/docs/fork-pr-testing.md index 0c9cb8c..90448ba 100644 --- a/docs/fork-pr-testing.md +++ b/docs/fork-pr-testing.md @@ -7,7 +7,7 @@ This document explains how testing works for external pull requests from forks. The testing system consists of two main workflows: 1. **E2E Tests** (`test-e2e.yml`) - Runs automatically for internal PRs, need manual trigger on external PRs. -2. **Ok To Test** (`ok-to-test.yml`) - Dispatches `repository_dispatch` event when maintainer put's `/ok-to-test sha=` comment in the forked PR thread. +2. **Ok To Test** (`ok-to-test.yml`) - Dispatches `repository_dispatch` event when maintainer puts the `/ok-to-test sha=` comment in the forked PR thread. ## How It Works @@ -21,7 +21,7 @@ For the PR created by external contributor `E2E Test` workflow **won't** start a Maintainer should make a sanity check of the changes and run it manually by: 1. Putting a comment `/ok-to-test sha=` in the PR thread. 2. `E2E Test` workflow starts. -3. After `E2E Test` workflow finishes, the commit with a link and workflow status will appear in the thread. +3. After `E2E Test` workflow finishes, a comment with a link to the workflow, along with its status will be posted in the PR. 4. Maintainer can merge PR or request the changes based on the `E2E Test` results. From 41a48813853b60d8a374512bce93952fd7fb312d Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Fri, 31 Oct 2025 09:58:35 -0500 Subject: [PATCH 24/25] Update job names to make it clearer for the reader in github UI --- .github/workflows/e2e-tests.yml | 2 +- .github/workflows/test-e2e.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 41bd5d8..b2ed907 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -14,7 +14,7 @@ on: required: true jobs: - e2e-test: + run: runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 7911043..c533e13 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -68,7 +68,7 @@ jobs: # Run tests for: # 1. Internal PRs on pull_request events # 2. External PRs on repository_dispatch (ok-to-test) events - e2e-test: + e2e: needs: check-external-pr if: | (needs.check-external-pr.outputs.condition == 'pr-creation-maintainer') @@ -81,7 +81,7 @@ jobs: OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} comment-pr: - needs: [check-external-pr, e2e-test] + needs: [check-external-pr, e2e] runs-on: ubuntu-latest if: always() && needs.check-external-pr.outputs.condition == 'dispatch-event' permissions: From 36719a202949ef58822ba1dc15440213a1f8299c Mon Sep 17 00:00:00 2001 From: Volodymyr Zotov Date: Fri, 31 Oct 2025 10:00:59 -0500 Subject: [PATCH 25/25] Improve readability --- .github/workflows/test-e2e.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index c533e13..04d24dc 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -18,7 +18,10 @@ on: types: [ ok-to-test-command ] concurrency: - group: ${{ github.event_name == 'pull_request' && format('e2e-{0}', github.event.pull_request.head.ref) || format('e2e-{0}', github.event.client_payload.pull_request.head.ref) }} + group: >- + ${{ github.event_name == 'pull_request' && + format('e2e-{0}', github.event.pull_request.head.ref) || + format('e2e-{0}', github.event.client_payload.pull_request.head.ref) }} cancel-in-progress: true # cancel previous job runs for the same branch jobs: @@ -96,8 +99,12 @@ jobs: with: issue-number: ${{ github.event.client_payload.pull_request.number }} body: | - ${{ needs.e2e-test.result == 'success' && '✅ E2E tests passed.' || needs.e2e-test.result == 'failure' && '❌ E2E tests failed.' || '⚠️ E2E tests completed.' }} - + ${{ + needs.e2e-test.result == 'success' && '✅ E2E tests passed.' || + needs.e2e-test.result == 'failure' && '❌ E2E tests failed.' || + '⚠️ E2E tests completed.' + }} + [View test run output][1] [1]: ${{ steps.vars.outputs.run-url }}