mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 19:46:16 -08:00
fix(packaging): validate Linux frame-copy runtimes
This commit is contained in:
1 parent
482630dd2a
commit
541d47ac96
15 files changed
+480
-145
No files matched your search
@@ -825,16 +825,32 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
cp "${RUNNER_TEMP}/electron-builder.base.json" electron-builder.json
|
||||
node tools/packaging/configure-linux-frame-copy-build.mjs --foreign-deb
|
||||
for foreign_arch in armv7l arm64; do
|
||||
rm -rf dist/executables-linux-foreign
|
||||
cp "${RUNNER_TEMP}/electron-builder.base.json" electron-builder.json
|
||||
node tools/packaging/configure-linux-frame-copy-build.mjs \
|
||||
--foreign-deb \
|
||||
--foreign-arch "${foreign_arch}"
|
||||
pnpm nx run electron-backend:make \
|
||||
--arch="${foreign_arch}" \
|
||||
--outputPath=dist/executables-linux-foreign \
|
||||
--publishPolicy=never
|
||||
mapfile -t foreign_debs < <(
|
||||
find dist/executables-linux-foreign -maxdepth 1 -type f -name '*.deb' -print
|
||||
)
|
||||
test "${#foreign_debs[@]}" -eq 1
|
||||
case "${foreign_arch}" in
|
||||
armv7l) expected_deb_arch=armhf ;;
|
||||
arm64) expected_deb_arch=arm64 ;;
|
||||
*)
|
||||
echo "::error::Unexpected foreign DEB build architecture ${foreign_arch}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
actual_deb_arch="$(dpkg-deb --field "${foreign_debs[0]}" Architecture)"
|
||||
test "${actual_deb_arch}" = "${expected_deb_arch}"
|
||||
mv "${foreign_debs[0]}" dist/executables/
|
||||
done
|
||||
find dist/executables-linux-foreign -maxdepth 1 -type f -name '*.deb' \
|
||||
-exec mv '{}' dist/executables/ ';'
|
||||
|
||||
- name: Verify DEB payloads and x64 system runtime
|
||||
if: matrix.os == 'linux' && matrix.linux_profile == 'system'
|
||||
@@ -856,7 +872,8 @@ jobs:
|
||||
bash -euo pipefail -c '
|
||||
apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||
binutils libegl1 libgl1-mesa-dri libmpv2 nodejs squashfs-tools xauth xvfb
|
||||
binutils libegl1 libgbm1 libgl1-mesa-dri libmpv2 libopengl0 \
|
||||
nodejs squashfs-tools xauth xvfb
|
||||
xvfb-run -a env LIBGL_ALWAYS_SOFTWARE=1 \
|
||||
node tools/packaging/verify-linux-frame-copy-runtime.mjs \
|
||||
--artifact /artifact.deb --profile system
|
||||
@@ -889,8 +906,9 @@ jobs:
|
||||
fedora:latest \
|
||||
bash -euo pipefail -c '
|
||||
dnf install -y \
|
||||
binutils bsdtar mesa-dri-drivers mpv-libs nodejs rpm \
|
||||
xorg-x11-server-Xvfb xorg-x11-xauth
|
||||
binutils bsdtar libglvnd-egl libglvnd-opengl mesa-dri-drivers \
|
||||
mesa-libgbm mpv-libs nodejs rpm xorg-x11-server-Xvfb \
|
||||
xorg-x11-xauth
|
||||
xvfb-run -a env LIBGL_ALWAYS_SOFTWARE=1 \
|
||||
node tools/packaging/verify-linux-frame-copy-runtime.mjs \
|
||||
--artifact /artifact.rpm --profile system
|
||||
@@ -911,7 +929,8 @@ jobs:
|
||||
archlinux:latest \
|
||||
bash -euo pipefail -c '
|
||||
pacman -Syu --noconfirm \
|
||||
binutils libarchive mesa mpv nodejs xorg-server-xvfb xorg-xauth
|
||||
binutils libarchive libglvnd mesa mpv nodejs xorg-server-xvfb \
|
||||
xorg-xauth
|
||||
xvfb-run -a env LIBGL_ALWAYS_SOFTWARE=1 \
|
||||
node tools/packaging/verify-linux-frame-copy-runtime.mjs \
|
||||
--artifact /artifact.pacman --profile system
|
||||
@@ -947,9 +966,9 @@ jobs:
|
||||
verification="$(
|
||||
xvfb-run -a env LIBGL_ALWAYS_SOFTWARE=1 \
|
||||
node tools/packaging/verify-linux-frame-copy-runtime.mjs \
|
||||
--artifact "${artifact}" --profile portable
|
||||
--artifact "${artifact}" --profile portable \
|
||||
2>&1 | tee /dev/stderr
|
||||
)"
|
||||
printf '%s\n' "${verification}"
|
||||
if printf '%s\n' "${verification}" | grep -Fq 'Verified snap x64 Linux'; then
|
||||
sudo snap install --dangerous "${artifact}"
|
||||
installed_x64=true
|
||||
|
||||
@@ -224,7 +224,9 @@ Key files:
|
||||
overrides.
|
||||
- Packaging runs three isolated profiles:
|
||||
- `system`: DEB/RPM/Pacman, no private `native/lib`, with package
|
||||
dependencies `libmpv2`/`mpv-libs`/`mpv`
|
||||
dependencies DEB=`libmpv2,libegl1,libopengl0,libgbm1`,
|
||||
RPM=`mpv-libs,libglvnd-egl,libglvnd-opengl,mesa-libgbm`, and
|
||||
Pacman=`mpv,libglvnd,mesa`
|
||||
- `portable`: AppImage/Snap with the pinned LGPL-compatible closure
|
||||
- `flatpak`: Flatpak with the same pinned closure
|
||||
- The DEB system-runtime contract is Ubuntu 24.04+ (`libmpv2`). Ubuntu 22.04
|
||||
|
||||
@@ -628,15 +628,18 @@ engine` (restart required) or
|
||||
UI; native-view retains the legacy dock. On Linux, only
|
||||
`iptvnator_mpv_helper` may link libmpv; Electron, its shipped libraries, the
|
||||
addon, and frame reader must not. Official x64 packages use three separate
|
||||
profiles: DEB/RPM/Pacman depend on system libmpv, AppImage/Snap bundle the
|
||||
pinned LGPL closure, and Flatpak bundles the same closure. The DEB contract
|
||||
requires `libmpv2` and is verified on Ubuntu 24.04+; Ubuntu 22.04 users need
|
||||
the x64 AppImage because Jammy provides `libmpv1`. ARM packages are
|
||||
marker-only. Stored or explicit opt-ins cannot bypass the fail-closed
|
||||
packaged manifest/file/hash gate and bounded `--runtime-probe`; any failure
|
||||
keeps the sandbox enabled, records a stable reason, and falls back to
|
||||
native-view without crashing. Snap uses an exact private `shared-memory`
|
||||
plug; probe and playback share a sanitized loader environment in which
|
||||
profiles: DEB/RPM/Pacman depend on system libmpv plus the helper's direct
|
||||
EGL/OpenGL/GBM interfaces, AppImage/Snap bundle the pinned LGPL closure, and
|
||||
Flatpak bundles the same closure. Exact system dependencies are
|
||||
DEB=`libmpv2,libegl1,libopengl0,libgbm1`,
|
||||
RPM=`mpv-libs,libglvnd-egl,libglvnd-opengl,mesa-libgbm`, and
|
||||
Pacman=`mpv,libglvnd,mesa`. The DEB contract is verified on Ubuntu 24.04+;
|
||||
Ubuntu 22.04 users need the x64 AppImage because Jammy provides `libmpv1`.
|
||||
ARM packages are marker-only. Stored or explicit opt-ins cannot bypass the
|
||||
fail-closed packaged manifest/file/hash gate and bounded `--runtime-probe`;
|
||||
any failure keeps the sandbox enabled, records a stable reason, and falls
|
||||
back to native-view without crashing. Snap uses an exact private
|
||||
`shared-memory` plug; probe and playback share a sanitized loader environment in which
|
||||
ambient audit, preload, and library paths are removed and the validated
|
||||
private closure and trusted Snap GL roots have explicit precedence. Bundled
|
||||
Linux packages carry hash-validated
|
||||
|
||||
+10
-5
@@ -257,11 +257,16 @@ export const DEVELOPMENT_MANIFEST_FIELDS = [
|
||||
'sourceRuntimeValidated',
|
||||
] as const;
|
||||
|
||||
export const SYSTEM_PACKAGE_DEPENDENCIES = {
|
||||
deb: 'libmpv2',
|
||||
rpm: 'mpv-libs',
|
||||
pacman: 'mpv',
|
||||
};
|
||||
export const SYSTEM_PACKAGE_DEPENDENCIES = Object.freeze({
|
||||
deb: Object.freeze(['libmpv2', 'libegl1', 'libopengl0', 'libgbm1']),
|
||||
rpm: Object.freeze([
|
||||
'mpv-libs',
|
||||
'libglvnd-egl',
|
||||
'libglvnd-opengl',
|
||||
'mesa-libgbm',
|
||||
]),
|
||||
pacman: Object.freeze(['mpv', 'libglvnd', 'mesa']),
|
||||
});
|
||||
|
||||
export const PROFILE_CONTRACTS = {
|
||||
system: {
|
||||
|
||||
+8
-3
@@ -160,9 +160,14 @@ export function createFixture(
|
||||
packageDependencies: bundled
|
||||
? {}
|
||||
: {
|
||||
deb: 'libmpv2',
|
||||
rpm: 'mpv-libs',
|
||||
pacman: 'mpv',
|
||||
deb: ['libmpv2', 'libegl1', 'libopengl0', 'libgbm1'],
|
||||
rpm: [
|
||||
'mpv-libs',
|
||||
'libglvnd-egl',
|
||||
'libglvnd-opengl',
|
||||
'mesa-libgbm',
|
||||
],
|
||||
pacman: ['mpv', 'libglvnd', 'mesa'],
|
||||
},
|
||||
runtimeFiles,
|
||||
runtimeTotalBytes: runtimeFiles.reduce(
|
||||
|
||||
@@ -77,16 +77,24 @@ or `ELECTRON_OZONE_PLATFORM_HINT` is never overridden.
|
||||
Linux packages are built in separate passes because Electron Builder reuses
|
||||
one unpacked application layout per pass:
|
||||
|
||||
| Profile | Formats | Frame-copy libmpv strategy |
|
||||
| ---------- | ---------------- | --------------------------------------------------------------------------------------------- |
|
||||
| `system` | DEB, RPM, Pacman | System `libmpv.so.2`; package dependencies are `libmpv2`, `mpv-libs`, and `mpv`, respectively |
|
||||
| `portable` | AppImage, Snap | Bundled pinned LGPL-compatible runtime under `native/lib` |
|
||||
| `flatpak` | Flatpak | The same bundled pinned LGPL-compatible runtime under `native/lib` |
|
||||
| Profile | Formats | Frame-copy runtime strategy |
|
||||
| ---------- | ---------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `system` | DEB, RPM, Pacman | System `libmpv.so.2` plus the helper's direct EGL/OpenGL/GBM interfaces; exact dependencies are listed below |
|
||||
| `portable` | AppImage, Snap | Bundled pinned LGPL-compatible runtime under `native/lib` |
|
||||
| `flatpak` | Flatpak | The same bundled pinned LGPL-compatible runtime under `native/lib` |
|
||||
|
||||
System package dependencies are fail-closed and format-specific:
|
||||
|
||||
- DEB: `libmpv2`, `libegl1`, `libopengl0`, `libgbm1`
|
||||
- RPM: `mpv-libs`, `libglvnd-egl`, `libglvnd-opengl`, `mesa-libgbm`
|
||||
- Pacman: `mpv`, `libglvnd`, `mesa`
|
||||
|
||||
The DEB contract deliberately names `libmpv2`, not a loose `libmpv`
|
||||
alternative. Release CI verifies that contract on Ubuntu 24.04 (Noble).
|
||||
Ubuntu 22.04 (Jammy) provides `libmpv1`, so its DEB cannot enable this
|
||||
system-runtime frame-copy path; use the x64 AppImage there instead.
|
||||
alternative, and explicitly names the GLVND OpenGL interface because
|
||||
`libmpv2` does not pull it in for the helper. Release CI verifies that contract
|
||||
on Ubuntu 24.04 (Noble). Ubuntu 22.04 (Jammy) provides `libmpv1`, so its DEB
|
||||
cannot enable this system-runtime frame-copy path; use the x64 AppImage there
|
||||
instead.
|
||||
|
||||
Every x64 layout contains the addon, frame reader, helper, and a normalized
|
||||
`embedded-mpv-runtime.json`. The Electron executable, Electron libraries,
|
||||
@@ -580,10 +588,10 @@ Linux release profiles:
|
||||
|
||||
- `IPTVNATOR_LINUX_FRAME_COPY_PROFILE=system` builds DEB, RPM, and Pacman.
|
||||
`afterPack` removes the private `lib` directory, writes a
|
||||
`system-libmpv-frame-copy` manifest, and package metadata requires
|
||||
`libmpv2`, `mpv-libs`, or `mpv`. The DEB path is verified on Ubuntu 24.04+;
|
||||
Ubuntu 22.04 users need the x64 AppImage because Jammy only provides
|
||||
`libmpv1`.
|
||||
`system-libmpv-frame-copy` manifest, and package metadata requires the exact
|
||||
libmpv plus EGL/OpenGL/GBM package set listed above. The DEB path is verified
|
||||
on Ubuntu 24.04+; Ubuntu 22.04 users need the x64 AppImage because Jammy only
|
||||
provides `libmpv1`.
|
||||
- `IPTVNATOR_LINUX_FRAME_COPY_PROFILE=portable` builds AppImage and Snap with
|
||||
the pinned source-built closure and a `bundled-lgpl-frame-copy` manifest.
|
||||
- `IPTVNATOR_LINUX_FRAME_COPY_PROFILE=flatpak` builds Flatpak with the same
|
||||
@@ -618,10 +626,11 @@ Release packaging must:
|
||||
|
||||
Users on macOS and Windows do not need the MPV GUI application for this
|
||||
architecture. Linux native-view still requires an `mpv` executable. Linux
|
||||
frame-copy system packages need the declared libmpv package, while AppImage,
|
||||
Snap, and Flatpak carry their own runtime closure. If frame-copy prerequisites
|
||||
are missing, x64 falls back to native-view; if all Embedded MPV prerequisites
|
||||
are unavailable, the existing inline/external players remain available.
|
||||
frame-copy system packages need their declared libmpv and EGL/OpenGL/GBM
|
||||
packages, while AppImage, Snap, and Flatpak carry their own runtime closure.
|
||||
If frame-copy prerequisites are missing, x64 falls back to native-view; if all
|
||||
Embedded MPV prerequisites are unavailable, the existing inline/external
|
||||
players remain available.
|
||||
|
||||
## Runtime Staging
|
||||
|
||||
|
||||
@@ -57,14 +57,15 @@ profile.
|
||||
|
||||
System package dependencies are:
|
||||
|
||||
- DEB: `libmpv2`
|
||||
- RPM: `mpv-libs`
|
||||
- Pacman: `mpv`
|
||||
- DEB: `libmpv2`, `libegl1`, `libopengl0`, `libgbm1`
|
||||
- RPM: `mpv-libs`, `libglvnd-egl`, `libglvnd-opengl`, `mesa-libgbm`
|
||||
- Pacman: `mpv`, `libglvnd`, `mesa`
|
||||
|
||||
These names match the current Debian, Fedora, and Arch package databases.
|
||||
System packages do not copy libmpv into IPTVnator. The helper keeps an
|
||||
`$ORIGIN/lib` RPATH first for a consistent binary, but naturally resolves the
|
||||
system SONAME when the private directory is absent.
|
||||
These names match the current Debian, Fedora, and Arch package databases and
|
||||
cover every direct helper interface: libmpv, EGL, OpenGL, and GBM. System
|
||||
packages do not copy libmpv into IPTVnator. The helper keeps an `$ORIGIN/lib`
|
||||
RUNPATH first for a consistent binary, but naturally resolves the system SONAME
|
||||
when the private directory is absent.
|
||||
|
||||
Portable and sandboxed packages use a source-built runtime rather than copying
|
||||
the Ubuntu runner's mpv package. The runtime build is checksum/version pinned,
|
||||
|
||||
@@ -110,15 +110,25 @@ Before publication, the Linux builder verifies:
|
||||
|
||||
Set one exact `IPTVNATOR_LINUX_FRAME_COPY_PROFILE` per packaging pass:
|
||||
|
||||
| Profile | Formats | Runtime handling |
|
||||
| ---------- | ---------------- | ------------------------------------------------------------ |
|
||||
| `system` | DEB, RPM, Pacman | Remove `native/lib`; require `libmpv2`, `mpv-libs`, or `mpv` |
|
||||
| `portable` | AppImage, Snap | Retain the pinned LGPL closure under `native/lib` |
|
||||
| `flatpak` | Flatpak | Retain the same pinned LGPL closure under `native/lib` |
|
||||
| Profile | Formats | Runtime handling |
|
||||
| ---------- | ---------------- | ---------------------------------------------------------------------------- |
|
||||
| `system` | DEB, RPM, Pacman | Remove `native/lib`; require the format-specific system runtime listed below |
|
||||
| `portable` | AppImage, Snap | Retain the pinned LGPL closure under `native/lib` |
|
||||
| `flatpak` | Flatpak | Retain the same pinned LGPL closure under `native/lib` |
|
||||
|
||||
The DEB metadata requires `libmpv2` and is release-tested on Ubuntu 24.04
|
||||
(Noble). Ubuntu 22.04 (Jammy) only provides `libmpv1`; use the x64 AppImage on
|
||||
that distribution rather than relaxing the runtime contract.
|
||||
The system helper directly links libmpv, EGL, OpenGL, and GBM. Package metadata
|
||||
therefore declares the full interface set:
|
||||
|
||||
- DEB: `libmpv2`, `libegl1`, `libopengl0`, `libgbm1`
|
||||
- RPM: `mpv-libs`, `libglvnd-egl`, `libglvnd-opengl`, `mesa-libgbm`
|
||||
- Pacman: `mpv`, `libglvnd`, `mesa`
|
||||
|
||||
The DEB metadata is release-tested on Ubuntu 24.04 (Noble). Ubuntu 22.04
|
||||
(Jammy) only provides `libmpv1`; use the x64 AppImage on that distribution
|
||||
rather than relaxing the runtime contract. CI explicitly installs the distro
|
||||
Mesa software renderer for headless smoke. IPTVnator does not add DRI-driver
|
||||
packages as direct dependencies; any transitive graphics-driver stack remains
|
||||
under the distro's dependency policy.
|
||||
|
||||
The strict Snap retains Electron Builder's default plugs and adds an
|
||||
auto-connected private `shared-memory` plug. This supplies a snap-specific
|
||||
|
||||
@@ -42,26 +42,29 @@ function fpmDependencyName(option) {
|
||||
}
|
||||
|
||||
function configureSystemDependencies(config) {
|
||||
const frameCopyDependencies = new Set(
|
||||
Object.values(LINUX_SYSTEM_PACKAGE_DEPENDENCIES)
|
||||
);
|
||||
for (const [format, dependency] of Object.entries(
|
||||
for (const [format, dependencies] of Object.entries(
|
||||
LINUX_SYSTEM_PACKAGE_DEPENDENCIES
|
||||
)) {
|
||||
const frameCopyDependencies = new Set(dependencies);
|
||||
const formatConfig = { ...(config[format] ?? {}) };
|
||||
const otherFpmOptions = (formatConfig.fpm ?? []).filter(
|
||||
(option) => !frameCopyDependencies.has(fpmDependencyName(option))
|
||||
);
|
||||
formatConfig.fpm = [...otherFpmOptions, `--depends=${dependency}`];
|
||||
formatConfig.fpm = [
|
||||
...otherFpmOptions,
|
||||
...dependencies.map((dependency) => `--depends=${dependency}`),
|
||||
];
|
||||
config[format] = formatConfig;
|
||||
}
|
||||
}
|
||||
|
||||
function removeForeignFrameCopyDependency(config, format) {
|
||||
const dependency = LINUX_SYSTEM_PACKAGE_DEPENDENCIES[format];
|
||||
const dependencies = new Set(
|
||||
LINUX_SYSTEM_PACKAGE_DEPENDENCIES[format] ?? []
|
||||
);
|
||||
const formatConfig = { ...(config[format] ?? {}) };
|
||||
const retainedFpmOptions = (formatConfig.fpm ?? []).filter(
|
||||
(option) => fpmDependencyName(option) !== dependency
|
||||
(option) => !dependencies.has(fpmDependencyName(option))
|
||||
);
|
||||
if (retainedFpmOptions.length > 0) {
|
||||
formatConfig.fpm = retainedFpmOptions;
|
||||
@@ -73,8 +76,9 @@ function removeForeignFrameCopyDependency(config, format) {
|
||||
|
||||
export function configureLinuxFrameCopyBuild(
|
||||
electronBuilderConfig,
|
||||
{ profileName, foreignDeb = false } = {}
|
||||
{ profileName, foreignDeb = false, foreignArch } = {}
|
||||
) {
|
||||
const hasForeignArch = foreignArch !== undefined;
|
||||
if (
|
||||
!electronBuilderConfig ||
|
||||
typeof electronBuilderConfig !== 'object' ||
|
||||
@@ -89,6 +93,11 @@ export function configureLinuxFrameCopyBuild(
|
||||
'The marker-only foreign DEB pass must not select a frame-copy profile.'
|
||||
);
|
||||
}
|
||||
if (hasForeignArch && !foreignDeb) {
|
||||
throw new Error(
|
||||
'A marker-only foreign architecture requires --foreign-deb.'
|
||||
);
|
||||
}
|
||||
const configured = cloneJson(electronBuilderConfig);
|
||||
const targets = configured.linux?.target;
|
||||
if (!Array.isArray(targets)) {
|
||||
@@ -116,7 +125,20 @@ export function configureLinuxFrameCopyBuild(
|
||||
'Electron Builder DEB target has no foreign architectures.'
|
||||
);
|
||||
}
|
||||
configuredDebTarget.arch = foreignArches;
|
||||
if (
|
||||
hasForeignArch &&
|
||||
(typeof foreignArch !== 'string' ||
|
||||
!foreignArches.includes(foreignArch))
|
||||
) {
|
||||
throw new Error(
|
||||
`Unsupported marker-only foreign DEB architecture "${foreignArch}". Expected one of: ${foreignArches.join(
|
||||
', '
|
||||
)}.`
|
||||
);
|
||||
}
|
||||
configuredDebTarget.arch = hasForeignArch
|
||||
? [foreignArch]
|
||||
: foreignArches;
|
||||
configured.linux.target = [configuredDebTarget];
|
||||
configured.directories = {
|
||||
...(configured.directories ?? {}),
|
||||
@@ -179,14 +201,31 @@ function parseArguments(argv) {
|
||||
let configPath = 'electron-builder.json';
|
||||
let profileName;
|
||||
let foreignDeb = false;
|
||||
let foreignArch;
|
||||
const nextValue = (flag, index) => {
|
||||
const value = normalized[index + 1];
|
||||
if (
|
||||
typeof value !== 'string' ||
|
||||
value.trim() === '' ||
|
||||
value.startsWith('--')
|
||||
) {
|
||||
throw new Error(`${flag} requires a value.`);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
for (let index = 0; index < normalized.length; index += 1) {
|
||||
const argument = normalized[index];
|
||||
if (argument === '--config') {
|
||||
configPath = normalized[++index];
|
||||
configPath = nextValue(argument, index);
|
||||
index += 1;
|
||||
} else if (argument === '--profile') {
|
||||
profileName = normalized[++index];
|
||||
profileName = nextValue(argument, index);
|
||||
index += 1;
|
||||
} else if (argument === '--foreign-deb') {
|
||||
foreignDeb = true;
|
||||
} else if (argument === '--foreign-arch') {
|
||||
foreignArch = nextValue(argument, index);
|
||||
index += 1;
|
||||
} else {
|
||||
throw new Error(`Unsupported configurator argument: ${argument}`);
|
||||
}
|
||||
@@ -198,6 +237,7 @@ function parseArguments(argv) {
|
||||
configPath: path.resolve(configPath),
|
||||
profileName,
|
||||
foreignDeb,
|
||||
foreignArch,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
import { parse as parseYaml } from 'yaml';
|
||||
@@ -48,9 +50,23 @@ test('configures an x64-only system pass with exact package dependencies', () =>
|
||||
{ target: 'rpm', arch: ['x64'] },
|
||||
{ target: 'pacman', arch: ['x64'] },
|
||||
]);
|
||||
assert.deepEqual(configured.deb.fpm, ['--depends=libmpv2']);
|
||||
assert.deepEqual(configured.rpm.fpm, ['--depends=mpv-libs']);
|
||||
assert.deepEqual(configured.pacman.fpm, ['--depends=mpv']);
|
||||
assert.deepEqual(configured.deb.fpm, [
|
||||
'--depends=libmpv2',
|
||||
'--depends=libegl1',
|
||||
'--depends=libopengl0',
|
||||
'--depends=libgbm1',
|
||||
]);
|
||||
assert.deepEqual(configured.rpm.fpm, [
|
||||
'--depends=mpv-libs',
|
||||
'--depends=libglvnd-egl',
|
||||
'--depends=libglvnd-opengl',
|
||||
'--depends=mesa-libgbm',
|
||||
]);
|
||||
assert.deepEqual(configured.pacman.fpm, [
|
||||
'--depends=mpv',
|
||||
'--depends=libglvnd',
|
||||
'--depends=mesa',
|
||||
]);
|
||||
});
|
||||
|
||||
test('configures portable and flatpak passes without mixing targets', () => {
|
||||
@@ -99,6 +115,76 @@ test('configures a separate marker-only foreign DEB pass without libmpv metadata
|
||||
);
|
||||
});
|
||||
|
||||
test('configures exactly one requested marker-only foreign DEB architecture', () => {
|
||||
for (const foreignArch of ['armv7l', 'arm64']) {
|
||||
const configured = configureLinuxFrameCopyBuild(electronBuilderConfig, {
|
||||
foreignDeb: true,
|
||||
foreignArch,
|
||||
});
|
||||
|
||||
assert.deepEqual(configuredTargets(configured), [
|
||||
{ target: 'deb', arch: [foreignArch] },
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test('CLI writes an exact marker-only foreign DEB architecture', (t) => {
|
||||
const temporaryDirectory = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'iptvnator-linux-build-config-')
|
||||
);
|
||||
t.after(() =>
|
||||
fs.rmSync(temporaryDirectory, { recursive: true, force: true })
|
||||
);
|
||||
const configPath = path.join(temporaryDirectory, 'electron-builder.json');
|
||||
fs.writeFileSync(
|
||||
configPath,
|
||||
`${JSON.stringify(electronBuilderConfig, null, 4)}\n`
|
||||
);
|
||||
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
path.join(
|
||||
workspaceRoot,
|
||||
'tools',
|
||||
'packaging',
|
||||
'configure-linux-frame-copy-build.mjs'
|
||||
),
|
||||
'--config',
|
||||
configPath,
|
||||
'--foreign-deb',
|
||||
'--foreign-arch',
|
||||
'arm64',
|
||||
],
|
||||
{ encoding: 'utf8' }
|
||||
);
|
||||
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
assert.deepEqual(
|
||||
configuredTargets(JSON.parse(fs.readFileSync(configPath, 'utf8'))),
|
||||
[{ target: 'deb', arch: ['arm64'] }]
|
||||
);
|
||||
|
||||
const missingValue = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
path.join(
|
||||
workspaceRoot,
|
||||
'tools',
|
||||
'packaging',
|
||||
'configure-linux-frame-copy-build.mjs'
|
||||
),
|
||||
'--config',
|
||||
configPath,
|
||||
'--foreign-deb',
|
||||
'--foreign-arch',
|
||||
],
|
||||
{ encoding: 'utf8' }
|
||||
);
|
||||
assert.notEqual(missingValue.status, 0);
|
||||
assert.match(missingValue.stderr, /--foreign-arch requires a value/);
|
||||
});
|
||||
|
||||
test('does not mutate the shared electron-builder configuration', () => {
|
||||
const before = JSON.stringify(electronBuilderConfig);
|
||||
configureLinuxFrameCopyBuild(electronBuilderConfig, {
|
||||
@@ -123,6 +209,31 @@ test('rejects an unknown profile and conflicting foreign/profile modes', () => {
|
||||
}),
|
||||
/must not select a frame-copy profile/
|
||||
);
|
||||
assert.throws(
|
||||
() =>
|
||||
configureLinuxFrameCopyBuild(electronBuilderConfig, {
|
||||
foreignArch: 'arm64',
|
||||
}),
|
||||
/foreign architecture requires --foreign-deb/
|
||||
);
|
||||
assert.throws(
|
||||
() =>
|
||||
configureLinuxFrameCopyBuild(electronBuilderConfig, {
|
||||
foreignDeb: true,
|
||||
foreignArch: 'x64',
|
||||
}),
|
||||
/Unsupported marker-only foreign DEB architecture/
|
||||
);
|
||||
for (const foreignArch of ['', 64]) {
|
||||
assert.throws(
|
||||
() =>
|
||||
configureLinuxFrameCopyBuild(electronBuilderConfig, {
|
||||
foreignDeb: true,
|
||||
foreignArch,
|
||||
}),
|
||||
/Unsupported marker-only foreign DEB architecture/
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('rejects duplicate profile targets even when target count looks complete', () => {
|
||||
@@ -142,20 +253,32 @@ test('rejects duplicate profile targets even when target count looks complete',
|
||||
test('preserves unrelated fpm dependencies and normalizes only frame-copy dependencies', () => {
|
||||
const customized = structuredClone(electronBuilderConfig);
|
||||
customized.deb = {
|
||||
fpm: ['--depends=unrelated-runtime', '--depends=libmpv2 >= 2'],
|
||||
fpm: [
|
||||
'--depends=unrelated-runtime',
|
||||
'--depends=mesa',
|
||||
'--depends=libmpv2 >= 2',
|
||||
'--depends=libopengl0',
|
||||
],
|
||||
};
|
||||
const system = configureLinuxFrameCopyBuild(customized, {
|
||||
profileName: 'system',
|
||||
});
|
||||
assert.deepEqual(system.deb.fpm, [
|
||||
'--depends=unrelated-runtime',
|
||||
'--depends=mesa',
|
||||
'--depends=libmpv2',
|
||||
'--depends=libegl1',
|
||||
'--depends=libopengl0',
|
||||
'--depends=libgbm1',
|
||||
]);
|
||||
|
||||
const foreign = configureLinuxFrameCopyBuild(customized, {
|
||||
foreignDeb: true,
|
||||
});
|
||||
assert.deepEqual(foreign.deb.fpm, ['--depends=unrelated-runtime']);
|
||||
assert.deepEqual(foreign.deb.fpm, [
|
||||
'--depends=unrelated-runtime',
|
||||
'--depends=mesa',
|
||||
]);
|
||||
});
|
||||
|
||||
test('Linux CI builds one cached source runtime and packages three isolated profiles', () => {
|
||||
@@ -173,7 +296,7 @@ test('Linux CI builds one cached source runtime and packages three isolated prof
|
||||
);
|
||||
assert.match(
|
||||
buildWorkflow,
|
||||
/configure-linux-frame-copy-build\.mjs --foreign-deb/
|
||||
/configure-linux-frame-copy-build\.mjs[\s\S]*--foreign-deb/
|
||||
);
|
||||
assert.match(
|
||||
buildWorkflow,
|
||||
@@ -368,12 +491,85 @@ test('foreign DEB CI explicitly selects both marker-only ARM architectures', ()
|
||||
);
|
||||
|
||||
assert.match(foreignDebStep, /for foreign_arch in armv7l arm64; do/);
|
||||
assert.match(
|
||||
foreignDebStep,
|
||||
/--foreign-deb\s+\\\s+--foreign-arch "\$\{foreign_arch\}"/
|
||||
);
|
||||
assert.match(foreignDebStep, /--arch="\$\{foreign_arch\}"/);
|
||||
assert.match(
|
||||
foreignDebStep,
|
||||
/for foreign_arch[\s\S]*cp "\$\{RUNNER_TEMP\}\/electron-builder\.base\.json" electron-builder\.json[\s\S]*configure-linux-frame-copy-build\.mjs/
|
||||
);
|
||||
assert.match(foreignDebStep, /rm -rf dist\/executables-linux-foreign/);
|
||||
assert.match(
|
||||
foreignDebStep,
|
||||
/mapfile -t foreign_debs < <\(\s*find dist\/executables-linux-foreign[\s\S]*-name '\*\.deb' -print\s*\)/
|
||||
);
|
||||
assert.match(foreignDebStep, /test "\$\{#foreign_debs\[@\]\}" -eq 1/);
|
||||
assert.match(foreignDebStep, /armv7l\) expected_deb_arch=armhf/);
|
||||
assert.match(foreignDebStep, /arm64\) expected_deb_arch=arm64/);
|
||||
assert.match(
|
||||
foreignDebStep,
|
||||
/actual_deb_arch="\$\(dpkg-deb --field "\$\{foreign_debs\[0\]\}" Architecture\)"[\s\S]*test "\$\{actual_deb_arch\}" = "\$\{expected_deb_arch\}"/
|
||||
);
|
||||
assert.match(
|
||||
foreignDebStep,
|
||||
/mv "\$\{foreign_debs\[0\]\}" dist\/executables\//
|
||||
);
|
||||
assert.match(foreignDebStep, /IPTVNATOR_LINUX_FRAME_COPY_PROFILE: ''/);
|
||||
assert.match(foreignDebStep, /IPTVNATOR_REQUIRE_EMBEDDED_MPV: '1'/);
|
||||
assert.doesNotMatch(foreignDebStep, /IPTVNATOR_REQUIRE_EMBEDDED_MPV: '0'/);
|
||||
});
|
||||
|
||||
test('system package smoke environments install every direct helper runtime dependency', () => {
|
||||
const debStep = workflowStep('Verify DEB payloads and x64 system runtime');
|
||||
for (const dependency of ['libmpv2', 'libegl1', 'libopengl0', 'libgbm1']) {
|
||||
assert.match(debStep, new RegExp(`\\b${dependency}\\b`));
|
||||
}
|
||||
|
||||
const rpmStep = workflowStep('Verify RPM payload and x64 system runtime');
|
||||
for (const dependency of [
|
||||
'mpv-libs',
|
||||
'libglvnd-egl',
|
||||
'libglvnd-opengl',
|
||||
'mesa-libgbm',
|
||||
]) {
|
||||
assert.match(rpmStep, new RegExp(`\\b${dependency}\\b`));
|
||||
}
|
||||
|
||||
const pacmanStep = workflowStep(
|
||||
'Verify Pacman payload and x64 system runtime'
|
||||
);
|
||||
for (const dependency of ['mpv', 'libglvnd', 'mesa']) {
|
||||
assert.match(pacmanStep, new RegExp(`\\b${dependency}\\b`));
|
||||
}
|
||||
});
|
||||
|
||||
test('Snap verifier preserves fail-closed status while exposing captured diagnostics', () => {
|
||||
const snapStep = workflowStep(
|
||||
'Verify Snap payloads and strict-confinement runtime'
|
||||
);
|
||||
|
||||
assert.match(snapStep, /set -euo pipefail/);
|
||||
assert.match(snapStep, /2>&1 \| tee \/dev\/stderr/);
|
||||
assert.doesNotMatch(
|
||||
snapStep,
|
||||
/^\s+printf '%s\\n' "\$\{verification\}"\s*$/m
|
||||
);
|
||||
assert.ok(
|
||||
snapStep.indexOf('verification="$(') <
|
||||
snapStep.indexOf("grep -Fq 'Verified snap x64 Linux'")
|
||||
);
|
||||
assert.ok(
|
||||
snapStep.indexOf("grep -Fq 'Verified snap x64 Linux'") <
|
||||
snapStep.indexOf('sudo snap install --dangerous')
|
||||
);
|
||||
assert.ok(
|
||||
snapStep.indexOf('sudo snap install --dangerous') <
|
||||
snapStep.indexOf('installed_x64=true')
|
||||
);
|
||||
});
|
||||
|
||||
test('dedicated packaged x64 smoke cannot silently skip', () => {
|
||||
const linuxDependencies = workflowStep('Install Linux system dependencies');
|
||||
assert.match(linuxDependencies, /--no-install-recommends/);
|
||||
|
||||
@@ -36,9 +36,9 @@ const {
|
||||
|
||||
const X64_ADDON_ENV = { IPTVNATOR_EMBEDDED_MPV_ARCH: 'x64' };
|
||||
const SYSTEM_PACKAGE_DEPENDENCIES = {
|
||||
deb: 'libmpv2',
|
||||
rpm: 'mpv-libs',
|
||||
pacman: 'mpv',
|
||||
deb: ['libmpv2', 'libegl1', 'libopengl0', 'libgbm1'],
|
||||
rpm: ['mpv-libs', 'libglvnd-egl', 'libglvnd-opengl', 'mesa-libgbm'],
|
||||
pacman: ['mpv', 'libglvnd', 'mesa'],
|
||||
};
|
||||
const FRAME_COPY_ARTIFACTS = {
|
||||
addon: 'embedded_mpv.node',
|
||||
|
||||
@@ -34,9 +34,14 @@ const SUPPORTED_PROFILE_NAMES = Object.freeze(
|
||||
);
|
||||
|
||||
const LINUX_SYSTEM_PACKAGE_DEPENDENCIES = Object.freeze({
|
||||
deb: 'libmpv2',
|
||||
rpm: 'mpv-libs',
|
||||
pacman: 'mpv',
|
||||
deb: Object.freeze(['libmpv2', 'libegl1', 'libopengl0', 'libgbm1']),
|
||||
rpm: Object.freeze([
|
||||
'mpv-libs',
|
||||
'libglvnd-egl',
|
||||
'libglvnd-opengl',
|
||||
'mesa-libgbm',
|
||||
]),
|
||||
pacman: Object.freeze(['mpv', 'libglvnd', 'mesa']),
|
||||
});
|
||||
|
||||
function expectedProfileNames() {
|
||||
|
||||
@@ -58,13 +58,18 @@ test('defines the exact immutable Linux frame-copy profile matrix', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('defines immutable system-package libmpv dependencies', () => {
|
||||
test('defines immutable system-package helper runtime dependencies', () => {
|
||||
assert.deepEqual(LINUX_SYSTEM_PACKAGE_DEPENDENCIES, {
|
||||
deb: 'libmpv2',
|
||||
rpm: 'mpv-libs',
|
||||
pacman: 'mpv',
|
||||
deb: ['libmpv2', 'libegl1', 'libopengl0', 'libgbm1'],
|
||||
rpm: ['mpv-libs', 'libglvnd-egl', 'libglvnd-opengl', 'mesa-libgbm'],
|
||||
pacman: ['mpv', 'libglvnd', 'mesa'],
|
||||
});
|
||||
assert.equal(Object.isFrozen(LINUX_SYSTEM_PACKAGE_DEPENDENCIES), true);
|
||||
for (const dependencies of Object.values(
|
||||
LINUX_SYSTEM_PACKAGE_DEPENDENCIES
|
||||
)) {
|
||||
assert.equal(Object.isFrozen(dependencies), true);
|
||||
}
|
||||
});
|
||||
|
||||
test('resolves each supported profile as an immutable defensive value', () => {
|
||||
@@ -158,7 +163,7 @@ test('rejects a non-array profile target list', () => {
|
||||
});
|
||||
|
||||
test('keeps frame-copy package dependencies out of the base Electron Builder config', () => {
|
||||
for (const [target, dependency] of Object.entries(
|
||||
for (const [target, dependencies] of Object.entries(
|
||||
LINUX_SYSTEM_PACKAGE_DEPENDENCIES
|
||||
)) {
|
||||
assert.equal(
|
||||
@@ -166,14 +171,16 @@ test('keeps frame-copy package dependencies out of the base Electron Builder con
|
||||
undefined,
|
||||
`${target}.depends must remain unset so electron-builder keeps its defaults`
|
||||
);
|
||||
assert.equal(
|
||||
hasSystemFrameCopyDependency(
|
||||
electronBuilderConfig,
|
||||
target,
|
||||
dependency
|
||||
),
|
||||
false
|
||||
);
|
||||
for (const dependency of dependencies) {
|
||||
assert.equal(
|
||||
hasSystemFrameCopyDependency(
|
||||
electronBuilderConfig,
|
||||
target,
|
||||
dependency
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -191,13 +198,15 @@ test('keeps frame-copy package dependencies out of non-system passes', () => {
|
||||
];
|
||||
|
||||
for (const config of configs) {
|
||||
for (const [format, dependency] of Object.entries(
|
||||
for (const [format, dependencies] of Object.entries(
|
||||
LINUX_SYSTEM_PACKAGE_DEPENDENCIES
|
||||
)) {
|
||||
assert.equal(
|
||||
hasSystemFrameCopyDependency(config, format, dependency),
|
||||
false
|
||||
);
|
||||
for (const dependency of dependencies) {
|
||||
assert.equal(
|
||||
hasSystemFrameCopyDependency(config, format, dependency),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -932,8 +932,8 @@ function dependencyMatches(dependency, expected) {
|
||||
}
|
||||
|
||||
export function validateSystemPackageDependencies(format, dependencies) {
|
||||
const expectedDependency = LINUX_SYSTEM_PACKAGE_DEPENDENCIES[format];
|
||||
if (!expectedDependency) {
|
||||
const expectedDependencies = LINUX_SYSTEM_PACKAGE_DEPENDENCIES[format];
|
||||
if (!expectedDependencies) {
|
||||
return [];
|
||||
}
|
||||
if (!Array.isArray(dependencies)) {
|
||||
@@ -941,31 +941,29 @@ export function validateSystemPackageDependencies(format, dependencies) {
|
||||
`Linux ${format} package dependency metadata must be an array.`,
|
||||
];
|
||||
}
|
||||
if (
|
||||
!dependencies.some((dependency) =>
|
||||
return expectedDependencies.flatMap((expectedDependency) =>
|
||||
dependencies.some((dependency) =>
|
||||
dependencyMatches(String(dependency), expectedDependency)
|
||||
)
|
||||
) {
|
||||
return [
|
||||
`Linux x64 ${format} package must declare ${expectedDependency}.`,
|
||||
];
|
||||
}
|
||||
return [];
|
||||
? []
|
||||
: [
|
||||
`Linux x64 ${format} package must declare ${expectedDependency}.`,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
function validateForeignPackageDependencies(format, dependencies) {
|
||||
const forbiddenDependency = LINUX_SYSTEM_PACKAGE_DEPENDENCIES[format];
|
||||
if (
|
||||
forbiddenDependency &&
|
||||
const forbiddenDependencies =
|
||||
LINUX_SYSTEM_PACKAGE_DEPENDENCIES[format] ?? [];
|
||||
return forbiddenDependencies.flatMap((forbiddenDependency) =>
|
||||
dependencies.some((dependency) =>
|
||||
dependencyMatches(String(dependency), forbiddenDependency)
|
||||
)
|
||||
) {
|
||||
return [
|
||||
`Linux foreign-architecture ${format} package must not declare frame-copy dependency ${forbiddenDependency}.`,
|
||||
];
|
||||
}
|
||||
return [];
|
||||
? [
|
||||
`Linux foreign-architecture ${format} package must not declare frame-copy dependency ${forbiddenDependency}.`,
|
||||
]
|
||||
: []
|
||||
);
|
||||
}
|
||||
|
||||
function dependencyFileName(dependencyName) {
|
||||
|
||||
@@ -77,13 +77,19 @@ const SYSTEM_MANIFEST = {
|
||||
nativeViewFallback: 'process-isolated mpv --wid',
|
||||
libmpvSoname: 'libmpv.so.2',
|
||||
packageDependencies: {
|
||||
deb: 'libmpv2',
|
||||
rpm: 'mpv-libs',
|
||||
pacman: 'mpv',
|
||||
deb: ['libmpv2', 'libegl1', 'libopengl0', 'libgbm1'],
|
||||
rpm: ['mpv-libs', 'libglvnd-egl', 'libglvnd-opengl', 'mesa-libgbm'],
|
||||
pacman: ['mpv', 'libglvnd', 'mesa'],
|
||||
},
|
||||
runtimeFiles: [],
|
||||
runtimeTotalBytes: 0,
|
||||
};
|
||||
const DEB_SYSTEM_PACKAGE_DEPENDENCIES = [
|
||||
'libmpv2',
|
||||
'libegl1',
|
||||
'libopengl0',
|
||||
'libgbm1',
|
||||
];
|
||||
|
||||
test('uses the shared frozen 3000 ms runtime probe timeout contract', async () => {
|
||||
assert.equal(
|
||||
@@ -613,25 +619,43 @@ test('reads x64, arm64, and armv7 ELF architectures without host execution', ()
|
||||
}
|
||||
});
|
||||
|
||||
test('requires the exact system package dependency for DEB, RPM, and Pacman', () => {
|
||||
test('requires every direct helper runtime dependency for DEB, RPM, and Pacman', () => {
|
||||
assert.deepEqual(
|
||||
validateSystemPackageDependencies('deb', [
|
||||
'libmpv2 (>= 0.35)',
|
||||
'libegl1',
|
||||
'libopengl0',
|
||||
'libgbm1',
|
||||
'libc6',
|
||||
]),
|
||||
[]
|
||||
);
|
||||
assert.deepEqual(
|
||||
validateSystemPackageDependencies('rpm', ['mpv-libs', 'glibc']),
|
||||
validateSystemPackageDependencies('rpm', [
|
||||
'mpv-libs',
|
||||
'libglvnd-egl',
|
||||
'libglvnd-opengl',
|
||||
'mesa-libgbm',
|
||||
'glibc',
|
||||
]),
|
||||
[]
|
||||
);
|
||||
assert.deepEqual(
|
||||
validateSystemPackageDependencies('pacman', ['mpv>=0.35', 'glibc']),
|
||||
validateSystemPackageDependencies('pacman', [
|
||||
'mpv>=0.35',
|
||||
'libglvnd',
|
||||
'mesa',
|
||||
'glibc',
|
||||
]),
|
||||
[]
|
||||
);
|
||||
assert.match(
|
||||
validateSystemPackageDependencies('deb', ['libmpv1'])[0],
|
||||
/libmpv2/
|
||||
validateSystemPackageDependencies('deb', [
|
||||
'libmpv2',
|
||||
'libegl1',
|
||||
'libgbm1',
|
||||
])[0],
|
||||
/libopengl0/
|
||||
);
|
||||
});
|
||||
|
||||
@@ -731,7 +755,12 @@ test('validates an x64 system payload and executes one bounded helper probe', ()
|
||||
resourceDir: fixture.resourceDir,
|
||||
artifactFormat: 'deb',
|
||||
profileName: 'system',
|
||||
packageDependencies: ['libmpv2 (>= 0.35)'],
|
||||
packageDependencies: [
|
||||
'libmpv2 (>= 0.35)',
|
||||
'libegl1',
|
||||
'libopengl0',
|
||||
'libgbm1',
|
||||
],
|
||||
elfInspector: validElfInspector,
|
||||
probeRunner(command, args, options) {
|
||||
probeCalls.push({ command, args, options });
|
||||
@@ -787,7 +816,7 @@ test('rejects helper probes terminated by a signal or hard timeout', () => {
|
||||
resourceDir: fixture.resourceDir,
|
||||
artifactFormat: 'deb',
|
||||
profileName: 'system',
|
||||
packageDependencies: ['libmpv2'],
|
||||
packageDependencies: DEB_SYSTEM_PACKAGE_DEPENDENCIES,
|
||||
elfInspector: validElfInspector,
|
||||
probeRunner() {
|
||||
return probeResult;
|
||||
@@ -1142,7 +1171,7 @@ test('rejects helper probe framing and fields that runtime capability rejects',
|
||||
resourceDir: fixture.resourceDir,
|
||||
artifactFormat: 'deb',
|
||||
profileName: 'system',
|
||||
packageDependencies: ['libmpv2'],
|
||||
packageDependencies: DEB_SYSTEM_PACKAGE_DEPENDENCIES,
|
||||
elfInspector: validElfInspector,
|
||||
probeRunner() {
|
||||
return {
|
||||
@@ -1219,7 +1248,7 @@ test('reports missing helper, wrong mode, wrong profile, isolation, and loader f
|
||||
resourceDir: fixture.resourceDir,
|
||||
artifactFormat: 'deb',
|
||||
profileName: testCase.profileName ?? 'system',
|
||||
packageDependencies: ['libmpv2'],
|
||||
packageDependencies: DEB_SYSTEM_PACKAGE_DEPENDENCIES,
|
||||
elfInspector: testCase.elfInspector ?? validElfInspector,
|
||||
probeRunner: testCase.probeRunner ?? successfulProbeRunner,
|
||||
});
|
||||
@@ -1245,7 +1274,7 @@ test('rejects an x64 package manifest produced from a target subset', () => {
|
||||
resourceDir: fixture.resourceDir,
|
||||
artifactFormat: 'deb',
|
||||
profileName: 'system',
|
||||
packageDependencies: ['libmpv2'],
|
||||
packageDependencies: DEB_SYSTEM_PACKAGE_DEPENDENCIES,
|
||||
elfInspector: validElfInspector,
|
||||
probeRunner: successfulProbeRunner,
|
||||
});
|
||||
@@ -1305,19 +1334,23 @@ test('requires marker-only foreign packages, scans Electron, and never probes',
|
||||
);
|
||||
assert.equal(probeCalls, 0);
|
||||
|
||||
const dependencyErrors = verifyExtractedLinuxFrameCopyRuntime({
|
||||
resourceDir: fixture.resourceDir,
|
||||
artifactFormat: 'deb',
|
||||
profileName: 'system',
|
||||
packageDependencies: ['libmpv2', 'libc6'],
|
||||
declaredArch: 'arm64',
|
||||
elfInspector: validElfInspector,
|
||||
probeRunner: successfulProbeRunner,
|
||||
});
|
||||
assert.match(
|
||||
dependencyErrors.join('\n'),
|
||||
/must not declare frame-copy dependency libmpv2/
|
||||
);
|
||||
for (const forbiddenDependency of DEB_SYSTEM_PACKAGE_DEPENDENCIES) {
|
||||
const dependencyErrors = verifyExtractedLinuxFrameCopyRuntime({
|
||||
resourceDir: fixture.resourceDir,
|
||||
artifactFormat: 'deb',
|
||||
profileName: 'system',
|
||||
packageDependencies: [forbiddenDependency, 'libc6'],
|
||||
declaredArch: 'arm64',
|
||||
elfInspector: validElfInspector,
|
||||
probeRunner: successfulProbeRunner,
|
||||
});
|
||||
assert.match(
|
||||
dependencyErrors.join('\n'),
|
||||
new RegExp(
|
||||
`must not declare frame-copy dependency ${forbiddenDependency}`
|
||||
)
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
fs.rmSync(fixture.root, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user