The workflow
name: e2e
on: [push, pull_request]
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
env:
ZYNTRA_API_KEY: ${{ secrets.ZYNTRA_API_KEY }}
ZYNTRA_TEAM_ID: ${{ vars.ZYNTRA_TEAM_ID }}
BASE_URL: https://staging.your-app.comThe API key is a secret (Settings → Secrets and variables → Actions → Secrets). The team ID is not sensitive, so a repository variable is enough and shows up readably in logs.
Addresses that are unique per run, attempt and test
GITHUB_RUN_ID is unique for each workflow run in a repository, but it stays the same when you re-run the workflow; GITHUB_RUN_ATTEMPT goes up by one on each re-run. Use both, plus a random part for the test itself:
import { randomUUID } from "node:crypto";
const run = process.env.GITHUB_RUN_ID
? `gh${process.env.GITHUB_RUN_ID}-${process.env.GITHUB_RUN_ATTEMPT}`
: "local";
export const newAddress = (tag: string) =>
`${process.env.ZYNTRA_TEAM_ID}.${tag}-${run}-${randomUUID().slice(0, 6)}@zyntramail.com`;The run ID in the address also helps when something fails: you can find every email a given run received.
Pull requests from forks
GitHub does not pass secrets (other than GITHUB_TOKEN) to workflows triggered from a forked repository. The key is empty, and every email test fails with an authentication error. Skip them instead, with a message that says why:
import { test } from "@playwright/test";
test.skip(!process.env.ZYNTRA_API_KEY, "No ZYNTRA_API_KEY: email tests skipped");Keep the number of requests in view
A workflow on every push and pull request runs far more often than a nightly job. Count the email reads per run and multiply; the polling post has the arithmetic. Running email tests only on the main branch and on a schedule is a common compromise.