From 7ab73cfc68c0447399d164151206515d213324b1 Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 22:33:11 +0700 Subject: [PATCH 1/8] ci: run e2e on direct main pushes only Keep E2E as a PR check, but skip redundant runs on merge commits by running on main only when the pushed commit is not associated with any PR. --- .github/workflows/e2e.yml | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 9316bfcb9..cca8a446b 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,13 +7,44 @@ on: - main workflow_dispatch: +permissions: + contents: read + pull-requests: read + concurrency: group: e2e-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: + direct_push_check: + name: Detect direct push to main + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + outputs: + is_direct: ${{ steps.detect.outputs.is_direct }} + steps: + - name: Determine if commit belongs to a PR + id: detect + uses: actions/github-script@v8 + with: + script: | + const sha = context.sha + // If this commit is associated with any PR, it's almost certainly coming from a PR merge. + // Direct pushes to main won't have associated PRs. + const { data } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ + owner: context.repo.owner, + repo: context.repo.repo, + commit_sha: sha, + }) + + core.setOutput('is_direct', String(data.length === 0)) + e2e: runs-on: ubuntu-latest + needs: [direct_push_check] + if: | + github.event_name == 'pull_request' || + (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.direct_push_check.outputs.is_direct == 'true') timeout-minutes: 45 strategy: fail-fast: false @@ -94,7 +125,7 @@ jobs: name: Merge Playwright report runs-on: ubuntu-latest if: always() - needs: [e2e] + needs: [direct_push_check, e2e] steps: - name: Checkout uses: actions/checkout@v6 From a5556bd9b10b17a9d69361d150eab8862ff14d8e Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 22:34:03 +0700 Subject: [PATCH 2/8] ci: ensure e2e runs on PRs Make the direct-push detection job always complete so PR-triggered E2E isn't skipped due to a missing/conditional dependency. --- .github/workflows/e2e.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index cca8a446b..6c26130c8 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -19,7 +19,6 @@ jobs: direct_push_check: name: Detect direct push to main runs-on: ubuntu-latest - if: github.event_name == 'push' && github.ref == 'refs/heads/main' outputs: is_direct: ${{ steps.detect.outputs.is_direct }} steps: @@ -28,6 +27,12 @@ jobs: uses: actions/github-script@v8 with: script: | + if (context.eventName !== 'push' || context.ref !== 'refs/heads/main') { + // Only `push` to `main` needs direct-vs-merge detection. + core.setOutput('is_direct', 'false') + return + } + const sha = context.sha // If this commit is associated with any PR, it's almost certainly coming from a PR merge. // Direct pushes to main won't have associated PRs. From 35fab9a94479aed62e1914a709386b29d003f03a Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 22:52:27 +0700 Subject: [PATCH 3/8] ci: update e2e workflow to use Playwright container Configure the e2e job to run in a Playwright container, improving consistency and reliability. Removed caching and installation steps for Playwright browsers as they are now handled within the container. --- .github/workflows/e2e.yml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 6c26130c8..9af39462a 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -46,6 +46,9 @@ jobs: e2e: runs-on: ubuntu-latest + container: + image: mcr.microsoft.com/playwright:v1.57.0-jammy + options: --ipc=host needs: [direct_push_check] if: | github.event_name == 'pull_request' || @@ -98,17 +101,6 @@ jobs: - name: Install dependencies run: bun install --frozen-lockfile - - name: Cache Playwright browsers - uses: actions/cache@v4 - with: - path: ~/.cache/ms-playwright - # Cache per-browser to avoid cross-job races and partial caches - # when matrix runs in parallel. - key: ${{ runner.os }}-playwright-${{ matrix.browser }}-${{ hashFiles('bun.lock') }} - - - name: Install Playwright browsers - run: bunx playwright install ${{ matrix.browser }} --with-deps - - name: Build app run: bun run build From c8fd5ab36dba9045714c60bd1509e4a417875bf9 Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 22:55:30 +0700 Subject: [PATCH 4/8] ci: install unzip in e2e container Ensure oven-sh/setup-bun works inside the Playwright container by installing unzip before setting up Bun. --- .github/workflows/e2e.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 9af39462a..8c5518094 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -85,6 +85,9 @@ jobs: - name: Checkout uses: actions/checkout@v6 + - name: Install unzip + run: apt-get update && apt-get install -y unzip + - name: Setup Bun uses: oven-sh/setup-bun@v2 with: @@ -127,6 +130,9 @@ jobs: - name: Checkout uses: actions/checkout@v6 + - name: Install unzip + run: sudo apt-get update && sudo apt-get install -y unzip + - name: Setup Bun uses: oven-sh/setup-bun@v2 with: From 249f22ed42d70cf9f5a27937b52eabf8b403b7e0 Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 23:04:28 +0700 Subject: [PATCH 5/8] ci: set HOME for Firefox in playwright container Playwright Firefox requires $HOME to be owned by the running user inside the container; set HOME=/root so Firefox can launch reliably in CI. --- .github/workflows/e2e.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 8c5518094..a6fa2749c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -53,6 +53,9 @@ jobs: if: | github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.direct_push_check.outputs.is_direct == 'true') + env: + # Playwright's Firefox won't launch in the container unless $HOME is owned by the current user. + HOME: /root timeout-minutes: 45 strategy: fail-fast: false From 95193fbd7bcad13dd6566381b463b267dffe3ad5 Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 23:14:31 +0700 Subject: [PATCH 6/8] ci: update e2e workflow to set HOME for Playwright user Change the HOME environment variable to /home/pwuser and add user option to the Playwright container to ensure proper permissions for Firefox execution in CI. --- .github/workflows/e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index a6fa2749c..9bef1f029 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -48,14 +48,14 @@ jobs: runs-on: ubuntu-latest container: image: mcr.microsoft.com/playwright:v1.57.0-jammy - options: --ipc=host + options: --ipc=host --user 1001 needs: [direct_push_check] if: | github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.direct_push_check.outputs.is_direct == 'true') env: # Playwright's Firefox won't launch in the container unless $HOME is owned by the current user. - HOME: /root + HOME: /home/pwuser timeout-minutes: 45 strategy: fail-fast: false From dc4a84181262f2d1793e3309d3943815995eb471 Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 23:28:27 +0700 Subject: [PATCH 7/8] ci: use correct Playwright container user uid Run the e2e container as uid 1000 so actions and Playwright Firefox share a writable, owned home directory and avoid checkout permission failures. --- .github/workflows/e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 9bef1f029..c7fe25845 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-latest container: image: mcr.microsoft.com/playwright:v1.57.0-jammy - options: --ipc=host --user 1001 + options: --ipc=host --user 1000 needs: [direct_push_check] if: | github.event_name == 'pull_request' || From a25c64a5169ce49c7dd40b3fc01226329963acde Mon Sep 17 00:00:00 2001 From: Nico Prananta <311343+nicnocquee@users.noreply.github.com> Date: Tue, 5 May 2026 23:31:35 +0700 Subject: [PATCH 8/8] ci: restore root runner context in e2e container Remove the custom container user so GitHub action file commands can write to runner temp paths, while keeping HOME on /root for Firefox launch stability. --- .github/workflows/e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index c7fe25845..a6fa2749c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -48,14 +48,14 @@ jobs: runs-on: ubuntu-latest container: image: mcr.microsoft.com/playwright:v1.57.0-jammy - options: --ipc=host --user 1000 + options: --ipc=host needs: [direct_push_check] if: | github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.direct_push_check.outputs.is_direct == 'true') env: # Playwright's Firefox won't launch in the container unless $HOME is owned by the current user. - HOME: /home/pwuser + HOME: /root timeout-minutes: 45 strategy: fail-fast: false