Merge pull request #214 from 23rd/feat/linux-hidpi-mutter-fractional #200
Workflow file for this run
This file contains hidden or 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 (All Platforms) | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| build: | |
| name: Build (${{ matrix.os }} / ${{ matrix.arch }}) | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 120 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| arch: amd64 | |
| - os: ubuntu-24.04-arm | |
| arch: arm64 | |
| - os: windows-latest | |
| arch: amd64 | |
| - os: windows-11-arm | |
| arch: arm64 | |
| node-version: '22' # npm 11 (Node 24) has ECOMPROMISED bugs on Windows ARM64 | |
| - os: macos-latest | |
| arch: arm64 | |
| jbr-download-url: 'https://github.com/kdroidFilter/JetBrainsRuntime/releases/download/v25.0.2b329.66-rtl/jdk-macos-aarch64.tar.gz' | |
| - os: macos-15-intel | |
| arch: amd64 | |
| jbr-download-url: 'https://github.com/kdroidFilter/JetBrainsRuntime/releases/download/v25.0.2b329.66-rtl/jdk-macos-x64.tar.gz' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RELEASE_VERSION: ${{ github.ref_name }} | |
| steps: | |
| - name: Checkout Repo | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Normalize version for manual runs | |
| if: github.event_name == 'workflow_dispatch' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| tag="$(git describe --tags --abbrev=0)" | |
| echo "RELEASE_VERSION=$tag" >> "$GITHUB_ENV" | |
| - name: Setup Nucleus | |
| uses: ./.github/actions/setup-nucleus | |
| with: | |
| jbr-version: '25.0.2b329.66' | |
| jbr-download-url: ${{ matrix.jbr-download-url || '' }} | |
| packaging-tools: 'true' | |
| flatpak: 'true' | |
| snap: 'true' | |
| setup-gradle: 'true' | |
| setup-node: 'true' | |
| node-version: ${{ matrix.node-version || '24' }} | |
| - name: Build packages | |
| shell: bash | |
| run: ./gradlew :example:packageReleaseDistributionForCurrentOS --stacktrace --no-daemon | |
| - name: Create sandboxed app ZIP (macOS only) | |
| if: runner.os == 'macOS' | |
| shell: bash | |
| run: | | |
| SANDBOXED_APP="$(find example/build/compose/binaries -path '*/app-sandboxed/*.app' -type d | head -1)" | |
| if [[ -n "$SANDBOXED_APP" ]]; then | |
| APP_NAME="$(basename "$SANDBOXED_APP")" | |
| # Derive name from existing ZIP to keep consistent naming | |
| EXISTING_ZIP="$(find example/build/compose/binaries -name '*.zip' -type f | head -1)" | |
| if [[ -n "$EXISTING_ZIP" ]]; then | |
| BASE="$(basename "$EXISTING_ZIP" .zip)" | |
| SANDBOXED_ZIP="example/build/compose/binaries/sandboxed-${BASE}.zip" | |
| else | |
| ARCH="$(uname -m | sed 's/x86_64/x64/;s/arm64/arm64/')" | |
| SANDBOXED_ZIP="example/build/compose/binaries/sandboxed-${APP_NAME%.app}-${ARCH}.zip" | |
| fi | |
| echo "==> Zipping sandboxed .app: $SANDBOXED_APP → $SANDBOXED_ZIP" | |
| ditto -c -k --keepParent "$SANDBOXED_APP" "$SANDBOXED_ZIP" | |
| else | |
| echo "==> No sandboxed .app found (no PKG target?), skipping" | |
| fi | |
| - name: Upload packaged artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-assets-${{ runner.os }}-${{ matrix.arch }} | |
| path: | | |
| example/build/compose/binaries/**/*.deb | |
| example/build/compose/binaries/**/*.rpm | |
| example/build/compose/binaries/**/*.snap | |
| example/build/compose/binaries/**/*.flatpak | |
| example/build/compose/binaries/**/*.AppImage | |
| example/build/compose/binaries/**/*.appimage | |
| example/build/compose/binaries/**/*.msi | |
| example/build/compose/binaries/**/*.exe | |
| example/build/compose/binaries/**/*.appx | |
| !example/build/compose/binaries/**/runtime/** | |
| example/build/compose/binaries/**/*.7z | |
| example/build/compose/binaries/**/*.pkg | |
| example/build/compose/binaries/**/*.dmg | |
| example/build/compose/binaries/**/*.zip | |
| example/build/compose/binaries/sandboxed-*.zip | |
| example/build/compose/binaries/**/*.tar | |
| example/build/compose/binaries/**/*.tar.gz | |
| example/build/compose/binaries/**/*.blockmap | |
| example/build/compose/binaries/**/signing-metadata.json | |
| example/build/compose/binaries/**/packaging-metadata.json | |
| !example/build/compose/binaries/**/app/** | |
| if-no-files-found: error | |
| universal-macos: | |
| name: Universal macOS Binary | |
| needs: [build] | |
| if: needs.build.result == 'success' | |
| runs-on: macos-latest | |
| timeout-minutes: 45 | |
| env: | |
| HAS_SIGNING_CERTS: ${{ secrets.MAC_CERTIFICATES_P12 != '' }} | |
| HAS_PROVISIONING: ${{ secrets.MAC_PROVISIONING_PROFILE != '' }} | |
| HAS_NOTARIZATION: ${{ secrets.MAC_NOTARIZATION_APPLE_ID != '' }} | |
| steps: | |
| - name: Checkout Repo | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| with: | |
| sparse-checkout: | | |
| .github/actions | |
| example/packaging/macos | |
| fetch-depth: 1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| - name: Setup macOS signing | |
| id: signing | |
| if: env.HAS_SIGNING_CERTS == 'true' | |
| uses: ./.github/actions/setup-macos-signing | |
| with: | |
| certificate-base64: ${{ secrets.MAC_CERTIFICATES_P12 }} | |
| certificate-password: ${{ secrets.MAC_CERTIFICATES_PASSWORD }} | |
| - name: Decode provisioning profiles | |
| if: env.HAS_PROVISIONING == 'true' | |
| shell: bash | |
| run: | | |
| echo "${{ secrets.MAC_PROVISIONING_PROFILE }}" | base64 -d > "$RUNNER_TEMP/embedded.provisionprofile" | |
| echo "PROVISIONING=$RUNNER_TEMP/embedded.provisionprofile" >> "$GITHUB_ENV" | |
| if [[ -n "${{ secrets.MAC_RUNTIME_PROVISIONING_PROFILE }}" ]]; then | |
| echo "${{ secrets.MAC_RUNTIME_PROVISIONING_PROFILE }}" | base64 -d > "$RUNNER_TEMP/runtime-embedded.provisionprofile" | |
| echo "RUNTIME_PROVISIONING=$RUNNER_TEMP/runtime-embedded.provisionprofile" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download macOS arm64 artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-assets-macOS-arm64 | |
| path: artifacts/release-assets-macOS-arm64 | |
| - name: Download macOS amd64 artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-assets-macOS-amd64 | |
| path: artifacts/release-assets-macOS-amd64 | |
| - name: Build universal binary | |
| uses: ./.github/actions/build-macos-universal | |
| with: | |
| arm64-path: artifacts/release-assets-macOS-arm64 | |
| x64-path: artifacts/release-assets-macOS-amd64 | |
| output-path: artifacts/release-assets-macOS-universal | |
| signing-identity: ${{ secrets.MAC_DEVELOPER_ID_APPLICATION }} | |
| app-store-identity: ${{ secrets.MAC_APP_STORE_APPLICATION }} | |
| installer-identity: ${{ secrets.MAC_APP_STORE_INSTALLER }} | |
| keychain-path: ${{ steps.signing.outputs.keychain-path }} | |
| entitlements-file: example/packaging/macos/entitlements.plist | |
| runtime-entitlements-file: example/packaging/macos/runtime-entitlements.plist | |
| sandboxed-entitlements-file: example/packaging/macos/entitlements-sandbox.plist | |
| sandboxed-runtime-entitlements-file: example/packaging/macos/runtime-entitlements-sandbox.plist | |
| provisioning-profile: ${{ env.PROVISIONING }} | |
| runtime-provisioning-profile: ${{ env.RUNTIME_PROVISIONING }} | |
| - name: Notarize DMG | |
| if: env.HAS_NOTARIZATION == 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| DMG="$(find artifacts/release-assets-macOS-universal -name '*.dmg' -type f | head -1)" | |
| if [[ -z "$DMG" ]]; then | |
| echo "::warning::No DMG found to notarize" | |
| exit 0 | |
| fi | |
| echo "==> Submitting DMG for notarization: $DMG" | |
| xcrun notarytool submit "$DMG" \ | |
| --apple-id "${{ secrets.MAC_NOTARIZATION_APPLE_ID }}" \ | |
| --password "${{ secrets.MAC_NOTARIZATION_PASSWORD }}" \ | |
| --team-id "${{ secrets.MAC_NOTARIZATION_TEAM_ID }}" \ | |
| --wait | |
| echo "==> Stapling DMG" | |
| xcrun stapler staple "$DMG" | |
| - name: Notarize ZIP | |
| if: env.HAS_NOTARIZATION == 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ZIP="$(find artifacts/release-assets-macOS-universal -name '*.zip' -type f | head -1)" | |
| if [[ -z "$ZIP" ]]; then | |
| echo "::warning::No ZIP found to notarize" | |
| exit 0 | |
| fi | |
| echo "==> Submitting ZIP for notarization: $ZIP" | |
| xcrun notarytool submit "$ZIP" \ | |
| --apple-id "${{ secrets.MAC_NOTARIZATION_APPLE_ID }}" \ | |
| --password "${{ secrets.MAC_NOTARIZATION_PASSWORD }}" \ | |
| --team-id "${{ secrets.MAC_NOTARIZATION_TEAM_ID }}" \ | |
| --wait | |
| # ZIP is NOT stapled: re-zipping would invalidate the blockmap and break | |
| # differential auto-updates. Gatekeeper verifies notarization online anyway. | |
| echo "==> Skipping staple for ZIP (preserves blockmap for auto-update)" | |
| - name: Cleanup keychain | |
| if: ${{ always() && env.HAS_SIGNING_CERTS == 'true' }} | |
| shell: bash | |
| run: security delete-keychain "${{ steps.signing.outputs.keychain-path }}" || true | |
| - name: Upload universal macOS artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-assets-macOS-universal | |
| path: artifacts/release-assets-macOS-universal | |
| if-no-files-found: error | |
| bundle-windows: | |
| name: Windows APPX Bundle | |
| needs: [build] | |
| if: needs.build.result == 'success' | |
| runs-on: windows-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout Repo | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| with: | |
| sparse-checkout: | | |
| .github/actions | |
| example/packaging | |
| fetch-depth: 1 | |
| - name: Download Windows amd64 artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-assets-Windows-amd64 | |
| path: artifacts/release-assets-Windows-amd64 | |
| - name: Download Windows arm64 artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-assets-Windows-arm64 | |
| path: artifacts/release-assets-Windows-arm64 | |
| - name: Build APPX Bundle | |
| uses: ./.github/actions/build-windows-appxbundle | |
| with: | |
| amd64-path: artifacts/release-assets-Windows-amd64 | |
| arm64-path: artifacts/release-assets-Windows-arm64 | |
| output-path: artifacts/release-assets-Windows-bundle | |
| certificate-password: 'ChangeMe-Temp123!' | |
| - name: Upload Windows bundle artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-assets-Windows-bundle | |
| path: artifacts/release-assets-Windows-bundle | |
| if-no-files-found: error | |
| publish: | |
| name: Publish Release | |
| needs: [build, universal-macos, bundle-windows] | |
| if: ${{ !cancelled() && needs.build.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| steps: | |
| - name: Checkout Repo | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| with: | |
| sparse-checkout: .github/actions | |
| fetch-depth: 1 | |
| - name: Download all build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| pattern: release-assets-* | |
| - name: Determine version and channel | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| TAG="${GITHUB_REF_NAME}" | |
| VERSION="${TAG#v}" | |
| echo "TAG=$TAG" >> "$GITHUB_ENV" | |
| echo "VERSION=$VERSION" >> "$GITHUB_ENV" | |
| if [[ "$VERSION" == *"-alpha"* ]]; then | |
| echo "CHANNEL=alpha" >> "$GITHUB_ENV" | |
| elif [[ "$VERSION" == *"-beta"* ]]; then | |
| echo "CHANNEL=beta" >> "$GITHUB_ENV" | |
| else | |
| echo "CHANNEL=latest" >> "$GITHUB_ENV" | |
| fi | |
| if [[ "$VERSION" == *"-alpha"* ]] || [[ "$VERSION" == *"-beta"* ]]; then | |
| echo "RELEASE_TYPE=prerelease" >> "$GITHUB_ENV" | |
| else | |
| echo "RELEASE_TYPE=release" >> "$GITHUB_ENV" | |
| fi | |
| - name: List downloaded artifacts | |
| shell: bash | |
| run: find artifacts -type f | head -100 | |
| - name: Generate update YML files | |
| uses: ./.github/actions/generate-update-yml | |
| with: | |
| artifacts-path: artifacts | |
| version: ${{ env.VERSION }} | |
| channel: ${{ env.CHANNEL }} | |
| - name: Show generated YML files | |
| shell: bash | |
| run: | | |
| echo "=== Generated update YML files ===" | |
| for f in artifacts/update-yml/*.yml; do | |
| echo "--- $(basename "$f") ---" | |
| cat "$f" | |
| echo | |
| done | |
| - name: Publish release | |
| uses: ./.github/actions/publish-release | |
| with: | |
| artifacts-path: artifacts | |
| tag: ${{ env.TAG }} | |
| release-type: ${{ env.RELEASE_TYPE }} |