# https://github.com/tauri-apps/tauri-action/blob/3013cac/examples/test-build-only.yml on: workflow_dispatch: workflow_call: inputs: rebuild_cloudsync: type: boolean default: false schedule: - cron: "0 9 * * *" push: branches: - main paths: - .github/actions/install_desktop_deps/** - .github/workflows/desktop_ci.yaml - scripts/repack-linux-appimage.mjs - scripts/repack-linux-appimage.test.mjs - apps/cli/** - apps/desktop/** - packages/utils/** - plugins/** - crates/** - Cargo.toml - Cargo.lock pull_request: paths: - .github/actions/install_desktop_deps/** - .github/workflows/desktop_ci.yaml - scripts/repack-linux-appimage.mjs - scripts/repack-linux-appimage.test.mjs - apps/cli/** - apps/desktop/** - packages/utils/** - plugins/** - crates/** - Cargo.toml - Cargo.lock concurrency: group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true jobs: js_ci: if: ${{ !startsWith(github.head_ref || '', 'blog/') }} runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - uses: ./.github/actions/pnpm_install - run: pnpm -F ui build - run: pnpm -F desktop typecheck - run: pnpm -F desktop test macos_ci: if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} defaults: run: shell: bash strategy: fail-fast: false matrix: include: - platform: "macos" runner: "macos-26" runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - uses: ./.github/actions/pnpm_install - uses: denoland/setup-deno@v2 - run: pnpm -F ui build - run: pnpm -F desktop typecheck - run: pnpm -F desktop test - uses: ./.github/actions/install_desktop_deps with: target: ${{ matrix.platform }} - uses: ./.github/actions/rust_install with: platform: ${{ matrix.platform }} - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: crates/cloudsync/scripts/rebuild-macos.sh - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: actions/upload-artifact@v4 with: name: cloudsync-macos-aarch64-${{ github.sha }} path: crates/cloudsync/vendor/cloudsync/macos/aarch64/cloudsync.dylib if-no-files-found: error retention-days: 7 - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: actions/upload-artifact@v4 with: name: cloudsync-macos-x86_64-${{ github.sha }} path: crates/cloudsync/vendor/cloudsync/macos/x86_64/cloudsync.dylib if-no-files-found: error retention-days: 7 - if: matrix.platform == 'macos' run: echo "SDKROOT=$(xcrun --sdk macosx --show-sdk-path)" >> $GITHUB_ENV - run: cargo check -p desktop --features direct-distribution - run: cargo check -p desktop --features app-store - run: cargo test -p desktop - run: cargo test --locked -p cloudsync - run: "cargo test --locked -p db-core 'cloudsync::' -- --test-threads=1" - run: | cargo test --workspace \ --exclude desktop \ --exclude control-tauri \ --exclude ai \ --exclude lago \ --exclude notch \ --exclude notification-macos \ --exclude tcc \ --exclude notification-linux \ --exclude am \ --exclude aec \ --exclude whisper \ --exclude whisper-local \ --exclude whisper-local-model \ --exclude vad2 \ --exclude vad \ --exclude vvad \ --exclude vad-masking \ --exclude vad-chunking \ --exclude onnx \ --exclude pyannote-local \ --exclude llama \ --exclude tools \ --exclude docs \ --exclude bundle \ --exclude host \ --exclude intercept \ --exclude frontmatter \ --exclude audio \ --exclude audio-device \ --exclude transcribe-whisper-local \ --exclude device-monitor \ --exclude local-llm-core \ --exclude mobile-bridge \ --exclude tauri-plugin-analytics\ --exclude tauri-plugin-apple-calendar \ --exclude tauri-plugin-audio-priority \ --exclude tauri-plugin-auth \ --exclude tauri-plugin-bedrock \ --exclude tauri-plugin-db2 \ --exclude tauri-plugin-deeplink2 \ --exclude tauri-plugin-detect \ --exclude tauri-plugin-fs-db \ --exclude tauri-plugin-fs-sync \ --exclude tauri-plugin-fs2 \ --exclude tauri-plugin-hooks \ --exclude tauri-plugin-icon \ --exclude tauri-plugin-importer \ --exclude tauri-plugin-js \ --exclude tauri-plugin-listener \ --exclude tauri-plugin-listener2 \ --exclude tauri-plugin-local-auth \ --exclude tauri-plugin-local-llm \ --exclude tauri-plugin-local-stt \ --exclude tauri-plugin-misc \ --exclude tauri-plugin-notification \ --exclude tauri-plugin-notify \ --exclude tauri-plugin-opener2 \ --exclude tauri-plugin-overlay \ --exclude tauri-plugin-path2 \ --exclude tauri-plugin-pdf \ --exclude tauri-plugin-permissions \ --exclude tauri-plugin-screen \ --exclude tauri-plugin-settings \ --exclude tauri-plugin-sfx \ --exclude tauri-plugin-sidecar2 \ --exclude tauri-plugin-store2 \ --exclude tauri-plugin-tantivy \ --exclude tauri-plugin-template \ --exclude tauri-plugin-tracing \ --exclude tauri-plugin-tray \ --exclude tauri-plugin-updater2 \ --exclude tauri-plugin-windows \ --exclude db3 \ --exclude db-core \ --exclude activity-capture-macos \ --exclude tauri-plugin-activity-capture - run: | git diff --exit-code -- \ plugins/db/js/bindings.gen.ts \ plugins/db/permissions/autogenerated \ plugins/db/permissions/schemas/schema.json windows_ci: if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} runs-on: windows-latest steps: - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - uses: ./.github/actions/rust_install with: platform: windows - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: msys2/setup-msys2@v2 with: msystem: UCRT64 install: git make mingw-w64-ucrt-x86_64-gcc update: true - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync shell: "msys2 {0}" run: crates/cloudsync/scripts/rebuild-windows.sh - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: actions/upload-artifact@v4 with: name: cloudsync-windows-x86_64-${{ github.sha }} path: crates/cloudsync/vendor/cloudsync/windows/x86_64/cloudsync.dll if-no-files-found: error retention-days: 7 - run: cargo check --locked -p desktop - run: cargo test --locked -p desktop --no-run - run: cargo test --locked -p tauri-plugin-notification --lib - run: cargo test --locked -p cloudsync - run: "cargo test --locked -p db-core 'cloudsync::' -- --test-threads=1" - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: ./.github/actions/pnpm_install - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync shell: bash run: | cargo build --locked --release -p anarlog-cli --target x86_64-pc-windows-msvc cp \ target/x86_64-pc-windows-msvc/release/anarlog.exe \ apps/desktop/src-tauri/resources/cli/anarlog-cli-x86_64-pc-windows-msvc.exe ./scripts/sidecar.sh \ ./apps/desktop/src-tauri/tauri.conf.staging.json \ resources/cli/anarlog-cli - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: pnpm -F ui build - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: pnpm -F desktop tauri build --ci --bundles nsis --no-sign --target x86_64-pc-windows-msvc --config ./src-tauri/tauri.conf.staging.json --features devtools --verbose env: POSTHOG_API_KEY: phc_windows_ci VITE_POSTHOG_API_KEY: phc_windows_ci SENTRY_DSN: ${{ secrets.SENTRY_DSN_HYPRNOTE_2 }} VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }} VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }} VITE_APP_URL: https://anarlog.so VITE_API_URL: https://api.anarlog.so VITE_PRO_PRODUCT_ID: ${{ secrets.VITE_PRO_PRODUCT_ID }} - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync shell: pwsh run: | $bundleDir = "apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis" $installer = Get-ChildItem $bundleDir -Filter "*.exe" | Select-Object -First 1 if (-not $installer) { throw "No NSIS installer found in $bundleDir" } $hash = (Get-FileHash -Algorithm SHA256 $installer.FullName).Hash.ToLowerInvariant() "$hash $($installer.Name)" | Out-File "$($installer.FullName).sha256" -Encoding ascii -NoNewline - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync shell: pwsh timeout-minutes: 10 run: | $ErrorActionPreference = "Stop" $bundleDir = "apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis" $installers = @(Get-ChildItem $bundleDir -Filter "*.exe" -File) if ($installers.Count -ne 1) { throw "Expected one NSIS installer in $bundleDir, found $($installers.Count)" } $installer = $installers[0] $uninstallKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Anarlog Staging" $expectedInstallDir = Join-Path $env:LOCALAPPDATA "Anarlog Staging" $installDir = $null $binary = $null $uninstaller = $null $stdoutLog = Join-Path $env:RUNNER_TEMP "anarlog-windows-smoke.stdout.log" $stderrLog = Join-Path $env:RUNNER_TEMP "anarlog-windows-smoke.stderr.log" $startedAt = Get-Date $appProcess = $null $uninstallCompleted = $false function Stop-ProcessTree { param([System.Diagnostics.Process] $Process) if ($null -ne $Process -and -not $Process.HasExited) { & taskkill.exe /PID $Process.Id /T /F 2>&1 | Out-Host $Process.WaitForExit(10000) | Out-Null } } function Wait-ForSuccessfulExit { param( [System.Diagnostics.Process] $Process, [int] $TimeoutSeconds, [string] $Description ) if (-not $Process.WaitForExit($TimeoutSeconds * 1000)) { Stop-ProcessTree $Process throw "$Description timed out after $TimeoutSeconds seconds" } $Process.WaitForExit() if ($Process.ExitCode -ne 0) { throw "$Description exited with status $($Process.ExitCode)" } } if ((Test-Path $uninstallKey) -or (Test-Path $expectedInstallDir)) { throw "Refusing to smoke-test over an existing Anarlog Staging installation" } try { $installerHash = (Get-FileHash -Algorithm SHA256 $installer.FullName).Hash.ToLowerInvariant() Write-Host "Installing $($installer.FullName) (sha256: $installerHash)" $installerProcess = Start-Process $installer.FullName -ArgumentList "/S" -PassThru Wait-ForSuccessfulExit $installerProcess 180 "NSIS installation" if (-not (Test-Path $uninstallKey)) { throw "NSIS installation did not register $uninstallKey" } $installProperties = Get-ItemProperty $uninstallKey $installDir = $installProperties.InstallLocation.Trim('"') $binary = Join-Path $installDir "anarlog-staging.exe" $uninstaller = Join-Path $installDir "uninstall.exe" Write-Host "Installed version: $($installProperties.DisplayVersion)" Write-Host "Install location: $installDir" if (-not (Test-Path $binary -PathType Leaf)) { Get-ChildItem $installDir -Recurse -ErrorAction SilentlyContinue | Select-Object FullName, Length, LastWriteTime | Format-Table -AutoSize | Out-Host throw "NSIS installation did not create $binary" } Get-Item $binary | Select-Object FullName, Length, LastWriteTime | Format-List | Out-Host $appProcess = Start-Process $binary ` -ArgumentList @("--onboarding", "0") ` -PassThru ` -RedirectStandardOutput $stdoutLog ` -RedirectStandardError $stderrLog if ($appProcess.WaitForExit(20000)) { $appProcess.WaitForExit() throw "Installed Anarlog exited before the 20-second smoke window with status $($appProcess.ExitCode)" } Write-Host "Installed Anarlog remained running for the 20-second smoke window" Stop-ProcessTree $appProcess $uninstallProcess = Start-Process $uninstaller ` -ArgumentList @("/S", "_?=$installDir") ` -PassThru Wait-ForSuccessfulExit $uninstallProcess 120 "NSIS uninstallation" if ((Test-Path $binary) -or (Test-Path $uninstallKey)) { throw "NSIS uninstallation left the application binary or uninstall registry key behind" } $uninstallCompleted = $true } finally { Stop-ProcessTree $appProcess foreach ($log in @($stdoutLog, $stderrLog)) { Write-Host "----- $log -----" if (Test-Path $log) { Get-Content $log -ErrorAction SilentlyContinue | Out-Host } else { Write-Host "" } } Get-WinEvent ` -FilterHashtable @{ LogName = "Application"; StartTime = $startedAt; Level = 1, 2, 3 } ` -MaxEvents 25 ` -ErrorAction SilentlyContinue | Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message | Format-List | Out-Host $cleanupUninstaller = if ($null -ne $uninstaller) { $uninstaller } else { Join-Path $expectedInstallDir "uninstall.exe" } if (-not $uninstallCompleted -and (Test-Path $cleanupUninstaller)) { $cleanupDir = Split-Path $cleanupUninstaller -Parent $cleanupProcess = Start-Process $cleanupUninstaller ` -ArgumentList @("/S", "_?=$cleanupDir") ` -PassThru Wait-ForSuccessfulExit $cleanupProcess 120 "NSIS cleanup uninstallation" } } - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: actions/upload-artifact@v4 with: name: anarlog-windows-x64-nsis-${{ github.sha }} path: | apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.sha256 if-no-files-found: error retention-days: 7 linux_ci: if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} strategy: fail-fast: false matrix: include: - runner: ubuntu-24.04 target: x86_64-unknown-linux-gnu rust_platform: linux-x86_64 artifact_name: x64 debian_arch: amd64 file_arch: x86-64 docker_arch: amd64 cloudsync_arch: x86_64 - runner: ubuntu-24.04-arm target: aarch64-unknown-linux-gnu rust_platform: linux-aarch64 artifact_name: arm64 debian_arch: arm64 file_arch: ARM aarch64 docker_arch: arm64 cloudsync_arch: aarch64 runs-on: ${{ matrix.runner }} defaults: run: shell: bash steps: - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - uses: ./.github/actions/install_desktop_deps with: target: linux - uses: ./.github/actions/rust_install with: platform: ${{ matrix.rust_platform }} - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: crates/cloudsync/scripts/rebuild-linux.sh - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: actions/upload-artifact@v4 with: name: cloudsync-linux-gnu-${{ matrix.cloudsync_arch }}-${{ github.sha }} path: crates/cloudsync/vendor/cloudsync/linux/gnu/${{ matrix.cloudsync_arch }}/cloudsync.so if-no-files-found: error retention-days: 7 - run: cargo check --locked --target ${{ matrix.target }} -p desktop - run: cargo test --locked --target ${{ matrix.target }} -p desktop embedded_cli --lib - run: cargo test --locked --target ${{ matrix.target }} -p cloudsync - run: "cargo test --locked --target ${{ matrix.target }} -p db-core 'cloudsync::' -- --test-threads=1" - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: ./.github/actions/pnpm_install - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: | TAURI_ENV_TARGET_TRIPLE=${{ matrix.target }} cargo xtask prepare-binaries ./scripts/sidecar.sh \ ./apps/desktop/src-tauri/tauri.conf.staging.json \ resources/cli/anarlog-cli - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: pnpm -F ui build - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: pnpm -F desktop tauri build --ci --bundles appimage,deb --target ${{ matrix.target }} --config ./src-tauri/tauri.conf.staging.json --features devtools --verbose env: POSTHOG_API_KEY: phc_linux_ci VITE_POSTHOG_API_KEY: phc_linux_ci SENTRY_DSN: ${{ secrets.SENTRY_DSN_HYPRNOTE_2 }} VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }} VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }} VITE_APP_URL: https://anarlog.so VITE_API_URL: https://api.anarlog.so VITE_PRO_PRODUCT_ID: ${{ secrets.VITE_PRO_PRODUCT_ID }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: node scripts/repack-linux-appimage.mjs "apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/appimage" env: ARCH: ${{ matrix.target == 'aarch64-unknown-linux-gnu' && 'aarch64' || 'x86_64' }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: | shopt -s nullglob appimage_dir="apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/appimage" deb_dir="apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/deb" appimages=("$appimage_dir"/*.AppImage) debs=("$deb_dir"/*.deb) appimage_signatures=("$appimage_dir"/*.AppImage.sig) deb_signatures=("$deb_dir"/*.deb.sig) if [[ ${#appimages[@]} -ne 1 || ${#debs[@]} -ne 1 ]]; then echo "Expected one AppImage and one .deb for ${{ matrix.target }}" exit 1 fi if [[ ${#appimage_signatures[@]} -ne 1 || ${#deb_signatures[@]} -ne 1 ]]; then echo "Expected AppImage and .deb updater signatures for ${{ matrix.target }}" exit 1 fi package_arch=$(dpkg-deb --field "${debs[0]}" Architecture) if [[ "$package_arch" != "${{ matrix.debian_arch }}" ]]; then echo "Expected Debian architecture ${{ matrix.debian_arch }}, got $package_arch" exit 1 fi if ! file "${appimages[0]}" | grep -Fq "${{ matrix.file_arch }}"; then file "${appimages[0]}" echo "AppImage architecture does not match ${{ matrix.target }}" exit 1 fi bundles=("$appimage_dir"/* "$deb_dir"/*) for bundle in "${bundles[@]}"; do [[ -f "$bundle" && "$bundle" != *.sha256 ]] || continue # Record the basename, like the Windows job does, so `sha256sum -c` # works next to the downloaded artifact rather than only inside the # CI directory layout. name=$(basename "$bundle") (cd "$(dirname "$bundle")" && sha256sum "$name" > "$name.sha256") done - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync timeout-minutes: 10 run: | sudo apt-get update sudo apt-get install -y dbus-x11 desktop-file-utils xvfb shopt -s nullglob appimage_dir="apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/appimage" appimages=("$appimage_dir"/*.AppImage) if [[ ${#appimages[@]} -ne 1 ]]; then echo "Expected one AppImage for ${{ matrix.target }}, found ${#appimages[@]}" exit 1 fi appimage="${appimages[0]}" log="$RUNNER_TEMP/anarlog-linux-appimage-smoke.log" smoke_home="$RUNNER_TEMP/anarlog-linux-appimage-home-${{ matrix.artifact_name }}" runtime_dir="$RUNNER_TEMP/anarlog-linux-appimage-runtime-${{ matrix.artifact_name }}" mkdir -p "$smoke_home" "$runtime_dir" chmod 700 "$runtime_dir" chmod +x "$appimage" file "$appimage" sha256sum "$appimage" set +e APPIMAGE_EXTRACT_AND_RUN=1 \ HOME="$smoke_home" \ NO_AT_BRIDGE=1 \ XDG_RUNTIME_DIR="$runtime_dir" \ timeout --signal=TERM --kill-after=5s 30s \ xvfb-run -a dbus-run-session -- "$appimage" --onboarding 0 >"$log" 2>&1 & smoke_pid=$! set -e app_pid="" for _ in {1..30}; do app_pid=$(pgrep -n -x anarlog-staging || true) if [[ -n "$app_pid" ]] || ! kill -0 "$smoke_pid" 2>/dev/null; then break fi sleep 1 done if [[ -n "$app_pid" ]]; then ps -p "$app_pid" -o pid,ppid,etime,stat,comm,args || true fi set +e wait "$smoke_pid" smoke_status=$? set -e cat "$log" if [[ -z "$app_pid" ]]; then echo "AppImage did not start the anarlog-staging process within 30 seconds" exit 1 fi case "$smoke_status" in 124 | 137) echo "AppImage started and remained running through the 30-second smoke window" ;; *) echo "AppImage exited before the smoke timeout with status $smoke_status" ps -ef | grep -E '[a]narlog|[X]vfb|[d]bus' || true exit 1 ;; esac - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync run: | deb=$(find "apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/deb" -maxdepth 1 -name '*.deb' -type f -print -quit) docker run --rm \ --platform linux/${{ matrix.docker_arch }} \ --volume "$PWD:/workspace:ro" \ --env DEB_PATH="/workspace/$deb" \ --env BINARY_PATH=/usr/bin/anarlog-staging \ ubuntu:24.04 \ bash -euxo pipefail -c ' export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y "$DEB_PATH" apt-get install -y dbus-x11 xvfb set +e timeout --signal=TERM 20s xvfb-run -a dbus-run-session -- "$BINARY_PATH" >/tmp/anarlog.log 2>&1 status=$? set -e cat /tmp/anarlog.log if [[ $status -ne 124 ]]; then echo "Anarlog exited before the smoke timeout with status $status" exit 1 fi ' - if: github.event_name == 'workflow_dispatch' || inputs.rebuild_cloudsync uses: actions/upload-artifact@v4 with: name: anarlog-linux-${{ matrix.artifact_name }}-${{ github.sha }} path: | apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/appimage/* apps/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/deb/* if-no-files-found: error retention-days: 7 desktop_i18n: if: ${{ !startsWith(github.head_ref || '', 'blog/') }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - uses: ./.github/actions/pnpm_install - run: pnpm -F desktop i18n:check desktop_swift: if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} runs-on: macos-15 defaults: run: shell: bash steps: - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - run: swift build --package-path plugins/windows/swift-lib ci: if: always() needs: [ js_ci, macos_ci, windows_ci, linux_ci, desktop_i18n, desktop_swift, ] runs-on: ubuntu-latest steps: - run: exit 1 if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')