diff --git a/.github/workflows/build-and-make.yaml b/.github/workflows/build-and-make.yaml index 3e22680436..13c7df3c2f 100644 --- a/.github/workflows/build-and-make.yaml +++ b/.github/workflows/build-and-make.yaml @@ -1119,6 +1119,17 @@ jobs: run: | set -euo pipefail + ensure_snap() { + local name="$1" delay + for delay in 0 15 30; do + sleep "${delay}" + if snap list "${name}" >/dev/null 2>&1 || sudo snap install "${name}"; then + return 0 + fi + done + return 1 + } + found=false installed_x64=false for artifact in dist/executables/*.snap; do @@ -1131,8 +1142,8 @@ jobs: 2>&1 | tee /dev/stderr )" if printf '%s\n' "${verification}" | grep -Fq 'Verified snap x64 Linux'; then - snap list mesa-core22 >/dev/null 2>&1 || sudo snap install mesa-core22 - snap list gnome-3-28-1804 >/dev/null 2>&1 || sudo snap install gnome-3-28-1804 + ensure_snap mesa-core22 + ensure_snap gnome-3-28-1804 sudo snap install --dangerous "${artifact}" installed_x64=true fi diff --git a/tools/embedded-mpv/README.md b/tools/embedded-mpv/README.md index f54eb8131f..6966b99b50 100644 --- a/tools/embedded-mpv/README.md +++ b/tools/embedded-mpv/README.md @@ -355,6 +355,9 @@ spent. Both constants live in `runtime-probe-contract.cjs`. For a locally installed `--dangerous` Snap, CI explicitly installs and connects `mesa-core22` and `gnome-3-28-1804`, verifies both connections, and then runs the application-level diagnostic under Xvfb. +Missing providers are installed from the Snap Store with up to three attempts +and pauses of 15 and 30 seconds after failures. If installation still fails, +the runtime check fails. The Linux packaging matrix alone depends on the runtime-builder job. macOS and Windows use an independent matrix, while both matrices share the same anchored step list; draft release assembly remains atomic and requires both matrices. diff --git a/tools/packaging/configure-linux-frame-copy-build.test.mjs b/tools/packaging/configure-linux-frame-copy-build.test.mjs index 785dcda5ff..63f3bc7482 100644 --- a/tools/packaging/configure-linux-frame-copy-build.test.mjs +++ b/tools/packaging/configure-linux-frame-copy-build.test.mjs @@ -771,6 +771,47 @@ test('system package smoke environments install every direct helper runtime depe } }); +test('Snap dependencies retry failed installs and fail after three attempts', () => { + const step = buildWorkflowConfig.jobs['build-linux'].steps.find( + ({ name }) => + name === 'Verify Snap payloads and strict-confinement runtime' + ); + const setup = step.run.split('\nfound=false\n')[0]; + const script = ` +${setup} +attempts=0 +snap() { [[ "$1 $2" == "list mesa-core22" && "$installed" == 1 ]]; } +sudo() { + printf '%s\\n' "$*" + (( ++attempts == succeeds_on )) +} +sleep() { printf 'sleep %s\\n' "$1"; } +installed="$1" +succeeds_on="$2" +ensure_snap mesa-core22 +`; + const install = 'snap install mesa-core22\n'; + for (const [installed, succeedsOn, status, stdout] of [ + ['1', '0', 0, 'sleep 0\n'], + ['0', '2', 0, `sleep 0\n${install}sleep 15\n${install}`], + [ + '0', + '0', + 1, + `sleep 0\n${install}sleep 15\n${install}sleep 30\n${install}`, + ], + ]) { + const result = spawnSync( + 'bash', + ['-c', script, 'snap-test', installed, succeedsOn], + { encoding: 'utf8' } + ); + assert.ifError(result.error); + assert.equal(result.status, status, result.stderr); + assert.equal(result.stdout, stdout); + } +}); + test('Snap verifier preserves fail-closed status while exposing captured diagnostics', () => { const snapStep = workflowStep( 'Verify Snap payloads and strict-confinement runtime' @@ -790,22 +831,13 @@ test('Snap verifier preserves fail-closed status while exposing captured diagnos snapStep.indexOf("grep -Fq 'Verified snap x64 Linux'") < snapStep.indexOf('sudo snap install --dangerous') ); - assert.match( - snapStep, - /snap list mesa-core22 >\/dev\/null 2>&1 \|\| sudo snap install mesa-core22/ - ); - assert.match( - snapStep, - /snap list gnome-3-28-1804 >\/dev\/null 2>&1 \|\| sudo snap install gnome-3-28-1804/ - ); - assert.ok( - snapStep.indexOf('sudo snap install mesa-core22') < - snapStep.indexOf('sudo snap install --dangerous') - ); - assert.ok( - snapStep.indexOf('sudo snap install gnome-3-28-1804') < - snapStep.indexOf('sudo snap install --dangerous') - ); + for (const dependency of ['mesa-core22', 'gnome-3-28-1804']) { + const install = snapStep.indexOf(`ensure_snap ${dependency}`); + assert.ok( + install > snapStep.indexOf("grep -Fq 'Verified snap x64 Linux'") + ); + assert.ok(install < snapStep.indexOf('sudo snap install --dangerous')); + } assert.ok( snapStep.indexOf('sudo snap install --dangerous') < snapStep.indexOf('installed_x64=true')