Compare commits

...

7 Commits

Author SHA1 Message Date
Benjamin Lu
01bf94ccfb ci: handle skipped e2e workflow consumers 2026-04-23 15:37:00 -07:00
Alexander Brown
b81b56cb4c Merge branch 'main' into fix/filter-e2e-workflow-on-pr 2026-04-23 15:19:46 -07:00
DrJKL
7f6aecdec5 fix: always run e2e on push, merge_group, and workflow_dispatch
Amp-Thread-ID: https://ampcode.com/threads/T-019dbc54-e90a-767e-ba8e-a5a0309181d7
Co-authored-by: Amp <amp@ampcode.com>
2026-04-23 15:18:19 -07:00
DrJKL
fb1079aa8f style: wrap job-level if conditions in expression syntax
Amp-Thread-ID: https://ampcode.com/threads/T-019dbc54-e90a-767e-ba8e-a5a0309181d7
Co-authored-by: Amp <amp@ampcode.com>
2026-04-23 15:15:26 -07:00
DrJKL
7819835327 ci: use path-filter job instead of paths-ignore for required checks
Replace paths-ignore on pull_request with a dorny/paths-filter changes
job that gates all downstream jobs. paths-ignore skips the workflow
entirely, so required status checks never report and PRs stall.
With an if-condition skip, GitHub sees 'skipped' which satisfies
required checks in the ProtectMain ruleset.

Amp-Thread-ID: https://ampcode.com/threads/T-019dbc1e-d506-7369-be4b-9893576d86fd
Co-authored-by: Amp <amp@ampcode.com>
2026-04-23 14:41:10 -07:00
Alexander Brown
2e3cfe7a0f Merge branch 'main' into fix/filter-e2e-workflow-on-pr 2026-04-23 13:51:44 -07:00
DrJKL
265d8a21d9 ci: filter e2e workflow on PRs to skip unrelated changes
Add paths-ignore to the pull_request trigger so PRs that only
touch apps/, docs/, markdown, or .storybook/ skip the e2e suite.

merge_group and push-to-main triggers remain unconditional.

Amp-Thread-ID: https://ampcode.com/threads/T-019dbb9a-ce5d-734a-801b-c730638a02cf
Co-authored-by: Amp <amp@ampcode.com>
2026-04-23 11:43:41 -07:00
3 changed files with 115 additions and 19 deletions

View File

@@ -20,6 +20,8 @@ jobs:
github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
has-coverage: ${{ steps.coverage-shards.outputs.has-coverage }}
steps:
- name: Checkout repository
@@ -37,24 +39,32 @@ jobs:
path: temp/coverage-shards
if_no_artifact_found: warn
- name: Detect shard coverage data
id: coverage-shards
run: |
if [ -d temp/coverage-shards ] && find temp/coverage-shards -name 'coverage.lcov' -type f | grep -q .; then
echo "has-coverage=true" >> "$GITHUB_OUTPUT"
else
echo "has-coverage=false" >> "$GITHUB_OUTPUT"
echo "No E2E coverage shard artifacts found; treating this run as skipped." >> "$GITHUB_STEP_SUMMARY"
fi
- name: Install lcov
if: steps.coverage-shards.outputs.has-coverage == 'true'
run: sudo apt-get install -y -qq lcov
- name: Merge shard coverage into single LCOV
if: steps.coverage-shards.outputs.has-coverage == 'true'
run: |
mkdir -p coverage/playwright
LCOV_FILES=$(find temp/coverage-shards -name 'coverage.lcov' -type f)
if [ -z "$LCOV_FILES" ]; then
echo "No coverage.lcov files found"
touch coverage/playwright/coverage.lcov
exit 0
fi
ADD_ARGS=""
for f in $LCOV_FILES; do ADD_ARGS="$ADD_ARGS -a $f"; done
lcov $ADD_ARGS -o coverage/playwright/coverage.lcov
wc -l coverage/playwright/coverage.lcov
- name: Validate merged coverage
if: steps.coverage-shards.outputs.has-coverage == 'true'
run: |
SHARD_COUNT=$(find temp/coverage-shards -name 'coverage.lcov' -type f | wc -l | tr -d ' ')
if [ "$SHARD_COUNT" -eq 0 ]; then
@@ -82,7 +92,7 @@ jobs:
done
- name: Upload merged coverage data
if: always()
if: steps.coverage-shards.outputs.has-coverage == 'true'
uses: actions/upload-artifact@v6
with:
name: e2e-coverage
@@ -91,7 +101,7 @@ jobs:
if-no-files-found: warn
- name: Upload E2E coverage to Codecov
if: always()
if: steps.coverage-shards.outputs.has-coverage == 'true'
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3
with:
files: coverage/playwright/coverage.lcov
@@ -100,6 +110,7 @@ jobs:
fail_ci_if_error: false
- name: Generate HTML coverage report
if: steps.coverage-shards.outputs.has-coverage == 'true'
run: |
if [ ! -s coverage/playwright/coverage.lcov ]; then
echo "No coverage data; generating placeholder report."
@@ -114,6 +125,7 @@ jobs:
--precision 1
- name: Upload HTML report artifact
if: steps.coverage-shards.outputs.has-coverage == 'true'
uses: actions/upload-artifact@v6
with:
name: e2e-coverage-html
@@ -122,7 +134,9 @@ jobs:
deploy:
needs: merge
if: github.event.workflow_run.head_branch == 'main'
if: >
github.event.workflow_run.head_branch == 'main' &&
needs.merge.outputs.has-coverage == 'true'
runs-on: ubuntu-latest
permissions:
pages: write

View File

@@ -20,6 +20,7 @@ jobs:
github.event.workflow_run.repository != null &&
github.event.workflow_run.head_repository.full_name != github.event.workflow_run.repository.full_name
permissions:
contents: read
pull-requests: write
actions: read
steps:
@@ -38,8 +39,40 @@ jobs:
id: pr
uses: ./.github/actions/resolve-pr-from-workflow-run
- name: Check for e2e-relevant changes
if: steps.pr.outputs.skip != 'true'
id: e2e-changes
uses: actions/github-script@v8
with:
script: |
const pull_number = Number('${{ steps.pr.outputs.number }}');
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number,
per_page: 100,
});
const isIgnored = (filename) =>
filename.startsWith('apps/') ||
filename.startsWith('docs/') ||
filename.startsWith('.storybook/') ||
filename.endsWith('.md');
const shouldRun = files.some((file) => !isIgnored(file.filename));
core.setOutput('should-run', String(shouldRun));
if (!shouldRun) {
core.notice(
'No E2E-relevant files changed; skipping forked PR report deployment.'
);
}
- name: Handle Test Start
if: steps.pr.outputs.skip != 'true' && github.event.action == 'requested'
if: >
steps.pr.outputs.skip != 'true' &&
steps.e2e-changes.outputs.should-run == 'true' &&
github.event.action == 'requested'
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
@@ -50,7 +83,10 @@ jobs:
"starting"
- name: Download and Deploy Reports
if: steps.pr.outputs.skip != 'true' && github.event.action == 'completed'
if: >
steps.pr.outputs.skip != 'true' &&
steps.e2e-changes.outputs.should-run == 'true' &&
github.event.action == 'completed'
uses: actions/download-artifact@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -59,7 +95,10 @@ jobs:
path: reports
- name: Handle Test Completion
if: steps.pr.outputs.skip != 'true' && github.event.action == 'completed'
if: >
steps.pr.outputs.skip != 'true' &&
steps.e2e-changes.outputs.should-run == 'true' &&
github.event.action == 'completed'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

View File

@@ -7,7 +7,6 @@ on:
paths-ignore: ['**/*.md']
pull_request:
branches-ignore: [wip/*, draft/*, temp/*]
paths-ignore: ['**/*.md']
merge_group:
workflow_dispatch:
@@ -16,7 +15,37 @@ concurrency:
cancel-in-progress: true
jobs:
# Detect whether e2e-relevant files changed. Required checks see "skipped"
# (which counts as passing) when only docs/apps/storybook files are touched,
# avoiding the stall that paths-ignore would cause.
changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ github.event_name != 'pull_request' || steps.filter.outputs.e2e }}
steps:
- name: Checkout repository
if: ${{ github.event_name == 'pull_request' }}
uses: actions/checkout@v6
- name: Check for e2e-relevant changes
if: ${{ github.event_name == 'pull_request' }}
id: filter
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
predicate-quantifier: 'every'
filters: |
e2e:
- '**'
- '!apps/**'
- '!docs/**'
- '!.storybook/**'
- '!**/*.md'
setup:
needs: changes
if: ${{ needs.changes.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
@@ -164,9 +193,9 @@ jobs:
# Merge sharded test reports (no container needed - only runs CLI)
merge-reports:
needs: [playwright-tests-chromium-sharded]
needs: [changes, playwright-tests-chromium-sharded]
runs-on: ubuntu-latest
if: ${{ !cancelled() }}
if: ${{ !cancelled() && needs.changes.outputs.should_run == 'true' }}
steps:
- name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
@@ -201,8 +230,14 @@ jobs:
# Post starting comment for non-forked PRs
comment-on-pr-start:
needs: changes
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
if: >-
${{
needs.changes.outputs.should_run == 'true' &&
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.fork == false
}}
permissions:
pull-requests: write
steps:
@@ -212,18 +247,25 @@ jobs:
- name: Post starting comment
env:
GITHUB_TOKEN: ${{ github.token }}
BRANCH_NAME: ${{ github.head_ref }}
run: |
chmod +x scripts/cicd/pr-playwright-deploy-and-comment.sh
./scripts/cicd/pr-playwright-deploy-and-comment.sh \
"${{ github.event.pull_request.number }}" \
"${{ github.head_ref }}" \
"$BRANCH_NAME" \
"starting"
# Deploy and comment for non-forked PRs only
deploy-and-comment:
needs: [playwright-tests, merge-reports]
needs: [changes, playwright-tests, merge-reports]
runs-on: ubuntu-latest
if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
if: >-
${{
always() &&
needs.changes.outputs.should_run == 'true' &&
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.fork == false
}}
permissions:
pull-requests: write
contents: read
@@ -243,9 +285,10 @@ jobs:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
GITHUB_TOKEN: ${{ github.token }}
GITHUB_SHA: ${{ github.event.pull_request.head.sha }}
BRANCH_NAME: ${{ github.head_ref }}
run: |
bash ./scripts/cicd/pr-playwright-deploy-and-comment.sh \
"${{ github.event.pull_request.number }}" \
"${{ github.head_ref }}" \
"$BRANCH_NAME" \
"completed"
#### END Deployment and commenting (non-forked PRs only)