@andwhy/e2e-pipeline 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,8 +48,9 @@ Re-running `init --force` in an existing project is the way to pick up a new ver
48
48
  - `.github/workflows/checkly-heal.yml` — a failing deployed monitor triggers a triage-and-heal agent: production regressions escalate to Slack immediately; stale tests get fixed and flaky tests hardened — including behavior-neutral test hooks (`data-testid`) in app source when needed — and opened as a human-review PR, whose own preview run validates the app-side hooks. Inert until a Checkly webhook alert channel dispatches to it — the skill walks through that setup.
49
49
 
50
50
  The workflows need repository secrets: `CHECKLY_API_KEY`, `CHECKLY_ACCOUNT_ID`,
51
- `VERCEL_AUTOMATION_BYPASS_SECRET`, and for auto-heal `ANTHROPIC_API_KEY` and
52
- `SLACK_WEBHOOK_URL` (values in 1Password).
51
+ `VERCEL_AUTOMATION_BYPASS_SECRET`, and for auto-heal `SLACK_WEBHOOK_URL`
52
+ (values in 1Password). `ANTHROPIC_API_KEY` is an organization secret inherited
53
+ by all repos — nothing to add.
53
54
 
54
55
  E2E specs live under **`tests/e2e/`** so a repo can keep unit tests elsewhere under
55
56
  `tests/` without Playwright trying to run them. Seeds sit in the same tree and are
package/dist/bin/init.js CHANGED
@@ -79,6 +79,11 @@ const run = async () => {
79
79
  console.log(` ${path.relative(projectRoot, f)}`);
80
80
  }
81
81
  }
82
+ // Dependencies install before the formatting pass: prettier is resolved
83
+ // from the project's node_modules, which a fresh clone doesn't have yet.
84
+ // Formatting after the install means scaffolded files pick up the project's
85
+ // style even on a first run in a bare checkout.
86
+ installDeps(projectRoot, fileFormat);
82
87
  const formatted = await formatFiles(projectRoot, [
83
88
  ...result.created,
84
89
  ...result.regenerated,
@@ -110,13 +115,12 @@ const run = async () => {
110
115
  " CHECKLY_API_KEY, CHECKLY_ACCOUNT_ID — deploy monitors, auto-heal",
111
116
  " VERCEL_AUTOMATION_BYPASS_SECRET — PR tests through Vercel",
112
117
  " deployment protection",
113
- " ANTHROPIC_API_KEY — Checkly auto-heal agent",
114
118
  " SLACK_WEBHOOK_URL — auto-heal notifications",
115
- "The auto-heal workflow stays inert until a Checkly webhook alert",
116
- "channel dispatches to it — the skill walks through that setup.",
119
+ "(ANTHROPIC_API_KEY is an org-level secret inherited by all repos —",
120
+ "nothing to add.) The auto-heal workflow stays inert until a Checkly",
121
+ "webhook alert channel dispatches to it — the skill walks through that.",
117
122
  ].join("\n"));
118
123
  }
119
- installDeps(projectRoot, fileFormat);
120
124
  console.log("Next steps:");
121
125
  let step = 1;
122
126
  const ext = fileFormat === "mjs" ? "mjs" : "ts";
@@ -47,8 +47,20 @@ export const installDeps = (projectRoot, fileFormat = "ts") => {
47
47
  console.log(` ${cmd}\n`);
48
48
  execSync(cmd, { cwd: projectRoot, stdio: "inherit" });
49
49
  console.log("\nInstalling Chromium browser…\n");
50
- execSync("npx playwright install chromium", {
51
- cwd: projectRoot,
52
- stdio: "inherit",
53
- });
50
+ // Non-fatal: restricted networks (CI sandboxes, proxied agents) block the
51
+ // browser CDN, and a failed download must not abort the install — the
52
+ // scaffolded files are already written and CI installs its own browsers.
53
+ try {
54
+ execSync("npx playwright install chromium", {
55
+ cwd: projectRoot,
56
+ stdio: "inherit",
57
+ });
58
+ }
59
+ catch {
60
+ console.warn([
61
+ "\nChromium download failed (restricted network?). The scaffold is",
62
+ "complete — run `npx playwright install chromium` yourself before",
63
+ "local test runs.",
64
+ ].join("\n"));
65
+ }
54
66
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andwhy/e2e-pipeline",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Scaffolds the full e2e testing pipeline: agent-assisted Playwright tests, CI runs against Vercel previews, and Checkly monitors that follow production deploys",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -59,11 +59,32 @@
59
59
  await expect(page).not.toHaveURL(initialUrl, { timeout: 10_000 });
60
60
  ```
61
61
 
62
- - **Skip unsupported domains in `beforeEach`.** If a domain has no entry in a spec's locale
63
- config, skip all tests up front rather than letting them fail:
62
+ - **Skip unsupported domains in `beforeEach` — but never previews.** If a domain has no
63
+ entry in a spec's locale config, skip all tests up front rather than letting them fail:
64
64
 
65
65
  ```ts
66
66
  test.beforeEach(async ({ page, baseURL }) => {
67
67
  test.skip(!getLocaleConfig(baseURL!), "No config for this domain");
68
68
  });
69
69
  ```
70
+
71
+ A preview deployment's hostname (`*.vercel.app`) is never in the locale map, so a plain
72
+ exact-match lookup silently skips the entire suite on every PR run and in
73
+ `checkly pw-test` — green checks that tested nothing. The lookup must resolve preview
74
+ hosts to the config of the production domain the preview serves (ask the user which one
75
+ if it isn't obvious; `PREVIEW_LOCALE_HOST` overrides it at runtime):
76
+
77
+ ```ts
78
+ const getLocaleConfig = (baseURL: string) => {
79
+ const hostname = new URL(baseURL).hostname.replace(/^www\./, "");
80
+ const config = LOCALE_CONFIG[hostname];
81
+ if (config) return config;
82
+ // Previews serve <primary domain>'s content; without this every preview run skips.
83
+ if (hostname.endsWith(".vercel.app"))
84
+ return LOCALE_CONFIG[process.env.PREVIEW_LOCALE_HOST ?? "<primary domain>"];
85
+ return undefined;
86
+ };
87
+ ```
88
+
89
+ Only a genuinely unknown non-preview host skips. Single-domain suites without a locale
90
+ map are unaffected — they have no lookup to fall through.
@@ -36,7 +36,10 @@ These rules apply to **all** agents (generator, healer, and orchestrator). Inclu
36
36
  project consent logic; do not reinvent it. The helper file extension must match rule 7.
37
37
 
38
38
  4. Never hardcode a single locale's URL pattern. Use a locale config map keyed
39
- by bare hostname and resolve at runtime.
39
+ by bare hostname and resolve at runtime. Preview hosts (`*.vercel.app`) are
40
+ never in the map and must fall back to the primary production domain's
41
+ config (overridable via `PREVIEW_LOCALE_HOST`) — an exact-match-only lookup
42
+ skips the whole suite on every PR run.
40
43
 
41
44
  5. After all tests pass locally, verify with
42
45
  `BASE_URL=<dev-url> pnpm playwright test` via the terminal tool. If failures
@@ -88,12 +88,11 @@ The scaffold writes templates, not a working setup. Walk these with the user:
88
88
  - `VERCEL_AUTOMATION_BYPASS_SECRET` — Vercel → project → Settings →
89
89
  Deployment Protection → Protection Bypass for Automation. Per project —
90
90
  never copied from another repo.
91
- - `ANTHROPIC_API_KEY` — 1Password ("Anthropic"); powers the Checkly
92
- auto-heal agent. Optional until Phase 5 wires the alert webhook, but
93
- cheapest to add alongside the others.
94
91
  - `SLACK_WEBHOOK_URL` — a Slack incoming webhook for the project's
95
92
  notification channel; the auto-heal workflow posts its alerts there.
96
93
  Ask which channel before creating one.
94
+ - `ANTHROPIC_API_KEY` needs **no action**: it is an organization-level
95
+ secret inherited by every repo. Do not tell the user to add it.
97
96
  5. **Existing tests under `tests/`** (unit, a11y — the scaffold lists them as
98
97
  "outside tests/e2e"): leave `testDir` at `./tests/e2e` and give that suite
99
98
  its own Playwright project with its own `testDir` if it should run under
@@ -180,8 +179,9 @@ overwritten):
180
179
  **Before the first merge, the repo needs secrets** (values in 1Password):
181
180
  `CHECKLY_API_KEY` and `CHECKLY_ACCOUNT_ID` for the deploy and auto-heal,
182
181
  `VERCEL_AUTOMATION_BYPASS_SECRET` for the PR run through deployment
183
- protection, `ANTHROPIC_API_KEY` and `SLACK_WEBHOOK_URL` for auto-heal. If
184
- the scaffold just created the workflows, say so explicitly and list the
182
+ protection, `SLACK_WEBHOOK_URL` for auto-heal notifications
183
+ (`ANTHROPIC_API_KEY` is inherited from the organization — nothing to add).
184
+ If the scaffold just created the workflows, say so explicitly and list the
185
185
  secrets — a merge without them fails CI and looks like a pipeline bug.
186
186
 
187
187
  After merge, monitors update once the production deployment goes live — the
@@ -198,14 +198,20 @@ team's Slack message is written by the pipeline *after* triage (regression
198
198
  vs. stale test), so it carries a diagnosis and, for stale tests, the fix PR.
199
199
  Set up once per project:
200
200
 
201
- 1. Confirm the `ANTHROPIC_API_KEY` and `SLACK_WEBHOOK_URL` repository
202
- secrets from Phase 0 exist — the workflow escalates nothing without them.
203
- 2. A GitHub token for Checkly to call `repository_dispatch`: fine-grained
204
- PAT, scoped to this repo only, **Contents: read and write** permission,
205
- the longest expiry policy allows — note the renewal date wherever the team
206
- tracks credentials, an expired token silences the trigger. Store it in
207
- Checkly as an environment variable (Checkly → Environment variables),
208
- e.g. `GH_DISPATCH_TOKEN` — never in code or `checkly.config`.
201
+ 1. Confirm the `SLACK_WEBHOOK_URL` repository secret from Phase 0 exists —
202
+ the workflow escalates nothing without it. (`ANTHROPIC_API_KEY` comes
203
+ from the organization automatically.)
204
+ 2. The shared `GH_DISPATCH_TOKEN` secret exists in Checkly and covers this
205
+ repo. This is **one-time organization setup, not yours to perform**: the
206
+ token (`checkly-heal-dispatch`, a fine-grained PAT) is created once and
207
+ maintained by its owner, named in 1Password — see "One-time organization
208
+ setup" in the usage guide
209
+ (https://app.notion.com/p/32df837b627080748719c0f94a3aeaaf). Your only
210
+ per-project concern: if this repo is not yet on the token's repository
211
+ list, the webhook channel's test (step 3) fails with a 404 — then ask
212
+ the token owner to widen it (a one-minute edit on their side; the token
213
+ value doesn't change). Do not walk the user through creating a PAT or a
214
+ Checkly secret.
209
215
  3. Checkly → Alert channels → "Add more channels" → **Webhook**:
210
216
  - Method `POST`, URL
211
217
  `https://api.github.com/repos/<org>/<repo>/dispatches`
@@ -9,9 +9,10 @@ name: Checkly auto-heal
9
9
  # validates those; a diff guard aborts changes to protected paths
10
10
  # (.github, .claude, configs, lockfiles). The agent never pushes: branch,
11
11
  # commit, PR, and Slack are workflow steps.
12
- # Needs repo secrets: ANTHROPIC_API_KEY, CHECKLY_API_KEY, CHECKLY_ACCOUNT_ID,
13
- # SLACK_WEBHOOK_URL (values in 1Password). Setup docs: the
14
- # playwright-test-pipeline skill walks through the Checkly webhook channel.
12
+ # Needs repo secrets CHECKLY_API_KEY, CHECKLY_ACCOUNT_ID, SLACK_WEBHOOK_URL
13
+ # (values in 1Password); ANTHROPIC_API_KEY is inherited from the organization.
14
+ # Setup docs: the playwright-test-pipeline skill walks through the Checkly
15
+ # webhook channel.
15
16
  on:
16
17
  repository_dispatch:
17
18
  types: [checkly-alert]
@@ -92,6 +92,9 @@ jobs:
92
92
  env:
93
93
  BASE_URL: ${{ github.event.deployment_status.target_url }}
94
94
  VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }}
95
+ # Which production domain's locale config preview hosts resolve to
96
+ # (repo variable, optional — specs default to the primary domain).
97
+ PREVIEW_LOCALE_HOST: ${{ vars.PREVIEW_LOCALE_HOST }}
95
98
  PLAYWRIGHT_JSON_OUTPUT_NAME: playwright-results.json
96
99
  run: |
97
100
  pnpm playwright test \