mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-08-01 16:58:43 +02:00
chore: linting
This commit is contained in:
@@ -9,9 +9,6 @@ on:
|
||||
default: true
|
||||
type: boolean
|
||||
secrets:
|
||||
TAURI_WEBDRIVER_TOKEN:
|
||||
description: Read-only token for the test-driver repository
|
||||
required: false
|
||||
WAYFERN_TEST_TOKEN:
|
||||
description: Token used by the full Wayfern integration suite
|
||||
required: false
|
||||
@@ -64,15 +61,6 @@ jobs:
|
||||
- name: Checkout Donut Browser
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
path: donutbrowser
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout test driver
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
repository: ${{ vars.TAURI_WEBDRIVER_REPOSITORY }}
|
||||
token: ${{ secrets.TAURI_WEBDRIVER_TOKEN || github.token }}
|
||||
path: tauri-wd
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install pnpm
|
||||
@@ -83,9 +71,9 @@ jobs:
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version-file: donutbrowser/.node-version
|
||||
node-version-file: .node-version
|
||||
cache: pnpm
|
||||
cache-dependency-path: donutbrowser/pnpm-lock.yaml
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
@@ -96,9 +84,14 @@ jobs:
|
||||
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
workspaces: |
|
||||
donutbrowser/src-tauri -> target
|
||||
donutbrowser/e2e/app -> target
|
||||
tauri-wd -> target
|
||||
src-tauri -> target
|
||||
e2e/app -> target
|
||||
|
||||
- name: Cache WebDriver test driver
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: e2e/.driver
|
||||
key: tauri-wd-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('e2e/app/Cargo.lock') }}
|
||||
|
||||
- name: Install Tauri dependencies
|
||||
if: runner.os == 'Linux'
|
||||
@@ -107,11 +100,9 @@ jobs:
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf libxdo-dev xvfb openvpn
|
||||
|
||||
- name: Install app dependencies
|
||||
working-directory: donutbrowser
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run isolated smoke suite
|
||||
working-directory: donutbrowser
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${RUNNER_OS}" == "Linux" ]]; then
|
||||
@@ -139,15 +130,6 @@ jobs:
|
||||
- name: Checkout Donut Browser
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
path: donutbrowser
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout test driver
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
repository: ${{ vars.TAURI_WEBDRIVER_REPOSITORY }}
|
||||
token: ${{ secrets.TAURI_WEBDRIVER_TOKEN || github.token }}
|
||||
path: tauri-wd
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install pnpm
|
||||
@@ -158,9 +140,9 @@ jobs:
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version-file: donutbrowser/.node-version
|
||||
node-version-file: .node-version
|
||||
cache: pnpm
|
||||
cache-dependency-path: donutbrowser/pnpm-lock.yaml
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
@@ -171,16 +153,19 @@ jobs:
|
||||
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
workspaces: |
|
||||
donutbrowser/src-tauri -> target
|
||||
donutbrowser/e2e/app -> target
|
||||
tauri-wd -> target
|
||||
src-tauri -> target
|
||||
e2e/app -> target
|
||||
|
||||
- name: Cache WebDriver test driver
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: e2e/.driver
|
||||
key: tauri-wd-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('e2e/app/Cargo.lock') }}
|
||||
|
||||
- name: Install app dependencies
|
||||
working-directory: donutbrowser
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run full isolated app suite
|
||||
working-directory: donutbrowser
|
||||
env:
|
||||
DONUT_E2E_SUITE: ${{ inputs.suite || 'full' }}
|
||||
DONUT_E2E_SKIP_NETWORK_TEST: "1"
|
||||
@@ -206,15 +191,6 @@ jobs:
|
||||
- name: Checkout Donut Browser
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
path: donutbrowser
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout test driver
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
repository: ${{ vars.TAURI_WEBDRIVER_REPOSITORY }}
|
||||
token: ${{ secrets.TAURI_WEBDRIVER_TOKEN || github.token }}
|
||||
path: tauri-wd
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install pnpm
|
||||
@@ -225,9 +201,9 @@ jobs:
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
node-version-file: donutbrowser/.node-version
|
||||
node-version-file: .node-version
|
||||
cache: pnpm
|
||||
cache-dependency-path: donutbrowser/pnpm-lock.yaml
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
|
||||
@@ -238,9 +214,14 @@ jobs:
|
||||
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
workspaces: |
|
||||
donutbrowser/src-tauri -> target
|
||||
donutbrowser/e2e/app -> target
|
||||
tauri-wd -> target
|
||||
src-tauri -> target
|
||||
e2e/app -> target
|
||||
|
||||
- name: Cache WebDriver test driver
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: e2e/.driver
|
||||
key: tauri-wd-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('e2e/app/Cargo.lock') }}
|
||||
|
||||
- name: Install Tauri dependencies
|
||||
run: |
|
||||
@@ -248,11 +229,9 @@ jobs:
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf libxdo-dev xvfb openvpn
|
||||
|
||||
- name: Install app dependencies
|
||||
working-directory: donutbrowser
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run isolated real-network suite
|
||||
working-directory: donutbrowser
|
||||
env:
|
||||
WAYFERN_TEST_TOKEN: ${{ secrets.WAYFERN_TEST_TOKEN }}
|
||||
RESIDENTIAL_PROXY_URL_ONE_SOCKS: ${{ secrets.RESIDENTIAL_PROXY_URL_ONE_SOCKS }}
|
||||
|
||||
@@ -84,14 +84,24 @@ jobs:
|
||||
response_format: { type: "json_object" }
|
||||
}')
|
||||
|
||||
RESPONSE=$(curl -fsSL https://models.github.ai/inference/chat/completions \
|
||||
# Never use curl -f here: a transport or quota error (402 once the repo's
|
||||
# GitHub Models allowance is spent) must not abort the job. The whole
|
||||
# step is fail-open, so capture the status and degrade instead.
|
||||
STATUS=$(curl -sSL -o /tmp/response.json -w '%{http_code}' \
|
||||
https://models.github.ai/inference/chat/completions \
|
||||
-H "Authorization: Bearer $GH_MODELS_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2026-03-10" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD")
|
||||
-d "$PAYLOAD" || echo "000")
|
||||
|
||||
jq -r '.choices[0].message.content // empty' <<< "$RESPONSE" > /tmp/raw.txt
|
||||
if [ "$STATUS" != "200" ]; then
|
||||
echo "::warning::GitHub Models returned HTTP $STATUS; treating as compliant"
|
||||
echo '{"is_compliant": true, "non_compliance_reasons": []}' > /tmp/result.json
|
||||
exit 0
|
||||
fi
|
||||
|
||||
jq -r '.choices[0].message.content // empty' /tmp/response.json > /tmp/raw.txt || : > /tmp/raw.txt
|
||||
|
||||
# Strip accidental markdown fences and parse. On parse failure, fall back
|
||||
# to a compliant result so a flaky model never closes a legitimate issue.
|
||||
|
||||
@@ -243,14 +243,23 @@ jobs:
|
||||
]
|
||||
}')
|
||||
|
||||
RESPONSE=$(curl -fsSL https://models.github.ai/inference/chat/completions \
|
||||
# Never use curl -f here: a transport or quota error (402 once the repo's
|
||||
# GitHub Models allowance is spent) must not abort the job. Capture the
|
||||
# status and fall through to the safe classification below.
|
||||
STATUS=$(curl -sSL -o /tmp/triage-response.json -w '%{http_code}' \
|
||||
https://models.github.ai/inference/chat/completions \
|
||||
-H "Authorization: Bearer $GH_MODELS_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2026-03-10" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD")
|
||||
-d "$PAYLOAD" || echo "000")
|
||||
|
||||
jq -r '.choices[0].message.content // empty' <<< "$RESPONSE" > /tmp/triage-raw.txt
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
jq -r '.choices[0].message.content // empty' /tmp/triage-response.json > /tmp/triage-raw.txt || : > /tmp/triage-raw.txt
|
||||
else
|
||||
echo "::warning::GitHub Models returned HTTP $STATUS for triage"
|
||||
: > /tmp/triage-raw.txt
|
||||
fi
|
||||
|
||||
# Normalize optional markdown fences before parsing.
|
||||
sed -E 's/^```(json)?$//; s/```$//' /tmp/triage-raw.txt > /tmp/triage.json
|
||||
@@ -375,6 +384,7 @@ jobs:
|
||||
wc -c /tmp/composer-system.txt
|
||||
|
||||
- name: Stage 2 (compose response)
|
||||
id: compose
|
||||
env:
|
||||
GH_MODELS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_AUTHOR: ${{ github.event.issue.user.login }}
|
||||
@@ -415,21 +425,34 @@ jobs:
|
||||
]
|
||||
}')
|
||||
|
||||
RESPONSE=$(curl -fsSL https://models.github.ai/inference/chat/completions \
|
||||
# Same as triage: a quota or transport error must not fail the run. When
|
||||
# no comment can be composed the remaining steps are skipped instead.
|
||||
STATUS=$(curl -sSL -o /tmp/compose-response.json -w '%{http_code}' \
|
||||
https://models.github.ai/inference/chat/completions \
|
||||
-H "Authorization: Bearer $GH_MODELS_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2026-03-10" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD")
|
||||
-d "$PAYLOAD" || echo "000")
|
||||
|
||||
jq -r '.choices[0].message.content // empty' <<< "$RESPONSE" > /tmp/ai-comment.txt
|
||||
|
||||
if [ ! -s /tmp/ai-comment.txt ]; then
|
||||
echo "::error::Composer returned empty response"
|
||||
exit 1
|
||||
if [ "$STATUS" != "200" ]; then
|
||||
echo "::warning::GitHub Models returned HTTP $STATUS; skipping the triage comment"
|
||||
echo "has_comment=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
jq -r '.choices[0].message.content // empty' /tmp/compose-response.json > /tmp/ai-comment.txt || : > /tmp/ai-comment.txt
|
||||
|
||||
if [ ! -s /tmp/ai-comment.txt ]; then
|
||||
echo "::warning::Composer returned empty response; skipping the triage comment"
|
||||
echo "has_comment=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "has_comment=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Strip forbidden sections (defense in depth)
|
||||
if: steps.compose.outputs.has_comment == 'true'
|
||||
run: |
|
||||
# LLMs still emit "Possible cause" and friends despite the prompt rules.
|
||||
# Strip any such heading and its block, plus stray `Label:` lines left
|
||||
@@ -452,6 +475,7 @@ jobs:
|
||||
EOF
|
||||
|
||||
- name: Post comment (no labeling)
|
||||
if: steps.compose.outputs.has_comment == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
@@ -524,6 +548,7 @@ jobs:
|
||||
mv /tmp/pr-file-context.safe.txt /tmp/pr-file-context.txt
|
||||
|
||||
- name: Analyze PR with AI
|
||||
id: analyze
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_MODELS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -583,21 +608,34 @@ jobs:
|
||||
]
|
||||
}')
|
||||
|
||||
RESPONSE=$(curl -fsSL https://models.github.ai/inference/chat/completions \
|
||||
# A quota or transport error must not fail the run; skip the review
|
||||
# comment instead of red-crossing an otherwise healthy pull request.
|
||||
STATUS=$(curl -sSL -o /tmp/pr-response.json -w '%{http_code}' \
|
||||
https://models.github.ai/inference/chat/completions \
|
||||
-H "Authorization: Bearer $GH_MODELS_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2026-03-10" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD")
|
||||
-d "$PAYLOAD" || echo "000")
|
||||
|
||||
jq -r '.choices[0].message.content // empty' <<< "$RESPONSE" > /tmp/ai-comment.txt
|
||||
|
||||
if [ ! -s /tmp/ai-comment.txt ]; then
|
||||
echo "::error::AI response was empty"
|
||||
exit 1
|
||||
if [ "$STATUS" != "200" ]; then
|
||||
echo "::warning::GitHub Models returned HTTP $STATUS; skipping the review comment"
|
||||
echo "has_comment=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
jq -r '.choices[0].message.content // empty' /tmp/pr-response.json > /tmp/ai-comment.txt || : > /tmp/ai-comment.txt
|
||||
|
||||
if [ ! -s /tmp/ai-comment.txt ]; then
|
||||
echo "::warning::AI response was empty; skipping the review comment"
|
||||
echo "has_comment=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "has_comment=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Post comment
|
||||
if: steps.analyze.outputs.has_comment == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
|
||||
@@ -121,14 +121,25 @@ jobs:
|
||||
response_format: { type: "json_object" }
|
||||
}')
|
||||
|
||||
RESPONSE=$(curl -fsSL https://models.github.ai/inference/chat/completions \
|
||||
# Never use curl -f here: a transport or quota error (402 once the repo's
|
||||
# GitHub Models allowance is spent) must not abort the job. The model
|
||||
# half of this check is fail-open, and the deterministic trailer scan
|
||||
# below still runs regardless.
|
||||
STATUS=$(curl -sSL -o /tmp/response.json -w '%{http_code}' \
|
||||
https://models.github.ai/inference/chat/completions \
|
||||
-H "Authorization: Bearer $GH_MODELS_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2026-03-10" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD")
|
||||
-d "$PAYLOAD" || echo "000")
|
||||
|
||||
jq -r '.choices[0].message.content // empty' <<< "$RESPONSE" > /tmp/raw.txt
|
||||
if [ "$STATUS" != "200" ]; then
|
||||
echo "::warning::GitHub Models returned HTTP $STATUS; treating as compliant"
|
||||
echo '{"compliant": true, "violations": []}' > /tmp/result.json
|
||||
exit 0
|
||||
fi
|
||||
|
||||
jq -r '.choices[0].message.content // empty' /tmp/response.json > /tmp/raw.txt || : > /tmp/raw.txt
|
||||
|
||||
# Strip accidental markdown fences and parse. On parse failure, fall
|
||||
# back to compliant so a flaky model never closes a legitimate PR.
|
||||
|
||||
@@ -46,7 +46,6 @@ jobs:
|
||||
name: Cross-platform App E2E
|
||||
uses: ./.github/workflows/app-e2e.yml
|
||||
secrets:
|
||||
TAURI_WEBDRIVER_TOKEN: ${{ secrets.TAURI_WEBDRIVER_TOKEN }}
|
||||
WAYFERN_TEST_TOKEN: ${{ secrets.WAYFERN_TEST_TOKEN }}
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# testing
|
||||
/coverage
|
||||
/e2e/app/target/
|
||||
/e2e/.driver/
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
|
||||
@@ -91,7 +91,8 @@ donutbrowser/
|
||||
|
||||
### Native app E2E tests are mandatory for affected behavior
|
||||
|
||||
The native suites use a sibling private test-driver repository and launch an `e2e`-feature build.
|
||||
The native suites use the published `tauri-wd` driver (pinned in `e2e/app/Cargo.toml`, installed
|
||||
into the ignored `e2e/.driver` root) and launch an `e2e`-feature build.
|
||||
Every session gets its own temporary Donut data/cache/log root, home directory,
|
||||
WebView store, ports, and sync bucket. Never point a suite at production or development data.
|
||||
|
||||
|
||||
+15
-17
@@ -1,6 +1,7 @@
|
||||
# Donut Browser native E2E tests
|
||||
|
||||
These tests exercise the actual Tauri application through a sibling native test driver. They do
|
||||
These tests exercise the actual Tauri application through the published
|
||||
[`tauri-wd`](https://crates.io/crates/tauri-wd) native test driver. They do
|
||||
not replace Rust or React unit tests; they
|
||||
cover the process boundaries those tests cannot: WKWebView/WebView2/WebKitGTK UI, Tauri invokes,
|
||||
REST and MCP servers, two-device sync, S3 payload encryption, Wayfern, CDP, and child-process
|
||||
@@ -8,15 +9,9 @@ cleanup.
|
||||
|
||||
## Local setup
|
||||
|
||||
Place both repositories beside each other:
|
||||
|
||||
```text
|
||||
Code/
|
||||
├── donutbrowser/
|
||||
└── <test-driver-checkout>/
|
||||
```
|
||||
|
||||
Install Donut dependencies with `pnpm install`. The browser suite also needs
|
||||
Install Donut dependencies with `pnpm install`. The runner installs the driver itself with
|
||||
`cargo install`, so a working Rust toolchain is the only extra requirement. The browser suite also
|
||||
needs
|
||||
`WAYFERN_TEST_TOKEN`. The runner reads it from the environment or Donut's ignored `.env` without
|
||||
printing it. When a local browser fixture is configured, the runner copies it into the test data
|
||||
root (using an isolated APFS clone on macOS); otherwise the browser suite downloads the current
|
||||
@@ -42,10 +37,13 @@ pnpm e2e:sync
|
||||
pnpm e2e:browser
|
||||
```
|
||||
|
||||
Run everything with `pnpm e2e`. A normal run builds the Next frontend, `donut-proxy`, the
|
||||
private harness in `e2e/app`, and `tauri-wd`. The harness enables Donut's `e2e` feature and injects
|
||||
the sibling WebDriver plugin without making the production crate depend on a private filesystem
|
||||
path. Add `--no-build` to `node e2e/run.mjs --suite=<name>` only when all four outputs are current.
|
||||
Run everything with `pnpm e2e`. A normal run builds the Next frontend, `donut-proxy`, and the
|
||||
harness in `e2e/app`, then installs the `tauri-wd` CLI into the ignored `e2e/.driver` root when the
|
||||
version pinned by `e2e/app/Cargo.lock` is not already there. The harness enables Donut's `e2e`
|
||||
feature and injects the WebDriver plugin so the production crate never depends on it. Both the
|
||||
plugin and the CLI come from the same pinned crates.io release, so they cannot drift apart. Bump
|
||||
the pin in `e2e/app/Cargo.toml` to move to a newer driver. Add `--no-build` to
|
||||
`node e2e/run.mjs --suite=<name>` only when all four outputs are current.
|
||||
`DONUT_E2E_KEEP_ARTIFACTS=1` retains successful local runs; failed runs are always retained and
|
||||
their location is printed. Raw screenshots, captured HTML, logs, and isolated app state stay local.
|
||||
The runner also creates a text-only `diagnostics/` directory whose logs are redacted and checked
|
||||
@@ -87,7 +85,7 @@ requests. Pushes to `main`, weekly schedules, and manual runs execute the full m
|
||||
including MinIO-backed sync and real Wayfern automation, plus a Linux/Docker job for residential
|
||||
proxy and local WireGuard browser traffic.
|
||||
|
||||
CI needs a `TAURI_WEBDRIVER_TOKEN` secret with read-only access and a
|
||||
`TAURI_WEBDRIVER_REPOSITORY` repository variable identifying the test-driver checkout. The full
|
||||
job also requires the `WAYFERN_TEST_TOKEN` secret. The network job requires that secret plus
|
||||
Every job restores the compiled driver from an `actions/cache` entry keyed by `e2e/app/Cargo.lock`,
|
||||
the same file the runner reads the version from, so only a driver bump pays for a rebuild. The full job requires the
|
||||
`WAYFERN_TEST_TOKEN` secret. The network job requires that secret plus
|
||||
`RESIDENTIAL_PROXY_URL_ONE_HTTP` and `RESIDENTIAL_PROXY_URL_ONE_SOCKS`.
|
||||
|
||||
Generated
+139
-22
@@ -1131,9 +1131,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.1"
|
||||
version = "4.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
|
||||
checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -1141,9 +1141,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.6.0"
|
||||
version = "4.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||
checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -1153,14 +1153,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.6.1"
|
||||
version = "4.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
|
||||
checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.118",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2370,9 +2370,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.32"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
||||
checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -2380,9 +2380,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.32"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||
checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
@@ -2397,9 +2397,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.32"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
||||
checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
@@ -2416,9 +2416,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.32"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||
checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2427,21 +2427,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.32"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
||||
checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.32"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
||||
checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.32"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||
checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -3819,6 +3819,15 @@ dependencies = [
|
||||
"web_atoms",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.8.4"
|
||||
@@ -4066,6 +4075,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.8"
|
||||
@@ -4950,6 +4968,19 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "process-wrap"
|
||||
version = "9.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e842efad9119158434d193c6682e2ebee4b44d6ad801d7b349623b3f57cdf55"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"indexmap 2.14.0",
|
||||
"nix",
|
||||
"tokio",
|
||||
"windows 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiling"
|
||||
version = "1.0.18"
|
||||
@@ -6019,6 +6050,15 @@ dependencies = [
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_child"
|
||||
version = "1.1.1"
|
||||
@@ -6327,6 +6367,17 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "1.0.2"
|
||||
@@ -6907,13 +6958,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-wd"
|
||||
version = "0.1.0"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "535cd782aac407a0bbf593013306e89e821017e3862ddd7b36925aa80a29e649"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
"base64 0.23.0",
|
||||
"block2",
|
||||
"cairo-rs",
|
||||
"clap",
|
||||
"futures-util",
|
||||
"glib 0.21.5",
|
||||
"gtk",
|
||||
"image",
|
||||
@@ -6922,13 +6977,17 @@ dependencies = [
|
||||
"objc2-app-kit",
|
||||
"objc2-foundation",
|
||||
"objc2-web-kit",
|
||||
"process-wrap",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"uuid",
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
@@ -7009,6 +7068,15 @@ dependencies = [
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.11.3"
|
||||
@@ -7418,6 +7486,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7789,6 +7900,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.12.0"
|
||||
|
||||
+1
-1
@@ -6,4 +6,4 @@ publish = false
|
||||
|
||||
[dependencies]
|
||||
donutbrowser-lib = { package = "donutbrowser", path = "../../src-tauri", features = ["e2e"] }
|
||||
tauri-wd = { path = "../../../tauri-wd/crates/tauri-wd" }
|
||||
tauri-wd = "=0.1.11"
|
||||
|
||||
+56
-17
@@ -5,6 +5,7 @@ import {
|
||||
createReadStream,
|
||||
createWriteStream,
|
||||
existsSync,
|
||||
readFileSync,
|
||||
statSync,
|
||||
} from "node:fs";
|
||||
import {
|
||||
@@ -28,21 +29,19 @@ import { createSafeDiagnostics } from "./lib/diagnostics.mjs";
|
||||
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.resolve(dirname, "..");
|
||||
const webdriverRoot = path.resolve(projectRoot, "../tauri-wd");
|
||||
const isWindows = process.platform === "win32";
|
||||
const executableSuffix = isWindows ? ".exe" : "";
|
||||
const appManifestDir = path.join(projectRoot, "e2e", "app");
|
||||
const appBinary = path.join(
|
||||
projectRoot,
|
||||
"e2e",
|
||||
"app",
|
||||
appManifestDir,
|
||||
"target",
|
||||
"debug",
|
||||
`donutbrowser-e2e${executableSuffix}`,
|
||||
);
|
||||
const driverRoot = path.join(projectRoot, "e2e", ".driver");
|
||||
const driverBinary = path.join(
|
||||
webdriverRoot,
|
||||
"target",
|
||||
"debug",
|
||||
driverRoot,
|
||||
"bin",
|
||||
`tauri-wd${executableSuffix}`,
|
||||
);
|
||||
|
||||
@@ -238,10 +237,55 @@ async function loadLocalValues(names) {
|
||||
return values;
|
||||
}
|
||||
|
||||
function buildAll() {
|
||||
if (!existsSync(webdriverRoot)) {
|
||||
throw new Error(`Missing sibling webdriver repository: ${webdriverRoot}`);
|
||||
function lockedDriverVersion() {
|
||||
const lockfile = readFileSync(
|
||||
path.join(appManifestDir, "Cargo.lock"),
|
||||
"utf8",
|
||||
);
|
||||
const match = lockfile.match(
|
||||
/\[\[package\]\]\s*\nname = "tauri-wd"\s*\nversion = "([^"]+)"/,
|
||||
);
|
||||
if (!match) {
|
||||
throw new Error("e2e/app/Cargo.lock does not resolve a tauri-wd version");
|
||||
}
|
||||
return match[1];
|
||||
}
|
||||
|
||||
function installedDriverVersion() {
|
||||
if (!existsSync(driverBinary)) {
|
||||
return null;
|
||||
}
|
||||
const result = spawnSync(driverBinary, ["--version"], { encoding: "utf8" });
|
||||
if (result.status !== 0) {
|
||||
return null;
|
||||
}
|
||||
return result.stdout.trim().split(/\s+/).pop() ?? null;
|
||||
}
|
||||
|
||||
function ensureDriver() {
|
||||
const version = lockedDriverVersion();
|
||||
if (installedDriverVersion() === version) {
|
||||
log(`tauri-wd ${version} already installed at ${driverBinary}`);
|
||||
return;
|
||||
}
|
||||
run(
|
||||
"cargo",
|
||||
[
|
||||
"install",
|
||||
"tauri-wd",
|
||||
"--version",
|
||||
version,
|
||||
"--locked",
|
||||
"--debug",
|
||||
"--force",
|
||||
"--root",
|
||||
driverRoot,
|
||||
],
|
||||
projectRoot,
|
||||
);
|
||||
}
|
||||
|
||||
function buildAll() {
|
||||
run("pnpm", ["build"], projectRoot);
|
||||
run("pnpm", ["copy-proxy-binary"], projectRoot);
|
||||
run(process.execPath, ["src-tauri/download-xray.mjs"], projectRoot);
|
||||
@@ -250,11 +294,7 @@ function buildAll() {
|
||||
["build", "--locked", "--manifest-path", "e2e/app/Cargo.toml"],
|
||||
projectRoot,
|
||||
);
|
||||
run(
|
||||
"cargo",
|
||||
["build", "--package", "tauri-cross-platform-webdriver"],
|
||||
webdriverRoot,
|
||||
);
|
||||
ensureDriver();
|
||||
}
|
||||
|
||||
function startFixtureServer(geoIpFixture) {
|
||||
@@ -866,7 +906,7 @@ async function main() {
|
||||
options.verbose ? "debug" : "info",
|
||||
],
|
||||
{
|
||||
cwd: webdriverRoot,
|
||||
cwd: projectRoot,
|
||||
env: process.env,
|
||||
runRoot,
|
||||
verbose: options.verbose,
|
||||
@@ -928,7 +968,6 @@ async function main() {
|
||||
...process.env,
|
||||
DONUT_E2E_RUN_ROOT: runRoot,
|
||||
DONUT_E2E_PROJECT_ROOT: projectRoot,
|
||||
DONUT_E2E_WEBDRIVER_ROOT: webdriverRoot,
|
||||
DONUT_E2E_APP: appBinary,
|
||||
DONUT_E2E_DRIVER_URL: `http://127.0.0.1:${driverPort}`,
|
||||
DONUT_E2E_FIXTURE_URL: `http://127.0.0.1:${fixture.port}`,
|
||||
|
||||
Generated
+14
-31
@@ -700,8 +700,8 @@ packages:
|
||||
'@emnapi/runtime@1.10.0':
|
||||
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
|
||||
|
||||
'@emnapi/runtime@1.11.3':
|
||||
resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
|
||||
'@emnapi/runtime@1.11.1':
|
||||
resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==}
|
||||
|
||||
'@emnapi/wasi-threads@1.2.1':
|
||||
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
|
||||
@@ -2837,8 +2837,8 @@ packages:
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
baseline-browser-mapping@2.11.3:
|
||||
resolution: {integrity: sha512-sbT0Ui/CZwyAyy7icT1Gw5P1LKRlFaHwaF6tDCW5YHq2X5SeeZFphBuIagopSfwSSZq3sQcbmEL072yphxm7ew==}
|
||||
baseline-browser-mapping@2.10.38:
|
||||
resolution: {integrity: sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -2905,8 +2905,8 @@ packages:
|
||||
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
caniuse-lite@1.0.30001806:
|
||||
resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==}
|
||||
caniuse-lite@1.0.30001799:
|
||||
resolution: {integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==}
|
||||
|
||||
canvas-confetti@1.9.4:
|
||||
resolution: {integrity: sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==}
|
||||
@@ -4098,11 +4098,6 @@ packages:
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
nanoid@3.3.16:
|
||||
resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
napi-postinstall@0.3.4:
|
||||
resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
|
||||
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
||||
@@ -4291,10 +4286,6 @@ packages:
|
||||
resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
postcss@8.5.23:
|
||||
resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
pretty-format@30.4.1:
|
||||
resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==}
|
||||
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
|
||||
@@ -5761,7 +5752,7 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@emnapi/runtime@1.11.3':
|
||||
'@emnapi/runtime@1.11.1':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
@@ -5878,7 +5869,7 @@ snapshots:
|
||||
|
||||
'@img/sharp-wasm32@0.35.3':
|
||||
dependencies:
|
||||
'@emnapi/runtime': 1.11.3
|
||||
'@emnapi/runtime': 1.11.1
|
||||
optional: true
|
||||
|
||||
'@img/sharp-webcontainers-wasm32@0.35.3':
|
||||
@@ -8023,7 +8014,7 @@ snapshots:
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
|
||||
baseline-browser-mapping@2.11.3: {}
|
||||
baseline-browser-mapping@2.10.38: {}
|
||||
|
||||
bl@4.1.0:
|
||||
dependencies:
|
||||
@@ -8053,8 +8044,8 @@ snapshots:
|
||||
|
||||
browserslist@4.28.4:
|
||||
dependencies:
|
||||
baseline-browser-mapping: 2.11.3
|
||||
caniuse-lite: 1.0.30001806
|
||||
baseline-browser-mapping: 2.10.38
|
||||
caniuse-lite: 1.0.30001799
|
||||
electron-to-chromium: 1.5.376
|
||||
node-releases: 2.0.48
|
||||
update-browserslist-db: 1.2.3(browserslist@4.28.4)
|
||||
@@ -8098,7 +8089,7 @@ snapshots:
|
||||
|
||||
camelcase@6.3.0: {}
|
||||
|
||||
caniuse-lite@1.0.30001806: {}
|
||||
caniuse-lite@1.0.30001799: {}
|
||||
|
||||
canvas-confetti@1.9.4: {}
|
||||
|
||||
@@ -9382,8 +9373,6 @@ snapshots:
|
||||
|
||||
nanoid@3.3.16: {}
|
||||
|
||||
nanoid@3.3.16: {}
|
||||
|
||||
napi-postinstall@0.3.4: {}
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
@@ -9401,8 +9390,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@next/env': 16.2.11
|
||||
'@swc/helpers': 0.5.15
|
||||
baseline-browser-mapping: 2.11.3
|
||||
caniuse-lite: 1.0.30001806
|
||||
baseline-browser-mapping: 2.10.38
|
||||
caniuse-lite: 1.0.30001799
|
||||
postcss: 8.5.23
|
||||
react: 19.2.7
|
||||
react-dom: 19.2.7(react@19.2.7)
|
||||
@@ -9544,12 +9533,6 @@ snapshots:
|
||||
|
||||
pluralize@8.0.0: {}
|
||||
|
||||
postcss@8.5.23:
|
||||
dependencies:
|
||||
nanoid: 3.3.16
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
postcss@8.5.23:
|
||||
dependencies:
|
||||
nanoid: 3.3.16
|
||||
|
||||
Reference in New Issue
Block a user