enh: macos code sign

This commit is contained in:
Timothy Jaeryang Baek 2025-01-16 17:41:16 -08:00
parent a4307e9fa7
commit 19d7cc76b1
4 changed files with 203 additions and 118 deletions

View File

@ -1,116 +0,0 @@
name: Build and Release Electron Forge App
on:
push:
branches:
- main
pull_request:
jobs:
build:
name: Build and Package
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
# - os: ubuntu-latest
# arch: x64
# - os: ubuntu-latest
# arch: arm64
- 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@v3
with:
node-version: 22
cache: 'npm'
architecture: ${{ matrix.arch }}
- name: Install Dependencies
run: npm ci
- name: Setup Miniconda
uses: conda-incubator/setup-miniconda@v3
with:
auto-activate-base: true
- name: Install conda-lock and conda-pack
shell: bash -l {0}
run: |
conda install -n base -c conda-forge conda-lock conda-pack
- name: Create Packaged Python
shell: bash -l {0}
run: |
conda activate base
npm run create:python-tar
- name: Create Builds
run: npm run make
- name: Find and Rename Windows Executable
if: ${{ matrix.os == 'windows-latest' }}
shell: pwsh
run: |
# Dynamically locate the `setup.exe` file within the `out/make` directory structure
$exePath = Get-ChildItem -Path out/make -Recurse -Filter "*.exe" | Select-Object -First 1
if (-not $exePath) {
throw "Error: No .exe file was found in the output directory."
}
Write-Host "The found executable is: $exePath"
# Rename/move the file to a more descriptive name with architecture/OS information
$destinationPath = "${{ matrix.os }}-${{ matrix.arch }}.exe"
Copy-Item -Path $exePath.FullName -Destination $destinationPath
Write-Host "Copied executable to: $destinationPath"
- name: Azure Trusted Signing (Windows Only)
if: ${{ matrix.os == 'windows-latest' }}
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
# Sign the generated .exe file
files-folder: .
files-folder-filter: exe
- name: Zip Artifacts for macOS/Linux
if: ${{ matrix.os != 'windows-latest' }}
run: |
7z a -tzip ${{ matrix.os }}-${{ matrix.arch }}.zip ./out/make/*
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.os }}-${{ matrix.arch }}
path: |
${{ matrix.os }}-${{ matrix.arch }}.exe
${{ matrix.os }}-${{ matrix.arch }}.zip
release:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Get Short SHA
id: slug
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT
- name: Download Artifacts
uses: actions/download-artifact@v3
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: build-${{ steps.slug.outputs.sha8 }}
name: Build ${{ steps.slug.outputs.sha8 }}
draft: false
prerelease: false
files: |
**/*.zip
**/*.exe

144
.github/workflows/build.yaml vendored Normal file
View File

@ -0,0 +1,144 @@
name: Build and Release Electron Forge App
on:
push:
branches:
- main
pull_request:
jobs:
build:
name: Build and Package
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
# - os: ubuntu-latest
# arch: x64
# - os: ubuntu-latest
# arch: arm64
# - 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@v3
with:
node-version: 22
cache: 'npm'
architecture: ${{ matrix.arch }}
- name: Install Dependencies
run: npm ci
- name: Setup Miniconda
uses: conda-incubator/setup-miniconda@v3
with:
auto-activate-base: true
- name: Install conda-lock and conda-pack
shell: bash -l {0}
run: |
conda install -n base -c conda-forge conda-lock conda-pack
- name: Create Packaged Python
shell: bash -l {0}
run: |
conda activate base
npm run create:python-tar
- name: Install Apple codesigning certificate
if: ${{ matrix.os == 'macos-latest' }}
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
# create temporary 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
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- name: Create Builds
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.CSC_LINK }}
run: npm run make
- name: Find and Rename Windows Executable
if: ${{ matrix.os == 'windows-latest' }}
shell: pwsh
run: |
# Dynamically locate the `setup.exe` file within the `out/make` directory structure
$exePath = Get-ChildItem -Path out/make -Recurse -Filter "*.exe" | Select-Object -First 1
if (-not $exePath) {
throw "Error: No .exe file was found in the output directory."
}
Write-Host "The found executable is: $exePath"
# Rename/move the file to a more descriptive name with architecture/OS information
$destinationPath = "${{ matrix.os }}-${{ matrix.arch }}.exe"
Copy-Item -Path $exePath.FullName -Destination $destinationPath
Write-Host "Copied executable to: $destinationPath"
- name: Azure Trusted Signing (Windows Only)
if: ${{ matrix.os == 'windows-latest' }}
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
# Sign the generated .exe file
files-folder: .
files-folder-filter: exe
- name: Zip Artifacts for macOS/Linux
if: ${{ matrix.os != 'windows-latest' }}
run: |
7z a -tzip ${{ matrix.os }}-${{ matrix.arch }}.zip ./out/make/*
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.os }}-${{ matrix.arch }}
path: |
${{ matrix.os }}-${{ matrix.arch }}.exe
${{ matrix.os }}-${{ matrix.arch }}.zip
release:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Get Short SHA
id: slug
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT
- name: Download Artifacts
uses: actions/download-artifact@v3
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: build-${{ steps.slug.outputs.sha8 }}
name: Build ${{ steps.slug.outputs.sha8 }}
draft: false
prerelease: false
files: |
**/*.zip
**/*.exe

40
entitlements.plist Normal file
View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.bluetooth</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.print</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.personal-information.location</key>
<true/>
</dict>
</plist>

View File

@ -12,10 +12,27 @@ const config: ForgeConfig = {
executableName: 'open-webui',
asar: true,
icon: 'public/assets/icon.png',
extraResource: ['public/assets', 'resources']
extraResource: ['public/assets', 'resources'],
osxSign: {
optionsForFile: (filePath) => {
return {
entitlements: 'entitlements.plist'
};
}
},
osxNotarize: {
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_PASSWORD,
teamId: process.env.APPLE_TEAM_ID
}
},
rebuildConfig: {},
makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})],
makers: [
new MakerSquirrel({}),
new MakerZIP({}, ['darwin']),
new MakerRpm({}),
new MakerDeb({})
],
plugins: [
new VitePlugin({
// `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc.