Files
2026-07-13 13:20:22 +08:00

688 lines
28 KiB
YAML

name: Build Pipeline (Reusable)
on:
workflow_call:
inputs:
matrix:
description: 'Build matrix as JSON string (passed via fromJSON in caller)'
type: string
required: true
ref:
description: 'Git ref to checkout (leave empty to use the triggering commit)'
type: string
default: ''
skip_code_quality:
description: 'Skip code quality checks (faster builds for debugging)'
type: boolean
default: false
append_commit_hash:
description: 'Append short commit hash to artifact names'
type: boolean
default: false
upload_installers_only:
description: 'Only upload primary installers (exe/msi/dmg/deb), skip zip/yml/blockmap'
type: boolean
default: false
aioncore_run_id:
description: 'Optional AionCore Manual Build workflow run id to bundle instead of the pinned release'
type: string
default: ''
env:
BUN_INSTALL_REGISTRY: 'https://registry.npmjs.org/'
AIONUI_HUB_TAG: 'dist-ebc6a2b'
jobs:
code-quality:
name: Code Quality
runs-on: ubuntu-latest
if: ${{ !inputs.skip_code_quality }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Setup bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Run postinstall
run: bun run postinstall || true
- name: Run ESLint
run: bun run lint
- name: Check Prettier formatting
run: bun run format:check
- name: TypeScript type check
run: bunx tsc --noEmit
- name: Run unit tests
run: bunx vitest run
build:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.os }}
needs: code-quality
if: ${{ always() && (inputs.skip_code_quality || needs.code-quality.result == 'success') }}
outputs:
commit-short: ${{ steps.commit.outputs.short }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(inputs.matrix) }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}
- name: Get commit hash
id: commit
shell: bash
run: |
SHORT=$(git rev-parse --short HEAD)
echo "short=$SHORT" >> $GITHUB_OUTPUT
echo "Commit: $SHORT"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Setup bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
# Restore Electron/Electron-Builder caches before any build-related install
- name: Cache Electron artifacts
id: electron-cache
uses: actions/cache@v4
with:
path: |
${{ runner.temp }}/.cache/electron
${{ runner.temp }}/.cache/electron-builder
~/.cache/electron
~/.cache/electron-builder
${{ env.LOCALAPPDATA }}\electron-builder\Cache
key: electron-cache-${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('package.json', 'bun.lock') }}
restore-keys: |
electron-cache-${{ matrix.platform }}-${{ matrix.arch }}-
electron-cache-${{ matrix.platform }}-
- name: Cache status
run: echo "electron-cache-hit=${{ steps.electron-cache.outputs.cache-hit }}"
- name: Install dependencies
uses: nick-fields/retry@v3
with:
timeout_minutes: 10
max_attempts: 3
retry_wait_seconds: 30
command: bun install --frozen-lockfile
- name: Run postinstall
run: bun run postinstall || true
- name: Setup Windows native dependencies (for Windows only)
if: startsWith(matrix.platform, 'windows')
run: |
bun install --global node-gyp
- name: Install MSVC ARM64 toolchain (Windows ARM64 only)
if: matrix.platform == 'windows-arm64'
continue-on-error: true
uses: nick-fields/retry@v3
with:
timeout_minutes: 20
max_attempts: 3
retry_wait_seconds: 60
shell: pwsh
command: |
choco install visualstudio2022buildtools --yes --params "'--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 --add Microsoft.VisualStudio.Component.Windows11SDK.22000 --includeRecommended --includeOptional'"
- name: Setup Windows build environment (for Windows only)
if: startsWith(matrix.platform, 'windows')
run: |
echo "Setting Windows SDK version for ConPty support"
echo "WindowsTargetPlatformVersion=10.0.19041.0" >> $env:GITHUB_ENV
- name: Setup MSBuild (for Windows only)
if: startsWith(matrix.platform, 'windows')
uses: microsoft/setup-msbuild@v2
with:
vs-version: '17.0'
- name: Rebuild native modules for Electron
if: "!startsWith(matrix.platform, 'windows')"
run: bunx electron-builder install-app-deps
env:
npm_config_runtime: electron
npm_config_disturl: https://electronjs.org/headers
ELECTRON_CACHE: ${{ runner.temp }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/.cache/electron-builder
- name: Print build configuration
shell: bash
run: |
echo "=========================================="
echo "BUILD CONFIGURATION"
echo "=========================================="
echo "Platform: ${{ matrix.platform }}"
echo "Target Architecture: ${{ matrix.arch }}"
echo "Build Command: ${{ matrix.command }}"
echo "Runner OS: ${{ runner.os }}"
echo "Runner Arch: ${{ runner.arch }}"
echo "Ref: ${{ inputs.ref || '(default)' }}"
echo "Commit: ${{ steps.commit.outputs.short }}"
echo "=========================================="
- name: Resolve Sentry release name
shell: bash
run: |
set -euo pipefail
VERSION=$(node -p "require('./package.json').version")
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
RELEASE_NAME="${GITHUB_REF_NAME}"
elif [[ "$GITHUB_REF_NAME" == "dev" ]]; then
RELEASE_NAME="v${VERSION}-dev-${{ steps.commit.outputs.short }}"
else
RELEASE_NAME="v${VERSION}-${{ steps.commit.outputs.short }}"
fi
echo "SENTRY_RELEASE=$RELEASE_NAME" >> "$GITHUB_ENV"
echo "Sentry release: $RELEASE_NAME"
- name: Configure Sentry source map upload owner
shell: bash
run: |
set -euo pipefail
if [[ "${{ matrix.platform }}" == "linux-x64" ]]; then
echo "SENTRY_UPLOAD_SOURCE_MAPS=true" >> "$GITHUB_ENV"
echo "Sentry source maps will be uploaded by linux-x64"
else
echo "SENTRY_UPLOAD_SOURCE_MAPS=false" >> "$GITHUB_ENV"
echo "Sentry source map upload skipped for ${{ matrix.platform }}"
fi
- name: Validate Sentry source map upload configuration
if: matrix.platform == 'linux-x64'
shell: bash
run: |
set -euo pipefail
missing=0
for name in SENTRY_AUTH_TOKEN SENTRY_ORG SENTRY_PROJECT SENTRY_RELEASE; do
if [ -z "${!name:-}" ]; then
echo "::error title=Sentry configuration missing::$name is required for desktop source map uploads"
missing=1
fi
done
if [ "$missing" -ne 0 ]; then
exit 1
fi
echo "Sentry source map upload configured for $SENTRY_ORG/$SENTRY_PROJECT ($SENTRY_RELEASE)"
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
# macOS code signing certificate installation
- name: Setup macOS code signing (macOS only)
if: startsWith(matrix.platform, 'macos')
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD || 'temp-keychain-password' }}
run: |
if [ -n "$BUILD_CERTIFICATE_BASE64" ]; then
echo "Installing code signing certificate..."
# Create certificate file
echo $BUILD_CERTIFICATE_BASE64 | base64 --decode > certificate.p12
# Create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
# Import certificate
security import certificate.p12 -k build.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
# Clean up certificate file
rm certificate.p12
echo "Certificate imported successfully"
else
echo "No certificate provided - building unsigned application"
echo "To enable code signing, add BUILD_CERTIFICATE_BASE64 and P12_PASSWORD secrets"
fi
- name: Install Linux dependencies
if: startsWith(matrix.platform, 'linux')
run: |
sudo apt-get update
sudo apt-get install -y build-essential python3 python3-pip pkg-config libsqlite3-dev fakeroot dpkg-dev rpm libnss3-dev libatk-bridge2.0-dev libdrm2 libxkbcommon-dev libxss1 libatspi2.0-dev libgtk-3-dev libxrandr2 libasound2-dev
- name: Rebuild native modules for Electron (Windows)
if: startsWith(matrix.platform, 'windows')
shell: pwsh
continue-on-error: false
run: |
$arch = "${{ matrix.arch }}"
$electronVer = (node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')").Trim()
Write-Host "=========================================="
Write-Host "Rebuilding native modules for Electron $electronVer ($arch)"
Write-Host "=========================================="
# Strategy: Try prebuild-install first (faster, more reliable)
# Fallback to electron-rebuild only if prebuild-install fails
$success = $false
# Step 1: Try prebuild-install (downloads prebuilt binaries)
Write-Host ""
Write-Host "[Step 1] Trying prebuild-install..."
$prebuildResult = $null
try {
$prebuildResult = bun x --yes prebuild-install --runtime=electron --target=$electronVer --platform=win32 --arch=$arch --force 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ prebuild-install succeeded"
$success = $true
} else {
Write-Host "⚠️ prebuild-install exited with code $LASTEXITCODE"
}
} catch {
Write-Host "⚠️ prebuild-install failed: $_"
}
# Step 2: Verify or fallback to electron-rebuild
$sqliteNode = "node_modules/better-sqlite3/build/Release/better_sqlite3.node"
if (-not (Test-Path $sqliteNode)) {
Write-Host ""
Write-Host "[Step 2] prebuild-install didn't produce binary, trying electron-rebuild..."
try {
bunx electron-rebuild -f -w better-sqlite3
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ electron-rebuild succeeded"
$success = $true
}
} catch {
Write-Host "❌ electron-rebuild failed: $_"
}
}
# Final verification
Write-Host ""
Write-Host "Verifying native modules..."
if (Test-Path $sqliteNode) {
$size = [math]::Round((Get-Item $sqliteNode).Length / 1MB, 1)
Write-Host "✅ better-sqlite3 found: $sqliteNode ($size MB)"
} else {
Write-Error "❌ better-sqlite3 native module not found at: $sqliteNode"
exit 1
}
Write-Host ""
Write-Host "=========================================="
Write-Host "✅ All critical native modules verified"
Write-Host "=========================================="
exit 0
env:
npm_config_runtime: electron
npm_config_arch: ${{ matrix.arch }}
npm_config_target_arch: ${{ matrix.arch }}
npm_config_disturl: https://electronjs.org/headers
# Don't force build_from_source - let prebuild-install try first
MSVS_VERSION: 2022
GYP_MSVS_VERSION: 2022
- name: Prepare aioncore binary
shell: bash
run: node scripts/prepareAioncore.js
env:
# Version is pinned in repo-root package.json (aioncoreVersion).
# Set AIONUI_BACKEND_VERSION here only to override for ad-hoc builds.
AIONUI_BACKEND_RUN_ID: ${{ inputs.aioncore_run_id }}
AIONUI_BACKEND_ARCH: ${{ matrix.arch }}
GH_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build with electron-builder (Windows)
if: startsWith(matrix.platform, 'windows')
id: windows-build
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$Command = $env:WINDOWS_BUILD_COMMAND
$BuildFailed = $false
try {
Write-Host "Running Windows build command: $Command"
iex $Command
Write-Host "Windows build completed successfully"
} catch {
$BuildFailed = $true
Write-Warning "${{ matrix.platform }} build failed but will not block the workflow"
Write-Host "::notice title=Windows build skipped::${{ matrix.platform }} build failed (see logs above) but workflow is allowed to continue."
}
if ($BuildFailed) {
"result=failure" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
} else {
"result=success" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
}
env:
WINDOWS_BUILD_COMMAND: ${{ matrix.command }}
AIONUI_BACKEND_RUN_ID: ${{ inputs.aioncore_run_id }}
# Node.js memory limit for vite bundling (prevents OOM during build)
# Node.js 内存限制,防止 vite 打包时内存不足
NODE_OPTIONS: '--max-old-space-size=8192'
# Target arch / 目标架构
npm_config_arch: ${{ matrix.arch }}
npm_config_target_arch: ${{ matrix.arch }}
# Native module compilation / 原生模块编译
npm_config_runtime: electron
npm_config_disturl: https://electronjs.org/headers
npm_config_build_from_source: true
npm_config_cache: ${{ runner.temp }}/.npm
ELECTRON_CACHE: ${{ runner.temp }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/.cache/electron-builder
# Signing & IDs / 签名与应用 ID 配置
APP_ID: ${{ secrets.APP_ID }}
appleId: ${{ secrets.APPLE_ID }}
appleIdPassword: ${{ secrets.APPLE_ID_PASSWORD }}
teamId: ${{ secrets.TEAM_ID }}
identity: ${{ secrets.IDENTITY }}
CSC_NAME: ${{ secrets.IDENTITY }}
CSC_IDENTITY_AUTO_DISCOVERY: false
# Windows build flags / Windows 构建参数
MSVS_VERSION: 2022
GYP_MSVS_VERSION: 2022
WindowsTargetPlatformVersion: 10.0.19041.0
_WIN32_WINNT: 0x0A00
# Sentry DSN (injected at build time via vite define)
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
# CI flag & GitHub token / CI 标识与 GitHub Token
CI: true
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Clean up any stale disk images before DMG creation (macOS only)
# 清理可能残留的磁盘镜像,避免 hdiutil "Device not configured" 错误
- name: Clean up stale disk images (macOS only)
if: startsWith(matrix.platform, 'macos')
run: |
echo "Cleaning up any stale disk images..."
# Detach any mounted disk images
hdiutil info 2>/dev/null | grep '/dev/disk' | awk '{print $1}' | while read disk; do
echo "Detaching $disk..."
hdiutil detach "$disk" -force 2>/dev/null || true
done
# Clean up any temporary DMG files
rm -f /tmp/*.dmg 2>/dev/null || true
echo "Cleanup complete"
# macOS: Build with notarization - DMG failure = CI failure, notarization failure = warning only
# macOS: 构建并公证 - DMG 失败 = CI 失败,公证失败 = 仅警告
- name: Build with electron-builder (macOS)
if: startsWith(matrix.platform, 'macos')
id: macos-build
shell: bash
run: |
set +e # Handle errors manually
# Run build command
${{ matrix.command }} 2>&1 | tee "${RUNNER_TEMP}/build.log"
BUILD_EXIT_CODE=${PIPESTATUS[0]}
# Check if DMG was created (most important artifact)
DMG_EXISTS=false
if ls out/*.dmg 1>/dev/null 2>&1; then
DMG_EXISTS=true
echo "✅ DMG created successfully"
fi
# If build succeeded completely
if [ $BUILD_EXIT_CODE -eq 0 ]; then
echo "✅ Build completed successfully"
echo "notarization_status=success" >> $GITHUB_OUTPUT
exit 0
fi
# Build failed - check if it's just notarization failure
if [ "$DMG_EXISTS" = true ]; then
# DMG exists but build failed - likely notarization issue
if grep -qiE "notariz|staple" "${RUNNER_TEMP}/build.log"; then
echo "⚠️ DMG created but notarization failed"
echo "notarization_status=failed" >> $GITHUB_OUTPUT
echo "::warning title=Notarization Failed::DMG was built and signed successfully, but **notarization failed**."
echo "" >> $GITHUB_STEP_SUMMARY
echo "## ⚠️ Notarization Warning" >> $GITHUB_STEP_SUMMARY
echo "DMG was built and signed successfully, but **notarization failed**." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Users may see Gatekeeper warnings when opening the app for the first time." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "To fix: Right-click the app → Open → Open" >> $GITHUB_STEP_SUMMARY
exit 0 # Allow CI to continue
fi
fi
# DMG doesn't exist or other fatal error - fail CI
echo "❌ Build failed - DMG was not created"
echo "notarization_status=build_failed" >> $GITHUB_OUTPUT
exit 1
env:
NODE_OPTIONS: '--max-old-space-size=8192'
AIONUI_BACKEND_RUN_ID: ${{ inputs.aioncore_run_id }}
npm_config_arch: ${{ matrix.arch }}
APP_ID: ${{ secrets.APP_ID }}
appleId: ${{ secrets.APPLE_ID }}
appleIdPassword: ${{ secrets.APPLE_ID_PASSWORD }}
teamId: ${{ secrets.TEAM_ID }}
identity: ${{ secrets.IDENTITY }}
CSC_NAME: ${{ secrets.IDENTITY }}
CSC_IDENTITY_AUTO_DISCOVERY: false
npm_config_cache: ${{ runner.temp }}/.npm
ELECTRON_CACHE: ${{ runner.temp }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/.cache/electron-builder
ELECTRON_BUILDER_BINARIES_MIRROR: https://github.com/electron-userland/electron-builder-binaries/releases/download/
npm_config_electron_builder_binaries_mirror: https://github.com/electron-userland/electron-builder-binaries/releases/download/
ELECTRON_MIRROR: ''
npm_config_disturl: https://electronjs.org/headers
npm_config_runtime: electron
npm_config_target_arch: ${{ matrix.arch }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
CI: true
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Linux: Standard build without special error handling
# Linux: 标准构建,无特殊错误处理
- name: Build with electron-builder (Linux)
if: startsWith(matrix.platform, 'linux')
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
max_attempts: 2
retry_wait_seconds: 60
command: ${{ matrix.command }}
env:
NODE_OPTIONS: '--max-old-space-size=8192'
AIONUI_BACKEND_RUN_ID: ${{ inputs.aioncore_run_id }}
npm_config_arch: ${{ matrix.arch }}
npm_config_cache: ${{ runner.temp }}/.npm
ELECTRON_CACHE: ${{ runner.temp }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/.cache/electron-builder
ELECTRON_BUILDER_BINARIES_MIRROR: https://github.com/electron-userland/electron-builder-binaries/releases/download/
npm_config_electron_builder_binaries_mirror: https://github.com/electron-userland/electron-builder-binaries/releases/download/
ELECTRON_MIRROR: ''
npm_config_disturl: https://electronjs.org/headers
npm_config_runtime: electron
npm_config_target_arch: ${{ matrix.arch }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
CI: true
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# macOS 钥匙串清理
- name: Clean up keychain (macOS only)
if: startsWith(matrix.platform, 'macos') && always()
run: |
if security list-keychains | grep -q build.keychain; then
security delete-keychain build.keychain
echo "Temporary keychain deleted"
fi
# macOS 构建失败通知
# macOS build failure notification
- name: Notify on macOS build failure
if: startsWith(matrix.platform, 'macos') && failure()
run: |
echo "::error title=macOS Build Failed::Build failed. Check the logs for details."
echo ""
echo "❌ macOS Build Failed"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Common causes:"
echo " • hdiutil/DMG creation failure (Device not configured)"
echo " • Code signing issues"
echo " • Notarization timeout"
echo " • Out of memory (OOM)"
echo ""
echo "Check the build logs above for the specific error."
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
- name: List build artifacts
if: success() || failure()
shell: bash
run: |
echo "=========================================="
echo "BUILD ARTIFACTS"
echo "=========================================="
if [ -d "out" ]; then
ls -lh out/ || true
echo "=========================================="
echo "Total artifacts:"
find out/ -type f \( -name "*.exe" -o -name "*.msi" -o -name "*.dmg" -o -name "*.deb" -o -name "*.zip" -o -name "*.yml" \) -exec basename {} \; || true
else
echo "No out directory found!"
fi
# Verify desktop asar does not contain packages/web-cli/ contamination
# 验证桌面 asar 没有被 web-cli 代码污染
- name: Verify desktop asar isolation
if: >-
success() &&
(!startsWith(matrix.platform, 'windows') || steps.windows-build.outputs.result == 'success')
shell: bash
run: |
set -euo pipefail
ASAR=$(find out -type f -name 'app.asar' -not -path '*node_modules*' | head -n 1 || true)
if [ -z "$ASAR" ]; then
echo "::notice::No app.asar found for ${{ matrix.platform }}, skipping isolation check"
exit 0
fi
echo "Inspecting $ASAR for web-cli leakage..."
LEAK_COUNT=$(bunx @electron/asar list "$ASAR" 2>/dev/null | grep -cE '^/packages/web-cli(/|$)' || true)
if [ "$LEAK_COUNT" != "0" ]; then
echo "::error::Desktop asar contains $LEAK_COUNT web-cli entries:"
bunx @electron/asar list "$ASAR" | grep -E '^/packages/web-cli(/|$)' | head -20
exit 1
fi
echo "✅ asar isolation verified: no packages/web-cli entries"
# Upload artifacts when:
# - Build succeeded (all platforms)
# - macOS: notarization timeout but artifacts exist (handled in build step)
# - Windows: only if windows-build step succeeded
# 上传产物条件:
# - 构建成功(所有平台)
# - macOS: 公证超时但有产物(已在构建步骤中处理)
# - Windows: 仅当 windows-build 步骤成功
- name: Clean up non-installer artifacts
if: >-
inputs.upload_installers_only && success() &&
(!startsWith(matrix.platform, 'windows') || steps.windows-build.outputs.result == 'success')
shell: bash
run: |
echo "Removing non-installer files from out/ ..."
rm -f out/*.blockmap out/*.zip out/*.yml out/builder-debug.yml 2>/dev/null || true
echo "Remaining artifacts:"
ls -lh out/ || true
- name: Upload build artifacts
uses: actions/upload-artifact@v6
if: >-
success() &&
(!startsWith(matrix.platform, 'windows') || steps.windows-build.outputs.result == 'success')
with:
name: ${{ inputs.append_commit_hash && format('{0}-{1}', matrix.artifact-name, steps.commit.outputs.short) || matrix.artifact-name }}
path: |
out/*.exe
out/*.msi
out/*.dmg
out/*.deb
out/AionUi-*-mac-*.zip
out/*.yml
if-no-files-found: warn
retention-days: 7
build-summary:
name: Build Summary
runs-on: ubuntu-latest
needs: [code-quality, build]
if: always()
steps:
- name: Write build summary
env:
MATRIX: ${{ inputs.matrix }}
run: |
PLATFORMS=$(echo "$MATRIX" | jq -r '[.include[].platform] | join(", ")')
echo "## Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Key | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-----|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Ref | \`${{ inputs.ref || '(default)' }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Commit | \`${{ needs.build.outputs.commit-short }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Platforms | $PLATFORMS |" >> $GITHUB_STEP_SUMMARY
echo "| Code Quality | ${{ needs.code-quality.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY