# 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.11.1.1413' NODE_VERSION: '18' JAVA_VERSION: '11' jobs: compile-cljs: runs-on: ubuntu-20.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@v3 with: ref: ${{ github.event.inputs.git-ref }} - name: Install Node.js, NPM and Yarn uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT - name: Cache yarn cache directory uses: actions/cache@v3 id: yarn-cache with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - name: Setup Java JDK uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - name: Cache clojure deps uses: actions/cache@v3 with: path: | ~/.m2/repository ~/.gitlibs key: ${{ runner.os }}-clojure-lib-${{ hashFiles('**/deps.edn') }} - name: Setup clojure uses: DeLaGuardo/setup-clojure@10.1 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: yarn install && gulp build && yarn cljs:release-electron env: LOGSEQ_SENTRY_DSN: ${{ secrets.LOGSEQ_SENTRY_DSN }} LOGSEQ_POSTHOG_TOKEN: ${{ secrets.LOGSEQ_POSTHOG_TOKEN }} - 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/ | 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@v3 with: name: static path: static e2e-test: name: E2E Test Shard ${{ matrix.shard }} runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3] needs: [ compile-cljs ] steps: - name: Checkout uses: actions/checkout@v3 - name: Download The Static Asset uses: actions/download-artifact@v3 with: name: static path: static - name: Set up Node uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} cache: 'yarn' cache-dependency-path: | yarn.lock static/yarn.lock - name: Fetch yarn deps for E2E test run: | yarn install (cd static && yarn install && yarn rebuild:all) env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true - name: Install Fluxbox run: sudo apt-get update && sudo apt-get install -y fluxbox # Emulate a virtual framebuffer on machines with no display hardware - name: Run XVFB run: Xvfb :1 -screen 0 1024x768x24 >/dev/null 2>&1 & # Start a lightweight window manager to simulate window actions (maximize,restore etc) - name: Start Fluxbox run: DISPLAY=:1.0 fluxbox >/dev/null 2>&1 & - name: Run Playwright test run: DISPLAY=:1.0 npx playwright test --reporter github --shard=${{ matrix.shard }}/3 env: LOGSEQ_CI: true DEBUG: "pw:api" RELEASE: true # skip dev only test build-linux-x64: runs-on: ubuntu-20.04 needs: [ compile-cljs ] steps: - name: Download The Static Asset uses: actions/download-artifact@v3 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, NPM and Yarn uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} # - name: Cache Node Modules # uses: actions/cache@v3 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Build/Release Electron App run: yarn install && yarn 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/out/make/*-*.AppImage ./builds/Logseq-linux-x64-${{ steps.ref.outputs.version }}.AppImage mv static/out/make/zip/linux/x64/*-linux-x64-*.zip ./builds/Logseq-linux-x64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: logseq-linux-x64-builds path: builds build-linux-arm64: runs-on: ubuntu-20.04 needs: [ compile-cljs ] steps: - name: Download The Static Asset uses: actions/download-artifact@v3 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, NPM and Yarn uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} - name: Fetch deps env: npm_config_arch: arm64 run: | yarn install --target_arch=arm64 --target_platform=linux rsapi_version=`node -e 'console.log(require("@logseq/rsapi/package.json").optionalDependencies["@logseq/rsapi-linux-arm64-gnu"])'` temp_dir=`mktemp -d` cd "$temp_dir" echo '{"dependencies": {"@logseq/rsapi-linux-arm64-gnu": "'"$rsapi_version"'"}}' > package.json yarn install --ignore-platform cd - mv "$temp_dir/node_modules/@logseq/rsapi-linux-arm64-gnu" node_modules/@logseq/rsapi-linux-arm64-gnu rm -rf "$temp_dir" "node_modules/@logseq/rsapi-linux-x64-gnu" working-directory: ./static - name: Build/Release Electron App run: yarn 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/out/make/*-*.AppImage ./builds/Logseq-linux-arm64-${{ steps.ref.outputs.version }}.AppImage mv static/out/make/zip/linux/arm64/*-linux-arm64-*.zip ./builds/Logseq-linux-arm64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: logseq-linux-arm64-builds path: builds build-windows: runs-on: windows-latest needs: [ compile-cljs ] steps: - name: Download The Static Asset uses: actions/download-artifact@v3 with: name: static path: static - name: Retrieve tag version id: ref run: echo "version=$(cat ./static/VERSION)" >> $env:GITHUB_OUTPUT - name: Install Node.js, NPM and Yarn uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} # - name: Cache Node Modules # uses: actions/cache@v3 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Deps Electron app run: yarn install working-directory: ./static - name: Fix Deps Electron app run: yarn run postinstall working-directory: ./static/node_modules/dugite/ - name: Build/Release Electron app run: yarn electron:make working-directory: ./static #env: # CODE_SIGN_CERTIFICATE_FILE: ../codesign.pfx # CODE_SIGN_CERTIFICATE_PASSWORD: ${{ secrets.CODE_SIGN_CERTIFICATE_PASSWORD }} - name: Save Artifact for Code Signing run: | mkdir builds mv static\out\make\squirrel.windows\x64\*.exe builds\Logseq-win-x64-${{ steps.ref.outputs.version }}.exe - name: Upload Artifact for Code Signing uses: actions/upload-artifact@v3 with: name: logseq-win64-unsigned-builds path: builds - name: Save Artifact run: | rm builds\*.exe mv static\out\make\squirrel.windows\x64\*.nupkg builds\Logseq-win-x64-${{ steps.ref.outputs.version }}-full.nupkg mv static\out\make\zip\win32\x64\*.zip builds\Logseq-win-x64-${{ steps.ref.outputs.version }}.zip mv static\out\make\wix\x64\Logseq.msi builds\Logseq-win-x64-${{ steps.ref.outputs.version }}.msi mv static\out\make\squirrel.windows\x64\RELEASES builds\RELEASES - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: logseq-win64-builds path: builds build-macos-x64: needs: [ compile-cljs ] runs-on: macos-11 steps: - name: Download The Static Asset uses: actions/download-artifact@v3 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, NPM and Yarn uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} - name: Install Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT - name: Cache yarn cache directory uses: actions/cache@v3 id: yarn-cache with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - 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@v3 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Build/Release Electron App for x64 run: yarn install && yarn electron:make working-directory: ./static env: APPLE_ID: ${{ secrets.APPLE_ID_EMAIL }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - name: Save x64 artifacts run: | mkdir -p builds mv static/out/make/Logseq.dmg ./builds/Logseq-darwin-x64-${{ steps.ref.outputs.version }}.dmg mv static/out/make/zip/darwin/x64/*.zip ./builds/Logseq-darwin-x64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: logseq-darwin-x64-builds path: builds build-macos-arm64: needs: [ compile-cljs ] runs-on: macos-11 steps: - name: Download The Static Asset uses: actions/download-artifact@v3 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, NPM and Yarn uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT - name: Cache yarn cache directory uses: actions/cache@v3 id: yarn-cache with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} key: ${{ runner.os }}-arm64-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-arm64-yarn- - 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@v3 # with: # path: | # **/node_modules # key: ${{ runner.os }}-node-modules - name: Fetch deps and fix dugit arch for arm64 run: yarn install --ignore-platform && cd node_modules/dugite && npm_config_arch=arm64 node script/download-git.js working-directory: ./static - name: Build/Release Electron App for arm64 run: yarn electron:make-macos-arm64 working-directory: ./static env: APPLE_ID: ${{ secrets.APPLE_ID_EMAIL }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - name: Save arm64 artifacts run: | mkdir -p builds mv static/out/make/Logseq.dmg ./builds/Logseq-darwin-arm64-${{ steps.ref.outputs.version }}.dmg mv static/out/make/zip/darwin/arm64/*.zip ./builds/Logseq-darwin-arm64-${{ steps.ref.outputs.version }}.zip - name: Upload Artifact uses: actions/upload-artifact@v3 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 }}" codesign-windows: if: ${{ github.event_name == 'schedule' || github.event.inputs.build-target == 'nightly' || github.event.inputs.build-target == 'beta' }} needs: [ build-windows ] runs-on: [self-hosted, macos, token] steps: - name: Download Windows Artifact uses: actions/download-artifact@v3 with: name: logseq-win64-unsigned-builds path: ./builds - name: Sign Windows Executable run: | ls -lah ./builds jsign --storetype ETOKEN --storepass "${PASS}" -t http://timestamp.digicert.com ./builds/*.exe env: PASS: ${{ secrets.CODE_SIGN_CERTIFICATE_PASSWORD }} - name: Upload Artifact uses: actions/upload-artifact@v3 with: name: logseq-win64-signed-builds path: builds 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, codesign-windows, build-android, e2e-test ] runs-on: ubuntu-20.04 steps: - name: Download MacOS x64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-darwin-x64-builds path: ./ - name: Download MacOS arm64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-darwin-arm64-builds path: ./ - name: Download The Linux x64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-linux-x64-builds path: ./ - name: Download The Linux arm64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-linux-arm64-builds path: ./ - name: Download The Windows Artifact (Signed) uses: actions/download-artifact@v3 with: name: logseq-win64-signed-builds path: ./ - name: Download The Windows Artifact uses: actions/download-artifact@v3 with: name: logseq-win64-builds path: ./ - name: Download Android Artifacts uses: actions/download-artifact@v3 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/Android 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 ./*.msi ./*.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, codesign-windows, build-android, e2e-test ] runs-on: ubuntu-20.04 steps: - name: Download MacOS x64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-darwin-x64-builds path: ./ - name: Download MacOS arm64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-darwin-arm64-builds path: ./ - name: Download The Linux x64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-linux-x64-builds path: ./ - name: Download The Linux arm64 Artifacts uses: actions/download-artifact@v3 with: name: logseq-linux-arm64-builds path: ./ - name: Download The Windows Artifact (Signed) uses: actions/download-artifact@v3 with: name: logseq-win64-signed-builds path: ./ - name: Download The Windows Artifact uses: actions/download-artifact@v3 with: name: logseq-win64-builds path: ./ - name: Download Android Artifacts uses: actions/download-artifact@v3 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: Fix .nupkg name in RELEASES file run: | sed -i "s/Logseq-.*.nupkg/Logseq-win-x64-${{ steps.ref.outputs.version }}-full.nupkg/g" RELEASES - name: Generate SHA256 checksums run: | sha256sum *-darwin-* > SHA256SUMS.txt sha256sum *-win-* >> SHA256SUMS.txt sha256sum *-linux-* >> SHA256SUMS.txt sha256sum *.apk >> SHA256SUMS.txt sha256sum RELEASES >> 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/Android 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 ./*.msi ./*.nupkg ./RELEASES ./*.AppImage ./*.apk