Files
desktop/.github/workflows/release.yml
T
Timothy Jaeryang Baek 8585558492 refac
2026-04-06 12:31:17 -05:00

293 lines
12 KiB
YAML

name: Build and Release Electron App (electron-builder)
on:
push:
branches:
- release
jobs:
compile:
name: Compile (Typecheck + Vite Build)
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Typecheck and Build
run: npm run build
- name: Upload Compiled Output
uses: actions/upload-artifact@v4
with:
name: compiled-output
path: out/
retention-days: 1
package:
name: Package (${{ matrix.os }}-${{ matrix.arch }})
needs: compile
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
arch: x64
- os: windows-latest
arch: x64
- os: macos-latest
arch: x64
- os: macos-latest
arch: arm64
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Download Compiled Output
uses: actions/download-artifact@v4
with:
name: compiled-output
path: out/
# ── Flatpak setup (Linux only) ──
- name: Cache Flatpak SDKs
if: matrix.os == 'ubuntu-latest'
uses: actions/cache@v4
with:
path: ~/.local/share/flatpak
key: flatpak-sdk-23.08-electron2-${{ runner.os }}
- name: Install Flatpak build tools
id: flatpak
if: matrix.os == 'ubuntu-latest'
continue-on-error: true
run: |
sudo apt-get update
sudo apt-get install -y flatpak flatpak-builder
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install --user -y flathub org.freedesktop.Platform//23.08 org.freedesktop.Sdk//23.08
flatpak install --user -y flathub org.electronjs.Electron2.BaseApp//23.08
# ── Apple codesigning (macOS only) ──
- name: Install Apple codesigning certificate
id: apple_cert
if: matrix.os == 'macos-latest'
continue-on-error: true
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
if [ -z "$BUILD_CERTIFICATE_BASE64" ]; then
echo "No certificate provided, will build unsigned"
exit 1
fi
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode > $CERTIFICATE_PATH
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
# ── Platform packaging ──
- name: Package for Windows
id: win_build
if: matrix.os == 'windows-latest'
continue-on-error: true
run: npx electron-builder --win --${{ matrix.arch }} --publish never
- name: Package for Windows (unsigned fallback)
if: matrix.os == 'windows-latest' && steps.win_build.outcome == 'failure'
env:
WIN_CSC_LINK: ''
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
run: |
rm -rf dist/
npx electron-builder --win --${{ matrix.arch }} --publish never
- name: Package for macOS (signed + notarized)
id: mac_build_signed
if: matrix.os == 'macos-latest' && steps.apple_cert.outcome == 'success'
continue-on-error: true
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ELECTRON_BUILDER_BINARIES_MIRROR: https://github.com/electron-userland/electron-builder-binaries/releases/download/
run: npx electron-builder --mac --${{ matrix.arch }} -c.mac.identity=auto -c.mac.notarize=true --publish never
- name: Package for macOS (unsigned fallback)
if: matrix.os == 'macos-latest' && (steps.apple_cert.outcome != 'success' || steps.mac_build_signed.outcome == 'failure')
env:
ELECTRON_BUILDER_BINARIES_MIRROR: https://github.com/electron-userland/electron-builder-binaries/releases/download/
run: |
rm -rf dist/
npx electron-builder --mac --${{ matrix.arch }} -c.mac.notarize=false --publish never
- name: Package for Linux
if: matrix.os == 'ubuntu-latest'
run: |
if [ "${{ steps.flatpak.outcome }}" == "success" ]; then
npx electron-builder --linux --${{ matrix.arch }} --publish never
else
echo "Flatpak not available, building without flatpak"
npx electron-builder --linux AppImage deb snap --${{ matrix.arch }} --publish never
fi
# ── Windows code signing ──
- name: Azure Trusted Signing (Windows Only)
if: matrix.os == 'windows-latest'
continue-on-error: true
uses: azure/trusted-signing-action@v0.5.1
with:
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
endpoint: https://eus.codesigning.azure.net/
trusted-signing-account-name: open-webui
certificate-profile-name: open-webui
files-folder: dist
files-folder-filter: exe
# ── Upload release artifacts ──
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-${{ matrix.arch }}
path: |
dist/*.exe
dist/*.dmg
dist/*.zip
dist/*.pkg
dist/*.deb
dist/*.rpm
dist/*.AppImage
dist/*.snap
dist/*.flatpak
dist/*.tar.gz
dist/*.blockmap
dist/latest*.yml
if-no-files-found: warn
release:
name: Create GitHub Release
needs: package
if: >-
github.event_name == 'push' &&
github.ref == 'refs/heads/release' &&
!cancelled() &&
needs.package.result != 'failure'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
sparse-checkout: |
package.json
CHANGELOG.md
sparse-checkout-cone-mode: false
- name: Get version from package.json
id: version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Release version: $VERSION"
- name: Extract changelog for this version
id: changelog
run: |
# Extract the section for the current version from CHANGELOG.md
VERSION="${{ steps.version.outputs.version }}"
# Get content between ## [VERSION] and the next ## [ heading
NOTES=$(awk "/^## \[$VERSION\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md)
if [ -z "$NOTES" ]; then
NOTES="Release v$VERSION"
fi
# Write to file to preserve multiline content
echo "$NOTES" > /tmp/release_notes.md
echo "Changelog notes:"
cat /tmp/release_notes.md
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
pattern: '*-*'
merge-multiple: false
- name: Merge macOS latest-mac.yml (x64 + arm64)
run: |
# Each macOS arch build produces its own latest-mac.yml with only
# that arch's entry. Merge them so electron-updater works for both.
X64_YML="macos-latest-x64/latest-mac.yml"
ARM_YML="macos-latest-arm64/latest-mac.yml"
if [ -f "$X64_YML" ] && [ -f "$ARM_YML" ]; then
echo "Merging latest-mac.yml from both architectures"
npm install --no-save js-yaml
node -e "
const fs = require('fs');
const yaml = require('js-yaml');
const x64 = yaml.load(fs.readFileSync('$X64_YML', 'utf8'));
const arm = yaml.load(fs.readFileSync('$ARM_YML', 'utf8'));
x64.files = [...(x64.files || []), ...(arm.files || [])];
const out = yaml.dump(x64, { lineWidth: -1 });
fs.writeFileSync('$X64_YML', out);
console.log(out);
"
# Remove duplicate so only one latest-mac.yml is uploaded
rm -f "$ARM_YML"
else
echo "Skipping merge — need both $X64_YML and $ARM_YML"
ls -la macos-latest-*/latest-mac.yml 2>/dev/null || true
fi
- name: Create Release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ steps.version.outputs.version }}
name: v${{ steps.version.outputs.version }}
body_path: /tmp/release_notes.md
draft: false
prerelease: false
files: |
windows-latest-*/*.exe
windows-latest-*/*.blockmap
windows-latest-*/latest*.yml
macos-latest-*/*.dmg
macos-latest-*/*.zip
macos-latest-*/*.pkg
macos-latest-*/*.blockmap
macos-latest-*/latest*.yml
ubuntu-latest-*/*.deb
ubuntu-latest-*/*.rpm
ubuntu-latest-*/*.AppImage
ubuntu-latest-*/*.snap
ubuntu-latest-*/*.flatpak
ubuntu-latest-*/*.tar.gz
ubuntu-latest-*/latest*.yml