mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-12 21:02:17 +02:00
* fixed workflow * fix(forge): hoist staged ACP node_modules to stay under Windows MAX_PATH The Squirrel/nuget Windows maker failed with 'path too long': stageAcpAdapters rebuilt the ACP dependency closure by always nesting each dep under its parent, producing 5-level chains (codex-acp -> open -> wsl-utils -> is-wsl -> is-inside-container -> is-docker) whose paths hit ~260 chars on the CI runner and blew past Windows' MAX_PATH (nuget.exe ignores long-path settings). Hoist every package to the top-level node_modules npm-style, nesting only on a genuine version conflict. Deepest staged path drops 177 -> 114 chars (worst-case CI absolute ~197, well under 260). Add verifyAcpStaging() which asserts every dependency edge resolves, in the staged tree, to the same version as the source pnpm tree, failing the build loudly instead of shipping a broken installer.
260 lines
8.9 KiB
YAML
260 lines
8.9 KiB
YAML
name: Build Electron App
|
|
|
|
on:
|
|
release:
|
|
types: [published]
|
|
|
|
permissions:
|
|
contents: write # Required to upload release assets
|
|
|
|
jobs:
|
|
build-macos:
|
|
runs-on: macos-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v6
|
|
with:
|
|
version: 10
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: 24.15.0
|
|
cache: 'pnpm'
|
|
cache-dependency-path: 'apps/x/pnpm-lock.yaml'
|
|
|
|
- name: Extract version from tag
|
|
id: version
|
|
run: |
|
|
VERSION="${GITHUB_REF#refs/tags/v}"
|
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
echo "Extracted version: ${VERSION}"
|
|
|
|
- name: Update package.json versions
|
|
run: |
|
|
node -e "
|
|
const fs = require('fs');
|
|
const version = '${{ steps.version.outputs.version }}';
|
|
|
|
// Update apps/x/package.json
|
|
const rootPackage = JSON.parse(fs.readFileSync('apps/x/package.json', 'utf8'));
|
|
rootPackage.version = version;
|
|
fs.writeFileSync('apps/x/package.json', JSON.stringify(rootPackage, null, 2) + '\n');
|
|
|
|
// Update apps/x/apps/main/package.json
|
|
const mainPackage = JSON.parse(fs.readFileSync('apps/x/apps/main/package.json', 'utf8'));
|
|
mainPackage.version = version;
|
|
fs.writeFileSync('apps/x/apps/main/package.json', JSON.stringify(mainPackage, null, 2) + '\n');
|
|
|
|
console.log('Updated version to:', version);
|
|
"
|
|
|
|
- name: Import Code Signing Certificate
|
|
env:
|
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
run: |
|
|
# Create a temporary keychain
|
|
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
|
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
|
|
|
|
# Create keychain
|
|
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
|
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
|
|
# Decode and import certificate
|
|
echo "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12
|
|
security import $RUNNER_TEMP/certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
|
|
|
|
# Allow codesign to access the keychain
|
|
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
|
|
# Add keychain to search list
|
|
security list-keychains -d user -s "$KEYCHAIN_PATH" login.keychain
|
|
|
|
# Verify certificate was imported
|
|
security find-identity -v "$KEYCHAIN_PATH"
|
|
|
|
# Clean up certificate file
|
|
rm -f $RUNNER_TEMP/certificate.p12
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
working-directory: apps/x
|
|
|
|
- name: Build electron app
|
|
env:
|
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
VITE_PUBLIC_POSTHOG_KEY: ${{ secrets.VITE_PUBLIC_POSTHOG_KEY }}
|
|
VITE_PUBLIC_POSTHOG_HOST: ${{ secrets.VITE_PUBLIC_POSTHOG_HOST }}
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: npx electron-forge publish --arch=arm64,x64 --platform=darwin
|
|
working-directory: apps/x/apps/main
|
|
|
|
- name: Cleanup keychain
|
|
if: always()
|
|
run: |
|
|
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
|
if [ -f "$KEYCHAIN_PATH" ]; then
|
|
security delete-keychain "$KEYCHAIN_PATH" || true
|
|
fi
|
|
|
|
- name: Upload workflow artifacts
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: distributables
|
|
path: apps/x/apps/main/out/make/*
|
|
if-no-files-found: error
|
|
retention-days: 30
|
|
|
|
build-linux:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v6
|
|
with:
|
|
version: 10
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: 24.15.0
|
|
cache: 'pnpm'
|
|
cache-dependency-path: 'apps/x/pnpm-lock.yaml'
|
|
|
|
- name: Extract version from tag
|
|
id: version
|
|
run: |
|
|
VERSION="${GITHUB_REF#refs/tags/v}"
|
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
echo "Extracted version: ${VERSION}"
|
|
|
|
- name: Update package.json versions
|
|
run: |
|
|
node -e "
|
|
const fs = require('fs');
|
|
const version = '${{ steps.version.outputs.version }}';
|
|
|
|
// Update apps/x/package.json
|
|
const rootPackage = JSON.parse(fs.readFileSync('apps/x/package.json', 'utf8'));
|
|
rootPackage.version = version;
|
|
fs.writeFileSync('apps/x/package.json', JSON.stringify(rootPackage, null, 2) + '\n');
|
|
|
|
// Update apps/x/apps/main/package.json
|
|
const mainPackage = JSON.parse(fs.readFileSync('apps/x/apps/main/package.json', 'utf8'));
|
|
mainPackage.version = version;
|
|
fs.writeFileSync('apps/x/apps/main/package.json', JSON.stringify(mainPackage, null, 2) + '\n');
|
|
|
|
console.log('Updated version to:', version);
|
|
"
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
working-directory: apps/x
|
|
|
|
- name: Build node-pty native binary for Linux
|
|
working-directory: apps/x
|
|
run: |
|
|
# node-pty ships prebuilt binaries only for darwin/win32; compile the
|
|
# linux-x64 binary so bundle.mjs can stage it into the package. Without
|
|
# this the Linux app crashes on launch (missing prebuilds/linux-x64/pty.node).
|
|
PTY="node_modules/.pnpm/node-pty@1.1.0/node_modules/node-pty"
|
|
cd "$PTY"
|
|
npx node-gyp rebuild
|
|
mkdir -p prebuilds/linux-x64
|
|
cp build/Release/pty.node prebuilds/linux-x64/
|
|
|
|
- name: Build electron app
|
|
env:
|
|
VITE_PUBLIC_POSTHOG_KEY: ${{ secrets.VITE_PUBLIC_POSTHOG_KEY }}
|
|
VITE_PUBLIC_POSTHOG_HOST: ${{ secrets.VITE_PUBLIC_POSTHOG_HOST }}
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
ROWBOAT_SKIP_PACMAN: '1' # Arch Linux package is built locally only, never in CI
|
|
run: npx electron-forge publish --arch=x64 --platform=linux
|
|
working-directory: apps/x/apps/main
|
|
|
|
- name: Upload workflow artifacts
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: distributables-linux
|
|
path: apps/x/apps/main/out/make/*
|
|
if-no-files-found: error
|
|
retention-days: 30
|
|
|
|
build-windows:
|
|
runs-on: windows-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v6
|
|
with:
|
|
version: 10
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: 24.15.0
|
|
cache: 'pnpm'
|
|
cache-dependency-path: 'apps/x/pnpm-lock.yaml'
|
|
|
|
- name: Extract version from tag
|
|
id: version
|
|
shell: bash
|
|
run: |
|
|
VERSION="${GITHUB_REF#refs/tags/v}"
|
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
echo "Extracted version: ${VERSION}"
|
|
|
|
- name: Update package.json versions
|
|
shell: bash
|
|
run: |
|
|
node -e "
|
|
const fs = require('fs');
|
|
const version = '${{ steps.version.outputs.version }}';
|
|
|
|
// Update apps/x/package.json
|
|
const rootPackage = JSON.parse(fs.readFileSync('apps/x/package.json', 'utf8'));
|
|
rootPackage.version = version;
|
|
fs.writeFileSync('apps/x/package.json', JSON.stringify(rootPackage, null, 2) + '\n');
|
|
|
|
// Update apps/x/apps/main/package.json
|
|
const mainPackage = JSON.parse(fs.readFileSync('apps/x/apps/main/package.json', 'utf8'));
|
|
mainPackage.version = version;
|
|
fs.writeFileSync('apps/x/apps/main/package.json', JSON.stringify(mainPackage, null, 2) + '\n');
|
|
|
|
console.log('Updated version to:', version);
|
|
"
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
working-directory: apps/x
|
|
|
|
- name: Build electron app
|
|
env:
|
|
VITE_PUBLIC_POSTHOG_KEY: ${{ secrets.VITE_PUBLIC_POSTHOG_KEY }}
|
|
VITE_PUBLIC_POSTHOG_HOST: ${{ secrets.VITE_PUBLIC_POSTHOG_HOST }}
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: npx electron-forge publish --arch=x64 --platform=win32
|
|
working-directory: apps/x/apps/main
|
|
|
|
- name: Upload workflow artifacts
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: distributables-windows
|
|
path: apps/x/apps/main/out/make/*
|
|
if-no-files-found: error
|
|
retention-days: 30
|