mirror of
https://github.com/nimbold/Firelink.git
synced 2026-10-24 20:52:39 +00:00
chore(deps): refresh compatible packages and FFmpeg sources
- update i18next, React i18n, Lucide, and compatible npm and Cargo locks - refresh Windows and Linux FFmpeg 9.0.2 archives with verified hashes - report compatible npm wanted versions and handle nested, duplicate, and optional packages - update Node and Rust CI pins and document Windows 10 22H2 qualification
This commit is contained in:
@@ -14,7 +14,9 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7.0.1
|
||||
- uses: dtolnay/rust-toolchain@686976e191b89faba57d3206551f0f330d8cb249 # stable action branch (2026-10-09)
|
||||
- uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable action branch (2026-10-16)
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: Install locked cargo-audit
|
||||
run: cargo install cargo-audit --version 0.22.2 --locked
|
||||
- name: Reject vulnerable resolved dependencies
|
||||
@@ -27,7 +29,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: [22.23.3, 24.21.0]
|
||||
node: [22.23.3, 24.22.0, 26.12.0]
|
||||
steps:
|
||||
- uses: actions/checkout@v7.0.1
|
||||
with:
|
||||
@@ -62,10 +64,11 @@ jobs:
|
||||
submodules: recursive
|
||||
- uses: actions/setup-node@v7.1.0
|
||||
with:
|
||||
node-version: 24.21.0
|
||||
node-version: 24.22.0
|
||||
cache: npm
|
||||
- uses: dtolnay/rust-toolchain@686976e191b89faba57d3206551f0f330d8cb249 # stable action branch (2026-10-09)
|
||||
- uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable action branch (2026-10-16)
|
||||
with:
|
||||
toolchain: stable
|
||||
targets: ${{ matrix.target }}
|
||||
- name: Cache Rust dependencies and build targets
|
||||
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v7.1.0
|
||||
with:
|
||||
node-version: 24.21.0
|
||||
node-version: 24.22.0
|
||||
cache: npm
|
||||
- name: Verify tagged release version
|
||||
if: github.event_name == 'push' || inputs.publish_release
|
||||
@@ -58,8 +58,9 @@ jobs:
|
||||
- name: Verify non-publishing Companion package metadata
|
||||
if: github.event_name == 'workflow_dispatch' && !inputs.publish_release
|
||||
run: node scripts/verify-companion-release.js --allow-untagged
|
||||
- uses: dtolnay/rust-toolchain@686976e191b89faba57d3206551f0f330d8cb249 # stable action branch (2026-10-09)
|
||||
- uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable action branch (2026-10-16)
|
||||
with:
|
||||
toolchain: stable
|
||||
targets: ${{ matrix.target }}
|
||||
- name: Install Linux dependencies
|
||||
if: runner.os == 'Linux'
|
||||
|
||||
@@ -62,8 +62,8 @@ Download the [latest Firelink release](https://github.com/nimbold/Firelink/relea
|
||||
| Platform | Package | Notes |
|
||||
| --- | --- | --- |
|
||||
| macOS Apple silicon | `.dmg` | Ad-hoc signed and not notarized. macOS may require approval in **System Settings -> Privacy & Security**. |
|
||||
| Windows x64 | NSIS `.exe` | Unsigned. Windows SmartScreen may display a warning. |
|
||||
| Windows x64 portable | `.zip` | Extract to a writable folder and launch `firelink.exe`. |
|
||||
| Windows x64 | NSIS `.exe` | Windows 10 22H2 or newer. Unsigned; SmartScreen may display a warning. |
|
||||
| Windows x64 portable | `.zip` | Windows 10 22H2 or newer. Extract to a writable folder and launch `firelink.exe`. |
|
||||
| Linux x64 | `.deb`, `.rpm`, or `.AppImage` | The current AppImage requires host glibc 2.35 or newer. |
|
||||
|
||||
All packages include aria2, yt-dlp, FFmpeg, Deno, and SQLite support. No separate engine installation is required.
|
||||
|
||||
+10
-1
@@ -31,7 +31,7 @@ provisioning now builds the checksum-pinned upstream source archive with
|
||||
`scripts/aria2/firelink.patch`; this patch also retains Firelink's native DNS,
|
||||
network target policy, and Torrent routing changes. CI installs the compiler
|
||||
and static-library prerequisites. Windows uses the MSYS2 UCRT64 environment,
|
||||
supported by Firelink's Windows 10+ target and returned by the setup action
|
||||
supported by Firelink's Windows 10 22H2+ target and returned by the setup action
|
||||
(`FIRELINK_MSYS2_ROOT`, default `C:/msys64` for local builds).
|
||||
The patch checksum is recorded in both source and payload provenance. Never
|
||||
replace these builds with stock Aria2 archives: package verification requires
|
||||
@@ -141,4 +141,13 @@ GitHub Actions builds all targets on native runners, verifies engines inside
|
||||
final package contents, performs packaged launch smoke where supported, and
|
||||
publishes the GitHub Release after the build matrix passes.
|
||||
|
||||
The Windows hosted runner smoke does not qualify the declared Windows 10
|
||||
22H2 minimum. Before claiming that minimum as verified for a release, run the
|
||||
NSIS-installed app and extracted portable package on a clean Windows 10 22H2
|
||||
client (OS build 19045.x). Run `scripts/smoke-packaged-app.js` against the
|
||||
installed executable with `--assert-no-visible-child-windows`; run it against
|
||||
the portable executable with both `--assert-no-visible-child-windows` and
|
||||
`--assert-portable-data`. Record the tested OS build and artifact version with
|
||||
release QA results.
|
||||
|
||||
No target may silently skip missing engines, failed extraction, checksum mismatch, or missing package output.
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
},
|
||||
"ffmpeg": {
|
||||
"version": "9.0.2-28-g669f5ab083",
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-10-15-13-03/ffmpeg-n9.0.2-28-g669f5ab083-win64-gpl-9.0.zip",
|
||||
"sha256": "1bb62cfd4bdc12a63a6a1151458ea5ae7001fd055202afc5463517028882a631"
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-10-17-20-51/ffmpeg-n9.0.2-28-g669f5ab083-win64-gpl-9.0.zip",
|
||||
"sha256": "e84429075cf1b1fa9a85c5d4a5f97899145b4f6a712da02a864393203a3d5cd3"
|
||||
},
|
||||
"aria2c": {
|
||||
"version": "1.37.0-firelink-native-dns-v1",
|
||||
@@ -46,8 +46,8 @@
|
||||
},
|
||||
"ffmpeg": {
|
||||
"version": "9.0.2-28-g669f5ab083",
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-10-15-13-03/ffmpeg-n9.0.2-28-g669f5ab083-linux64-gpl-9.0.tar.xz",
|
||||
"sha256": "715ce3c292c749c00b196fc0ff703fe3be12351aa71a626c00d19617b3b280e4"
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-10-17-20-51/ffmpeg-n9.0.2-28-g669f5ab083-linux64-gpl-9.0.tar.xz",
|
||||
"sha256": "cc171d4d373f9ca633741d38fae6a17cd914075818febb1465f6f64e6d57f7ca"
|
||||
},
|
||||
"aria2c": {
|
||||
"version": "1.37.0-firelink-native-dns-v1",
|
||||
|
||||
Generated
+100
-86
@@ -22,11 +22,11 @@
|
||||
"@tauri-apps/plugin-log": "^2.10.1",
|
||||
"@tauri-apps/plugin-notification": "^2.7.0",
|
||||
"@tauri-apps/plugin-opener": "^2.7.2",
|
||||
"i18next": "^26.4.7",
|
||||
"lucide-react": "^1.58.0",
|
||||
"i18next": "^26.5.2",
|
||||
"lucide-react": "^1.59.0",
|
||||
"react": "^19.3.1",
|
||||
"react-dom": "^19.3.1",
|
||||
"react-i18next": "^17.0.19",
|
||||
"react-i18next": "^17.1.0",
|
||||
"zustand": "^5.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -34,6 +34,7 @@
|
||||
"@types/react": "^19.3.0",
|
||||
"@types/react-dom": "^19.3.0",
|
||||
"@vitejs/plugin-react": "^6.1.2",
|
||||
"semver": "^7.8.5",
|
||||
"tailwindcss": "^4.3.3",
|
||||
"typescript": "^7.0.2",
|
||||
"vite": "^8.3.4",
|
||||
@@ -44,9 +45,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.29.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
|
||||
"integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
|
||||
"version": "7.29.10",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.10.tgz",
|
||||
"integrity": "sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -152,18 +153,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-project/types": {
|
||||
"version": "0.152.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.152.0.tgz",
|
||||
"integrity": "sha512-oM/5rLBm2tPkg0iBgkH/FOeR3PCDpY19GTgAZjMFM8h9WI9VW7cLgzp6nwtarYKmovavIQZ+Fe/RKX/8C8O/Rw==",
|
||||
"version": "0.154.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.154.0.tgz",
|
||||
"integrity": "sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/oxc-project"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm-eabi": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.12.tgz",
|
||||
"integrity": "sha512-dB/a1214qKfHMXCpgqR4OZT+jS4kTyEXbQGJPqzobt5EwH5rX080pxE37alt3RzvR1bf1Yz/yGqRfrYAxuPw0A==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.14.tgz",
|
||||
"integrity": "sha512-aWR+XKH9+rW7m5fWq/5360J3mHycrx/o6xZM2DQFdJnTMdyP7/WzxPjhtLbVWdKo2y612/4U1bWqb3HQhiF7vg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -177,9 +178,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.12.tgz",
|
||||
"integrity": "sha512-7KHFgQ5VJxIHcLlrwrc3Xbds7oTNQT7Pgi9gQCJKrd2VGab/UksIOYp6VD8MzCstGxOKMgNamPwUCfxPdP1OHg==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.14.tgz",
|
||||
"integrity": "sha512-QiVxHofl6A8lQU7WAtOUY4QMVZXohxwz7WJJoeh8NBEUyKfIkMRKhYyq8az/1RypNiIXzNTtiS6KwHz0erxYRQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -193,9 +194,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.12.tgz",
|
||||
"integrity": "sha512-3YIhqHD96nA5SaYNRBR16HnGv4oavZvXfD/ayHM+oYZ0WD/8lBAtf6zQua4kEyAvpqrluKXl0lnOBoiNby7x9w==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.14.tgz",
|
||||
"integrity": "sha512-lTQOzHuBIooh3jIr5XINQkjPGEuGy+Dsy0meXDr6Sjty0b99kYgGh4uBC/8mJX1T0kC8d6S0aPP1Y+bHkh6aBw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -209,9 +210,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-x64": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.12.tgz",
|
||||
"integrity": "sha512-UuuJ35MFw4gmFOrE9pEqIV+K3syIKveph+Qc1/ljHZVdoDW4pz/JHR/eMVom+TZGl/5OOvGJOWaOCVt3ZfqhxA==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.14.tgz",
|
||||
"integrity": "sha512-hyMKEGatjmBYCs/Q4sbIcL/GqpFEqsX3wc+HYVQ/85A4rxc1o7rPm4DUI4GV4k/h0ITddwFSGpqQunI14GXjTA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -225,9 +226,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.12.tgz",
|
||||
"integrity": "sha512-uMvssit0a4W+/7D8CbHUvG719mH3R2jwXAlh/XcPvuHTE0g++LymF88DCGNX0HM2rBOn0xrzgXktIB6fLSJBTQ==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.14.tgz",
|
||||
"integrity": "sha512-u371GbXoVXrEgP20PwzoGNOdAOqAMhzo19JzzY+V4YmmnC+DTOoqdbMu+O+54emM59Mik/UdrtWgcuEDKWRPKA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -241,9 +242,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.12.tgz",
|
||||
"integrity": "sha512-XcFu0R0xWnwzSf4IQgFH1rJIckPN1pLy2R+4r9IDB7Yfu/ys9cVqfa4pBrMHj7a3gl8mIR4nRNPg0e5IvEVs6g==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.14.tgz",
|
||||
"integrity": "sha512-BqwKsdZQf6EqVWr8fv2MrDYzAvOZ7+NYFSJESRGs87fkseEhs0TU9TXgRJTkZoRRkxTizyEg1LKUXfU3/78uqg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -257,9 +258,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.12.tgz",
|
||||
"integrity": "sha512-260UrKgn8tz39ak+SMDOirKzr7V04M9dWPw5llW00SwBivCZoWcRBKV1d8cXnRkUmSZA3BdiUmBHWk7734Ulpw==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.14.tgz",
|
||||
"integrity": "sha512-SD9kY8M009x/7s57Z1dgUVlP5+uYBgKQK0Tkr1WIWngrtUJmRCW1RJFMY7QDla2khXhmg2i5Io7MUjcmZNZ/KQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -276,9 +277,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.12.tgz",
|
||||
"integrity": "sha512-5YK1I9SqDkbPgc1IA8BgDl34suqUS2q0KWnBrirm0E51YjOs6eo6dV6jbQfNE/argHRSvd0QUGgtpIoYx+WWpw==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.14.tgz",
|
||||
"integrity": "sha512-BJ2CL19M6uuWesMgnqJzgxoI+N+eV7b0A9O9vLV42y+gitC41fNa8KElau1tHVzuLWX5GzEuxMPhAO0tQXQMkg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -295,9 +296,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.12.tgz",
|
||||
"integrity": "sha512-Rkcrmp7eFRg74yL5fXEU91JEWbdEPLevWwGtXpmhbjlD1StScbWTmO94Bhly+Mo+ketKYkdmM1vNUKeWSlx8cQ==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.14.tgz",
|
||||
"integrity": "sha512-4+Kl8daPV8NDHaD7mfCcc1pRM+Qg7ab8DyMm5FG5WoZgv4h2i3KFN1CybYBNbQqmuYm7ftJLvmMI1eHYJ22S/Q==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -314,9 +315,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.12.tgz",
|
||||
"integrity": "sha512-qvK4DuAsQc2BSjlx+Xr+IzOIvvxbGZqxFwdWfG6F518Erj0GGISyQbJ6pIappnOxlNPzNHvo/L0BwB30GZ+zVw==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.14.tgz",
|
||||
"integrity": "sha512-V/h8ePq1fKDrmtFMz6xcCN3DKvuvMRrwwD1q0PkBeeo4DpK64biaKvqWGVxqCeYKqeRk7gE7/iKPxLCn08O97A==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -333,9 +334,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.12.tgz",
|
||||
"integrity": "sha512-Q9uLBO53Xd4QIq1WOycVQyPP1O4HhraEV2qqb3uTrnVw6QZih9duY4vNXOivL1xoUS1/z+W8eF4NMfl2a8Sdjw==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.14.tgz",
|
||||
"integrity": "sha512-WxalXzgrLVpKC93xfpaJ3gCXUWzeCr+FRCbDVD2mUAy4L6Vo3lNVz0epUEUpxPWJkLNYUwM4OSIikv36OJ9mLg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -352,9 +353,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-musl": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.12.tgz",
|
||||
"integrity": "sha512-3IBxWFMjbOZskDPKv8Lf9BCnahlKuHthWkYnyIxOH/QcJrFcS4EmcenthApkwr/5+nEqZlLzeYbxeMaX7A5u4g==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.14.tgz",
|
||||
"integrity": "sha512-3G3tnAmTpdk9jO3GQtyHXqeFD2SlecfTws/Y3M2mmj9nMBwwuLT4kur8sZKeu7ENUHSpVO3cIsm5A52LEWWwlg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -371,9 +372,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.12.tgz",
|
||||
"integrity": "sha512-xtX61xg4LKPkPWilZU1ynKClz5Gj4bf74LML4r3eVLWumKnGjoEr1OSHQhMdbBDoYTi+yjrujvpZe2pUnqCrrA==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.14.tgz",
|
||||
"integrity": "sha512-qyr5XiNGxm2ytx17vvtcJ9nXn6v1gENETi503bJx3OGwZ1tSonj7BosxbMa/xeAfSl5iS9X6KjEWYXLu6v1L7Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -387,9 +388,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.12.tgz",
|
||||
"integrity": "sha512-At7fPB6PCaIjzgIhEZFxuT+BBFqiQibJDT4d3PhiR3f4E7bbMZF4aKblbFfEM3sETRDd1YiQx/+U/g/B/ou5Ew==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.14.tgz",
|
||||
"integrity": "sha512-oA4o5o0S2yB199YyYXDzKUv1Z56Rc+mgOjwm7Z/vJ9Z8igiDPYvoOuDyo6g7AK/ZaF09nPhDKVnGBcYHO11GXA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -403,9 +404,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.12.tgz",
|
||||
"integrity": "sha512-WIw2haVKwjuYdXkHaoC0mF8Le71TuCBxjrdKqLbJGctbBABj+ClfmNvtbOnzpq3RokNo5+V1qhtSzJyXorsklQ==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.14.tgz",
|
||||
"integrity": "sha512-9mE94bf2GZUaR/fUSXCMpBoWkctu421Mi0ORpm4zqfbkjKep7RxzPFa5etcGs5h+2KApoWBOA/hAJa/7saGgEQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1606,9 +1607,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "26.4.7",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.4.7.tgz",
|
||||
"integrity": "sha512-p/3hqy6EcuqRs6wNwBYwGGC1fzBJSMxV9zMuN814ab/7QjdZbXfjXwuPZdQbngX6KDOTxM01uUiZyqmMB8ghZg==",
|
||||
"version": "26.5.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.2.tgz",
|
||||
"integrity": "sha512-6fIXt//2MZNok3tULyjnypxe3vbsy3pV1bVg8p2x3yKrzZvp7z3T+wXx/88LQsATRdhyJeAUAvUxEtxsHdJ29w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -1904,9 +1905,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lucide-react": {
|
||||
"version": "1.58.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.58.0.tgz",
|
||||
"integrity": "sha512-hXaFNm6mk6QVtBnDGBn1YAs8j2tGUk0A4s/CpclIcczfxeXiW1rdOLVo6zCsoIih9XXsGvDODQerl749a2n7bA==",
|
||||
"version": "1.59.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.59.0.tgz",
|
||||
"integrity": "sha512-5qgMyyCPU6OvnKpLS2t693+ZtiqA8oaSweWoUows0BLFKFf6V75m4+CptpmohZHpD5IuOVIBXHBBiv2vpLJmtw==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
@@ -1978,9 +1979,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.29",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz",
|
||||
"integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==",
|
||||
"version": "8.5.30",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.30.tgz",
|
||||
"integrity": "sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -1997,7 +1998,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.19",
|
||||
"nanoid": "^3.3.20",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.2"
|
||||
},
|
||||
@@ -2027,9 +2028,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-i18next": {
|
||||
"version": "17.0.19",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.19.tgz",
|
||||
"integrity": "sha512-BRHqiqOfW4J/LBVtbBFHoBoZm/Ez2/tkHPitYtn0CSpkYhEaEAsZMPsg7hZlomu30UJYQ6ZKiP3pwa3QnxGvQw==",
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.1.0.tgz",
|
||||
"integrity": "sha512-4VouOnTDyvhvqXx6WZ+s3/cgSiaLutILdYkO3P1Ms+4qcKR7At+JP4Vi7IeHkVLyVV+DmN1l23Pn73UcwSGGPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.29.7",
|
||||
@@ -2054,12 +2055,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown": {
|
||||
"version": "1.2.12",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.12.tgz",
|
||||
"integrity": "sha512-8wafseiaG80xmXSfqidUNqZcylTlhmPZZt+za2m+js2sFZ8dTNlhIOV2WcbIPx2hgwPBJpEUGFAMZ9bgBBLTSQ==",
|
||||
"version": "1.2.14",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.14.tgz",
|
||||
"integrity": "sha512-eTBTTqMR6uHKLgcUqpJP8ntzDI6V4LYA8negAMBEI7gkgVvOdrx6VsvS2Ym+83KhOPdLCHWJu0w7UQFJZhHKNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "=0.152.0",
|
||||
"@oxc-project/types": "=0.154.0",
|
||||
"@rolldown/pluginutils": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -2069,21 +2070,21 @@
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rolldown/binding-android-arm-eabi": "1.2.12",
|
||||
"@rolldown/binding-android-arm64": "1.2.12",
|
||||
"@rolldown/binding-darwin-arm64": "1.2.12",
|
||||
"@rolldown/binding-darwin-x64": "1.2.12",
|
||||
"@rolldown/binding-freebsd-x64": "1.2.12",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.2.12",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.2.12",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.2.12",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.2.12",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.2.12",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.2.12",
|
||||
"@rolldown/binding-linux-x64-musl": "1.2.12",
|
||||
"@rolldown/binding-openharmony-arm64": "1.2.12",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.2.12",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.2.12"
|
||||
"@rolldown/binding-android-arm-eabi": "1.2.14",
|
||||
"@rolldown/binding-android-arm64": "1.2.14",
|
||||
"@rolldown/binding-darwin-arm64": "1.2.14",
|
||||
"@rolldown/binding-darwin-x64": "1.2.14",
|
||||
"@rolldown/binding-freebsd-x64": "1.2.14",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.2.14",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.2.14",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.2.14",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.2.14",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.2.14",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.2.14",
|
||||
"@rolldown/binding-linux-x64-musl": "1.2.14",
|
||||
"@rolldown/binding-openharmony-arm64": "1.2.14",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.2.14",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.2.14"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
@@ -2092,6 +2093,19 @@
|
||||
"integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.8.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
||||
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
|
||||
|
||||
+4
-3
@@ -58,11 +58,11 @@
|
||||
"@tauri-apps/plugin-log": "^2.10.1",
|
||||
"@tauri-apps/plugin-notification": "^2.7.0",
|
||||
"@tauri-apps/plugin-opener": "^2.7.2",
|
||||
"i18next": "^26.4.7",
|
||||
"lucide-react": "^1.58.0",
|
||||
"i18next": "^26.5.2",
|
||||
"lucide-react": "^1.59.0",
|
||||
"react": "^19.3.1",
|
||||
"react-dom": "^19.3.1",
|
||||
"react-i18next": "^17.0.19",
|
||||
"react-i18next": "^17.1.0",
|
||||
"zustand": "^5.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -70,6 +70,7 @@
|
||||
"@types/react": "^19.3.0",
|
||||
"@types/react-dom": "^19.3.0",
|
||||
"@vitejs/plugin-react": "^6.1.2",
|
||||
"semver": "^7.8.5",
|
||||
"tailwindcss": "^4.3.3",
|
||||
"typescript": "^7.0.2",
|
||||
"vite": "^8.3.4",
|
||||
|
||||
+178
-16
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { execFileSync, execSync } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import semver from 'semver';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = path.resolve(__dirname, '..');
|
||||
@@ -72,16 +73,29 @@ function npmExecutable(platform = process.platform) {
|
||||
return platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||
}
|
||||
|
||||
function npmOutdated(cwd) {
|
||||
function npmOutdated(cwd, {
|
||||
platform = process.platform,
|
||||
runFile = execFileSync,
|
||||
runShell = execSync,
|
||||
} = {}) {
|
||||
if (!fs.existsSync(path.join(cwd, 'package.json'))) {
|
||||
throw new Error(`npm workspace is missing package.json: ${cwd}`);
|
||||
}
|
||||
const args = ['outdated', '--all', '--json'];
|
||||
const options = {
|
||||
cwd,
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 16 * 1024 * 1024,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
};
|
||||
try {
|
||||
execFileSync(npmExecutable(), ['outdated', '--json'], {
|
||||
cwd,
|
||||
encoding: 'utf8',
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
if (platform === 'win32') {
|
||||
// npm.cmd is a command shim, not a native executable. Keep the command
|
||||
// fixed here (no user-controlled arguments) and let cmd.exe run it.
|
||||
runShell(`${npmExecutable(platform)} ${args.join(' ')}`, options);
|
||||
} else {
|
||||
runFile(npmExecutable(platform), args, options);
|
||||
}
|
||||
return {};
|
||||
} catch (error) {
|
||||
if (error.status !== 1) {
|
||||
@@ -323,6 +337,140 @@ function printCargoReport(updates) {
|
||||
return updates.length;
|
||||
}
|
||||
|
||||
function npmUpdateRows(outdated, { cwd = process.cwd(), lockfilePackages = {} } = {}) {
|
||||
if (!outdated || typeof outdated !== 'object' || Array.isArray(outdated)) {
|
||||
throw new Error('npm outdated response was not a package map');
|
||||
}
|
||||
|
||||
const lockfileVersionAtLocation = location => {
|
||||
if (typeof location !== 'string' || !location.trim()) return undefined;
|
||||
let lockfilePath = location.trim().replaceAll('\\', '/');
|
||||
if (path.isAbsolute(location)) {
|
||||
const relativePath = path.relative(cwd, location);
|
||||
if (path.isAbsolute(relativePath) || relativePath === '..' || relativePath.startsWith(`..${path.sep}`)) {
|
||||
return undefined;
|
||||
}
|
||||
lockfilePath = relativePath.split(path.sep).join('/');
|
||||
}
|
||||
lockfilePath = lockfilePath.replace(/^\.\//, '');
|
||||
if (lockfilePath === '..' || lockfilePath.startsWith('../')) return undefined;
|
||||
return normalizeVersion(lockfilePackages[lockfilePath]?.version);
|
||||
};
|
||||
const lockfileVersionsForName = name => {
|
||||
const suffix = `/node_modules/${name}`;
|
||||
return Object.entries(lockfilePackages)
|
||||
.filter(([lockfilePath]) => lockfilePath === `node_modules/${name}` || lockfilePath.endsWith(suffix))
|
||||
.map(([, entry]) => normalizeVersion(entry?.version))
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
const rows = new Map();
|
||||
for (const [name, value] of Object.entries(outdated)) {
|
||||
const records = Array.isArray(value) ? value : [value];
|
||||
const normalizedRecords = records.map(info => {
|
||||
if (!info || typeof info !== 'object' || Array.isArray(info)) {
|
||||
throw new Error(`npm outdated response for ${name} was not a package record`);
|
||||
}
|
||||
return {
|
||||
info,
|
||||
installedVersion: normalizeVersion(info.current),
|
||||
locatedVersion: lockfileVersionAtLocation(info.location),
|
||||
wanted: normalizeVersion(info.wanted),
|
||||
latest: normalizeVersion(info.latest),
|
||||
};
|
||||
});
|
||||
for (const record of normalizedRecords) {
|
||||
if (!record.wanted || !record.latest) {
|
||||
throw new Error(`npm outdated response for ${name} omitted wanted or latest version`);
|
||||
}
|
||||
}
|
||||
|
||||
const unresolved = normalizedRecords
|
||||
.map((record, index) => ({ record, index }))
|
||||
.filter(({ record }) => !record.installedVersion && !record.locatedVersion);
|
||||
const lockVersions = unresolved.length ? lockfileVersionsForName(name) : [];
|
||||
const resolvedLockVersions = new Map();
|
||||
if (lockVersions.length === 1) {
|
||||
for (const { index } of unresolved) resolvedLockVersions.set(index, lockVersions[0]);
|
||||
} else if (lockVersions.length > 1) {
|
||||
if (lockVersions.length !== unresolved.length) {
|
||||
throw new Error(`npm outdated response for ${name} omitted locations for duplicate package-lock entries`);
|
||||
}
|
||||
|
||||
const remainingLockVersions = [...lockVersions];
|
||||
const remainingRecords = [];
|
||||
for (const { record, index } of unresolved) {
|
||||
const wanted = semver.valid(record.wanted);
|
||||
if (!wanted) continue;
|
||||
const exactIndex = remainingLockVersions.findIndex(version => semver.valid(version)
|
||||
&& semver.eq(version, wanted));
|
||||
if (exactIndex >= 0) {
|
||||
resolvedLockVersions.set(index, remainingLockVersions.splice(exactIndex, 1)[0]);
|
||||
} else {
|
||||
remainingRecords.push({ record, index, wanted });
|
||||
}
|
||||
}
|
||||
|
||||
if (remainingRecords.length !== remainingLockVersions.length) {
|
||||
throw new Error(`npm outdated response for ${name} could not be matched safely to package-lock entries`);
|
||||
}
|
||||
remainingRecords.sort((left, right) => semver.compare(left.wanted, right.wanted));
|
||||
remainingLockVersions.sort((left, right) => {
|
||||
const leftVersion = semver.valid(left);
|
||||
const rightVersion = semver.valid(right);
|
||||
if (!leftVersion || !rightVersion) {
|
||||
throw new Error(`npm lockfile contains a non-semver duplicate for ${name}`);
|
||||
}
|
||||
return semver.compare(leftVersion, rightVersion);
|
||||
});
|
||||
remainingRecords.forEach(({ index }, offset) => {
|
||||
resolvedLockVersions.set(index, remainingLockVersions[offset]);
|
||||
});
|
||||
}
|
||||
|
||||
for (const [index, record] of normalizedRecords.entries()) {
|
||||
const currentVersions = record.installedVersion
|
||||
? [record.installedVersion]
|
||||
: record.locatedVersion
|
||||
? [record.locatedVersion]
|
||||
: resolvedLockVersions.has(index)
|
||||
? [resolvedLockVersions.get(index)]
|
||||
: [];
|
||||
// npm can include optional or peer packages that are absent from both
|
||||
// this host's physical tree and the lockfile. They are not resolved
|
||||
// Firelink dependencies. When lock entries exist, map them to records
|
||||
// by physical location or the matching npm `wanted` version.
|
||||
if (!currentVersions.length) continue;
|
||||
|
||||
if (!semver.valid(record.wanted) || !semver.valid(record.latest)) continue;
|
||||
for (const current of currentVersions) {
|
||||
if (!semver.valid(current) || semver.gte(current, record.wanted)) continue;
|
||||
|
||||
const key = `${name}\0${current}\0${record.wanted}\0${record.latest}`;
|
||||
const row = rows.get(key) || {
|
||||
name,
|
||||
current,
|
||||
wanted: record.wanted,
|
||||
latest: record.latest,
|
||||
lockfileOnly: !record.installedVersion,
|
||||
dependents: new Set(),
|
||||
};
|
||||
row.lockfileOnly = row.lockfileOnly && !record.installedVersion;
|
||||
if (typeof record.info.dependent === 'string' && record.info.dependent.trim()) {
|
||||
row.dependents.add(record.info.dependent.trim());
|
||||
}
|
||||
rows.set(key, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [...rows.values()]
|
||||
.map(row => ({ ...row, dependents: [...row.dependents].sort() }))
|
||||
.sort((left, right) => left.name.localeCompare(right.name)
|
||||
|| left.current.localeCompare(right.current)
|
||||
|| left.wanted.localeCompare(right.wanted));
|
||||
}
|
||||
|
||||
function hasUpdateCheckFailures({
|
||||
outdatedCount,
|
||||
engineIssueCount,
|
||||
@@ -335,17 +483,28 @@ function hasUpdateCheckFailures({
|
||||
|| providerBehind.length > 0;
|
||||
}
|
||||
|
||||
function printNpmReport(label, outdated) {
|
||||
const entries = Object.entries(outdated);
|
||||
if (!entries.length) {
|
||||
function printNpmReport(label, outdated, cwd) {
|
||||
let lockfilePackages = {};
|
||||
if (Object.keys(outdated).length > 0) {
|
||||
const lockfilePath = path.join(cwd, 'package-lock.json');
|
||||
const lockfile = JSON.parse(fs.readFileSync(lockfilePath, 'utf8'));
|
||||
if (!lockfile.packages || typeof lockfile.packages !== 'object' || Array.isArray(lockfile.packages)) {
|
||||
throw new Error(`npm lockfile did not contain a package map: ${lockfilePath}`);
|
||||
}
|
||||
lockfilePackages = lockfile.packages;
|
||||
}
|
||||
const rows = npmUpdateRows(outdated, { cwd, lockfilePackages });
|
||||
if (!rows.length) {
|
||||
console.log(`${label}: current`);
|
||||
return 0;
|
||||
}
|
||||
console.log(`${label}: ${entries.length} outdated package(s)`);
|
||||
for (const [name, info] of entries) {
|
||||
console.log(` ${name}: ${info.current} -> ${info.latest} (wanted ${info.wanted})`);
|
||||
console.log(`${label}: ${rows.length} compatible package update(s)`);
|
||||
for (const row of rows) {
|
||||
const dependents = row.dependents.length ? ` via ${row.dependents.join(', ')}` : '';
|
||||
const source = row.lockfileOnly ? ' (from lockfile)' : '';
|
||||
console.log(` ${row.name}: ${row.current}${source} -> ${row.wanted} (latest ${row.latest})${dependents}`);
|
||||
}
|
||||
return entries.length;
|
||||
return rows.length;
|
||||
}
|
||||
|
||||
function sourceEngineVersions(sourceLock) {
|
||||
@@ -500,10 +659,11 @@ function checkRows(
|
||||
async function main() {
|
||||
let outdatedCount = 0;
|
||||
|
||||
outdatedCount += printNpmReport('root npm', npmOutdated(repoRoot));
|
||||
outdatedCount += printNpmReport('root npm', npmOutdated(repoRoot), repoRoot);
|
||||
outdatedCount += printNpmReport(
|
||||
'Browser extension npm',
|
||||
npmOutdated(path.join(repoRoot, 'Extensions', 'Browser'))
|
||||
npmOutdated(path.join(repoRoot, 'Extensions', 'Browser')),
|
||||
path.join(repoRoot, 'Extensions', 'Browser')
|
||||
);
|
||||
outdatedCount += printCargoReport(cargoCompatibleUpdates());
|
||||
|
||||
@@ -726,5 +886,7 @@ export {
|
||||
latestBtbnFfmpegStableBuild,
|
||||
latestMartinRiedlMacArm64Release,
|
||||
npmExecutable,
|
||||
npmOutdated,
|
||||
npmUpdateRows,
|
||||
providerAssetHashes,
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
latestMartinRiedlMacArm64Release,
|
||||
hasUpdateCheckFailures,
|
||||
npmExecutable,
|
||||
npmOutdated,
|
||||
npmUpdateRows,
|
||||
providerAssetHashes,
|
||||
} from './check-updates.js';
|
||||
|
||||
@@ -243,10 +245,209 @@ test('update checks pass only when every blocking count is clear', () => {
|
||||
}), false);
|
||||
});
|
||||
|
||||
test('npm executable selection uses the Windows command shim when needed', () => {
|
||||
test('npm outdated runs the Windows command shim through a shell', () => {
|
||||
assert.equal(npmExecutable('win32'), 'npm.cmd');
|
||||
assert.equal(npmExecutable('darwin'), 'npm');
|
||||
assert.equal(npmExecutable('linux'), 'npm');
|
||||
|
||||
let shellCommand;
|
||||
let shellOptions;
|
||||
let fileRunCalled = false;
|
||||
assert.deepEqual(npmOutdated(process.cwd(), {
|
||||
platform: 'win32',
|
||||
runFile: () => { fileRunCalled = true; },
|
||||
runShell: (command, options) => {
|
||||
shellCommand = command;
|
||||
shellOptions = options;
|
||||
return '{}';
|
||||
},
|
||||
}), {});
|
||||
assert.equal(shellCommand, 'npm.cmd outdated --all --json');
|
||||
assert.equal(shellOptions.cwd, process.cwd());
|
||||
assert.equal(shellOptions.encoding, 'utf8');
|
||||
assert.equal(fileRunCalled, false);
|
||||
});
|
||||
|
||||
test('npm update rows deduplicate nested records and retain compatible and major versions', () => {
|
||||
const rows = npmUpdateRows({
|
||||
'@babel/runtime': [
|
||||
{
|
||||
current: '7.29.7',
|
||||
wanted: '7.29.10',
|
||||
latest: '8.0.7',
|
||||
dependent: 'react-i18next',
|
||||
location: '/workspace/node_modules/@babel/runtime',
|
||||
},
|
||||
{
|
||||
current: '7.29.7',
|
||||
wanted: '7.29.10',
|
||||
latest: '8.0.7',
|
||||
dependent: 'another-package',
|
||||
location: '/workspace/node_modules/@babel/runtime',
|
||||
},
|
||||
{
|
||||
current: '7.29.7',
|
||||
wanted: '7.29.10',
|
||||
latest: '8.0.7',
|
||||
dependent: 'react-i18next',
|
||||
location: '/workspace/node_modules/@babel/runtime',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
assert.deepEqual(rows, [{
|
||||
name: '@babel/runtime',
|
||||
current: '7.29.7',
|
||||
wanted: '7.29.10',
|
||||
latest: '8.0.7',
|
||||
lockfileOnly: false,
|
||||
dependents: ['another-package', 'react-i18next'],
|
||||
}]);
|
||||
});
|
||||
|
||||
test('npm update rows safely ignore absent optional platform packages', () => {
|
||||
const rows = npmUpdateRows({
|
||||
'@rolldown/binding-linux-x64-gnu': {
|
||||
wanted: '1.2.14',
|
||||
latest: '1.2.14',
|
||||
dependent: 'rolldown',
|
||||
location: '/workspace/node_modules/@rolldown/binding-linux-x64-gnu',
|
||||
},
|
||||
'@types/node': [
|
||||
{
|
||||
wanted: '26.6.5',
|
||||
latest: '26.6.5',
|
||||
dependent: 'vite',
|
||||
},
|
||||
{
|
||||
wanted: '26.6.5',
|
||||
latest: '26.6.5',
|
||||
dependent: 'vitest',
|
||||
},
|
||||
],
|
||||
}, {
|
||||
cwd: '/workspace',
|
||||
lockfilePackages: {
|
||||
'node_modules/@rolldown/binding-linux-x64-gnu': { version: '1.2.14' },
|
||||
'node_modules/@types/node': { version: '26.6.5' },
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(rows, []);
|
||||
});
|
||||
|
||||
test('npm update rows find compatible lockfile updates for absent optional packages', () => {
|
||||
const rows = npmUpdateRows({
|
||||
'@rolldown/binding-linux-x64-gnu': {
|
||||
wanted: '1.2.14',
|
||||
latest: '1.2.14',
|
||||
dependent: 'rolldown',
|
||||
},
|
||||
}, {
|
||||
cwd: '/workspace',
|
||||
lockfilePackages: {
|
||||
'node_modules/@rolldown/binding-linux-x64-gnu': { version: '1.2.12' },
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(rows, [{
|
||||
name: '@rolldown/binding-linux-x64-gnu',
|
||||
current: '1.2.12',
|
||||
wanted: '1.2.14',
|
||||
latest: '1.2.14',
|
||||
lockfileOnly: true,
|
||||
dependents: ['rolldown'],
|
||||
}]);
|
||||
});
|
||||
|
||||
test('npm update rows match duplicate optional records to lockfile wanted versions', () => {
|
||||
const rows = npmUpdateRows({
|
||||
'lightningcss-linux-x64-gnu': [
|
||||
{ wanted: '1.32.0', latest: '1.33.0', dependent: 'lightningcss' },
|
||||
{ wanted: '1.33.0', latest: '1.33.0', dependent: 'lightningcss' },
|
||||
],
|
||||
}, {
|
||||
cwd: '/workspace',
|
||||
lockfilePackages: {
|
||||
'node_modules/lightningcss-linux-x64-gnu': { version: '1.32.0' },
|
||||
'node_modules/vite/node_modules/lightningcss-linux-x64-gnu': { version: '1.33.0' },
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(rows, []);
|
||||
});
|
||||
|
||||
test('npm update rows retain stale duplicates when current is absent on this platform', () => {
|
||||
const rows = npmUpdateRows({
|
||||
'lightningcss-linux-x64-gnu': [
|
||||
{ wanted: '1.33.0', latest: '1.33.0', dependent: 'lightningcss' },
|
||||
{ wanted: '1.33.0', latest: '1.33.0', dependent: 'lightningcss' },
|
||||
],
|
||||
}, {
|
||||
cwd: '/workspace',
|
||||
lockfilePackages: {
|
||||
'node_modules/lightningcss-linux-x64-gnu': { version: '1.32.0' },
|
||||
'node_modules/vite/node_modules/lightningcss-linux-x64-gnu': { version: '1.33.0' },
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(rows, [{
|
||||
name: 'lightningcss-linux-x64-gnu',
|
||||
current: '1.32.0',
|
||||
wanted: '1.33.0',
|
||||
latest: '1.33.0',
|
||||
lockfileOnly: true,
|
||||
dependents: ['lightningcss'],
|
||||
}]);
|
||||
});
|
||||
|
||||
test('npm update rows recognize a prerelease to its compatible stable version', () => {
|
||||
const rows = npmUpdateRows({
|
||||
package: {
|
||||
current: '1.0.0-rc.1',
|
||||
wanted: '1.0.0',
|
||||
latest: '2.0.0',
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(rows, [{
|
||||
name: 'package',
|
||||
current: '1.0.0-rc.1',
|
||||
wanted: '1.0.0',
|
||||
latest: '2.0.0',
|
||||
lockfileOnly: false,
|
||||
dependents: [],
|
||||
}]);
|
||||
});
|
||||
|
||||
test('npm update rows ignore absent optional packages that are not in the lockfile', () => {
|
||||
assert.deepEqual(npmUpdateRows({
|
||||
'optional-package': {
|
||||
wanted: '1.2.0',
|
||||
latest: '2.0.0',
|
||||
},
|
||||
}, { cwd: '/workspace' }), []);
|
||||
});
|
||||
|
||||
test('npm update rows fail closed when an absent duplicate has ambiguous lockfile versions', () => {
|
||||
assert.throws(() => npmUpdateRows({
|
||||
package: {
|
||||
wanted: '1.2.0',
|
||||
latest: '2.0.0',
|
||||
},
|
||||
}, {
|
||||
lockfilePackages: {
|
||||
'node_modules/first/node_modules/package': { version: '1.0.0' },
|
||||
'node_modules/second/node_modules/package': { version: '1.1.0' },
|
||||
},
|
||||
}), /omitted locations for duplicate package-lock entries/);
|
||||
});
|
||||
|
||||
test('npm update rows fail closed for malformed package records', () => {
|
||||
assert.throws(
|
||||
() => npmUpdateRows({ broken: [{ current: '1.0.0', latest: '2.0.0' }] }),
|
||||
/omitted wanted or latest version/,
|
||||
);
|
||||
});
|
||||
|
||||
test('selects a complete BtbN build for the current stable series', async () => {
|
||||
|
||||
@@ -34,10 +34,11 @@ test('frontend CI covers the supported Node lines and native builds use the curr
|
||||
const desktopJob = ciWorkflow.slice(ciWorkflow.indexOf('\n desktop:'));
|
||||
|
||||
assert.match(ciWorkflow, /uses: actions\/setup-node@v7(?:\.\d+){0,2}/);
|
||||
assert.match(frontendJob, /node:\s*\[22\.23\.3,\s*24\.21\.0\]/);
|
||||
assert.match(frontendJob, /node:\s*\[22\.23\.3,\s*24\.22\.0,\s*26\.12\.0\]/);
|
||||
assert.match(frontendJob, /node-version: \$\{\{ matrix\.node \}\}/);
|
||||
assert.match(desktopJob, /node-version: 24\.21\.0/);
|
||||
assert.match(releaseWorkflow, /node-version: 24\.21\.0/);
|
||||
assert.match(desktopJob, /node-version: 24\.22\.0/);
|
||||
assert.match(releaseWorkflow, /node-version: 24\.22\.0/);
|
||||
assert.doesNotMatch(`${ciWorkflow}\n${releaseWorkflow}`, /node-version: 24\.21\.0/);
|
||||
assert.doesNotMatch(`${ciWorkflow}\n${releaseWorkflow}`, /node-version: 22\.12(?:\D|$)/);
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,12 @@ const releaseWorkflow = fs.readFileSync(
|
||||
path.join(repositoryRoot, '.github', 'workflows', 'release.yml'),
|
||||
'utf8',
|
||||
);
|
||||
const ciWorkflow = fs.readFileSync(
|
||||
path.join(repositoryRoot, '.github', 'workflows', 'ci.yml'),
|
||||
'utf8',
|
||||
);
|
||||
const readme = fs.readFileSync(path.join(repositoryRoot, 'README.md'), 'utf8');
|
||||
const releaseGuide = fs.readFileSync(path.join(repositoryRoot, 'RELEASE.md'), 'utf8');
|
||||
|
||||
test('release Linux dependency installation is mirror-normalized and bounded', () => {
|
||||
assert.match(releaseWorkflow, /azure\\\.archive\\\.ubuntu\\\.com/);
|
||||
@@ -40,6 +46,24 @@ test('Linux release pins and verifies appimagetool and its runtime inputs', () =
|
||||
assert.match(releaseWorkflow, /APPIMAGETOOL_RUNTIME_FILE: \$\{\{ runner\.temp \}\}\/appimage-runtime/);
|
||||
});
|
||||
|
||||
test('CI covers the declared Node floor and current runtimes while native jobs use Node 24 LTS', () => {
|
||||
assert.match(ciWorkflow, /node: \[22\.23\.3, 24\.22\.0, 26\.12\.0\]/);
|
||||
assert.equal((ciWorkflow.match(/node-version: 24\.22\.0/g) || []).length, 1);
|
||||
assert.equal((releaseWorkflow.match(/node-version: 24\.22\.0/g) || []).length, 1);
|
||||
assert.doesNotMatch(`${ciWorkflow}\n${releaseWorkflow}`, /node-version: 24\.21\.0/);
|
||||
});
|
||||
|
||||
test('Tauri CI and release workflows pin stable explicitly and Windows support floor is consistent', () => {
|
||||
const workflows = `${ciWorkflow}\n${releaseWorkflow}`;
|
||||
assert.equal((workflows.match(/dtolnay\/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec/g) || []).length, 3);
|
||||
assert.equal((workflows.match(/toolchain: stable/g) || []).length, 3);
|
||||
assert.doesNotMatch(workflows, /dtolnay\/rust-toolchain@686976e191b89faba57d3206551f0f330d8cb249/);
|
||||
assert.match(readme, /Windows 10 22H2 or newer/);
|
||||
assert.match(releaseGuide, /Windows 10 22H2\+ target/);
|
||||
assert.match(releaseGuide, /clean Windows 10 22H2\s+client \(OS build 19045\.x\)/);
|
||||
assert.match(releaseGuide, /--assert-no-visible-child-windows.*--assert-portable-data/s);
|
||||
});
|
||||
|
||||
test('Windows release job packages portable ZIP with portable.flag and data cleanup', () => {
|
||||
assert.match(releaseWorkflow, /Set-Content -Path \(Join-Path \$portableRoot 'portable\.flag'\) -Value 'portable'/);
|
||||
assert.match(releaseWorkflow, /node scripts\/smoke-packaged-app\.js --executable \$portableExe --assert-no-visible-child-windows --assert-portable-data/);
|
||||
|
||||
Generated
+16
-16
@@ -2341,9 +2341,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8c0d789294fb457b791f7797a04478704788f30b407e5d0b01deaa846572d9f"
|
||||
checksum = "3ce983bb6fb399067d101fbfc9e74174e07e9f29a2bc679efefeb8c645819c3f"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"hybrid-array",
|
||||
@@ -2624,9 +2624,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.190"
|
||||
version = "0.2.191"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
|
||||
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
@@ -2996,9 +2996,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
checksum = "cabcc654086861f9e1bc5115258de62ef92c79b20f4615a1b0cc57c4e82027d4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -4056,9 +4056,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.29"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
|
||||
checksum = "9cb23c424d8ee841bb4d813677ca237e2a610067d594fec130f87d6093495ab5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
@@ -5705,9 +5705,9 @@ checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.25"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
|
||||
checksum = "75cd3fb03d5288b3ba9a1ee103ac7e9cbb59f0b03d64f8ddfcc04dd42758a85d"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
@@ -6747,9 +6747,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zbus_names"
|
||||
version = "4.3.4"
|
||||
version = "4.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e"
|
||||
checksum = "812a12be4ead7a59e18ea8f047d08add0066b73bc62fc1467066a2472ae088dd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"winnow 1.0.4",
|
||||
@@ -6874,9 +6874,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "5.15.0"
|
||||
version = "5.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147"
|
||||
checksum = "80bf6d6cd6a4b601acb64cfb8284cdc643fcfa75ef26ae3c46ec8aa4e8a1fbb7"
|
||||
dependencies = [
|
||||
"endi",
|
||||
"enumflags2",
|
||||
@@ -6889,9 +6889,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_derive"
|
||||
version = "5.15.0"
|
||||
version = "5.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497"
|
||||
checksum = "ef2672456ba1cb54b5eaec136e63135b3c7495fb938e53b28a62e633496d486d"
|
||||
dependencies = [
|
||||
"proc-macro-crate 3.5.0",
|
||||
"proc-macro2",
|
||||
|
||||
@@ -74,7 +74,7 @@ objc2-app-kit = { version = "0.3", default-features = false, features = ["NSAppl
|
||||
objc2-core-services = "0.3"
|
||||
objc2-foundation = { version = "0.3", default-features = false, features = ["NSAppleEventDescriptor", "NSAppleEventManager", "NSAppleScript", "NSDictionary", "NSNotification", "NSObject", "NSString", "objc2-core-services", "std"] }
|
||||
smappservice-rs = "0.1.3"
|
||||
unicode-normalization = "0.1.25"
|
||||
unicode-normalization = "0.1.26"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
windows-native-keyring-store = "1.1.0"
|
||||
|
||||
Reference in New Issue
Block a user