Skip to main content

fxa-pr-debug

Boots a branch's FxA stack in CircleCI with `yarn pr-debug`, tunnels it to localhost with `yarn pr-debug --tunnel`, and reports when it is up. Given a description of what to check, also writes and runs a throwaway Playwright test against it in a headed local Firefox. Requires CIRCLECI_TOKEN. Use to try a branch or PR without checking it out.

소스 정보

저장소
mozilla/fxa
최근 소스 활동
2026년 9월 12일 00:19
감지된 SKILL.md 언어
영어
스타
685
포크
239

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
fxa-pr-debug
description
Boots a branch's FxA stack in CircleCI with `yarn pr-debug`, tunnels it to localhost with `yarn pr-debug --tunnel`, and reports when it is up. Given a description of what to check, also writes and runs a throwaway Playwright test against it in a headed local Firefox. Requires CIRCLECI_TOKEN. Use to try a branch or PR without checking it out.
# Debug a PR on a CI stack Two commands: `yarn pr-debug [pr]` boots the branch's stack in CircleCI and returns once it is up; `yarn pr-debug --tunnel [pr]` then forwards every service port to `localhost`, so `http://localhost:3030` *is* the CI stack and `yarn playwright test --project=local` runs against it unchanged. The stack stays up 30 minutes after boot whether or not a tunnel is open, so several can run side by side and `--tunnel` hops between them. How the script gets there is documented in `.circleci/README.md` (Interactive stack); this skill only drives it. Arguments: a leading integer is a PR number; everything else is the test description. Either is optional. ## Hard rules - The stack is a public CI job: only throwaway identities (`testAccountTracker` makes them), never real accounts or stage/production credentials, and never print the container's `env`. - Scratch specs live in `packages/functional-tests/tests/scratch/` and are deleted before this skill ends. Never stage or commit one. If the user wants to keep it, say it must become a real test (`/fxa-test-draft`) first. - Ask before `yarn stop` (their local stack) or `npx playwright install` (network). Do not edit `_scripts/pr-debug.sh` or `.circleci/config.yml` here. - `--tunnel` closes any tunnel already open from this machine. If `pgrep -f fxa-pr-debug-tunnel` finds one, say which stack it will drop and ask first. - A host key mismatch from the script is a stop, not something to bypass. ## Steps ### 1. Preflight (run these in parallel) - Token present, without printing it: `if [ -n "$CIRCLECI_TOKEN" ] || [ -n "$CIRCLECI_CLI_TOKEN" ]; then echo set; else echo missing; fi`. Missing → point at https://app.circleci.com/settings/user/tokens and stop. - `git status -sb`. Without a PR number, the branch must not be `main`/`HEAD`, and must exist on origin; if local is ahead, say so — CI builds origin. - `ssh-add -l`. `--tunnel` runs ssh non-interactively, so the key registered with the user's GitHub account must be in the agent. If the agent is empty, ask them to `ssh-add` it in their terminal and stop until they confirm. - Existing tunnel: `pgrep -fl fxa-pr-debug-tunnel` (see hard rules). - Forwarded ports free: `for p in 3030 3000 9000 9001 1111 1112 8080 8091 8095 9130 9160 6379; do nc -z -w1 127.0.0.1 $p && echo "$p busy"; done`. Busy ports with no tunnel running usually mean a local `yarn start`; ask before `yarn stop`. - With a test description: a local Firefox for Playwright (`ls ~/Library/Caches/ms-playwright | grep -c firefox`). None → ask before `npx playwright install firefox`. ### 2. Boot the stack Run from the repo root in the background with the maximum timeout: ```sh yarn pr-debug [pr-number] ``` It prints each CI step as it goes ("Canceling first pass" is expected — SSH can only be enabled on a rerun), then `Job #N: <url>`, and exits with "Stack for <branch> is up". A cold boot is about seven minutes (two of them the throwaway first pass); a rerun on the same commit skips that pass and takes about five. If a stack is already running for the commit it says so and exits at once. ### 3. Draft the test while it boots (only with a description) Write `packages/functional-tests/tests/scratch/<kebab-slug>.spec.ts`: - `import { test, expect } from '../../lib/fixtures/standard';` — fixtures are `target`, `page`, `pages` (the POMs under `pages/`), `testAccountTracker`, `syncBrowserPages`. Read `lib/testAccountTracker.ts` for how accounts are created and cleaned up, and the spec under `tests/` closest to the request for the flow. - One `test.describe('scratch: <description>')` with one `test()`. Assert with `expect`; no severity tags. - Locator rules in `.claude/rules/testing/functional-pages.md` apply (they load when you touch the file): structural locators and POM getters, never CMS copy. ### 4. Open the tunnel Once the boot task has exited successfully, run in the background with the maximum timeout: ```sh yarn pr-debug --tunnel [pr-number] ``` It prints `Job #N`, the SSH endpoint, then "Tunnel open". Then confirm the ports answer, in one bounded call rather than a sleep loop: ```sh curl -sf --retry 20 --retry-all-errors --retry-delay 5 --retry-max-time 120 \ -o /dev/null http://localhost:3030/ && curl -sf -o /dev/null http://localhost:9000/__heartbeat__ && echo up ``` `--retry-all-errors` matters: a forwarded port whose remote side is not listening yet returns an empty reply, which curl otherwise treats as final. If either task fails, read its output: "No stack is running" means the boot did not finish or the stack has shut down (rerun step 2); a "Step failed" line carries the job URL. Do not guess at the cause; relay the failing step. ### 5. Tell the user One message: the stack is at <http://localhost:3030>, the job URL, when the 30-minute hold ends, and that mail for `@restmail.net` signups is read at `http://localhost:9001/mail/<local-part>` (the request blocks until mail arrives). For a shell on the box alongside the tunnel — `yarn pm2 log`, say — they run `yarn pr-debug --ssh [pr-number]` in their own terminal; it binds no ports. ### 6. Run the test (only with a description) ```sh cd packages/functional-tests && DEBUG=1 PLAYWRIGHT_WORKERS=1 \ yarn test tests/scratch/<slug>.spec.ts --retries=0 ``` The package's `test` script pins `--project=local` and the ipv4-first DNS order the tunnel needs. `DEBUG=1` runs headed, so the user watches the CI stack drive a local Firefox. An existing spec works just as well as a scratch one when the request matches a flow the suite already covers; pick one test with `-g "<title>$"`. In a checkout without `node_modules` (a fresh worktree), `yarn` refuses to run. Node resolution walks up to the main checkout's `node_modules`, so run its binary against this checkout's config instead: `NODE_OPTIONS=--dns-result-order=ipv4first <main-checkout>/node_modules/.bin/playwright test --config <this-checkout>/packages/functional-tests/playwright.config.ts --project=local …`. Report the result plainly: which assertion failed and what the page showed. On failure the trace is under `artifacts/functional/`; give the `yarn playwright show-trace <zip>` command. Offer to adjust and rerun — the stack is warm, so a rerun is seconds. ### 7. Wrap up Delete `tests/scratch/` and confirm `git status --short packages/functional-tests` is clean. Then ask what to do with the stack: - **Keep the tunnel** — they browse `localhost:3030` until the session cap. - **Stop the tunnel** (`TaskStop`) — the stack stays up for the rest of its hold, and `yarn pr-debug --tunnel` reconnects to it. - **Release now** — stop the tunnel, then cancel the job (URL first, so the Bash permission rule for CircleCI POSTs matches): `curl https://circleci.com/api/v2/project/gh/mozilla/fxa/job/<N>/cancel -sS -X POST -H "Circle-Token: $CIRCLECI_TOKEN"`. ## Notes - Docker `xlarge` bills 20 credits/min while the job is up. The 30-minute hold is set at boot (`PR_DEBUG_MINUTES` overrides it); after it the job shuts down about ten minutes after the last SSH session closes. Tunnel and shell sessions are capped at the same number of minutes and never cancel the job. - Redis (6379) is forwarded because the `target` fixture resets rate limits through it; without that forward every test hangs on connect. - Script errors to relay verbatim rather than work around: "No stack is running", "Local ports in use", "Host key mismatch", "Step failed", "Timed out waiting".
GitHub에서 보기