# This is the main desktop application release workflow for both nightly and beta/stable releases. name: Build-Desktop-Release on: workflow_dispatch: inputs: build-target: description: 'Build Target (Release Type)' type: choice required: true options: - beta - nightly - non-release default: "non-release" git-ref: description: "Release Git Ref (Which branch or tag to build?)" required: true default: "master" is-draft: description: 'Draft Release? (Beta only, Nightly will always be a non-draft)' type: boolean required: true default: true is-pre-release: description: 'Pre Release? (labeled as "PreRelease")' type: boolean required: true default: true enable-file-sync-production: description: 'File sync production mode' type: boolean required: true default: true enable-plugins: description: 'Build with plugin system support' type: boolean required: true default: true build-android: description: 'Build Android App' type: boolean required: true default: true # schedule: # Every workday at the 2 P.M. (UTC) we run a scheduled nightly build # - cron: '0 14 * * MON-FRI' env: CLOJURE_VERSION: '1.12.4.1618' NODE_VERSION: '24' JAVA_VERSION: '21' jobs: compile-cljs: runs-on: ubuntu-22.04 steps: - name: Check build options if: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.build-target == 'nightly' || github.event.inputs.build-target == 'beta') && github.event.inputs.git-ref != 'master' }} run: | echo "::error title=CheckFail::Nightly and Beta Release MUST be built from master" exit 1 - name: Check out Git repository uses: actions/checkout@v4 with: ref: ${{ github.event.inputs.git-ref }} - name: Install Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Set up pnpm uses: pnpm/action-setup@v4 with: version: 10.33.0 - name: Get pnpm store directory path id: pnpm-store-dir-path run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT - name: Cache pnpm store directory uses: actions/cache@v4 id: pnpm-cache with: path: ${{ steps.pnpm-store-dir-path.outputs.dir }} key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm- - name: Setup Java JDK uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Cache clojure deps uses: actions/cache@v4 with: path: | ~/.m2/repository ~/.gitlibs key: ${{ runner.os }}-clojure-lib-${{ hashFiles('**/deps.edn') }} - name: Setup clojure uses: DeLaGuardo/setup-clojure@13.5 with: cli: ${{ env.CLOJURE_VERSION }} - name: Retrieve tag version id: ref run: | pkgver=$(node ./scripts/get-pkg-version.js "${{ github.event.inputs.build-target }}") echo "version=$pkgver" >> $GITHUB_OUTPUT - name: Do Not Overwrite Existing Release if: ${{ github.event.inputs.build-target == 'beta' }} run: | if curl -f "https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ steps.ref.outputs.version }}" &>/dev/null; then echo "::error title=CheckFail::Release already exists" exit 1 fi - name: Update Nightly APP Version if: ${{ github.event.inputs.build-target == 'nightly' || github.event_name == 'schedule' }} run: | sed -i 's/defonce version ".*"/defonce version "${{ steps.ref.outputs.version }}"/g' src/main/frontend/version.cljs - name: Set Build Environment Variables (only when workflow_dispatch) if: ${{ github.event_name == 'workflow_dispatch' }} # if scheduled, use default settings run: | echo "ENABLE_PLUGINS=${{ github.event_name == 'schedule' || github.event.inputs.enable-plugins == 'true' }}" >> $GITHUB_ENV echo "ENABLE_FILE_SYNC_PRODUCTION=${{ github.event_name == 'schedule' || github.event.inputs.enable-file-sync-production == 'true' }}" >> $GITHUB_ENV - name: Compile CLJS run: pnpm install --frozen-lockfile && gulp build && pnpm cljs:release-electron && pnpm db-worker-node:bundle && pnpm webpack-app-build && pnpm desktop:prepare-runtime-js env: LOGSEQ_SENTRY_DSN: ${{ secrets.LOGSEQ_SENTRY_DSN }} LOGSEQ_POSTHOG_TOKEN: ${{ secrets.LOGSEQ_POSTHOG_TOKEN }} - name: Verify bundled db-worker-node runtime run: | test -f ./dist/db-worker-node.js test -f ./dist/db-worker-node-assets.json - name: Verify bundled CLI run: | test -f ./static/js/logseq-cli.js node ./static/js/logseq-cli.js --help >/tmp/logseq-cli-help.txt grep -E "USAGE|Usage|COMMANDS|Commands" /tmp/logseq-cli-help.txt >/dev/null - name: Verify desktop runtime script locations run: | test -f ./static/js/db-worker-node.js test -f ./static/js/logseq-cli.js test -f ./static/.agents/skills/logseq-cli/SKILL.md - name: Update APP Version run: | sed -i 's/"version": "0.0.1"/"version": "${{ steps.ref.outputs.version }}"/g' ./package.json working-directory: ./static - name: Display Package.json run: cat ./package.json working-directory: ./static - name: Save VERSION file run: echo "${{ steps.ref.outputs.version }}" > ./VERSION working-directory: ./static - name: List Files run: ls -al working-directory: ./static - name: Upload Sentry Sourcemaps (beta only) # if: ${{ github.repository == 'logseq/logseq' && github.event_name == 'workflow_dispatch' && github.event.inputs.build-target == 'beta' }} run: | curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION=2.58.4 bash release_name="logseq@${{ steps.ref.outputs.version }}" sentry-cli releases new "${release_name}" sentry-cli releases files "${release_name}" upload-sourcemaps --ext map --ext js ./static/js --url-prefix '~/static/js' sentry-cli releases finalize "${release_name}" env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_ORG: logseq SENTRY_PROJECT: logseq - name: Cache Static File uses: actions/upload-artifact@v4 with: name: static path: static include-hidden-files: true build-linux-x64: runs-on: ubuntu-22.04 needs: [ compile-cljs ] steps: - name: Download The Static Asset uses: actions/download-artifact@v4 with: name: static path: static - name: Retrieve tag version id: ref run: | pkgver=$(cat ./static/VERSION) echo "version=$pkgver" >> $GITHUB_OUTPUT - name: Install Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Set up pnpm uses: pnpm/action-setup@v4 with: version: 10.33.0 # - name: Cache Node Modules # uses: actions/cache@v4 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Build/Release Electron App run: pnpm install --frozen-lockfile && pnpm electron:make working-directory: ./static - name: Save artifacts run: | mkdir -p builds # NOTE: save VERSION file to builds directory cp static/VERSION ./builds/VERSION mv static/dist/*.AppImage ./builds/ shopt -s nullglob blockmaps=(static/dist/*.blockmap) if [ ${#blockmaps[@]} -gt 0 ]; then mv static/dist/*.blockmap ./builds/ fi mv static/dist/latest-linux.yml ./builds/latest-linux.yml mv static/dist/*.zip ./builds/Logseq-linux-x86_64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: logseq-linux-x64-builds path: builds build-linux-arm64: runs-on: ubuntu-22.04 needs: [ compile-cljs ] steps: - name: Download The Static Asset uses: actions/download-artifact@v4 with: name: static path: static - name: Retrieve tag version id: ref run: | pkgver=$(cat ./static/VERSION) echo "version=$pkgver" >> $GITHUB_OUTPUT - name: Install Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Set up pnpm uses: pnpm/action-setup@v4 with: version: 10.33.0 - name: Fetch deps env: npm_config_arch: arm64 npm_config_target_platform: linux run: | pnpm install --frozen-lockfile working-directory: ./static - name: Build/Release Electron App run: pnpm electron:make-linux-arm64 working-directory: ./static - name: Save artifacts run: | mkdir -p builds # NOTE: save VERSION file to builds directory cp static/VERSION ./builds/VERSION mv static/dist/*.AppImage ./builds/Logseq-linux-arm64-${{ steps.ref.outputs.version }}.AppImage shopt -s nullglob blockmaps=(static/dist/*.blockmap) if [ ${#blockmaps[@]} -gt 0 ]; then mv static/dist/*.blockmap ./builds/ fi mv static/dist/latest-linux-arm64.yml ./builds/latest-linux-arm64.yml mv static/dist/*.zip ./builds/Logseq-linux-arm64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: logseq-linux-arm64-builds path: builds build-windows-x64: runs-on: windows-latest needs: [ compile-cljs ] steps: - name: Download The Static Asset uses: actions/download-artifact@v4 with: name: static path: static - name: Retrieve tag version id: ref run: echo "version=$(cat ./static/VERSION)" >> $env:GITHUB_OUTPUT - name: Install Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Set up pnpm uses: pnpm/action-setup@v4 with: version: 10.33.0 # - name: Cache Node Modules # uses: actions/cache@v4 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Deps Electron app run: pnpm install --frozen-lockfile working-directory: ./static - name: Build/Release Electron app shell: pwsh run: | $signCfg = @' { "extends": "./electron-builder.yml", "win": { "azureSignOptions": { "publisherName": "Logseq, Inc.", "endpoint": "https://eus.codesigning.azure.net/", "certificateProfileName": "Logseq", "codeSigningAccountName": "logseqwin" } } } '@ $signCfgPath = Join-Path $PWD "electron-builder.sign-win.json" $signCfg | Out-File -FilePath $signCfgPath -Encoding utf8NoBOM pnpm exec electron-builder --config $signCfgPath --publish never working-directory: ./static env: AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} - name: Save Artifact run: | mkdir builds mv static\dist\*-nsis.exe builds\Logseq-win-x64-${{ steps.ref.outputs.version }}-nsis.exe mv static\dist\*.blockmap builds\ mv static\dist\latest.yml builds\latest-x64.yml mv static\dist\*.zip builds\Logseq-win-x64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: logseq-win-x64-builds path: builds build-windows-arm64: runs-on: windows-latest needs: [ compile-cljs ] steps: - name: Download The Static Asset uses: actions/download-artifact@v4 with: name: static path: static - name: Retrieve tag version id: ref run: echo "version=$(cat ./static/VERSION)" >> $env:GITHUB_OUTPUT - name: Install Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Set up pnpm uses: pnpm/action-setup@v4 with: version: 10.33.0 # - name: Cache Node Modules # uses: actions/cache@v4 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Deps Electron app run: pnpm install --frozen-lockfile working-directory: ./static - name: Build/Release Electron app shell: pwsh run: | $signCfg = @' { "extends": "./electron-builder.yml", "win": { "azureSignOptions": { "publisherName": "Logseq, Inc.", "endpoint": "https://eus.codesigning.azure.net/", "certificateProfileName": "Logseq", "codeSigningAccountName": "logseqwin" } } } '@ $signCfgPath = Join-Path $PWD "electron-builder.sign-win.json" $signCfg | Out-File -FilePath $signCfgPath -Encoding utf8NoBOM pnpm exec electron-builder --config $signCfgPath --win nsis zip --arm64 --publish never working-directory: ./static env: AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} - name: Save Artifact run: | mkdir builds mv static\dist\*-nsis.exe builds\Logseq-win-arm64-${{ steps.ref.outputs.version }}-nsis.exe mv static\dist\*.blockmap builds\ mv static\dist\latest.yml builds\latest-arm64.yml mv static\dist\*.zip builds\Logseq-win-arm64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: logseq-win-arm64-builds path: builds build-macos-x64: needs: [ compile-cljs ] runs-on: macos-15-intel steps: - name: Download The Static Asset uses: actions/download-artifact@v4 with: name: static path: static - name: Retrieve tag version id: ref run: | pkgver=$(cat ./static/VERSION) echo "version=$pkgver" >> $GITHUB_OUTPUT - name: List Static Files run: ls -al ./static - name: Install Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Set up pnpm uses: pnpm/action-setup@v4 with: version: 10.33.0 - name: Install Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Get pnpm store directory path id: pnpm-store-dir-path run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT - name: Cache pnpm store directory uses: actions/cache@v4 id: pnpm-cache with: path: ${{ steps.pnpm-store-dir-path.outputs.dir }} key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm- - name: Signing By Apple Developer ID if: ${{ github.repository == 'logseq/logseq' }} uses: apple-actions/import-codesign-certs@v1 with: p12-file-base64: ${{ secrets.APPLE_CERTIFICATES_P12 }} p12-password: ${{ secrets.APPLE_CERTIFICATES_P12_PASSWORD }} # - name: Cache Node Modules # uses: actions/cache@v4 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Build/Release Electron App for x64 run: pnpm install --frozen-lockfile && pnpm rebuild:all && pnpm electron:make working-directory: ./static env: APPLE_ID: ${{ secrets.APPLE_ID_EMAIL }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - name: Save x64 artifacts run: | mkdir -p builds cp static/VERSION ./builds/VERSION mv static/dist/*.dmg ./builds/Logseq-darwin-x64-${{ steps.ref.outputs.version }}.dmg mv static/dist/*.zip ./builds/Logseq-darwin-x64-${{ steps.ref.outputs.version }}.zip mv static/dist/*.blockmap ./builds/ mv static/dist/latest-mac.yml ./builds/latest-x64-mac.yml - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: logseq-darwin-x64-builds path: builds build-macos-arm64: needs: [ compile-cljs ] runs-on: macos-14 steps: - name: Download The Static Asset uses: actions/download-artifact@v4 with: name: static path: static - name: Retrieve tag version id: ref run: | pkgver=$(cat ./static/VERSION) echo "version=$pkgver" >> $GITHUB_OUTPUT - name: Install Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Set up pnpm uses: pnpm/action-setup@v4 with: version: 10.33.0 - name: Get pnpm store directory path id: pnpm-store-dir-path run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT - name: Cache pnpm store directory uses: actions/cache@v4 id: pnpm-cache with: path: ${{ steps.pnpm-store-dir-path.outputs.dir }} key: ${{ runner.os }}-arm64-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-arm64-pnpm- - name: Install Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Signing By Apple Developer ID if: ${{ github.repository == 'logseq/logseq' }} uses: apple-actions/import-codesign-certs@v1 with: p12-file-base64: ${{ secrets.APPLE_CERTIFICATES_P12 }} p12-password: ${{ secrets.APPLE_CERTIFICATES_P12_PASSWORD }} # - name: Cache Node Modules # uses: actions/cache@v4 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Fetch deps run: pnpm install --frozen-lockfile --config.supportedArchitectures.os=darwin --config.supportedArchitectures.cpu=arm64 && pnpm rebuild:all working-directory: ./static - name: Build/Release Electron App for arm64 run: pnpm electron:make-macos-arm64 working-directory: ./static env: APPLE_ID: ${{ secrets.APPLE_ID_EMAIL }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - name: Save arm64 artifacts run: | mkdir -p builds cp static/VERSION ./builds/VERSION mv static/dist/*.dmg ./builds/Logseq-darwin-arm64-${{ steps.ref.outputs.version }}.dmg mv static/dist/*.zip ./builds/Logseq-darwin-arm64-${{ steps.ref.outputs.version }}.zip mv static/dist/*.blockmap ./builds/ mv static/dist/latest-mac.yml ./builds/latest-arm64-mac.yml - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: logseq-darwin-arm64-builds path: builds # reuse workflow via workflow_call build-android: uses: ./.github/workflows/build-android.yml if: ${{ github.event_name == 'schedule' || github.event.inputs.build-android == 'true' }} with: build-target: "${{ github.event.inputs.build-target }}" # if scheduled, use production mode enable-file-sync-production: "${{ github.event_name == 'schedule' || github.event.inputs.enable-file-sync-production == 'true' }}" secrets: ANDROID_KEYSTORE: "${{ secrets.ANDROID_KEYSTORE }}" ANDROID_KEYSTORE_PASSWORD: "${{ secrets.ANDROID_KEYSTORE_PASSWORD }}" SENTRY_AUTH_TOKEN: "${{ secrets.SENTRY_AUTH_TOKEN }}" nightly-release: if: ${{ github.event_name == 'schedule' || github.event.inputs.build-target == 'nightly' }} needs: [ build-macos-x64, build-macos-arm64, build-linux-x64, build-linux-arm64, build-windows-x64, build-windows-arm64 ] runs-on: ubuntu-22.04 steps: - name: Download MacOS x64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-darwin-x64-builds path: ./ - name: Download MacOS arm64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-darwin-arm64-builds path: ./ - name: Download The Linux x64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-linux-x64-builds path: ./ - name: Download The Linux arm64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-linux-arm64-builds path: ./ - name: Download The Windows Artifact x64 uses: actions/download-artifact@v4 with: name: logseq-win-x64-builds path: ./ - name: Download The Windows Artifact arm64 uses: actions/download-artifact@v4 with: name: logseq-win-arm64-builds path: ./ - name: Download Android Artifacts uses: actions/download-artifact@v4 with: name: logseq-android-builds path: ./ - name: Generate SHA256 checksums run: | sha256sum *-darwin-* > SHA256SUMS.txt sha256sum *-win-* >> SHA256SUMS.txt sha256sum *-linux-* >> SHA256SUMS.txt sha256sum *.apk >> SHA256SUMS.txt cat SHA256SUMS.txt - name: List files run: ls -rl - name: Update Nightly Release uses: andelf/nightly-release@main env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: nightly name: 'Desktop app Nightly Release $$' draft: false prerelease: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.is-pre-release) || (github.event_name == 'schedule')}} body: | This is a nightly release of the Logseq desktop app. It's unstable compared to the official releases, **use it with caution**! files: | ./SHA256SUMS.txt ./*.zip ./*.dmg ./*.exe ./*.yml ./*.blockmap ./*.AppImage ./*.apk release: # NOTE: For now, we only have beta channel to be released on GitHub if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.build-target == 'beta' }} needs: [ build-macos-x64, build-macos-arm64, build-linux-x64, build-linux-arm64, build-windows-x64, build-windows-arm64 ] runs-on: ubuntu-22.04 steps: - name: Download MacOS x64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-darwin-x64-builds path: ./ - name: Download MacOS arm64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-darwin-arm64-builds path: ./ - name: Download The Linux x64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-linux-x64-builds path: ./ - name: Download The Linux arm64 Artifacts uses: actions/download-artifact@v4 with: name: logseq-linux-arm64-builds path: ./ - name: Download The Windows Artifact uses: actions/download-artifact@v4 with: name: logseq-win-x64-builds path: ./ - name: Download The Windows Artifact uses: actions/download-artifact@v4 with: name: logseq-win-arm64-builds path: ./ - name: Download Android Artifacts uses: actions/download-artifact@v4 if: ${{ github.event_name == 'schedule' || github.event.inputs.build-android == 'true' }} with: name: logseq-android-builds path: ./ - name: List files run: ls -rl - name: Retrieve tag version id: ref run: | pkgver=$(cat VERSION) echo "version=$pkgver" >> $GITHUB_OUTPUT - name: Generate SHA256 checksums run: | sha256sum *-darwin-* > SHA256SUMS.txt sha256sum *-win-* >> SHA256SUMS.txt sha256sum *-linux-* >> SHA256SUMS.txt sha256sum *.apk >> SHA256SUMS.txt cat SHA256SUMS.txt - name: Create Release Draft uses: softprops/action-gh-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ steps.ref.outputs.version }} name: Desktop APP ${{ steps.ref.outputs.version }} (Beta Testing) body: "TODO: Fill this changelog. Sorry for the inconvenience!" draft: ${{ github.event.inputs.is-draft }} prerelease: ${{ github.event.inputs.is-pre-release }} files: | ./VERSION ./SHA256SUMS.txt ./*.zip ./*.dmg ./*.exe ./*.yml ./*.blockmap ./*.AppImage ./*.apk