Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 117 additions & 35 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 \
Expand Down
34 changes: 26 additions & 8 deletions scripts/merge-latest-mac.mjs
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -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 = {
Expand All @@ -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);
}
Loading