diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index df49400..ad37f62 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,11 +8,11 @@ jobs: preflight: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm @@ -32,36 +32,74 @@ jobs: - name: Run unit tests run: pnpm exec vp test + - name: Upload frontend build + uses: actions/upload-artifact@v7 + with: + name: frontend-build + path: | + dist + dist-electron + archive: false + retention-days: 1 + build-linux: needs: preflight runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm + - name: Cache node_modules + id: cache-nm + uses: actions/cache@v5 + with: + path: node_modules + key: ${{ runner.os }}-nm-${{ hashFiles('pnpm-lock.yaml') }} + - name: Install dependencies + if: steps.cache-nm.outputs.cache-hit != 'true' run: pnpm install --frozen-lockfile - - name: Build frontend - run: pnpm exec vp build + - name: Cache Electron binaries + uses: actions/cache@v5 + with: + path: | + ~/.cache/electron + ~/.cache/electron-builder + key: electron-cache-${{ runner.os }}-x64-${{ hashFiles('package.json') }} + + - name: Restore frontend build + uses: actions/download-artifact@v8 + with: + name: frontend-build + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Build Docker image - run: docker build -t opengui:web . + uses: docker/build-push-action@v6 + with: + context: . + load: true + tags: opengui:web + cache-from: type=gha + cache-to: type=gha,mode=max - name: Package .deb run: pnpm exec electron-builder --linux deb --publish never - name: Upload .deb artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: linux-deb path: release/*.deb + archive: false retention-days: 30 build-mac: @@ -72,63 +110,95 @@ jobs: fail-fast: false runs-on: macos-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm + - name: Cache node_modules + id: cache-nm + uses: actions/cache@v5 + with: + path: node_modules + key: ${{ runner.os }}-${{ matrix.arch }}-nm-${{ hashFiles('pnpm-lock.yaml') }} + + - name: Install dependencies + if: steps.cache-nm.outputs.cache-hit != 'true' + run: pnpm install --frozen-lockfile + - name: Cache Electron binaries - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | ~/.cache/electron ~/.cache/electron-builder - key: electron-cache-mac-${{ matrix.arch }}-${{ hashFiles('package.json') }} + key: electron-cache-${{ runner.os }}-${{ matrix.arch }}-${{ hashFiles('package.json') }} - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build frontend - run: pnpm exec vp build + - name: Restore frontend build + uses: actions/download-artifact@v8 + with: + name: frontend-build - name: Package mac ${{ matrix.arch }} run: pnpm exec electron-builder --mac dmg zip --${{ matrix.arch }} --publish never env: CSC_IDENTITY_AUTO_DISCOVERY: "false" + - name: Normalize update manifest filename + run: | + if ls release/latest-mac-*.yml >/dev/null 2>&1; then + cp release/latest-mac-*.yml release/latest-mac.yml + fi + ls -la release/latest-mac*.yml + - name: Upload mac ${{ matrix.arch }} artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: mac-release-${{ matrix.arch }} - path: | - release/*.dmg - release/*.zip - release/*.blockmap - release/latest-mac.yml + path: release/* + archive: false retention-days: 30 build-windows: needs: preflight runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm + - name: Cache node_modules + id: cache-nm + uses: actions/cache@v5 + with: + path: node_modules + key: ${{ runner.os }}-nm-${{ hashFiles('pnpm-lock.yaml') }} + - name: Install dependencies + if: steps.cache-nm.outputs.cache-hit != 'true' run: pnpm install --frozen-lockfile - - name: Build frontend - run: pnpm exec vp build + - name: Cache Electron binaries + uses: actions/cache@v5 + with: + path: | + ~/.cache/electron + ~/.cache/electron-builder + key: electron-cache-${{ runner.os }}-x64-${{ hashFiles('package.json') }} + + - name: Restore frontend build + uses: actions/download-artifact@v8 + with: + name: frontend-build - name: Package .exe (NSIS) run: pnpm exec electron-builder --win nsis --publish never @@ -164,13 +234,14 @@ jobs: } - name: Upload Windows updater artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: windows-nsis path: | release/*.exe release/*.blockmap release/latest.yml + archive: false retention-days: 30 publish-docker: @@ -181,7 +252,7 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -230,11 +301,11 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm @@ -243,29 +314,40 @@ jobs: run: pnpm install --frozen-lockfile - name: Download linux artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: linux-deb path: artifacts/linux-deb - name: Download mac x64 artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: mac-release-x64 path: artifacts/mac-release - name: Download mac arm64 artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: mac-release-arm64 path: artifacts/mac-release-arm64 - name: Download windows artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: windows-nsis path: artifacts/windows-nsis + - name: List downloaded artifacts + run: | + echo "=== linux-deb ===" + ls -la artifacts/linux-deb/ 2>/dev/null || echo "(empty)" + echo "=== mac-release ===" + ls -la artifacts/mac-release/ 2>/dev/null || echo "(empty)" + echo "=== mac-release-arm64 ===" + ls -la artifacts/mac-release-arm64/ 2>/dev/null || echo "(empty)" + echo "=== windows-nsis ===" + ls -la artifacts/windows-nsis/ 2>/dev/null || echo "(empty)" + - name: Merge mac update manifests run: | node scripts/merge-latest-mac.mjs \ diff --git a/scripts/merge-latest-mac.mjs b/scripts/merge-latest-mac.mjs index 198790f..ee93639 100644 --- a/scripts/merge-latest-mac.mjs +++ b/scripts/merge-latest-mac.mjs @@ -1,4 +1,4 @@ -import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs"; +import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "node:fs"; import { join, resolve } from "node:path"; import { createRequire } from "node:module"; @@ -23,22 +23,35 @@ function parseArgs() { } function readManifest(dir) { - const p = join(dir, "latest-mac.yml"); - if (!existsSync(p)) { - console.error(`Manifest not found: ${p}`); - process.exit(1); + const candidates = ["latest-mac.yml", "latest-mac-arm64.yml", "latest-mac-x64.yml"]; + for (const name of candidates) { + const p = join(dir, name); + if (existsSync(p)) { + console.log(` found manifest: ${p}`); + return yaml.load(readFileSync(p, "utf8")); + } + } + console.error(`Manifest not found in ${dir}`); + console.error(` dir exists: ${existsSync(dir)}`); + if (existsSync(dir)) { + console.error(` contents: ${readdirSync(dir).join(", ")}`); } - return yaml.load(readFileSync(p, "utf8")); + process.exit(1); } function merge() { const { x64Dir, arm64Dir, outDir } = parseArgs(); + console.log(`Reading x64 manifest from: ${x64Dir}`); const x64 = readManifest(x64Dir); + console.log(`Reading arm64 manifest from: ${arm64Dir}`); const arm64 = readManifest(arm64Dir); const releaseDate = new Date( - Math.max(new Date(x64.releaseDate ?? 0).getTime(), new Date(arm64.releaseDate ?? 0).getTime()), + Math.max( + new Date(x64.releaseDate ?? 0).getTime(), + new Date(arm64.releaseDate ?? 0).getTime(), + ), ).toISOString(); const merged = { @@ -59,4 +72,9 @@ function merge() { console.log(` total: ${merged.files.length}`); } -merge(); +try { + merge(); +} catch (err) { + console.error("Merge failed:", err.message); + process.exit(1); +}