mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-12 15:46:29 +08:00
431 lines
16 KiB
YAML
431 lines
16 KiB
YAML
name: Release Desktop
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
build-type:
|
|
required: true
|
|
type: string
|
|
app-version:
|
|
required: true
|
|
type: string
|
|
git-short-hash:
|
|
required: true
|
|
type: string
|
|
desktop_macos:
|
|
description: 'Desktop - macOS'
|
|
required: false
|
|
default: true
|
|
type: boolean
|
|
desktop_windows:
|
|
description: 'Desktop - Windows'
|
|
required: false
|
|
default: true
|
|
type: boolean
|
|
desktop_linux:
|
|
description: 'Desktop - Linux'
|
|
required: false
|
|
default: true
|
|
type: boolean
|
|
require-windows-signing:
|
|
description: 'Require all Windows signing steps to succeed before release'
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
|
|
permissions:
|
|
actions: write
|
|
contents: write
|
|
security-events: write
|
|
id-token: write
|
|
attestations: write
|
|
|
|
env:
|
|
BUILD_TYPE: ${{ inputs.build-type }}
|
|
RELEASE_VERSION: ${{ inputs.app-version }}
|
|
DEBUG: 'affine:*,napi:*'
|
|
APP_NAME: affine
|
|
MACOSX_DEPLOYMENT_TARGET: '11.6'
|
|
|
|
jobs:
|
|
before-make:
|
|
if: ${{ inputs.desktop_macos || inputs.desktop_windows || inputs.desktop_linux }}
|
|
runs-on: ubuntu-latest
|
|
environment: ${{ inputs.build-type }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Setup Version
|
|
uses: ./.github/actions/setup-version
|
|
with:
|
|
app-version: ${{ inputs.app-version }}
|
|
- name: Setup Node.js
|
|
uses: ./.github/actions/setup-node
|
|
- name: Setup @sentry/cli
|
|
uses: ./.github/actions/setup-sentry
|
|
- name: generate-assets
|
|
run: yarn affine @affine/electron generate-assets
|
|
env:
|
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
SENTRY_PROJECT: 'affine'
|
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
|
SENTRY_RELEASE: ${{ inputs.app-version }}
|
|
RELEASE_VERSION: ${{ inputs.app-version }}
|
|
|
|
- name: Upload web artifact
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: desktop-web
|
|
path: packages/frontend/apps/electron/resources/web-static
|
|
|
|
windows-signer-gate:
|
|
if: ${{ inputs.desktop_windows }}
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
signer_available: ${{ steps.check.outputs.signer_available }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Check windows signer availability
|
|
id: check
|
|
run: node ./scripts/check-windows-signer.mjs
|
|
env:
|
|
AFFINE_SIGN_CLIENT_HASH: ${{ secrets.AFFINE_SIGN_CLIENT_HASH }}
|
|
AFFINE_SIGNER_ADDR: ${{ secrets.AFFINE_SIGNER_ADDR }}
|
|
AFFINE_SIGNER_TOKEN: ${{ secrets.AFFINE_SIGNER_TOKEN }}
|
|
AFFINE_SIGNER_TS_AUTH_KEY: ${{ secrets.AFFINE_SIGNER_TS_AUTH_KEY }}
|
|
BUILD_TYPE: ${{ inputs.build-type }}
|
|
REQUIRE_SIGNER: ${{ inputs.require-windows-signing }}
|
|
WINDOWS_SIGNER_PUBLIC_CERT_BASE64: ${{ secrets.WINDOWS_SIGNER_PUBLIC_CERT_BASE64 }}
|
|
|
|
make-distribution-macos:
|
|
if: ${{ inputs.desktop_macos }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
spec:
|
|
- runner: macos-latest
|
|
platform: darwin
|
|
arch: x64
|
|
target: x86_64-apple-darwin
|
|
- runner: macos-latest
|
|
platform: darwin
|
|
arch: arm64
|
|
target: aarch64-apple-darwin
|
|
needs: before-make
|
|
uses: ./.github/workflows/release-desktop-platform.yml
|
|
secrets: inherit
|
|
with:
|
|
build_type: ${{ inputs.build-type }}
|
|
app_version: ${{ inputs.app-version }}
|
|
git_short_hash: ${{ inputs.git-short-hash }}
|
|
runner: ${{ matrix.spec.runner }}
|
|
platform: ${{ matrix.spec.platform }}
|
|
arch: ${{ matrix.spec.arch }}
|
|
target: ${{ matrix.spec.target }}
|
|
apple_codesign: true
|
|
|
|
make-distribution-linux:
|
|
if: ${{ inputs.desktop_linux }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
spec:
|
|
- runner: ubuntu-latest
|
|
platform: linux
|
|
arch: x64
|
|
target: x86_64-unknown-linux-gnu
|
|
needs: before-make
|
|
uses: ./.github/workflows/release-desktop-platform.yml
|
|
secrets: inherit
|
|
with:
|
|
build_type: ${{ inputs.build-type }}
|
|
app_version: ${{ inputs.app-version }}
|
|
git_short_hash: ${{ inputs.git-short-hash }}
|
|
runner: ${{ matrix.spec.runner }}
|
|
platform: ${{ matrix.spec.platform }}
|
|
arch: ${{ matrix.spec.arch }}
|
|
target: ${{ matrix.spec.target }}
|
|
install_linux_deps: true
|
|
|
|
build-and-sign-windows:
|
|
if: ${{ inputs.desktop_windows && needs.windows-signer-gate.outputs.signer_available == 'true' }}
|
|
needs:
|
|
- before-make
|
|
- windows-signer-gate
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
spec:
|
|
- platform: win32
|
|
arch: x64
|
|
target: x86_64-pc-windows-msvc
|
|
- platform: win32
|
|
arch: arm64
|
|
target: aarch64-pc-windows-msvc
|
|
runs-on: windows-latest
|
|
env:
|
|
AFFINE_SIGNER_ADDR: ${{ secrets.AFFINE_SIGNER_ADDR }}
|
|
AFFINE_SIGNER_TOKEN: ${{ secrets.AFFINE_SIGNER_TOKEN }}
|
|
APP_NAME: affine
|
|
BUILD_TYPE: ${{ inputs.build-type }}
|
|
DEBUG: 'affine:*,napi:*'
|
|
RELEASE_VERSION: ${{ inputs.app-version }}
|
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
SENTRY_PROJECT: 'affine'
|
|
SENTRY_RELEASE: ${{ inputs.app-version }}
|
|
SKIP_GENERATE_ASSETS: 1
|
|
TS_RS_EXPERIMENT: this_is_unstable_software
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- name: Setup Version
|
|
uses: ./.github/actions/setup-version
|
|
with:
|
|
app-version: ${{ inputs.app-version }}
|
|
|
|
- name: Setup Node.js
|
|
timeout-minutes: 10
|
|
uses: ./.github/actions/setup-node
|
|
with:
|
|
extra-flags: workspaces focus @affine/electron @affine/monorepo @affine/nbstore @toeverything/infra
|
|
enableScripts: true
|
|
hard-link-nm: false
|
|
nmHoistingLimits: workspaces
|
|
env:
|
|
npm_config_arch: ${{ matrix.spec.arch }}
|
|
|
|
- name: Build AFFiNE native
|
|
uses: ./.github/actions/build-rust
|
|
with:
|
|
target: ${{ matrix.spec.target }}
|
|
package: '@affine/native'
|
|
|
|
- name: Download web artifact
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: desktop-web
|
|
path: packages/frontend/apps/electron/resources/web-static
|
|
|
|
- name: Build Desktop Layers
|
|
run: yarn affine @affine/electron build
|
|
|
|
- name: Remove nbstore node_modules
|
|
shell: bash
|
|
run: |
|
|
rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite/affine/node_modules
|
|
rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules
|
|
|
|
- name: Package windows app
|
|
run: yarn affine @affine/electron package --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
|
env:
|
|
HOIST_NODE_MODULES: 1
|
|
NODE_OPTIONS: --max-old-space-size=14384
|
|
SKIP_WEB_BUILD: 1
|
|
|
|
- name: Connect Tailscale
|
|
uses: tailscale/github-action@v4
|
|
with:
|
|
authkey: ${{ secrets.AFFINE_SIGNER_TS_AUTH_KEY }}
|
|
hostname: affine-signer-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.spec.arch }}
|
|
|
|
- name: Check signer connectivity
|
|
shell: pwsh
|
|
run: |
|
|
$Parts = "$env:AFFINE_SIGNER_ADDR".Split(':')
|
|
if ($Parts.Count -ne 2) {
|
|
throw "AFFINE_SIGNER_ADDR must be host:port, got $env:AFFINE_SIGNER_ADDR"
|
|
}
|
|
|
|
$Result = Test-NetConnection -ComputerName $Parts[0] -Port ([int]$Parts[1])
|
|
if (!$Result.TcpTestSucceeded) {
|
|
throw "Unable to connect to signer at $env:AFFINE_SIGNER_ADDR"
|
|
}
|
|
|
|
- name: Download remote signer client
|
|
shell: pwsh
|
|
run: |
|
|
if (!$env:AFFINE_SIGN_CLIENT_HASH) {
|
|
throw 'AFFINE_SIGN_CLIENT_HASH is required.'
|
|
}
|
|
Invoke-WebRequest -Uri "https://cdn.affine.pro/sign-client/$env:AFFINE_SIGN_CLIENT_HASH" -OutFile affine-sign-client.exe
|
|
env:
|
|
AFFINE_SIGN_CLIENT_HASH: ${{ secrets.AFFINE_SIGN_CLIENT_HASH }}
|
|
|
|
- name: Prepare public signing certificate
|
|
shell: pwsh
|
|
run: |
|
|
if (!$env:WINDOWS_SIGNER_PUBLIC_CERT_BASE64) {
|
|
throw 'WINDOWS_SIGNER_PUBLIC_CERT_BASE64 is required.'
|
|
}
|
|
[IO.File]::WriteAllBytes('windows-signer-public.cer', [Convert]::FromBase64String($env:WINDOWS_SIGNER_PUBLIC_CERT_BASE64))
|
|
env:
|
|
WINDOWS_SIGNER_PUBLIC_CERT_BASE64: ${{ secrets.WINDOWS_SIGNER_PUBLIC_CERT_BASE64 }}
|
|
|
|
- name: Resolve signtool
|
|
shell: pwsh
|
|
run: |
|
|
$Command = Get-Command signtool.exe -ErrorAction SilentlyContinue
|
|
if ($Command) {
|
|
"SIGNTOOL=$($Command.Source)" >> $env:GITHUB_ENV
|
|
Write-Host "Using signtool: $($Command.Source)"
|
|
exit 0
|
|
}
|
|
|
|
$KitsRoot = "${env:ProgramFiles(x86)}\Windows Kits\10\bin"
|
|
$Candidates = @()
|
|
if (Test-Path -LiteralPath $KitsRoot) {
|
|
$Candidates = Get-ChildItem -Path $KitsRoot -Recurse -Filter signtool.exe |
|
|
Where-Object { $_.FullName -match '\\x64\\signtool\.exe$' } |
|
|
Sort-Object FullName -Descending
|
|
}
|
|
|
|
if ($Candidates.Count -eq 0) {
|
|
throw "Unable to find signtool.exe under PATH or $KitsRoot"
|
|
}
|
|
|
|
"SIGNTOOL=$($Candidates[0].FullName)" >> $env:GITHUB_ENV
|
|
Write-Host "Using signtool: $($Candidates[0].FullName)"
|
|
|
|
- name: Get packaged files to sign
|
|
id: packaged_files_to_sign
|
|
shell: pwsh
|
|
run: |
|
|
Set-Variable -Name FILES_TO_BE_SIGNED -Value ((Get-ChildItem -Path packages/frontend/apps/electron/out -Recurse -File | Where-Object { $_.Extension -in @(".exe", ".node", ".dll", ".msi") } | ForEach-Object { '"' + $_.FullName.Replace((Get-Location).Path + '\packages\frontend\apps\electron\out\', '') + '"' }) -join ' ')
|
|
"FILES_TO_BE_SIGNED=$FILES_TO_BE_SIGNED" >> $env:GITHUB_OUTPUT
|
|
echo $FILES_TO_BE_SIGNED
|
|
|
|
- name: Sign packaged files
|
|
shell: pwsh
|
|
run: |
|
|
./affine-sign-client.exe `
|
|
--server "$env:AFFINE_SIGNER_ADDR" `
|
|
--token "$env:AFFINE_SIGNER_TOKEN" `
|
|
--workdir packages/frontend/apps/electron/out `
|
|
--files '${{ steps.packaged_files_to_sign.outputs.FILES_TO_BE_SIGNED }}' `
|
|
--cert windows-signer-public.cer `
|
|
--plain-tcp
|
|
|
|
- name: Make squirrel.windows installer
|
|
run: yarn affine @affine/electron make-squirrel --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
|
|
|
- name: Make nsis.windows installer
|
|
run: yarn affine @affine/electron make-nsis --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
|
|
|
- name: Get installer files to sign
|
|
id: installer_files_to_sign
|
|
shell: pwsh
|
|
run: |
|
|
Set-Variable -Name FILES_TO_BE_SIGNED -Value ((Get-ChildItem -Path packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make -Recurse -File | Where-Object { $_.Extension -in @(".exe", ".node", ".dll", ".msi") } | ForEach-Object { '"' + $_.FullName.Replace((Get-Location).Path + '\packages\frontend\apps\electron\out\${{ env.BUILD_TYPE }}\make\', '') + '"' }) -join ' ')
|
|
"FILES_TO_BE_SIGNED=$FILES_TO_BE_SIGNED" >> $env:GITHUB_OUTPUT
|
|
echo $FILES_TO_BE_SIGNED
|
|
|
|
- name: Sign installer files
|
|
shell: pwsh
|
|
run: |
|
|
./affine-sign-client.exe `
|
|
--server "$env:AFFINE_SIGNER_ADDR" `
|
|
--token "$env:AFFINE_SIGNER_TOKEN" `
|
|
--workdir packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make `
|
|
--files '${{ steps.installer_files_to_sign.outputs.FILES_TO_BE_SIGNED }}' `
|
|
--cert windows-signer-public.cer `
|
|
--plain-tcp
|
|
|
|
- name: Save artifacts
|
|
run: |
|
|
mkdir -p builds
|
|
mv packages/frontend/apps/electron/out/*/make/zip/win32/${{ matrix.spec.arch }}/AFFiNE*-win32-${{ matrix.spec.arch }}-*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip
|
|
mv packages/frontend/apps/electron/out/*/make/squirrel.windows/${{ matrix.spec.arch }}/*.exe ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.exe
|
|
mv packages/frontend/apps/electron/out/*/make/nsis.windows/${{ matrix.spec.arch }}/*.exe ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.nsis.exe
|
|
|
|
- uses: actions/attest-build-provenance@v4
|
|
with:
|
|
subject-path: |
|
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip
|
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.exe
|
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.nsis.exe
|
|
|
|
- name: Upload Artifact
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: affine-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}-builds
|
|
path: builds
|
|
|
|
release:
|
|
if: >-
|
|
${{
|
|
always() &&
|
|
(inputs.desktop_macos || inputs.desktop_linux || inputs.desktop_windows) &&
|
|
needs.before-make.result == 'success' &&
|
|
(!inputs.desktop_macos || needs.make-distribution-macos.result == 'success') &&
|
|
(!inputs.desktop_linux || needs.make-distribution-linux.result == 'success') &&
|
|
(
|
|
!inputs.desktop_windows ||
|
|
!inputs.require-windows-signing ||
|
|
needs.build-and-sign-windows.result == 'success'
|
|
)
|
|
}}
|
|
needs:
|
|
[
|
|
before-make,
|
|
make-distribution-macos,
|
|
make-distribution-linux,
|
|
build-and-sign-windows,
|
|
]
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Download Artifacts (macos-x64)
|
|
if: ${{ inputs.desktop_macos }}
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: affine-darwin-x64-builds
|
|
path: ./release
|
|
- name: Download Artifacts (macos-arm64)
|
|
if: ${{ inputs.desktop_macos }}
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: affine-darwin-arm64-builds
|
|
path: ./release
|
|
- name: Download Artifacts (windows-x64)
|
|
if: ${{ inputs.desktop_windows && needs.build-and-sign-windows.result == 'success' }}
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: affine-win32-x64-builds
|
|
path: ./release
|
|
- name: Download Artifacts (windows-arm64)
|
|
if: ${{ inputs.desktop_windows && needs.build-and-sign-windows.result == 'success' }}
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: affine-win32-arm64-builds
|
|
path: ./release
|
|
- name: Download Artifacts (linux-x64)
|
|
if: ${{ inputs.desktop_linux }}
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: affine-linux-x64-builds
|
|
path: ./release
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version: 20
|
|
- name: Copy Selfhost Release Files
|
|
run: |
|
|
cp ./.docker/selfhost/compose.yml ./release/docker-compose.yml
|
|
cp ./.docker/selfhost/.env.example ./release/.env.example
|
|
cp ./.docker/selfhost/schema.json ./release/config.schema.json
|
|
- name: Generate Release yml
|
|
run: |
|
|
node ./scripts/generate-release-yml.mjs
|
|
env:
|
|
RELEASE_VERSION: ${{ env.RELEASE_VERSION }}
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
name: ${{ env.RELEASE_VERSION }}
|
|
draft: ${{ inputs.build-type == 'stable' }}
|
|
prerelease: ${{ inputs.build-type != 'stable' }}
|
|
tag_name: v${{ env.RELEASE_VERSION}}
|
|
files: ./release/*
|