Release Desktop App #586
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Release Desktop App | |
on: | |
workflow_dispatch: | |
inputs: | |
build-type: | |
description: 'Build Type' | |
type: choice | |
required: true | |
default: canary | |
options: | |
- canary | |
- beta | |
- stable | |
is-draft: | |
description: 'Draft Release?' | |
type: boolean | |
required: true | |
default: true | |
is-pre-release: | |
description: 'Pre Release? (labeled as "PreRelease")' | |
type: boolean | |
required: true | |
default: true | |
permissions: | |
actions: write | |
contents: write | |
security-events: write | |
id-token: write | |
attestations: write | |
env: | |
BUILD_TYPE: ${{ github.event.inputs.build-type }} | |
DEBUG: napi:* | |
APP_NAME: affine | |
MACOSX_DEPLOYMENT_TARGET: '10.13' | |
jobs: | |
before-make: | |
runs-on: ubuntu-latest | |
environment: ${{ github.event.inputs.build-type }} | |
outputs: | |
RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup Version | |
id: version | |
uses: ./.github/actions/setup-version | |
- name: Setup Node.js | |
uses: ./.github/actions/setup-node | |
- name: Setup @sentry/cli | |
uses: ./.github/actions/setup-sentry | |
- name: generate-assets | |
run: yarn workspace @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: ${{ steps.version.outputs.APP_VERSION }} | |
RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }} | |
SKIP_NX_CACHE: 'true' | |
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} | |
- name: Upload web artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: web | |
path: packages/frontend/apps/electron/resources/web-static | |
make-distribution: | |
strategy: | |
matrix: | |
spec: | |
- runner: macos-14 | |
platform: darwin | |
arch: x64 | |
target: x86_64-apple-darwin | |
- runner: macos-14 | |
platform: darwin | |
arch: arm64 | |
target: aarch64-apple-darwin | |
- runner: ubuntu-latest | |
platform: linux | |
arch: x64 | |
target: x86_64-unknown-linux-gnu | |
runs-on: ${{ matrix.spec.runner }} | |
needs: before-make | |
env: | |
APPLE_ID: ${{ secrets.APPLE_ID }} | |
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
SKIP_GENERATE_ASSETS: 1 | |
SENTRY_ORG: ${{ secrets.SENTRY_ORG }} | |
SENTRY_PROJECT: 'affine' | |
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup Version | |
id: version | |
uses: ./.github/actions/setup-version | |
- name: Setup Node.js | |
timeout-minutes: 10 | |
uses: ./.github/actions/setup-node | |
with: | |
extra-flags: workspaces focus @affine/electron @affine/monorepo | |
hard-link-nm: false | |
nmHoistingLimits: workspaces | |
enableScripts: false | |
- name: Build AFFiNE native | |
uses: ./.github/actions/build-rust | |
with: | |
target: ${{ matrix.spec.target }} | |
package: '@affine/native' | |
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} | |
- uses: actions/download-artifact@v4 | |
with: | |
name: web | |
path: packages/frontend/apps/electron/resources/web-static | |
- name: Build Desktop Layers | |
run: yarn workspace @affine/electron build | |
- name: Signing By Apple Developer ID | |
if: ${{ matrix.spec.platform == 'darwin' }} | |
uses: apple-actions/import-codesign-certs@v3 | |
with: | |
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }} | |
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }} | |
- name: Install fuse on Linux (for patching AppImage) | |
if: ${{ matrix.spec.platform == 'linux' }} | |
run: | | |
sudo add-apt-repository universe | |
sudo apt install libfuse2 -y | |
- name: make | |
run: yarn workspace @affine/electron make --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }} | |
env: | |
SKIP_WEB_BUILD: 1 | |
HOIST_NODE_MODULES: 1 | |
- name: signing DMG | |
if: ${{ matrix.spec.platform == 'darwin' }} | |
run: | | |
codesign --force --sign "Developer ID Application: TOEVERYTHING PTE. LTD." packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make/AFFiNE.dmg | |
- name: Save artifacts (mac) | |
if: ${{ matrix.spec.platform == 'darwin' }} | |
run: | | |
mkdir -p builds | |
mv packages/frontend/apps/electron/out/*/make/*.dmg ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg | |
mv packages/frontend/apps/electron/out/*/make/zip/darwin/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip | |
- name: Save artifacts (linux) | |
if: ${{ matrix.spec.platform == 'linux' }} | |
run: | | |
mkdir -p builds | |
mv packages/frontend/apps/electron/out/*/make/zip/linux/x64/*.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.zip | |
mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.appimage | |
- uses: actions/attest-build-provenance@v1 | |
if: ${{ matrix.spec.platform == 'darwin' }} | |
with: | |
subject-path: | | |
./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip | |
./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg | |
- uses: actions/attest-build-provenance@v1 | |
if: ${{ matrix.spec.platform == 'linux' }} | |
with: | |
subject-path: | | |
./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.zip | |
./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.appimage | |
- name: Upload Artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: affine-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}-builds | |
path: builds | |
package-distribution-windows: | |
strategy: | |
matrix: | |
spec: | |
- runner: windows-latest | |
platform: win32 | |
arch: x64 | |
target: x86_64-pc-windows-msvc | |
runs-on: ${{ matrix.spec.runner }} | |
needs: before-make | |
outputs: | |
FILES_TO_BE_SIGNED: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED }} | |
env: | |
SKIP_GENERATE_ASSETS: 1 | |
SENTRY_ORG: ${{ secrets.SENTRY_ORG }} | |
SENTRY_PROJECT: 'affine' | |
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup Version | |
id: version | |
uses: ./.github/actions/setup-version | |
- name: Setup Node.js | |
timeout-minutes: 10 | |
uses: ./.github/actions/setup-node | |
with: | |
extra-flags: workspaces focus @affine/electron @affine/monorepo | |
hard-link-nm: false | |
nmHoistingLimits: workspaces | |
- name: Build AFFiNE native | |
uses: ./.github/actions/build-rust | |
with: | |
target: ${{ matrix.spec.target }} | |
package: '@affine/native' | |
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} | |
- uses: actions/download-artifact@v4 | |
with: | |
name: web | |
path: packages/frontend/apps/electron/resources/web-static | |
- name: Build Desktop Layers | |
run: yarn workspace @affine/electron build | |
- name: package | |
run: yarn workspace @affine/electron package --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }} | |
env: | |
SKIP_WEB_BUILD: 1 | |
HOIST_NODE_MODULES: 1 | |
- name: get all files to be signed | |
id: get_files_to_be_signed | |
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: Zip artifacts for faster upload | |
run: Compress-Archive -CompressionLevel Fastest -Path packages/frontend/apps/electron/out/* -DestinationPath archive.zip | |
- name: Save packaged artifacts for signing | |
uses: actions/upload-artifact@v4 | |
with: | |
name: packaged-${{ matrix.spec.platform }}-${{ matrix.spec.arch }} | |
path: | | |
archive.zip | |
!**/*.map | |
sign-packaged-artifacts-windows: | |
needs: package-distribution-windows | |
uses: ./.github/workflows/windows-signer.yml | |
with: | |
files: ${{ needs.package-distribution-windows.outputs.FILES_TO_BE_SIGNED }} | |
artifact-name: packaged-win32-x64 | |
make-windows-installer: | |
needs: sign-packaged-artifacts-windows | |
strategy: | |
matrix: | |
spec: | |
- runner: windows-latest | |
platform: win32 | |
arch: x64 | |
target: x86_64-pc-windows-msvc | |
runs-on: ${{ matrix.spec.runner }} | |
outputs: | |
FILES_TO_BE_SIGNED: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup Version | |
id: version | |
uses: ./.github/actions/setup-version | |
- name: Setup Node.js | |
timeout-minutes: 10 | |
uses: ./.github/actions/setup-node | |
with: | |
extra-flags: workspaces focus @affine/electron @affine/monorepo | |
hard-link-nm: false | |
nmHoistingLimits: workspaces | |
- name: Download and overwrite packaged artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: signed-packaged-${{ matrix.spec.platform }}-${{ matrix.spec.arch }} | |
path: . | |
- name: unzip file | |
run: Expand-Archive -Path signed.zip -DestinationPath packages/frontend/apps/electron/out | |
- name: Make squirrel.windows installer | |
run: yarn workspace @affine/electron make-squirrel --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }} | |
- name: Make nsis.windows installer | |
run: yarn workspace @affine/electron make-nsis --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }} | |
- name: Zip artifacts for faster upload | |
run: Compress-Archive -CompressionLevel Fastest -Path packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make/* -DestinationPath archive.zip | |
- name: get all files to be signed | |
id: get_files_to_be_signed | |
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: Save installer for signing | |
uses: actions/upload-artifact@v4 | |
with: | |
name: installer-${{ matrix.spec.platform }}-${{ matrix.spec.arch }} | |
path: archive.zip | |
sign-installer-artifacts-windows: | |
needs: make-windows-installer | |
uses: ./.github/workflows/windows-signer.yml | |
with: | |
files: ${{ needs.make-windows-installer.outputs.FILES_TO_BE_SIGNED }} | |
artifact-name: installer-win32-x64 | |
finalize-installer-windows: | |
needs: [sign-installer-artifacts-windows, before-make] | |
strategy: | |
matrix: | |
spec: | |
- runner: windows-latest | |
platform: win32 | |
arch: x64 | |
target: x86_64-pc-windows-msvc | |
runs-on: ${{ matrix.spec.runner }} | |
steps: | |
- name: Download and overwrite installer artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: signed-installer-${{ matrix.spec.platform }}-${{ matrix.spec.arch }} | |
path: . | |
- name: unzip file | |
run: Expand-Archive -Path signed.zip -DestinationPath packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make | |
- name: Save artifacts | |
run: | | |
mkdir -p builds | |
mv packages/frontend/apps/electron/out/*/make/zip/win32/x64/AFFiNE*-win32-x64-*.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-x64.zip | |
mv packages/frontend/apps/electron/out/*/make/squirrel.windows/x64/*.exe ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-x64.exe | |
mv packages/frontend/apps/electron/out/*/make/nsis.windows/x64/*.exe ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-x64.nsis.exe | |
- uses: actions/attest-build-provenance@v1 | |
with: | |
subject-path: | | |
./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-x64.zip | |
./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-x64.exe | |
./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-x64.nsis.exe | |
- name: Upload Artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: affine-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}-builds | |
path: builds | |
release: | |
needs: [before-make, make-distribution, finalize-installer-windows] | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/download-artifact@v4 | |
with: | |
name: web | |
path: web-static | |
- name: Zip web-static | |
run: zip -r web-static.zip web-static | |
- name: Download Artifacts (macos-x64) | |
uses: actions/download-artifact@v4 | |
with: | |
name: affine-darwin-x64-builds | |
path: ./ | |
- name: Download Artifacts (macos-arm64) | |
uses: actions/download-artifact@v4 | |
with: | |
name: affine-darwin-arm64-builds | |
path: ./ | |
- name: Download Artifacts (windows-x64) | |
uses: actions/download-artifact@v4 | |
with: | |
name: affine-win32-x64-builds | |
path: ./ | |
- name: Download Artifacts (linux-x64) | |
uses: actions/download-artifact@v4 | |
with: | |
name: affine-linux-x64-builds | |
path: ./ | |
- uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
- name: Generate Release yml | |
run: | | |
node ./packages/frontend/apps/electron/scripts/generate-yml.js | |
env: | |
RELEASE_VERSION: ${{ needs.before-make.outputs.RELEASE_VERSION }} | |
- name: Create Release Draft | |
if: ${{ github.ref_type == 'tag' }} | |
uses: softprops/action-gh-release@v2 | |
with: | |
name: ${{ needs.before-make.outputs.RELEASE_VERSION }} | |
body: '' | |
draft: ${{ github.event.inputs.is-draft }} | |
prerelease: ${{ github.event.inputs.is-pre-release }} | |
files: | | |
./VERSION | |
./*.zip | |
./*.dmg | |
./*.exe | |
./*.appimage | |
./*.apk | |
./*.yml | |
- name: Create Nightly Release Draft | |
if: ${{ github.ref_type == 'branch' }} | |
uses: softprops/action-gh-release@v2 | |
env: | |
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
with: | |
# Temporarily, treat release from branch as nightly release, artifact saved to AFFiNE-Releases. | |
# Need to improve internal build and nightly release logic. | |
repository: 'toeverything/AFFiNE-Releases' | |
name: ${{ needs.before-make.outputs.RELEASE_VERSION }} | |
tag_name: ${{ needs.before-make.outputs.RELEASE_VERSION }} | |
body: '' | |
draft: false | |
prerelease: true | |
files: | | |
./VERSION | |
./*.zip | |
./*.dmg | |
./*.exe | |
./*.appimage | |
./*.apk | |
./*.yml |