diff --git a/.github/workflows/release-desktop-platform.yml b/.github/workflows/release-desktop-platform.yml new file mode 100644 index 0000000000..94fea60e75 --- /dev/null +++ b/.github/workflows/release-desktop-platform.yml @@ -0,0 +1,226 @@ +name: Release Desktop Platform + +on: + workflow_call: + inputs: + build_type: + required: true + type: string + app_version: + required: true + type: string + git_short_hash: + required: true + type: string + runner: + required: true + type: string + platform: + required: true + type: string + arch: + required: true + type: string + target: + required: true + type: string + apple_codesign: + required: false + default: false + type: boolean + install_linux_deps: + required: false + default: false + type: boolean + enable_scripts: + required: false + default: false + type: boolean + outputs: + files_to_be_signed: + description: Files to be signed (Windows only) + value: ${{ jobs.build.outputs.files_to_be_signed }} + +permissions: + actions: write + contents: write + security-events: write + id-token: write + attestations: write + +jobs: + build: + runs-on: ${{ inputs.runner }} + outputs: + files_to_be_signed: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED }} + env: + BUILD_TYPE: ${{ inputs.build_type }} + RELEASE_VERSION: ${{ inputs.app_version }} + DEBUG: 'affine:*,napi:*' + APP_NAME: affine + MACOSX_DEPLOYMENT_TARGET: '12.0' + SKIP_GENERATE_ASSETS: 1 + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + 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 }} + MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - 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 + hard-link-nm: false + nmHoistingLimits: workspaces + enableScripts: ${{ inputs.enable_scripts }} + + - name: Build AFFiNE native + uses: ./.github/actions/build-rust + with: + target: ${{ inputs.target }} + package: '@affine/native' + + - 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: Signing By Apple Developer ID + if: ${{ inputs.platform == 'darwin' && inputs.apple_codesign }} + uses: apple-actions/import-codesign-certs@v5 + with: + p12-file-base64: ${{ secrets.CERTIFICATES_P12 }} + p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }} + + - name: Install additional dependencies on Linux + if: ${{ inputs.platform == 'linux' && inputs.install_linux_deps }} + run: | + df -h + sudo add-apt-repository universe + sudo apt install -y libfuse2 elfutils flatpak flatpak-builder + flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo + flatpak update + # some flatpak deps need git protocol.file.allow + git config --global protocol.file.allow always + # clean up apt cache to save disk space + sudo -E apt-get -y purge azure-cli* zulu* hhvm* llvm* firefox* google* dotnet* aspnetcore* powershell* adoptopenjdk* mysql* php* mongodb* moby* snap* || true + sudo -E apt-get -qq autoremove --purge + sudo rm -rf /usr/share/dotnet /opt/ghc /opt/hostedtoolcache/CodeQL /usr/local/lib/android + sudo apt-get clean + rm -rf ~/.cache/yarn ~/.npm + df -h + + - name: Remove nbstore node_modules (darwin/linux) + if: ${{ inputs.platform != 'win32' }} + shell: bash + # node_modules of nbstore is not needed for building, and it will make the build process out of memory + run: | + cargo clean + rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite + rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules + + - name: Remove nbstore node_modules (windows) + if: ${{ inputs.platform == 'win32' }} + 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: make + if: ${{ inputs.platform != 'win32' }} + run: yarn affine @affine/electron make --platform=${{ inputs.platform }} --arch=${{ inputs.arch }} + env: + SKIP_WEB_BUILD: 1 + HOIST_NODE_MODULES: 1 + NODE_OPTIONS: --max-old-space-size=14384 + + - name: package + if: ${{ inputs.platform == 'win32' }} + run: | + yarn affine @affine/electron package --platform=${{ inputs.platform }} --arch=${{ inputs.arch }} + env: + SKIP_WEB_BUILD: 1 + HOIST_NODE_MODULES: 1 + NODE_OPTIONS: --max-old-space-size=14384 + + - name: signing DMG + if: ${{ inputs.platform == 'darwin' && inputs.apple_codesign }} + 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: ${{ inputs.platform == 'darwin' }} + run: | + mkdir -p builds + mv packages/frontend/apps/electron/out/*/make/*.dmg ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.dmg + mv packages/frontend/apps/electron/out/*/make/zip/darwin/${{ inputs.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.zip + + - name: Save artifacts (linux) + if: ${{ inputs.platform == 'linux' }} + run: | + mkdir -p builds + mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ inputs.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.zip + mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.appimage + mv packages/frontend/apps/electron/out/*/make/deb/${{ inputs.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.deb + mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.flatpak + + - uses: actions/attest-build-provenance@v2 + if: ${{ inputs.platform == 'darwin' }} + with: + subject-path: | + ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.zip + ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.dmg + + - uses: actions/attest-build-provenance@v2 + if: ${{ inputs.platform == 'linux' }} + with: + subject-path: | + ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.zip + ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.appimage + ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.deb + ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.flatpak + + - name: Upload Artifact + if: ${{ inputs.platform == 'darwin' || inputs.platform == 'linux' }} + uses: actions/upload-artifact@v4 + with: + name: affine-${{ inputs.platform }}-${{ inputs.arch }}-builds + path: builds + + - name: get all files to be signed + id: get_files_to_be_signed + if: ${{ inputs.platform == 'win32' }} + 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: Zip artifacts for faster upload + if: ${{ inputs.platform == 'win32' }} + shell: pwsh + run: Compress-Archive -CompressionLevel Fastest -Path packages/frontend/apps/electron/out/* -DestinationPath archive.zip + + - name: Save packaged artifacts for signing + if: ${{ inputs.platform == 'win32' }} + uses: actions/upload-artifact@v4 + with: + name: packaged-${{ inputs.platform }}-${{ inputs.arch }} + path: | + archive.zip + !**/*.map diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index 9c2249ef1d..e89634b361 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -12,6 +12,21 @@ on: 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 permissions: actions: write @@ -29,6 +44,7 @@ env: jobs: before-make: + if: ${{ inputs.desktop_macos || inputs.desktop_windows || inputs.desktop_linux }} runs-on: ubuntu-latest environment: ${{ inputs.build-type }} steps: @@ -58,7 +74,8 @@ jobs: name: desktop-web path: packages/frontend/apps/electron/resources/web-static - make-distribution: + make-distribution-macos: + if: ${{ inputs.desktop_macos }} strategy: fail-fast: false matrix: @@ -71,236 +88,90 @@ jobs: 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 - environment: ${{ inputs.build-type }} - 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 }} - SENTRY_RELEASE: ${{ inputs.app-version }} - MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} - steps: - - uses: actions/checkout@v4 - - 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 - hard-link-nm: false - nmHoistingLimits: workspaces - enableScripts: false + 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 - - name: Build AFFiNE native - uses: ./.github/actions/build-rust - with: - target: ${{ matrix.spec.target }} - package: '@affine/native' - - - 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: Signing By Apple Developer ID - if: ${{ matrix.spec.platform == 'darwin' }} - uses: apple-actions/import-codesign-certs@v5 - with: - p12-file-base64: ${{ secrets.CERTIFICATES_P12 }} - p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }} - - - name: Install additional dependencies on Linux - if: ${{ matrix.spec.platform == 'linux' }} - run: | - df -h - sudo add-apt-repository universe - sudo apt install -y libfuse2 elfutils flatpak flatpak-builder - flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo - flatpak update - # some flatpak deps need git protocol.file.allow - git config --global protocol.file.allow always - # clean up apt cache to save disk space - sudo -E apt-get -y purge azure-cli* zulu* hhvm* llvm* firefox* google* dotnet* aspnetcore* powershell* adoptopenjdk* mysql* php* mongodb* moby* snap* || true - sudo -E apt-get -qq autoremove --purge - sudo rm -rf /usr/share/dotnet /opt/ghc /opt/hostedtoolcache/CodeQL /usr/local/lib/android - sudo apt-get clean - rm -rf ~/.cache/yarn ~/.npm - df -h - - - name: Remove nbstore node_modules - shell: bash - # node_modules of nbstore is not needed for building, and it will make the build process out of memory - run: | - cargo clean - rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite - rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules - - - name: make - run: yarn affine @affine/electron make --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }} - env: - SKIP_WEB_BUILD: 1 - HOIST_NODE_MODULES: 1 - NODE_OPTIONS: --max-old-space-size=14384 - - - 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-${{ env.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-${{ env.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/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.zip - mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.appimage - mv packages/frontend/apps/electron/out/*/make/deb/${{ matrix.spec.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.deb - mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.flatpak - - - uses: actions/attest-build-provenance@v2 - if: ${{ matrix.spec.platform == 'darwin' }} - with: - subject-path: | - ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip - ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg - - - uses: actions/attest-build-provenance@v2 - if: ${{ matrix.spec.platform == 'linux' }} - with: - subject-path: | - ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.zip - ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.appimage - ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.deb - ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.flatpak - - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: affine-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}-builds - path: builds - - package-distribution-windows: - environment: ${{ inputs.build-type }} + make-distribution-linux: + if: ${{ inputs.desktop_linux }} strategy: fail-fast: false matrix: spec: - - runner: windows-latest - platform: win32 + - runner: ubuntu-latest + platform: linux arch: x64 - target: x86_64-pc-windows-msvc - - runner: windows-latest - platform: win32 - arch: arm64 - target: aarch64-pc-windows-msvc - runs-on: ${{ matrix.spec.runner }} + target: x86_64-unknown-linux-gnu needs: before-make - outputs: - FILES_TO_BE_SIGNED_x64: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED_x64 }} - FILES_TO_BE_SIGNED_arm64: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED_arm64 }} - 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 }} - SENTRY_RELEASE: ${{ inputs.app-version }} - MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} - steps: - - uses: actions/checkout@v4 - - 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 - hard-link-nm: false - nmHoistingLimits: workspaces - - name: Build AFFiNE native - uses: ./.github/actions/build-rust - with: - target: ${{ matrix.spec.target }} - package: '@affine/native' - - uses: actions/download-artifact@v4 - with: - name: desktop-web - path: packages/frontend/apps/electron/resources/web-static + 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 - - name: Build Desktop Layers - run: yarn affine @affine/electron build + package-distribution-windows-x64: + if: ${{ inputs.desktop_windows }} + 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: windows-latest + platform: win32 + arch: x64 + target: x86_64-pc-windows-msvc + enable_scripts: true - - name: Remove nbstore node_modules - shell: bash - # node_modules of nbstore is not needed for building, and it will make the build process out of memory - 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 - run: | - yarn affine @affine/electron package --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }} - env: - SKIP_WEB_BUILD: 1 - HOIST_NODE_MODULES: 1 - NODE_OPTIONS: --max-old-space-size=14384 - - - 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_${{ matrix.spec.arch }}=$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 + package-distribution-windows-arm64: + if: ${{ inputs.desktop_windows }} + 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: windows-latest + platform: win32 + arch: arm64 + target: aarch64-pc-windows-msvc + enable_scripts: true sign-packaged-artifacts-windows_x64: - needs: package-distribution-windows + if: ${{ inputs.desktop_windows }} + needs: package-distribution-windows-x64 uses: ./.github/workflows/windows-signer.yml with: - files: ${{ needs.package-distribution-windows.outputs.FILES_TO_BE_SIGNED_x64 }} + files: ${{ needs.package-distribution-windows-x64.outputs.files_to_be_signed }} artifact-name: packaged-win32-x64 sign-packaged-artifacts-windows_arm64: - needs: package-distribution-windows + if: ${{ inputs.desktop_windows }} + needs: package-distribution-windows-arm64 uses: ./.github/workflows/windows-signer.yml with: - files: ${{ needs.package-distribution-windows.outputs.FILES_TO_BE_SIGNED_arm64 }} + files: ${{ needs.package-distribution-windows-arm64.outputs.files_to_be_signed }} artifact-name: packaged-win32-arm64 make-windows-installer: + if: ${{ inputs.desktop_windows }} needs: - sign-packaged-artifacts-windows_x64 - sign-packaged-artifacts-windows_arm64 @@ -362,6 +233,7 @@ jobs: path: archive.zip sign-installer-artifacts-windows-x64: + if: ${{ inputs.desktop_windows }} needs: make-windows-installer uses: ./.github/workflows/windows-signer.yml with: @@ -369,6 +241,7 @@ jobs: artifact-name: installer-win32-x64 sign-installer-artifacts-windows-arm64: + if: ${{ inputs.desktop_windows }} needs: make-windows-installer uses: ./.github/workflows/windows-signer.yml with: @@ -376,6 +249,7 @@ jobs: artifact-name: installer-win32-arm64 finalize-installer-windows: + if: ${{ inputs.desktop_windows }} needs: [ sign-installer-artifacts-windows-x64, @@ -423,7 +297,14 @@ jobs: path: builds release: - needs: [before-make, make-distribution, finalize-installer-windows] + if: ${{ inputs.desktop_macos && inputs.desktop_linux && inputs.desktop_windows }} + needs: + [ + before-make, + make-distribution-macos, + make-distribution-linux, + finalize-installer-windows, + ] runs-on: ubuntu-latest steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1cb2efe3e5..822c50c828 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,8 +11,18 @@ on: required: true type: boolean default: false - desktop: - description: 'Release Desktop?' + desktop_macos: + description: 'Desktop - macOS' + required: true + type: boolean + default: false + desktop_windows: + description: 'Desktop - Windows' + required: true + type: boolean + default: false + desktop_linux: + description: 'Desktop - Linux' required: true type: boolean default: false @@ -166,7 +176,13 @@ jobs: desktop: name: Release Desktop - if: ${{ inputs.desktop || github.event_name != 'workflow_dispatch' && needs.canary-gate.outputs.SHOULD_RELEASE == 'true' }} + if: >- + ${{ + (github.event_name != 'workflow_dispatch' && needs.canary-gate.outputs.SHOULD_RELEASE == 'true') || + inputs.desktop_macos || + inputs.desktop_windows || + inputs.desktop_linux + }} needs: - prepare - canary-gate @@ -176,6 +192,9 @@ jobs: build-type: ${{ needs.prepare.outputs.BUILD_TYPE }} app-version: ${{ needs.prepare.outputs.APP_VERSION }} git-short-hash: ${{ needs.prepare.outputs.GIT_SHORT_HASH }} + desktop_macos: ${{ github.event_name != 'workflow_dispatch' || inputs.desktop_macos }} + desktop_windows: ${{ github.event_name != 'workflow_dispatch' || inputs.desktop_windows }} + desktop_linux: ${{ github.event_name != 'workflow_dispatch' || inputs.desktop_linux }} mobile: name: Release Mobile diff --git a/package.json b/package.json index 16f703a857..8504eb3aa0 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@vitest/coverage-istanbul": "^3.2.4", "@vitest/ui": "^3.2.4", "cross-env": "^10.1.0", - "electron": "^36.0.0", + "electron": "^39.0.0", "eslint": "^9.16.0", "eslint-config-prettier": "^10.0.0", "eslint-import-resolver-typescript": "^4.0.0", diff --git a/packages/common/nbstore/src/impls/cloud/blob.ts b/packages/common/nbstore/src/impls/cloud/blob.ts index 6d9bc0d2a7..53800bbb06 100644 --- a/packages/common/nbstore/src/impls/cloud/blob.ts +++ b/packages/common/nbstore/src/impls/cloud/blob.ts @@ -352,7 +352,8 @@ export class CloudBlobStorage extends BlobStorageBase { : undefined; try { - return await globalThis.fetch(input, { + const resolvedUrl = new URL(input, this.options.serverBaseUrl).toString(); + return await globalThis.fetch(resolvedUrl, { ...init, signal: abortController.signal, }); diff --git a/packages/frontend/apps/electron/package.json b/packages/frontend/apps/electron/package.json index 84a25fb9b3..98193eb63c 100644 --- a/packages/frontend/apps/electron/package.json +++ b/packages/frontend/apps/electron/package.json @@ -59,7 +59,7 @@ "builder-util-runtime": "^9.5.0", "cross-env": "^10.1.0", "debug": "^4.4.0", - "electron": "^36.0.0", + "electron": "^39.0.0", "electron-log": "^5.4.3", "electron-squirrel-startup": "1.0.1", "electron-window-state": "^5.0.3", diff --git a/packages/frontend/apps/electron/src/main/index.ts b/packages/frontend/apps/electron/src/main/index.ts index 455ef968a8..a6992bdf44 100644 --- a/packages/frontend/apps/electron/src/main/index.ts +++ b/packages/frontend/apps/electron/src/main/index.ts @@ -4,7 +4,7 @@ import path from 'node:path'; import * as Sentry from '@sentry/electron/main'; import { IPCMode } from '@sentry/electron/main'; -import { app } from 'electron'; +import { app, protocol } from 'electron'; import { createApplicationMenu } from './application-menu/create'; import { buildType, isDev, overrideSession } from './config'; @@ -22,26 +22,40 @@ import { launchStage } from './windows-manager/stage'; app.enableSandbox(); -app.commandLine.appendSwitch('enable-features', 'CSSTextAutoSpace'); if (isDev) { // In electron the dev server will be resolved to 0.0.0.0, but it // might be blocked by electron. // See https://github.com/webpack/webpack-dev-server/pull/384 - app.commandLine.appendSwitch('host-rules', 'MAP 0.0.0.0 127.0.0.1'); + app.commandLine.appendSwitch('host-resolver-rules', 'MAP 0.0.0.0 127.0.0.1'); } // https://github.com/electron/electron/issues/43556 // // `CalculateNativeWinOcclusion` - Disable native window occlusion tracker (https://groups.google.com/a/chromium.org/g/embedder-dev/c/ZF3uHHyWLKw/m/VDN2hDXMAAAJ) -app.commandLine.appendSwitch( - 'disable-features', - 'PlzDedicatedWorker,CalculateNativeWinOcclusion' -); +const disabledFeatures = [ + 'PlzDedicatedWorker', + 'CalculateNativeWinOcclusion', + // Disable Chrome autofill and password save prompts + 'AutofillServerCommunication', + 'AutofillProfileCleanup', + 'AutofillAddressProfileSavePrompt', + 'AutofillPaymentCards', + 'AutofillEnableAccountWalletStorage', + 'SavePasswordBubble', +].join(','); +app.commandLine.appendSwitch('disable-features', disabledFeatures); +app.commandLine.appendSwitch('disable-blink-features', 'Autofill'); // Following features are enabled from the runtime: // `DocumentPolicyIncludeJSCallStacksInCrashReports` - https://www.electronjs.org/docs/latest/api/web-frame-main#framecollectjavascriptcallstack-experimental // `EarlyEstablishGpuChannel` - Refs https://issues.chromium.org/issues/40208065 // `EstablishGpuChannelAsync` - Refs https://issues.chromium.org/issues/40208065 -const featuresToEnable = `DocumentPolicyIncludeJSCallStacksInCrashReports,EarlyEstablishGpuChannel,EstablishGpuChannelAsync`; -app.commandLine.appendSwitch('enable-features', featuresToEnable); +const enabledFeatures = [ + 'DocumentPolicyIncludeJSCallStacksInCrashReports', + 'EarlyEstablishGpuChannel', + 'EstablishGpuChannelAsync', +].join(','); +app.commandLine.appendSwitch('enable-features', enabledFeatures); +const enabledBlinkFeatures = ['CSSTextAutoSpace', 'WebCodecs'].join(','); +app.commandLine.appendSwitch('enable-blink-features', enabledBlinkFeatures); app.commandLine.appendSwitch('force-color-profile', 'srgb'); // use the same data for internal & beta for testing @@ -123,3 +137,16 @@ if (process.env.SENTRY_RELEASE) { appVersion: app.getVersion(), }); } + +protocol.registerSchemesAsPrivileged([ + { + scheme: 'assets', + privileges: { + secure: true, + corsEnabled: true, + supportFetchAPI: true, + standard: true, + stream: true, + }, + }, +]); diff --git a/packages/frontend/apps/electron/src/main/protocol.ts b/packages/frontend/apps/electron/src/main/protocol.ts index f2952c4869..1f5e1ae1c2 100644 --- a/packages/frontend/apps/electron/src/main/protocol.ts +++ b/packages/frontend/apps/electron/src/main/protocol.ts @@ -5,24 +5,12 @@ import { app, net, protocol, session } from 'electron'; import cookieParser from 'set-cookie-parser'; import { isWindows, resourcesPath } from '../shared/utils'; -import { isDev } from './config'; +import { buildType, isDev } from './config'; import { anotherHost, mainHost } from './constants'; import { logger } from './logger'; -protocol.registerSchemesAsPrivileged([ - { - scheme: 'assets', - privileges: { - secure: true, - corsEnabled: true, - supportFetchAPI: true, - standard: true, - stream: true, - }, - }, -]); - const webStaticDir = join(resourcesPath, 'web-static'); +const devServerBase = process.env.DEV_SERVER_URL; const localWhiteListDirs = [ path.resolve(app.getPath('sessionData')).toLowerCase(), path.resolve(app.getPath('temp')).toLowerCase(), @@ -35,6 +23,41 @@ function isPathInWhiteList(filepath: string) { ); } +const apiBaseByBuildType: Record = { + stable: 'https://app.affine.pro', + beta: 'https://insider.affine.pro', + internal: 'https://insider.affine.pro', + canary: 'https://affine.fail', +}; + +function resolveApiBaseUrl() { + if (isDev && devServerBase) { + return devServerBase; + } + + return apiBaseByBuildType[buildType] ?? apiBaseByBuildType.stable; +} + +function buildTargetUrl(base: string, urlObject: URL) { + return new URL(`${urlObject.pathname}${urlObject.search}`, base).toString(); +} + +function proxyRequest( + request: Request, + urlObject: URL, + base: string, + options: { bypassCustomProtocolHandlers?: boolean } = {} +) { + const { bypassCustomProtocolHandlers = true } = options; + const targetUrl = buildTargetUrl(base, urlObject); + const proxiedRequest = bypassCustomProtocolHandlers + ? Object.assign(request.clone(), { + bypassCustomProtocolHandlers: true, + }) + : request; + return net.fetch(targetUrl, proxiedRequest); +} + async function handleFileRequest(request: Request) { const urlObject = new URL(request.url); @@ -43,22 +66,24 @@ async function handleFileRequest(request: Request) { } const isAbsolutePath = urlObject.host !== '.'; + const isApiRequest = + !isAbsolutePath && + (urlObject.pathname.startsWith('/api/') || + urlObject.pathname === '/graphql'); + + if (isApiRequest) { + return proxyRequest(request, urlObject, resolveApiBaseUrl()); + } + const isFontRequest = urlObject.pathname && /\.(woff2?|ttf|otf)$/i.test(urlObject.pathname.split('?')[0] ?? ''); // Redirect to webpack dev server if available - if ( - isDev && - process.env.DEV_SERVER_URL && - !isAbsolutePath && - !isFontRequest - ) { - const devServerUrl = new URL( - `${urlObject.pathname}${urlObject.search}`, - process.env.DEV_SERVER_URL - ); - return net.fetch(devServerUrl.toString(), request); + if (isDev && devServerBase && !isAbsolutePath && !isFontRequest) { + return proxyRequest(request, urlObject, devServerBase, { + bypassCustomProtocolHandlers: false, + }); } const clonedRequest = Object.assign(request.clone(), { bypassCustomProtocolHandlers: true, diff --git a/yarn.lock b/yarn.lock index ad328b9dc0..dd2b9644cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -583,7 +583,7 @@ __metadata: builder-util-runtime: "npm:^9.5.0" cross-env: "npm:^10.1.0" debug: "npm:^4.4.0" - electron: "npm:^36.0.0" + electron: "npm:^39.0.0" electron-log: "npm:^5.4.3" electron-squirrel-startup: "npm:1.0.1" electron-updater: "npm:^6.6.2" @@ -786,7 +786,7 @@ __metadata: "@vitest/coverage-istanbul": "npm:^3.2.4" "@vitest/ui": "npm:^3.2.4" cross-env: "npm:^10.1.0" - electron: "npm:^36.0.0" + electron: "npm:^39.0.0" eslint: "npm:^9.16.0" eslint-config-prettier: "npm:^10.0.0" eslint-import-resolver-typescript: "npm:^4.0.0" @@ -22392,16 +22392,16 @@ __metadata: languageName: node linkType: hard -"electron@npm:^36.0.0": - version: 36.9.5 - resolution: "electron@npm:36.9.5" +"electron@npm:^39.0.0": + version: 39.2.7 + resolution: "electron@npm:39.2.7" dependencies: "@electron/get": "npm:^2.0.0" "@types/node": "npm:^22.7.7" extract-zip: "npm:^2.0.1" bin: electron: cli.js - checksum: 10/2c78ce37b6cdcf2388dc3f3932f2104f7bd529c51ee8d00e0201ce86089966309c0ba62c2045abc4dad81893ebe7f7070bb047dcb9c05366f31ddd7fb73790ca + checksum: 10/a76dd5ee2568e533bd32e653f36795de6732b2a2a36d8af01b3a9105f5da47a8af18b7688454aa210ff03415dfba736a55acc191ef71887be1edceb536822b8f languageName: node linkType: hard