chore: linting

This commit is contained in:
zhom
2026-07-31 20:45:45 +04:00
parent 1f1878239d
commit 1e2c41d4a7
12 changed files with 340 additions and 164 deletions
+30 -51
View File
@@ -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 }}
+13 -3
View File
@@ -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.
+55 -17
View File
@@ -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 }}
+14 -3
View File
@@ -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.
-1
View File
@@ -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
+1
View File
@@ -12,6 +12,7 @@
# testing
/coverage
/e2e/app/target/
/e2e/.driver/
# next.js
/.next/
+2 -1
View File
@@ -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
View File
@@ -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`.
+139 -22
View File
@@ -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
View File
@@ -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
View File
@@ -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}`,
+14 -31
View File
@@ -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