From 98f3210d0c55aa7393037454275eed367b23bc83 Mon Sep 17 00:00:00 2001 From: thesiti92 Date: Fri, 25 Sep 2026 18:32:59 -0400 Subject: [PATCH 1/2] Run Windows package CI only on manual dispatch Agent-Session: a0723c20-a7fd-4b2e-b50c-b621ca51f94b Agent-Session: 01a0d953-cb6c-7910-8027-6fa068237471 Agent-Session: 66ee4e22-2629-43a1-8bd2-84389011dec2 --- .github/workflows/review-windows-ci.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/review-windows-ci.yml b/.github/workflows/review-windows-ci.yml index 8db4ce3fd..74bd6a39a 100644 --- a/.github/workflows/review-windows-ci.yml +++ b/.github/workflows/review-windows-ci.yml @@ -1,13 +1,6 @@ name: Review Windows package CI on: - pull_request: - paths: - - ".github/workflows/review-windows-*.yml" - - ".github/workflows/review-desktop-release.yml" - - ".github/workflows/review-desktop-preview.yml" - - "apps/review-desktop/**" - - "packages/review/**" workflow_dispatch: inputs: sign: @@ -19,13 +12,11 @@ permissions: contents: read concurrency: - group: review-windows-ci-${{ github.event.pull_request.number || github.ref }} + group: review-windows-ci-${{ github.ref }} cancel-in-progress: true jobs: packages: - # Fork pull requests would otherwise run on the paid 16-core runner. - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository strategy: fail-fast: false matrix: @@ -39,7 +30,7 @@ jobs: id-token: write uses: ./.github/workflows/review-windows-build.yml with: - commit: ${{ github.event.pull_request.head.sha || github.sha }} + commit: ${{ github.sha }} version: ${{ matrix.version }} artifact_name: windows-packages-${{ matrix.channel }} sign: ${{ inputs.sign == true }} From 795fcb355a5141c37c17a2bcec14af70e7a95fdd Mon Sep 17 00:00:00 2001 From: thesiti92 Date: Fri, 25 Sep 2026 18:34:09 -0400 Subject: [PATCH 2/2] Delete the OS-specific package CI workflows Agent-Session: a0723c20-a7fd-4b2e-b50c-b621ca51f94b Agent-Session: 01a0d953-cb6c-7910-8027-6fa068237471 Agent-Session: 66ee4e22-2629-43a1-8bd2-84389011dec2 --- .github/workflows/review-linux-ci.yml | 73 ------- .github/workflows/review-windows-build.yml | 7 - .github/workflows/review-windows-ci.yml | 62 ------ .../scripts/build-windows-upgrade-fixture.mjs | 57 ----- apps/review-desktop/scripts/linux/UBUNTU.md | 4 +- .../scripts/verify-installed-windows.mjs | 194 ------------------ 6 files changed, 1 insertion(+), 396 deletions(-) delete mode 100644 .github/workflows/review-linux-ci.yml delete mode 100644 .github/workflows/review-windows-ci.yml delete mode 100644 apps/review-desktop/scripts/build-windows-upgrade-fixture.mjs delete mode 100644 apps/review-desktop/scripts/verify-installed-windows.mjs diff --git a/.github/workflows/review-linux-ci.yml b/.github/workflows/review-linux-ci.yml deleted file mode 100644 index e87fbec3d..000000000 --- a/.github/workflows/review-linux-ci.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Review Linux package CI - -on: - pull_request: - paths: - - '.github/workflows/review-linux-*.yml' - - '.github/workflows/review-desktop-release.yml' - - '.github/workflows/review-desktop-preview.yml' - - 'apps/review-desktop/code-oss/build/linux/**' - - 'apps/review-desktop/code-oss/build/gulpfile.vscode.linux.ts' - - 'apps/review-desktop/scripts/*linux*' - - 'apps/review-desktop/scripts/linux/**' - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: review-linux-ci-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - packages: - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository - strategy: - fail-fast: false - matrix: - include: - - channel: stable - version: '0.0.1' - - channel: preview - version: '0.0.2-preview.20000101.1' - uses: ./.github/workflows/review-linux-build.yml - with: - commit: ${{ github.event.pull_request.head.sha || github.sha }} - version: ${{ matrix.version }} - artifact_name: linux-packages-${{ matrix.channel }} - release_signing: false - runner: ubuntu-24.04 - - ubuntu-desktop: - name: Ubuntu desktop, AppArmor and channel coexistence - needs: packages - # Keep the native AppArmor check independent of container validation, but - # skip it when no packages were built (fork pull requests skip that job). - if: ${{ !cancelled() && needs.packages.result != 'skipped' }} - runs-on: ubuntu-24.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 - with: - pattern: linux-packages-* - merge-multiple: true - path: linux-packages - - name: Install on Ubuntu with namespace restrictions enabled - run: | - sudo apt-get update - sudo apt-get install -y xvfb dbus-x11 apparmor ./linux-packages/*.deb - sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=1 - sudo aa-status - - name: Launch the installed desktop with its sandbox - env: - DO_NOT_TRACK: '1' - run: | - dpkg-query -W dev-fast-review dev-fast-review-preview - for APP in review review-preview; do - export APP APPARMOR_PROFILE="dev-fast-$APP" - "$APP" --help >/dev/null - dbus-run-session -- xvfb-run -a bash apps/review-desktop/scripts/linux/smoke-installed-linux.sh - done diff --git a/.github/workflows/review-windows-build.yml b/.github/workflows/review-windows-build.yml index fed7546ef..c174fea9f 100644 --- a/.github/workflows/review-windows-build.yml +++ b/.github/workflows/review-windows-build.yml @@ -15,10 +15,6 @@ on: sign: type: boolean default: false - upgrade_fixture: - description: Also build a newer-versioned installer for the upgrade test. - type: boolean - default: false permissions: contents: read @@ -148,9 +144,6 @@ jobs: } - name: Verify the packaged desktop and CLI run: node apps/review-desktop/scripts/smoke-windows.mjs apps/review-desktop/VSCode-win32-x64 artifacts/windows - - name: Build upgrade test installer - if: inputs.upgrade_fixture - run: node apps/review-desktop/scripts/build-windows-upgrade-fixture.mjs - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ inputs.artifact_name }} diff --git a/.github/workflows/review-windows-ci.yml b/.github/workflows/review-windows-ci.yml deleted file mode 100644 index 74bd6a39a..000000000 --- a/.github/workflows/review-windows-ci.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Review Windows package CI - -on: - workflow_dispatch: - inputs: - sign: - description: "Sign with Azure Artifact Signing (uses the shared monthly signature quota)" - type: boolean - default: false - -permissions: - contents: read - -concurrency: - group: review-windows-ci-${{ github.ref }} - cancel-in-progress: true - -jobs: - packages: - strategy: - fail-fast: false - matrix: - include: - - channel: stable - version: "0.1.2" - - channel: preview - version: "0.1.3-preview.1" - permissions: - contents: read - id-token: write - uses: ./.github/workflows/review-windows-build.yml - with: - commit: ${{ github.sha }} - version: ${{ matrix.version }} - artifact_name: windows-packages-${{ matrix.channel }} - sign: ${{ inputs.sign == true }} - upgrade_fixture: true - - installed: - name: Installation, coexistence and removal - needs: packages - runs-on: review_big_boy_windows - timeout-minutes: 30 - steps: - - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 - - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 - with: - node-version-file: apps/review-desktop/code-oss/.nvmrc - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 - with: - pattern: windows-packages-* - path: artifacts/installers - - name: Test installation, coexistence and removal - # A step timeout fails the step and keeps its log; the job timeout would discard it. - timeout-minutes: 20 - run: node apps/review-desktop/scripts/verify-installed-windows.mjs artifacts/installers - - name: Upload installed desktop evidence - if: always() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - with: - name: windows-installed-evidence - path: artifacts/windows-installed/* diff --git a/apps/review-desktop/scripts/build-windows-upgrade-fixture.mjs b/apps/review-desktop/scripts/build-windows-upgrade-fixture.mjs deleted file mode 100644 index 5d640ccd9..000000000 --- a/apps/review-desktop/scripts/build-windows-upgrade-fixture.mjs +++ /dev/null @@ -1,57 +0,0 @@ -// A second installer version built from the same payload exercises Inno's -// upgrade behavior without downloading or trusting an unrelated old release. -import { execFileSync } from "node:child_process"; -import { copyFile, readFile, writeFile } from "node:fs/promises"; -import path from "node:path"; - -const app = path.resolve(import.meta.dirname, ".."); - -const checkout = path.join(app, "code-oss"); - -const files = [ - path.join(checkout, "product.json"), - path.join(app, "VSCode-win32-x64/resources/app/product.json"), -]; - -const originals = await Promise.all( - files.map((file) => readFile(file, "utf8")), -); - -try { - for (let index = 0; index < files.length; index++) { - const product = JSON.parse(originals[index]); - product.reviewVersion = - product.quality === "preview" ? "0.1.4-preview.1" : "0.1.3"; - await writeFile(files[index], JSON.stringify(product)); - } - - execFileSync( - process.execPath, - [ - path.join(checkout, "node_modules/gulp/bin/gulp.js"), - "vscode-win32-x64-user-setup", - ], - { - cwd: checkout, - stdio: "inherit", - // Inno Setup needs the commit that package-windows.sh stamped; the - // vendored checkout has no .git of its own for Code OSS to read. - env: { - ...process.env, - BUILD_SOURCEVERSION: - process.env.BUILD_SOURCEVERSION || - execFileSync("git", ["rev-parse", "HEAD"], { - cwd: app, - encoding: "utf8", - }).trim(), - }, - }, - ); - await copyFile( - path.join(checkout, ".build/win32-x64/user-setup/VSCodeSetup.exe"), - path.join(app, "dist/windows/Whiteboard-win32-x64-upgrade-fixture.exe"), - ); -} finally { - for (let index = 0; index < files.length; index++) - await writeFile(files[index], originals[index]); -} diff --git a/apps/review-desktop/scripts/linux/UBUNTU.md b/apps/review-desktop/scripts/linux/UBUNTU.md index 8176f9742..d6856e8c4 100644 --- a/apps/review-desktop/scripts/linux/UBUNTU.md +++ b/apps/review-desktop/scripts/linux/UBUNTU.md @@ -29,9 +29,7 @@ publication. `linux/verify-repository.sh ubuntu` checks: The tests use a pinned Ubuntu container. Docker's outer seccomp filter is relaxed for Chromium namespace creation; Chromium's sandbox remains enabled. Containers share the host kernel, so this does not replace a GNOME/Wayland test -on an Ubuntu host with AppArmor enforcement. `review-linux-ci.yml` runs the -packaging checks for packaging PRs and supports manual builds. It checks both channels, then starts each installed -app on an Ubuntu 24.04 runner with AppArmor namespace restrictions enabled. +on an Ubuntu host with AppArmor enforcement. ## Publication contract diff --git a/apps/review-desktop/scripts/verify-installed-windows.mjs b/apps/review-desktop/scripts/verify-installed-windows.mjs deleted file mode 100644 index 20bc7c914..000000000 --- a/apps/review-desktop/scripts/verify-installed-windows.mjs +++ /dev/null @@ -1,194 +0,0 @@ -import assert from "node:assert/strict"; -import { execFileSync } from "node:child_process"; -import { access, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; -import os from "node:os"; -import path from "node:path"; - -import { smokeWindows } from "./smoke-windows.mjs"; - -assert.equal(process.platform, "win32"); - -const artifacts = path.resolve(process.argv[2]); - -const evidence = path.resolve(process.argv[3] ?? "artifacts/windows-installed"); - -// Bundled extensions nest up to ~185 characters deep, so a runner temp -// directory would push installed files past MAX_PATH. Keep the root short but -// spaced, like a real install location. -const root = await mkdtemp( - path.join(path.parse(os.tmpdir()).root, "Whiteboard test "), -); - -const installed = []; - -const step = (message) => console.log(`[${new Date().toISOString()}] ${message}`); - -const run = (exe, args) => { - step(`${path.basename(exe)} ${args.join(" ")}`); - execFileSync(exe, args, { timeout: 180000, stdio: "inherit" }); -}; - -const installer = (channel, kind) => - path.join( - artifacts, - `windows-packages-${channel}`, - `Whiteboard-win32-x64-${kind}.exe`, - ); - -const install = (exe, destination) => - run(exe, [ - "/VERYSILENT", - "/SUPPRESSMSGBOXES", - "/NORESTART", - "/TASKS=addtopath", - `/DIR=${destination}`, - ]); - -const uninstall = (destination) => - run(path.join(destination, "unins000.exe"), [ - "/VERYSILENT", - "/SUPPRESSMSGBOXES", - "/NORESTART", - ]); - -try { - for (const channel of ["stable", "preview"]) { - const destination = path.join(root, `${channel} user install`); - install(installer(channel, "user"), destination); - installed.push(destination); - - const product = JSON.parse( - await readFile( - path.join(destination, "resources/app/product.json"), - "utf8", - ), - ); - - assert.equal(product.quality, channel); - assert.equal(product.target, "user"); - const uninstallKey = `HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${product.win32x64UserAppId.slice(1)}_is1`; - - const registry = execFileSync( - "reg.exe", - ["query", uninstallKey, "/v", "DisplayVersion"], - { encoding: "utf8" }, - ); - - assert.ok(registry.includes(product.reviewVersion)); - - const protocol = execFileSync( - "reg.exe", - [ - "query", - `HKCU\\Software\\Classes\\${product.urlProtocol}\\shell\\open\\command`, - "/ve", - ], - { encoding: "utf8" }, - ); - - assert.ok( - protocol.includes(path.join(destination, `${product.nameShort}.exe`)), - ); - assert.ok(protocol.includes('--open-url -- "%1"')); - // Shortcut names become file names, so a "/" in the display name would - // nest the shortcut inside folders instead of creating it. - await access( - path.join( - process.env.APPDATA, - "Microsoft/Windows/Start Menu/Programs", - product.nameShort, - `${product.nameShort}.lnk`, - ), - ); - // "Add to PATH" puts the Whiteboard CLI on PATH, not the Code OSS editor launcher. - const bin = path.join(destination, "bin"); - await assert.rejects( - access(path.join(bin, `${product.applicationName}.cmd`)), - ); - assert.match( - execFileSync("cmd.exe", ["/d", "/c", path.join(bin, "whiteboard.cmd"), "version"], { - encoding: "utf8", - timeout: 30000, - }), - /\d+\.\d+\.\d+/, - ); - assert.ok( - execFileSync("reg.exe", ["query", "HKCU\\Environment", "/v", "Path"], { - encoding: "utf8", - }) - .toLowerCase() - .includes(bin.toLowerCase()), - ); - step(`smoke ${destination}`); - await smokeWindows(destination, evidence); - - // A reinstall must replace the embedded dependency closure, including files - // removed by a newer release, while leaving user data outside the app intact. - const stale = path.join( - destination, - "resources/app/review-runtime/removed-in-next-version.txt", - ); - - await writeFile(stale, "obsolete runtime file"); - const saved = path.join(root, `${channel}-saved-review.json`); - await writeFile(saved, '{"review":"preserve"}'); - install(installer(channel, "upgrade-fixture"), destination); - await assert.rejects(access(stale)); - - const updated = JSON.parse( - await readFile( - path.join(destination, "resources/app/product.json"), - "utf8", - ), - ); - - assert.notEqual(updated.reviewVersion, product.reviewVersion); - - const updatedRegistry = execFileSync( - "reg.exe", - ["query", uninstallKey, "/v", "DisplayVersion"], - { encoding: "utf8" }, - ); - - assert.ok(updatedRegistry.includes(updated.reviewVersion)); - step(`smoke ${destination}`); - await smokeWindows(destination, evidence); - - assert.equal(await readFile(saved, "utf8"), '{"review":"preserve"}'); - } - - // Both identities are installed together. Removing preview cannot unregister - // stable's protocol or break its runtime. - uninstall(installed.pop()); - step(`smoke ${installed[0]}`); - await smokeWindows(installed[0], evidence); - uninstall(installed.pop()); - const system = path.join(root, "system install"); - install(installer("stable", "system"), system); - installed.push(system); - - const product = JSON.parse( - await readFile(path.join(system, "resources/app/product.json"), "utf8"), - ); - - assert.equal(product.target, "system"); - step(`smoke ${system}`); - await smokeWindows(system, evidence); - uninstall(installed.pop()); - console.log( - "User/system installs, replacement, channel coexistence and uninstall passed.", - ); -} finally { - for (const destination of installed.reverse()) { - try { - uninstall(destination); - } catch {} - } - - await rm(root, { - recursive: true, - force: true, - maxRetries: 20, - retryDelay: 250, - }); -}