name: build desktop on: workflow_dispatch: inputs: channel: description: Release channel label (stable or canary). Source is always this repository's main branch. required: false type: choice options: - stable - canary default: stable build_version: description: Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation. required: false default: "" type: string skip_targets: description: Comma-separated platforms or targets to skip, such as windows, macos, linux-x64. required: false default: "" type: string shell_contract: description: "Did the shell contract change since the oldest shell these modules still reach? unchanged refuses if it did. compatible keeps older shells on these modules because the renderer still works on them. raise stops sending these modules to shells without the new contract: Linux and managed shells keep their current renderer, Windows and macOS update their shell first." required: true type: choice options: - unchanged - compatible - raise default: unchanged permissions: contents: write id-token: write actions: read concurrency: group: desktop-${{ inputs.channel }} cancel-in-progress: false env: CHANNEL: ${{ inputs.channel }} BUILD_CHANNEL: ${{ inputs.channel == 'canary' && 'canary' || 'stable' }} jobs: meta: name: Resolve build metadata runs-on: ubuntu-24.04-arm environment: desktop-releases timeout-minutes: 25 permissions: contents: read outputs: version: ${{ steps.meta.outputs.version }} pub_date: ${{ steps.meta.outputs.pub_date }} channel: ${{ steps.meta.outputs.channel }} build_channel: ${{ steps.meta.outputs.build_channel }} source_sha: ${{ steps.meta.outputs.source_sha }} steps: - name: Checkout source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: main fetch-depth: 0 - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" - name: Create token id: create-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 with: client-id: ${{ vars.FLUXER_CI_APP_ID }} private-key: ${{ secrets.FLUXER_CI_APP_KEY }} owner: fluxerapp repositories: fluxer permission-contents: read - name: Set metadata id: meta env: GH_TOKEN: ${{ steps.create-token.outputs.token }} FLUXER_BUILD_VERSION: ${{ inputs.build_version }} run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step set_metadata --channel "${{ inputs.channel }}" - name: Check which shells run these modules env: GH_TOKEN: ${{ steps.create-token.outputs.token }} CHANNEL: ${{ steps.meta.outputs.build_channel }} SOURCE_SHA: ${{ steps.meta.outputs.source_sha }} VERSION: ${{ steps.meta.outputs.version }} SHELL_CONTRACT: ${{ inputs.shell_contract }} DESKTOP_MODULES_ONLY_RELEASE: false run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step check_shell_contract matrix: name: Resolve build matrix runs-on: ubuntu-24.04-arm environment: desktop-releases timeout-minutes: 25 permissions: contents: read outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Checkout source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" - name: Build platform matrix id: set-matrix run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step set_matrix --skip-targets "${{ inputs.skip_targets }}" shared_assets: name: Build shared renderer assets needs: - meta runs-on: ubuntu-24.04 environment: desktop-releases timeout-minutes: 60 permissions: contents: read env: CHANNEL: ${{ needs.meta.outputs.channel }} BUILD_CHANNEL: ${{ needs.meta.outputs.build_channel }} RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }} PUBLIC_RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }} VERSION: ${{ needs.meta.outputs.version }} BUILD_VERSION: ${{ needs.meta.outputs.version }} PUBLIC_BUILD_VERSION: ${{ needs.meta.outputs.version }} SOURCE_SHA: ${{ needs.meta.outputs.source_sha }} steps: - name: Checkout CI helpers uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{ needs.meta.outputs.source_sha }} path: _ci - name: Checkout source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{ needs.meta.outputs.source_sha }} path: source - name: Set up Rust toolchain (renderer wasm) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" targets: wasm32-unknown-unknown - name: Set workdir (Unix) env: SUBST_TARGET: ${{ github.workspace }}/source run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step set_workdir_unix - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: 26 - name: Set up pnpm run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step setup_pnpm - name: Resolve pnpm store path (Unix) run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step resolve_pnpm_store_unix - name: Cache pnpm store uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: ${{ env.PNPM_STORE_PATH }} key: ${{ runner.os }}-shared-renderer-pnpm-store-${{ hashFiles('source/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-shared-renderer-pnpm-store- - name: Cache cargo registry uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: | ~/.cargo/registry ~/.cargo/git key: ${{ runner.os }}-shared-renderer-cargo-registry-${{ hashFiles('source/Cargo.lock') }} restore-keys: | ${{ runner.os }}-shared-renderer-cargo-registry- - name: Install dependencies working-directory: ${{ env.WORKDIR }}/fluxer_desktop run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_dependencies - name: Update version working-directory: ${{ env.WORKDIR }}/fluxer_desktop run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step update_version - name: Set build channel working-directory: ${{ env.WORKDIR }}/fluxer_desktop run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step set_build_channel - name: Build shared renderer assets working-directory: ${{ env.WORKDIR }}/fluxer_desktop run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step build_shared_assets - name: Prepare shared renderer artifact run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step prepare_shared_assets - name: Upload shared renderer artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: desktop-shared-${{ needs.meta.outputs.build_channel }}-${{ needs.meta.outputs.version }}-${{ needs.meta.outputs.source_sha }} path: source/desktop-shared-assets if-no-files-found: error retention-days: 1 compression-level: 0 - name: Split renderer into desktop modules run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step split_modules - name: Pack desktop modules run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step pack_modules - name: Upload desktop module packages uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: desktop-modules-${{ needs.meta.outputs.build_channel }}-${{ needs.meta.outputs.version }}-${{ needs.meta.outputs.source_sha }} path: | source/desktop-modules/classification.json source/desktop-modules/*/module.json source/desktop-modules/*/package.br source/desktop-modules/*/package.br.sha256 if-no-files-found: error retention-days: 1 compression-level: 0 build: name: Build ${{ matrix.platform }} (${{ matrix.arch }}) needs: - meta - matrix - shared_assets runs-on: ${{ matrix.os }} environment: desktop-releases timeout-minutes: 180 permissions: actions: read contents: read id-token: write strategy: fail-fast: false matrix: ${{ fromJson(needs.matrix.outputs.matrix) }} env: CHANNEL: ${{ needs.meta.outputs.channel }} BUILD_CHANNEL: ${{ needs.meta.outputs.build_channel }} RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }} PUBLIC_RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }} VERSION: ${{ needs.meta.outputs.version }} BUILD_VERSION: ${{ needs.meta.outputs.version }} PUBLIC_BUILD_VERSION: ${{ needs.meta.outputs.version }} PUB_DATE: ${{ needs.meta.outputs.pub_date }} SOURCE_SHA: ${{ needs.meta.outputs.source_sha }} DESKTOP_PLATFORM: ${{ matrix.platform }} DESKTOP_ARCH: ${{ matrix.arch }} FLUXER_MODULES: "1" PLATFORM: ${{ matrix.platform }} ARCH: ${{ matrix.arch }} ELECTRON_ARCH: ${{ matrix.electron_arch }} steps: - name: Checkout CI helpers uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{ needs.meta.outputs.source_sha }} path: _ci - name: Checkout source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{ needs.meta.outputs.source_sha }} path: source - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" - name: Set up Python (Windows) if: runner.os == 'Windows' uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 with: python-version: "3.14" - name: Ensure python3 command (Windows) if: runner.os == 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step ensure_python3_windows - name: Shorten Windows paths and pin pnpm store if: runner.os == 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step windows_paths env: SUBST_TARGET: ${{ github.workspace }}/source - name: Set workdir (Unix) if: runner.os != 'Windows' env: SUBST_TARGET: ${{ github.workspace }}/source run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step set_workdir_unix - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: 26 - name: Set up pnpm run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step setup_pnpm - name: Resolve pnpm store path (Windows) if: runner.os == 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step resolve_pnpm_store_windows - name: Resolve pnpm store path (Unix) if: runner.os != 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step resolve_pnpm_store_unix - name: Cache pnpm store uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with: path: ${{ env.PNPM_STORE_PATH }} key: ${{ runner.os }}-${{ matrix.arch }}-pnpm-store-${{ hashFiles('source/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-${{ matrix.arch }}-pnpm-store- - name: Install Python setuptools (Windows ARM64) if: matrix.platform == 'windows' && matrix.arch == 'arm64' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_setuptools_windows_arm64 - name: Install Python setuptools (macOS) if: matrix.platform == 'macos' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_setuptools_macos - name: Install Linux dependencies if: matrix.platform == 'linux' env: DEBIAN_FRONTEND: noninteractive run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_linux_deps - name: Set up Rust toolchain (Unix) if: matrix.platform != 'windows' uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" targets: ${{ matrix.platform == 'macos' && 'aarch64-apple-darwin,x86_64-apple-darwin' || (matrix.arch == 'arm64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu') }} - name: Install MSVC ARM64 build tools if: matrix.platform == 'windows' && matrix.arch == 'arm64' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_msvc_arm64_tools - name: Set up MSVC env (Windows) if: matrix.platform == 'windows' uses: TheMrMilchmann/setup-msvc-dev@368ef7d1ee4d1171b31d4a7f67f4d954f903f5a9 with: arch: ${{ matrix.arch == 'arm64' && 'amd64_arm64' || 'amd64' }} - name: Set up Rust toolchain (Windows) if: matrix.platform == 'windows' env: ARCH: ${{ matrix.arch }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_rust_windows_targets - name: Install dependencies working-directory: ${{ env.WORKDIR }}/fluxer_desktop run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_dependencies - name: Update version working-directory: ${{ env.WORKDIR }}/fluxer_desktop run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step update_version - name: Set build channel working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step set_build_channel - name: Download shared renderer artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with: name: desktop-shared-${{ needs.meta.outputs.build_channel }}-${{ needs.meta.outputs.version }}-${{ needs.meta.outputs.source_sha }} path: source/desktop-shared-assets - name: Restore shared renderer assets run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step restore_shared_assets - name: Build Electron main process working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step build_electron_main - name: Set up .NET SDK (Windows) if: matrix.platform == 'windows' uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 with: dotnet-version: "10.0.x" - name: Install Velopack CLI if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step install_velopack_cli - name: Build Electron app (macOS) if: matrix.platform == 'macos' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }} CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step build_app_macos - name: Verify macOS artifact (bundle ID + profile + signature) if: matrix.platform == 'macos' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step verify_bundle_id - name: Build Electron app (Windows) if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} TEMP: C:\t TMP: C:\t ELECTRON_BUILDER_CACHE: C:\ebcache run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step build_app_windows - name: Validate Windows signing inputs if: matrix.platform == 'windows' env: AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} AZURE_ARTIFACT_SIGNING_ENDPOINT: ${{ secrets.AZURE_ARTIFACT_SIGNING_ENDPOINT }} AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME: ${{ secrets.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }} AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME: ${{ secrets.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step validate_windows_signing_inputs - name: Azure login for Artifact Signing if: matrix.platform == 'windows' uses: azure/login@a641126d1b8aa4d1fa005f4f92df94a3a4c4c906 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Write Velopack Trusted Signing metadata if: matrix.platform == 'windows' env: AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} AZURE_ARTIFACT_SIGNING_ENDPOINT: ${{ secrets.AZURE_ARTIFACT_SIGNING_ENDPOINT }} AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME: ${{ secrets.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }} AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME: ${{ secrets.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step write_windows_signing_metadata - name: Resolve unpacked Windows app directory id: resolve_unpacked if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step resolve_windows_unpacked_dir - name: Sign unpacked Windows binaries with Artifact Signing if: matrix.platform == 'windows' uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 with: endpoint: ${{ secrets.AZURE_ARTIFACT_SIGNING_ENDPOINT }} signing-account-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }} certificate-profile-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }} files-folder: ${{ steps.resolve_unpacked.outputs.unpacked_dir }} files-folder-filter: exe,dll,node files-folder-recurse: true file-digest: SHA256 timestamp-rfc3161: http://timestamp.acs.microsoft.com timestamp-digest: SHA256 exclude-environment-credential: true - name: Verify unpacked Windows signatures if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step verify_windows_unpacked_signatures - name: Verify the packaged shell starts and boots its bundled renderer (Windows) if: matrix.platform == 'windows' && matrix.arch == 'x64' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} BUILD_VERSION: ${{ env.VERSION }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step verify_bundled_renderer_windows - name: Create portable ZIP (Windows) if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step create_portable_zip_windows - name: Package Windows app with Velopack if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step package_app_windows_velopack - name: Analyze Velopack nupkg for long paths if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_VERSION: ${{ env.VERSION }} BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} MAX_WINDOWS_PATH_LEN: 260 PATH_HEADROOM: 10 run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step analyse_velopack_paths - name: Build Electron app (Linux) if: matrix.platform == 'linux' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} USE_SYSTEM_FPM: true run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step build_app_linux - name: Verify the packaged shell boots its bundled renderer (Linux) if: matrix.platform == 'linux' && matrix.arch == 'x64' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} BUILD_VERSION: ${{ env.VERSION }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step verify_bundled_renderer_linux - name: Verify signed Windows artifacts if: matrix.platform == 'windows' working-directory: ${{ env.WORKDIR }}/fluxer_desktop env: BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }} run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step verify_windows_signed_artifacts - name: Prepare artifacts (Windows) if: runner.os == 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step prepare_artifacts_windows - name: Prepare artifacts (Unix) if: runner.os != 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step prepare_artifacts_unix - name: Build AppImage update feed (Linux) if: matrix.platform == 'linux' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step build_appimage_update_feed - name: Normalize updater YAML (macOS) if: matrix.platform == 'macos' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step normalise_updater_yaml - name: Generate SHA256 checksums (Unix) if: runner.os != 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step generate_checksums_unix - name: Generate SHA256 checksums (Windows) if: runner.os == 'Windows' run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step generate_checksums_windows - name: Stage build artifacts id: handoff run: >- cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop --step stage_handoff - name: Upload build artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: ${{ steps.handoff.outputs.artifact_name }} path: upload_staging if-no-files-found: error retention-days: 1 compression-level: 0 verify_windows_arm64: name: Verify windows (arm64) if: ${{ !cancelled() && needs.build.result == 'success' }} needs: - meta - build runs-on: windows-11-arm timeout-minutes: 30 permissions: actions: read contents: read env: CHANNEL: ${{ needs.meta.outputs.build_channel }} VERSION: ${{ needs.meta.outputs.version }} steps: - name: Checkout source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{ needs.meta.outputs.source_sha }} sparse-checkout: fluxer_desktop/scripts - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 with: node-version: 24 - name: Download windows arm64 build artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with: path: artifacts pattern: fluxer-desktop-${{ needs.meta.outputs.build_channel }}-windows-arm64* - name: Verify the packaged shell starts and boots its bundled renderer shell: pwsh run: | $ErrorActionPreference = 'Stop' $zip = Get-ChildItem -Path artifacts -Recurse -Filter "*-$env:VERSION-portable-win-arm64.zip" | Select-Object -First 1 if ($null -eq $zip) { Write-Host 'This build has no windows arm64 portable zip'; exit 0 } $app = Join-Path $env:RUNNER_TEMP 'app' Expand-Archive -Path $zip.FullName -DestinationPath $app $exe = Get-ChildItem -Path $app -Recurse -Filter 'Fluxer*.exe' | Where-Object { $_.Name -notlike '*_ExecutionStub.exe' } | Select-Object -First 1 if ($null -eq $exe) { throw "$($zip.Name) holds no Fluxer executable" } node fluxer_desktop/scripts/release-check.mjs --app $exe.DirectoryName --channel $env:CHANNEL --expect-renderer $env:VERSION --expect-source bundled --package-origin http://127.0.0.1:9 --app-arg=--disable-gpu --workdir (Join-Path $env:RUNNER_TEMP 'runs') --timeout-seconds 240 if ($LASTEXITCODE -ne 0) { throw "The windows arm64 build fails its release check" } upload: name: Assemble desktop release assets if: ${{ !cancelled() && needs.build.result == 'success' && needs.verify_windows_arm64.result == 'success' }} needs: - meta - shared_assets - build - verify_windows_arm64 runs-on: ubuntu-24.04-arm environment: desktop-releases timeout-minutes: 180 permissions: actions: read contents: read env: CHANNEL: ${{ needs.meta.outputs.build_channel }} DISPLAY_CHANNEL: ${{ needs.meta.outputs.channel }} RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }} PUBLIC_RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }} VERSION: ${{ needs.meta.outputs.version }} BUILD_VERSION: ${{ needs.meta.outputs.version }} PUBLIC_BUILD_VERSION: ${{ needs.meta.outputs.version }} PUB_DATE: ${{ needs.meta.outputs.pub_date }} SOURCE_SHA: ${{ needs.meta.outputs.source_sha }} steps: - name: Checkout source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{ needs.meta.outputs.source_sha }} fetch-depth: 0 - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" - name: Download build artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with: path: artifacts pattern: fluxer-desktop-${{ needs.meta.outputs.build_channel }}-* - name: Build payload layout (+ manifest.json) env: VERSION: ${{ needs.meta.outputs.version }} PUB_DATE: ${{ needs.meta.outputs.pub_date }} run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step build_payload - name: Download desktop module packages uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with: name: desktop-modules-${{ needs.meta.outputs.build_channel }}-${{ needs.meta.outputs.version }}-${{ needs.meta.outputs.source_sha }} path: desktop-modules - name: Create token id: create-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 with: client-id: ${{ vars.FLUXER_CI_APP_ID }} private-key: ${{ secrets.FLUXER_CI_APP_KEY }} owner: fluxerapp repositories: fluxer permission-contents: read - name: Check which shells run these modules env: GH_TOKEN: ${{ steps.create-token.outputs.token }} SHELL_CONTRACT: ${{ inputs.shell_contract }} DESKTOP_MODULES_ONLY_RELEASE: false run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step check_shell_contract - name: Build desktop module manifest run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step build_module_manifest - name: Prepare GitHub release assets run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step prepare_release_assets - name: Upload GitHub release assets uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: fluxer-desktop-release-assets path: release_assets if-no-files-found: error retention-days: 1 compression-level: 0 - name: Build summary run: >- cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop --step build_summary publish_release: name: Publish GitHub desktop release if: ${{ !cancelled() && needs.upload.result == 'success' }} needs: - meta - upload runs-on: ubuntu-24.04-arm environment: desktop-releases timeout-minutes: 60 permissions: contents: write env: CHANNEL: ${{ needs.meta.outputs.build_channel }} VERSION: ${{ needs.meta.outputs.version }} steps: - name: Checkout source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{ needs.meta.outputs.source_sha }} - name: Set up Rust toolchain (CI helpers) uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de with: toolchain: "1.98.1" - name: Download GitHub release assets uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with: name: fluxer-desktop-release-assets path: release_assets - name: Create token id: create-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 with: client-id: ${{ vars.FLUXER_CI_APP_ID }} private-key: ${{ secrets.FLUXER_CI_APP_KEY }} owner: fluxerapp repositories: fluxer permission-contents: write - name: Publish GitHub desktop release env: GH_TOKEN: ${{ steps.create-token.outputs.token }} CHANNEL: ${{ needs.meta.outputs.build_channel }} VERSION: ${{ needs.meta.outputs.version }} SOURCE_SHA: ${{ needs.meta.outputs.source_sha }} RELEASE_BASELINE_SHA: ${{ vars.RELEASE_BASELINE_SHA }} run: | set -euo pipefail release_args=( release publish --component "fluxer-desktop-${CHANNEL}" --build-version "${VERSION}" --source-sha "${SOURCE_SHA}" --previous-sha "${RELEASE_BASELINE_SHA}" --asset-dir release_assets ) if [[ "${CHANNEL}" == "canary" ]]; then release_args+=(--prerelease) fi cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- "${release_args[@]}"