-
Notifications
You must be signed in to change notification settings - Fork 2
ci(web-wallet): nightly non-gating E2E workflow (#177 item 2c) #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| # Real-MetaMask-Flask E2E suite for the web-wallet — SIGNAL ONLY, NON-GATING. | ||
| # | ||
| # This runs on a schedule (not per-PR) purely to surface rot in the on-demand E2E infrastructure | ||
| # (see packages/web-wallet/tests/e2e/e2e.md). It is NOT a required check and MUST NOT be added to | ||
| # branch protection. A red run means "a real-MetaMask journey didn't pass on the runner", which is | ||
| # often a slow cold-start rather than a broken product — triage via the uploaded artifacts. | ||
| name: E2E Web Wallet (nightly, non-gating) | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '0 6 * * *' # 06:00 UTC daily | ||
| workflow_dispatch: {} # allow manual runs from the Actions tab | ||
|
|
||
| concurrency: | ||
| group: e2e-web-wallet-nightly | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| e2e: | ||
| runs-on: ubuntu-latest | ||
| # Non-gating: never fail the workflow status in a way that could be mistaken for a gate. | ||
| # The step-level result + artifacts carry the signal; a red job here blocks nobody. | ||
| timeout-minutes: 60 | ||
| env: | ||
| # Pin the Flask build the selectors are verified against (driver/selectors.ts). | ||
| E2E_FLASK_VERSION: '13.31.0' | ||
| # Stretch every driver + page-object deadline for a slower shared runner. | ||
| E2E_TIMEOUT_SCALE: '2' | ||
| # MetaMask password for the throwaway wallet the driver onboards/imports each run. NOT a | ||
| # secret — it guards a fresh local MetaMask created per run; the funded seed is already public | ||
| # in wallets.config.json. The driver defaults to DEFAULT_PASSWORD ('Test1234!Test') if unset; | ||
| # 'Hathor@123' matches the owner's local .env.e2e so CI reproduces local runs 1:1. Override via | ||
| # a repo Actions variable `vars.E2E_PASSWORD` if desired. | ||
| E2E_PASSWORD: ${{ vars.E2E_PASSWORD || 'Hathor@123' }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Nix | ||
| uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b | ||
| with: | ||
| nix_path: nixpkgs=channel:nixos-unstable | ||
| extra_nix_config: | | ||
| experimental-features = nix-command flakes | ||
|
|
||
| - name: Cache Nix | ||
| uses: DeterminateSystems/magic-nix-cache-action@v7 | ||
|
|
||
| - name: Install dependencies | ||
| run: nix develop . -c yarn install | ||
|
Comment on lines
+52
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files .github/workflows package.json yarn.lock | sed -n '1,120p'
echo
echo "== workflow context =="
if [ -f ".github/workflows/e2e-web-wallet-nightly.yml" ]; then
nl -ba .github/workflows/e2e-web-wallet-nightly.yml | sed -n '45,95p'
fi
echo
echo "== main workflow searches =="
rg -n "yarn install|immutable|e2e-web-wallet-nightly|nix develop.*yarn install" .github/workflows || true
echo
echo "== root package scripts =="
if [ -f package.json ]; then nl -ba package.json | sed -n '1,140p'; fi
echo
echo "== package manager metadata =="
if [ -f .yarnrc.yml ]; then nl -ba .yarnrc.yml | sed -n '1,160p'; fi
if [ -f corepack/package.json ]; then nl -ba corepack/package.json | sed -n '1,120p'; fi
echo
echo "== deterministic config probe =="
python3 - <<'PY'
import json, pathlib, re
p=pl.Path('.github/workflows/e2e-web-wallet-nightly.yml')
if not p.exists():
print("no nightly workflow")
else:
text=p.read_text()
for i,line in enumerate(text.splitlines(),1):
if 'yarn install' in line:
print(f"{i}: {line.strip()}")
PYRepository: HathorNetwork/hathor-rpc-lib Length of output: 427 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== read workflow file =="
awk '{printf "%4d\t%s\n", NR, $0}' .github/workflows/e2e-web-wallet-nightly.yml
echo
echo "== compare workflows for yarn installation =="
python3 - <<'PY'
import pathlib, re
for path in pathlib.Path(".github/workflows").glob("*.yml"):
text = path.read_text()
print(f"\n## {path}")
for i, line in enumerate(text.splitlines(), 1):
if "yarn install" in line or "immutable" in line or re.search(r"yarn\s+(install|set-version|enable-corepack)", line):
print(f"{i}: {line}")
PY
echo
echo "== root package/config files =="
awk '{printf "%4d\t%s\n", NR, $0}' package.json
echo
if [ -f .yarnrc.yml ]; then awk '{printf "%4d\t%s\n", NR, $0}' .yarnrc.yml; else echo "no .yarnrc.yml"; fi
echo
echo "== lockfile first bytes =="
awk 'NR<=40 {printf "%4d\t%s\n", NR, $0}' yarn.lockRepository: HathorNetwork/hathor-rpc-lib Length of output: 7291 Enforce the workspace lockfile during dependency installation. Yarn 4’s plain 🤖 Prompt for AI Agents |
||
|
|
||
| # Independent of PR 1: build the workspace dependency the snap dev build consumes, so this | ||
| # workflow is self-sufficient whether or not PR 1's self-building `yarn e2e` has merged. | ||
| - name: Build hathor-rpc-handler (snap dependency) | ||
| run: nix develop . -c yarn workspace @hathor/hathor-rpc-handler build | ||
|
|
||
| - name: Install Playwright Chromium | ||
| run: nix develop . -c yarn workspace @hathor/web-wallet exec playwright install chromium --with-deps | ||
|
|
||
| - name: Install xvfb | ||
| run: sudo apt-get update && sudo apt-get install -y xvfb | ||
|
|
||
| # Headed Chromium under a virtual display (MV3 extensions need a real display). The Playwright | ||
| # config's webServer boots the local snap (:8080) and the dApp dev server (:5173) itself. | ||
| - name: Run real-MetaMask E2E suite | ||
| run: | | ||
| xvfb-run -a nix develop . -c \ | ||
| yarn workspace @hathor/web-wallet exec \ | ||
| playwright test --config playwright.e2e.config.ts | ||
|
|
||
| - name: Upload Playwright report | ||
| if: ${{ always() }} | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: playwright-report | ||
| path: packages/web-wallet/playwright-report/ | ||
| retention-days: 14 | ||
| if-no-files-found: ignore | ||
|
|
||
| - name: Upload traces & videos | ||
| if: ${{ always() }} | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: playwright-traces | ||
| path: packages/web-wallet/test-results/ | ||
| retention-days: 14 | ||
| if-no-files-found: ignore | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| # PR 3 — Nightly non-gating real-MetaMask E2E CI (issue #177, item 2c) | ||
|
|
||
| Status: **ready to implement (autonomous)** | ||
| Issue: HathorNetwork/hathor-rpc-lib#177 (item 2c) | ||
| Design: `docs/superpowers/specs/2026-07-09-web-wallet-e2e-followups-177-design.md` | ||
| Base branch: **`master`** (independent — the workflow builds the handler explicitly, so it does not | ||
| depend on PR 1's self-sufficient `yarn e2e`) | ||
| Feature branch: `raul-oliveira/feat/web-wallet-e2e-followups-pr3` | ||
|
|
||
| > **For the implementing subagent:** git is authorized for this branch (commit + push + open-PR | ||
| > autopilot for this sequence). No `Co-Authored-By`. English artifacts. Full green requires a real | ||
| > scheduled GitHub run; locally you validate by **linting the YAML and dry-running the individual | ||
| > steps** — do **not** run the full headed suite here (that browser slot is PR 2's). | ||
|
|
||
| ## Problem | ||
|
|
||
| Nothing exercises the real-MetaMask suite in CI. `main.yml` runs on `[push]` and only runs the | ||
| lightweight smoke (`playwright test --project=chromium`), not `playwright.e2e.config.ts`. So rot like | ||
| item 1 (clean checkout can't run the suite) goes unnoticed until someone runs it by hand. The suite | ||
| is **explicitly non-gating**, so the fix is a **scheduled, signal-only** run — never a required | ||
| check, never blocking a PR. | ||
|
|
||
| ## Decision | ||
|
|
||
| A new **scheduled** GitHub Actions workflow, separate from `main.yml`, that runs the real-MetaMask | ||
| suite for signal only. A scheduled workflow never attaches as a PR status check, so it is inherently | ||
| non-gating; additionally it must **not** be added to branch protection / required checks. It reuses | ||
| the Nix toolchain from `main.yml`, boots a real headed Chromium under **xvfb** (MV3 extension loading | ||
| needs a real display; true `--headless` is deferred per the design's out-of-scope), and uploads the | ||
| HTML report + traces + videos as artifacts for triage. | ||
|
|
||
| ## Change — `.github/workflows/e2e-web-wallet-nightly.yml` (new) | ||
|
|
||
| ```yaml | ||
| # Real-MetaMask-Flask E2E suite for the web-wallet — SIGNAL ONLY, NON-GATING. | ||
| # | ||
| # This runs on a schedule (not per-PR) purely to surface rot in the on-demand E2E infrastructure | ||
| # (see packages/web-wallet/tests/e2e/e2e.md). It is NOT a required check and MUST NOT be added to | ||
| # branch protection. A red run means "a real-MetaMask journey didn't pass on the runner", which is | ||
| # often a slow cold-start rather than a broken product — triage via the uploaded artifacts. | ||
| name: E2E Web Wallet (nightly, non-gating) | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '0 6 * * *' # 06:00 UTC daily | ||
| workflow_dispatch: {} # allow manual runs from the Actions tab | ||
|
|
||
| concurrency: | ||
| group: e2e-web-wallet-nightly | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| e2e: | ||
| runs-on: ubuntu-latest | ||
| # Non-gating: never fail the workflow status in a way that could be mistaken for a gate. | ||
| # The step-level result + artifacts carry the signal; a red job here blocks nobody. | ||
| timeout-minutes: 60 | ||
| env: | ||
| # Pin the Flask build the selectors are verified against (driver/selectors.ts). | ||
| E2E_FLASK_VERSION: '13.31.0' | ||
| # Stretch every driver + page-object deadline for a slower shared runner. | ||
| E2E_TIMEOUT_SCALE: '2' | ||
| # MetaMask password for the throwaway wallet the driver onboards/imports each run. NOT a | ||
| # secret — it guards a fresh local MetaMask created per run; the funded seed is already public | ||
| # in wallets.config.json. The driver defaults to DEFAULT_PASSWORD ('Test1234!Test') if unset; | ||
| # 'Hathor@123' matches the owner's local .env.e2e so CI reproduces local runs 1:1. Override via | ||
| # a repo Actions variable `vars.E2E_PASSWORD` if desired. | ||
| E2E_PASSWORD: ${{ vars.E2E_PASSWORD || 'Hathor@123' }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Nix | ||
| uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b | ||
| with: | ||
| nix_path: nixpkgs=channel:nixos-unstable | ||
| extra_nix_config: | | ||
| experimental-features = nix-command flakes | ||
|
|
||
| - name: Cache Nix | ||
| uses: DeterminateSystems/magic-nix-cache-action@v7 | ||
|
|
||
| - name: Install dependencies | ||
| run: nix develop . -c yarn install --immutable | ||
|
|
||
| # Independent of PR 1: build the workspace dependency the snap dev build consumes, so this | ||
| # workflow is self-sufficient whether or not PR 1's self-building `yarn e2e` has merged. | ||
| - name: Build hathor-rpc-handler (snap dependency) | ||
| run: nix develop . -c yarn workspace @hathor/hathor-rpc-handler build | ||
|
|
||
| - name: Install Playwright Chromium | ||
| run: nix develop . -c yarn workspace @hathor/web-wallet exec playwright install chromium --with-deps | ||
|
|
||
| - name: Install xvfb | ||
| run: sudo apt-get update && sudo apt-get install -y xvfb | ||
|
|
||
| # Headed Chromium under a virtual display (MV3 extensions need a real display). The Playwright | ||
| # config's webServer boots the local snap (:8080) and the dApp dev server (:5173) itself. | ||
| - name: Run real-MetaMask E2E suite | ||
| run: | | ||
| xvfb-run -a nix develop . -c \ | ||
| yarn workspace @hathor/web-wallet exec \ | ||
| playwright test --config playwright.e2e.config.ts | ||
|
|
||
| - name: Upload Playwright report | ||
| if: ${{ always() }} | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: playwright-report | ||
| path: packages/web-wallet/playwright-report/ | ||
| retention-days: 14 | ||
| if-no-files-found: ignore | ||
|
|
||
| - name: Upload traces & videos | ||
| if: ${{ always() }} | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: playwright-traces | ||
| path: packages/web-wallet/test-results/ | ||
| retention-days: 14 | ||
| if-no-files-found: ignore | ||
| ``` | ||
|
|
||
| ### Notes for the subagent (verify, don't assume) | ||
|
|
||
| - **`--immutable`** on install: confirm the repo's yarn install is clean in CI; if `main.yml` uses a | ||
| plain `yarn install`, match that instead to avoid lockfile-churn failures. Prefer matching | ||
| `main.yml`'s exact invocation. | ||
| - **`E2E_PASSWORD`** (confirmed): the driver reads it at `MetaMaskDriver.ts:128,229` with fallback | ||
| `DEFAULT_PASSWORD = 'Test1234!Test'`. The env line is therefore optional, but keep it set to | ||
| `Hathor@123` (the owner's local value) so CI reproduces local runs 1:1. Any valid MetaMask password | ||
| works — the wallet is created fresh each run, so the value only needs to be internally consistent. | ||
| - **No PIN is consumed.** The E2E suite reads only `E2E_PASSWORD` (plus `E2E_FLASK_VERSION`, | ||
| `E2E_TIMEOUT_SCALE`, `E2E_HEADED/HEADLESS`, `E2E_METAMASK_PATH`, `E2E_DEBUG`, `E2E_SPLIT_WINDOWS`). | ||
| There is no PIN env var and no page object types a PIN — the Snap signs off MetaMask's unlocked | ||
| seed, so the standalone-wallet PIN (`123123`) is not needed anywhere in these workflows. Do not wire | ||
| an unused `E2E_PIN`. | ||
| - **Funded journeys**: `import`, `feature-example`, `token-lifecycle` use the committed `funded` | ||
| testnet stub seed; they pass only while that testnet address has balance. On a dry wallet they fail | ||
| at their first funded step — acceptable for a non-gating signal run. If the team wants a clean | ||
| always-green signal, a follow-up can restrict the schedule to `--project=onboarding` (dry); leave | ||
| the full matrix here and document the caveat in the PR body. | ||
| - **xvfb availability**: `xvfb-run` comes from the `xvfb` apt package (installed above); | ||
| `playwright install --with-deps` does not guarantee it. Keep the explicit apt step. | ||
| - **Pin actions** the way `main.yml` does (it pins `install-nix-action` by SHA, uses | ||
| `magic-nix-cache-action@v7`). Match those exact refs. | ||
|
|
||
| ## Validation | ||
|
|
||
| - **Lint the YAML**: `nix develop . -c npx --yes @action-validator/cli .github/workflows/e2e-web-wallet-nightly.yml` | ||
| (or `actionlint` if available in the shell); at minimum, parse it with a YAML loader to confirm it | ||
| is well-formed. Confirm indentation and that every `uses:` ref matches `main.yml`'s style. | ||
| - **Dry-run the load-bearing steps locally** (inside `nix develop`): `yarn install`, the handler | ||
| build, `playwright install chromium` — confirm each succeeds. Do **not** run the full headed suite | ||
| locally (PR 2 owns the browser slot during the sequence). | ||
| - State plainly in the PR that **full green requires a real scheduled/`workflow_dispatch` run on | ||
| GitHub**; the local checks only prove the workflow is well-formed and its steps resolve. | ||
|
|
||
| ## Files | ||
|
|
||
| | File | Change | | ||
| |------|--------| | ||
| | `.github/workflows/e2e-web-wallet-nightly.yml` | **new** scheduled non-gating workflow | | ||
| | `packages/web-wallet/tests/e2e/e2e.md` | one line pointing at the nightly workflow as the CI signal (optional, keep tiny) | | ||
| | `docs/superpowers/specs/2026-07-28-web-wallet-e2e-pr3-nightly-ci.md` | copy this spec into the worktree | | ||
|
|
||
| ## PR | ||
|
|
||
| - **Single commit.** Message: `ci(web-wallet): nightly non-gating real-MetaMask E2E workflow` | ||
| - **Title:** `ci(web-wallet): nightly non-gating E2E workflow (#177 item 2c)` | ||
| - **Template** feature-branch: Motivation / Acceptance Criteria (**plain bullets**) / Checklist. | ||
| - **Assignee** `raul-oliveira`; **Board** project #15 → In Progress (Done). REST for | ||
| title/body/assignee. In the body: PR 3 of the #177 sequence, closes item 2c; note it is | ||
| intentionally non-gating and must not be added to required checks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: HathorNetwork/hathor-rpc-lib
Length of output: 4289
🌐 Web query:
actions/checkout v4 persist-credentials default true README💡 Result:
In the actions/checkout action, the persist-credentials input has a default value of true [1][2][3]. When set to true (the default), the action automatically configures the repository's local git configuration with the provided token or SSH key [1][3]. This allows subsequent git commands (such as git fetch or git push) run within the same job to be authenticated automatically [4][3]. This token is removed during the post-job cleanup process [4][3]. To opt out of this behavior, you can explicitly set persist-credentials to false in your workflow file: - uses: actions/checkout@v4 with: persist-credentials: false Note that in newer versions (v6.0.0 and later), the implementation of this feature was updated to store credentials in a file under $RUNNER_TEMP rather than directly in the local.git/config file, which improves security [3][5][6].
Citations:
🏁 Script executed:
Repository: HathorNetwork/hathor-rpc-lib
Length of output: 247
🌐 Web query:
site:github.com/actions/checkout v4 persist-credentials default true README💡 Result:
In the
actions/checkoutaction, thepersist-credentialsinput controls whether the authentication token (or SSH key) is configured in the local git repository's configuration [1][2]. As of the current version (v4), the default value forpersist-credentialsremainstrue[1][2]. When set totrue, the action persists the credentials in the local git config, allowing subsequent steps in your workflow to execute authenticated git commands (e.g.,git fetch,git push) [1][3]. These credentials are automatically removed during the post-job cleanup phase [1]. If you wish to opt out of this behavior for security reasons or because it is not required, you can explicitly set the input tofalsein your workflow YAML [1]: - name: Checkout uses: actions/checkout@v4 with: persist-credentials: false While there has been community discussion and proposed pull requests (such as PR#1687) to change this default tofalseto reduce the risk of credential exposure, the officialaction.ymland documentation foractions/checkout@v4continue to listtrueas the default [1][2][4].Citations:
Disable checkout credential persistence.
actions/checkout@v4persists the read-onlyGITHUB_TOKENin.git/configby default. This workflow’s remaining steps only install dependencies, build, install Playwright, and run/upload E2E artifacts, so authenticated Git commands are not needed.Proposed fix
- name: Checkout code uses: actions/checkout@v4 + with: + persist-credentials: false📝 Committable suggestion
🧰 Tools
🪛 zizmor (1.28.0)
[warning] 39-40: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Source: Linters/SAST tools