Commit aa32d5e
fix(EdgedriverBinary): generate per-platform URLs, drop dead listing API (#1026)
`EdgedriverBinary.fetch('/<version>/')` has been broken since around
**2026-04-07** — the legacy Azure Blob container listing API now returns
**HTTP 409 `PublicAccessNotPermitted`** after Microsoft disabled public
access on the storage account:
```
https://msedgewebdriverstorage.blob.core.windows.net/edgewebdriver?prefix=<version>/&delimiter=/&comp=list
→ HTTP 409 PublicAccessNotPermitted
```
This made `test/common/adapter/binary/EdgedriverBinary.test.ts > fetch()
> should work` fail on the `items.length >= 3` assertion, blocking
`@eggjs/egg` monorepo's E2E pipeline and any project depending on
EdgedriverBinary.
Microsoft has migrated Edge WebDriver hosting to
`https://msedgedriver.microsoft.com/`. Per-version files are still
reachable at the same path pattern:
```
https://msedgedriver.microsoft.com/<version>/edgedriver_<platform>.zip
```
The new host **also** serves a `listing.json` dump (used by Microsoft's
own catalog page at https://msedgedriver.microsoft.com/catalog/), but it
has two drawbacks:
1. **It's a single static file containing every version since
`112.0.1722.39`** — ~9000 entries, ~1.2MB. I verified empirically that
**none of `?top` / `?limit` / `?max` / `?pageSize` / `?prefix` /
`?latest` query parameters do anything** — the response is
byte-identical regardless of query string. There is no server-side
filtering.
2. Even with caching, that's 1.2MB extra per sync.
So instead this PR mirrors the approach already used by
[`FirefoxBinary`](https://github.com/cnpm/cnpmcore/blob/master/app/common/adapter/binary/FirefoxBinary.ts)
and
[`ChromeForTestingBinary`](https://github.com/cnpm/cnpmcore/blob/master/app/common/adapter/binary/ChromeForTestingBinary.ts):
**don't call any listing API for sub-dirs at all.** Instead, enumerate
the per-version download URLs from a static list of known platform
filenames:
```ts
const EDGEDRIVER_PLATFORM_FILES = [
'edgedriver_arm64.zip',
'edgedriver_linux64.zip',
'edgedriver_mac64.zip',
'edgedriver_mac64_m1.zip',
'edgedriver_win32.zip',
'edgedriver_win64.zip',
] as const;
```
Each emitted `BinaryItem` carries `ignoreDownloadStatuses: [404]`, so
any version that doesn't ship every platform (e.g. older builds without
`mac64_m1`) is skipped cleanly by cnpmcore's sync pipeline rather than
failing the task.
The root-dir listing path (`#syncDirItems` →
`https://edgeupdates.microsoft.com/api/products`) is **completely
unchanged** — that JSON API still works.
| | Use `listing.json` | Generate URLs (this PR) |
|---|---|---|
| Network per sub-dir fetch | ~1.2MB JSON dump | **0 bytes** |
| Per-sync caching needed | yes (~1.2MB cached + reset logic) | no |
| Failure modes | listing endpoint down → all sub-dir fetches fail |
per-platform 404 handled cleanly |
| Code surface | listing parse + cache + error path | one `.map()` over
a const array |
| Singleton state safety | needs careful reset in `initFetch` | none,
stateless |
| Platform discovery | from server response | static const (loses any
net-new platform until updated) |
The trade-off is that if Microsoft adds a new Edge WebDriver platform
(e.g. `linux_arm64`), this adapter won't pick it up until the const list
is updated. That's a maintenance cost but a small one — the platform
list has been stable at six entries throughout the entire history of the
new CDN.
- **Root-dir listing (`fetch('/')`)**: still uses
`https://edgeupdates.microsoft.com/api/products`. Microsoft only exposes
the very latest release of each channel via this API, so the result
today is ~5 versions total (one per channel: Stable / Beta / Dev /
Canary). Historical version coverage was — and still is — governed by
what cnpmcore had previously synced, not by what edgeupdates returns
now.
- **Version ordering in the root listing**: items come out in the order
Microsoft's API returns them, which is grouped by channel (Stable → Beta
→ Dev → Canary), newest within each channel. This is *not* a strict
latest-first sort, but it matches the pre-PR behavior. If a strict
ordering is desired, that's a separate change.
Microsoft's per-version download URL works for **versions from
`112.0.1722.39` onwards**. Versions older than 112 are no longer
downloadable from any public Microsoft endpoint:
| Version | Old Blob URL | New URL |
|---|---|---|
| 80.0.361.111 | 409 PublicAccessNotPermitted | 404 |
| 100.0.1185.27 | 409 PublicAccessNotPermitted | 404 |
| 110.0.1587.69 | 409 PublicAccessNotPermitted | 404 |
| **112.0.1722.39** | 409 PublicAccessNotPermitted | **200 ✓** |
| 120.0.2210.133 | 409 PublicAccessNotPermitted | 200 ✓ |
| 148.0.3966.0 | 409 PublicAccessNotPermitted | 200 ✓ |
This is a Microsoft-side cutoff, not something cnpmcore can work around.
**Existing mirrored copies of pre-112 Edge WebDriver binaries in
cnpmcore's own storage are unaffected** — this PR only changes
*discovery* of new files from upstream.
Also adds `await binary.initFetch()` in the test's `beforeEach`.
`EdgedriverBinary` is a `@SingletonProto`, so
`app.getEggObject(EdgedriverBinary)` returns the same instance across
tests, which means `dirItems` populated by one test would leak into the
next. This was a pre-existing latent issue masked by the old test only
having one `it` block, but it surfaces immediately when adding more
cases.
There is no formal Microsoft announcement for this specific storage
lockdown, but the migration off `azureedge.net` and the gradual lockdown
of the legacy XML listing have been documented across multiple community
projects. Timeline:
- **2024-05** —
[MicrosoftEdge/EdgeWebDriver#146](MicrosoftEdge/EdgeWebDriver#146):
Azure Blob listing stopped updating for versions ≥ 125.0.
- **2025-01** —
[MicrosoftEdge/EdgeWebDriver#183](MicrosoftEdge/EdgeWebDriver#183):
`azureedge.net` CDN sunset (Edgio bankruptcy); Microsoft initially said
it would continue under a different CDN provider.
- **2025-07** —
[seleniumbase/SeleniumBase#3888](seleniumbase/SeleniumBase#3888),
[MicrosoftEdge/EdgeWebDriver#201](MicrosoftEdge/EdgeWebDriver#201),
[#203](MicrosoftEdge/EdgeWebDriver#203):
`msedgedriver.azureedge.net` DNS stopped resolving; new CDN is
`msedgedriver.microsoft.com`. SeleniumBase fixed this in 4.40.6.
- **2026-04-07** — (this PR): The Azure Blob container backing the old
XML listing also had public access disabled; only
`msedgedriver.microsoft.com` works now.
- [x] `EdgedriverBinary.test.ts > should list recent stable versions
from edgeupdates.microsoft.com` — green
- [x] `EdgedriverBinary.test.ts > should generate all known platform
driver URLs for a version` — green (asserts the exact 6 generated items
with `ignoreDownloadStatuses: [404]` on each)
- [x] **All 6 cnpmcore CI matrices** (`mysql node@22/24 × jsonBuilder
true/false`, `postgresql node@22/24`) green
- [x] `test-deployment`, `typecheck` (lint + fmtcheck + tsc),
`codecov/patch`, `codecov/project` green
- [ ] Manual smoke (suggested for reviewer): a fresh sync of a recent
Edge WebDriver version (e.g. 148.0.3966.0) enumerates all 6 platform
binaries and downloads all of them successfully, without 404s
- [ ] Manual smoke (suggested for reviewer): a sync of an older version
that doesn't ship every platform (e.g. 112.0.1722.39 has no `mac64_m1`)
— the missing platform should be skipped via `ignoreDownloadStatuses:
[404]` and the rest should complete
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
* **Bug Fixes**
* Improved handling of unavailable EdgeDriver versions for specific
platforms—missing combinations are now skipped instead of causing
failures.
* **Improvements**
* Enhanced EdgeDriver binary delivery infrastructure for greater
reliability and consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent bcdc08a commit aa32d5e
File tree
2 files changed
+109
-154
lines changed- app/common/adapter/binary
- test/common/adapter/binary
2 files changed
+109
-154
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | 2 | | |
4 | 3 | | |
5 | 4 | | |
6 | 5 | | |
7 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
8 | 34 | | |
9 | 35 | | |
10 | 36 | | |
| |||
32 | 58 | | |
33 | 59 | | |
34 | 60 | | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | 61 | | |
121 | 62 | | |
122 | 63 | | |
| |||
163 | 104 | | |
164 | 105 | | |
165 | 106 | | |
166 | | - | |
167 | | - | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
168 | 112 | | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
183 | | - | |
184 | | - | |
185 | | - | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
193 | | - | |
194 | | - | |
195 | | - | |
196 | | - | |
197 | | - | |
198 | | - | |
199 | | - | |
200 | | - | |
201 | | - | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
206 | | - | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
211 | | - | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
212 | 122 | | |
213 | 123 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
10 | 14 | | |
11 | 15 | | |
12 | 16 | | |
13 | | - | |
| 17 | + | |
14 | 18 | | |
15 | 19 | | |
16 | 20 | | |
17 | 21 | | |
18 | | - | |
| 22 | + | |
19 | 23 | | |
20 | 24 | | |
21 | 25 | | |
| |||
49 | 53 | | |
50 | 54 | | |
51 | 55 | | |
| 56 | + | |
52 | 57 | | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
74 | 119 | | |
75 | 120 | | |
76 | 121 | | |
0 commit comments