From f5bdf0bfc55e632752c24dfb7f98b3b52c46cb1b Mon Sep 17 00:00:00 2001 From: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 Date: Fri, 12 Jun 2026 23:18:30 -0400 Subject: [PATCH 1/3] fix(desktop): make Windows release compile cleanly The release workflow's Windows job failed to compile two source files containing platform-conditional code never validated on Windows: PR CI builds the desktop app for macOS/Linux only, so these surfaced only at release time. migration.rs called std::os::unix::fs::symlink unconditionally in the dev-only worktree-sync helper; gate it behind a #[cfg]-selected symlink helper (no-op on non-unix), matching the existing copy_dir_all convention. media.rs cast a file handle to isize, but windows-sys 0.61 changed HANDLE to *mut c_void; cast to the matching type. Co-authored-by: Will Pfleger Signed-off-by: Will Pfleger --- desktop/src-tauri/src/commands/media.rs | 2 +- desktop/src-tauri/src/migration.rs | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/desktop/src-tauri/src/commands/media.rs b/desktop/src-tauri/src/commands/media.rs index 94451c8e7..e96e1f36c 100644 --- a/desktop/src-tauri/src/commands/media.rs +++ b/desktop/src-tauri/src/commands/media.rs @@ -83,7 +83,7 @@ fn fd_real_path(file: &std::fs::File) -> Result { use windows_sys::Win32::Storage::FileSystem::{ GetFinalPathNameByHandleW, FILE_NAME_NORMALIZED, }; - let handle = file.as_raw_handle() as isize; + let handle = file.as_raw_handle() as *mut core::ffi::c_void; let mut buf = vec![0u16; 1024]; let len = unsafe { GetFinalPathNameByHandleW( diff --git a/desktop/src-tauri/src/migration.rs b/desktop/src-tauri/src/migration.rs index 5ddf7e143..48df3af84 100644 --- a/desktop/src-tauri/src/migration.rs +++ b/desktop/src-tauri/src/migration.rs @@ -36,6 +36,21 @@ const SHARED_AGENT_FILES: &[&str] = &[ /// dev data directory. Each entry becomes a single directory symlink. const SHARED_AGENT_DIRS: &[&str] = &["agents/teams"]; +/// Create a symlink at `dst` pointing to `src`. +/// +/// Worktree sync is a dev-only feature (`BUZZ_SHARE_IDENTITY=1`); on Windows +/// this is a no-op so the rest of `sync_shared_agent_data` keeps compiling and +/// running harmlessly. +#[cfg(unix)] +fn symlink(src: &Path, dst: &Path) -> std::io::Result<()> { + std::os::unix::fs::symlink(src, dst) +} + +#[cfg(not(unix))] +fn symlink(_src: &Path, _dst: &Path) -> std::io::Result<()> { + Ok(()) +} + fn canonical_dev_data_dir(current: &Path) -> Option { current.parent().map(|p| p.join(CANONICAL_DEV_IDENTIFIER)) } @@ -244,7 +259,7 @@ pub fn sync_shared_agent_data(app: &tauri::AppHandle) { let _ = std::fs::remove_file(&dst); } - match std::os::unix::fs::symlink(&src, &dst) { + match symlink(&src, &dst) { Ok(_) => synced += 1, Err(e) => { eprintln!("buzz-desktop: shared-agent-sync: failed to symlink {rel}: {e}"); @@ -284,7 +299,7 @@ pub fn sync_shared_agent_data(app: &tauri::AppHandle) { } // Replace the sibling's dir with a symlink to canonical. let _ = std::fs::remove_dir_all(&sibling_dir); - let _ = std::os::unix::fs::symlink(&canonical_target, &sibling_dir); + let _ = symlink(&canonical_target, &sibling_dir); eprintln!( "buzz-desktop: shared-agent-sync: migrated {rel} from {}", sibling.display() @@ -329,7 +344,7 @@ pub fn sync_shared_agent_data(app: &tauri::AppHandle) { let _ = std::fs::remove_dir_all(&dst); } - match std::os::unix::fs::symlink(&src, &dst) { + match symlink(&src, &dst) { Ok(_) => synced += 1, Err(e) => { eprintln!("buzz-desktop: shared-agent-sync: failed to symlink {rel}: {e}"); From f89ca18e98c9b5f936920a40e025b9af813b63a3 Mon Sep 17 00:00:00 2001 From: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 Date: Sat, 13 Jun 2026 12:18:12 -0400 Subject: [PATCH 2/3] refactor(release): run all four platform builds concurrently after shared setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The arm64 'release' job created the GitHub release objects and computed the version string, so the other three platform jobs were chained behind it via needs: release. That serialized four independent builds and coupled them to arm64 codesign — a branch dispatch could never reach the Windows job because arm64's OIDC AssumeRole is denied on non-release refs, skipping everything downstream. Extract a no-OIDC 'setup' job that determines the version and creates both the versioned and rolling releases up front. All four platform jobs now depend only on setup and run concurrently; setup is the sole release creator, the platform jobs are pure uploaders, removing the create race the concurrency change would otherwise expose. Rolling-release uploads and the latest.json assembly are gated on tag pushes so a branch dispatch can validate compiles without clobbering the live auto-update channel. Co-authored-by: Will Pfleger Signed-off-by: Will Pfleger --- .github/workflows/release.yml | 130 +++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 49 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d6007c234..820e40975 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,18 +15,19 @@ on: required: true jobs: - release: - name: Release + # Shared setup: determine the version and create the release objects all four + # platform jobs upload into. Runs on ubuntu with no OIDC so a branch + # workflow_dispatch can exercise the platform builds without the codesign + # AssumeRole wall that gates the arm64 job. + setup: + name: Setup if: github.repository == 'block/buzz' - runs-on: macos-latest - timeout-minutes: 60 + runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: write - id-token: write # required by block/apple-codesign-action for OIDC outputs: version: ${{ steps.version.outputs.version }} - archive_name: ${{ steps.artifacts.outputs.archive_name }} - sig: ${{ steps.read-sig.outputs.sig }} steps: - name: Determine version id: version @@ -50,6 +51,61 @@ jobs: exit 1 fi + # Checkout at the same ref the platform jobs use so git rev-parse HEAD + # pins the release to the right commit via --target. + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + ref: ${{ github.event_name == 'push' && github.ref || inputs.ref }} + persist-credentials: false + + - name: Create versioned GitHub release + env: + VERSION: ${{ steps.version.outputs.version }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + RELEASE_SHA=$(git rev-parse HEAD) + NOTES="" + if [[ -f CHANGELOG.md ]]; then + NOTES=$(awk "/^## v${VERSION}$/,/^## v/" CHANGELOG.md | sed '$d') + fi + if [[ -z "$NOTES" ]]; then + NOTES="Buzz Desktop v${VERSION}" + fi + PRERELEASE_FLAGS=() + if [[ "$VERSION" =~ -(test|alpha|beta|rc)([.-]|$) ]]; then + PRERELEASE_FLAGS=(--prerelease --latest=false) + fi + gh release create "v${VERSION}" \ + --target "$RELEASE_SHA" \ + --title "Buzz Desktop v${VERSION}" \ + --notes "$NOTES" \ + "${PRERELEASE_FLAGS[@]}" + + - name: Create rolling auto-update release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create buzz-desktop-latest \ + --prerelease \ + --title "Buzz Desktop Auto-Update" \ + --notes "Rolling release for the Tauri auto-updater. Do not download manually — use the versioned release instead." \ + 2>/dev/null || true + + release: + name: Release + if: github.repository == 'block/buzz' + runs-on: macos-latest + needs: setup + timeout-minutes: 60 + permissions: + contents: write + id-token: write # required by block/apple-codesign-action for OIDC + outputs: + archive_name: ${{ steps.artifacts.outputs.archive_name }} + sig: ${{ steps.read-sig.outputs.sig }} + env: + VERSION: ${{ needs.setup.outputs.version }} + steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: ref: ${{ github.event_name == 'push' && github.ref || inputs.ref }} @@ -61,8 +117,6 @@ jobs: run: just desktop-install-ci - name: Patch version - env: - VERSION: ${{ steps.version.outputs.version }} run: | cd desktop && node scripts/set-version-from-tag.mjs "$VERSION" cd src-tauri && cargo update --workspace @@ -218,38 +272,15 @@ jobs: env: SIG_PATH: ${{ steps.artifacts.outputs.sig }} - - name: Create versioned GitHub release + - name: Upload arm64 DMG to versioned GitHub release env: - VERSION: ${{ steps.version.outputs.version }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} DMG_PATH: ${{ steps.artifacts.outputs.dmg }} - run: | - RELEASE_SHA=$(git rev-parse HEAD) - NOTES="" - if [[ -f CHANGELOG.md ]]; then - NOTES=$(awk "/^## v${VERSION}$/,/^## v/" CHANGELOG.md | sed '$d') - fi - if [[ -z "$NOTES" ]]; then - NOTES="Buzz Desktop v${VERSION}" - fi - PRERELEASE_FLAGS=() - if [[ "$VERSION" =~ -(test|alpha|beta|rc)([.-]|$) ]]; then - PRERELEASE_FLAGS=(--prerelease --latest=false) - fi - gh release create "v${VERSION}" \ - --target "$RELEASE_SHA" \ - --title "Buzz Desktop v${VERSION}" \ - --notes "$NOTES" \ - "${PRERELEASE_FLAGS[@]}" \ - "$DMG_PATH" + run: gh release upload "v${VERSION}" "$DMG_PATH" --clobber - name: Upload updater archive to rolling release + if: github.event_name == 'push' run: | - gh release create buzz-desktop-latest \ - --prerelease \ - --title "Buzz Desktop Auto-Update" \ - --notes "Rolling release for the Tauri auto-updater. Do not download manually — use the versioned release instead." \ - 2>/dev/null || true gh release upload buzz-desktop-latest \ "$ARCHIVE_PATH" \ "$SIG_PATH" \ @@ -263,7 +294,7 @@ jobs: name: Release macOS (Intel) if: github.repository == 'block/buzz' runs-on: macos-latest - needs: release + needs: setup timeout-minutes: 60 permissions: contents: write @@ -272,7 +303,7 @@ jobs: archive_name: ${{ steps.artifacts.outputs.archive_name }} sig: ${{ steps.read-sig.outputs.sig }} env: - VERSION: ${{ needs.release.outputs.version }} + VERSION: ${{ needs.setup.outputs.version }} TARGET: x86_64-apple-darwin steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -397,6 +428,7 @@ jobs: DMG_PATH: ${{ steps.unsigned.outputs.dmg }} - name: Upload updater archive to rolling release + if: github.event_name == 'push' run: | gh release upload buzz-desktop-latest \ "$ARCHIVE_PATH" \ @@ -411,7 +443,7 @@ jobs: name: Release Linux if: github.repository == 'block/buzz' runs-on: ubuntu-latest - needs: release + needs: setup timeout-minutes: 60 permissions: contents: write @@ -462,7 +494,7 @@ jobs: - name: Patch version env: - VERSION: ${{ needs.release.outputs.version }} + VERSION: ${{ needs.setup.outputs.version }} run: | cd desktop && node scripts/set-version-from-tag.mjs "$VERSION" cd src-tauri && cargo update --workspace @@ -531,7 +563,7 @@ jobs: # NOTE: .deb is NOT auto-updatable (Tauri updater constraint — only AppImage supports it on Linux) - name: Upload Linux artifacts to versioned GitHub release env: - VERSION: ${{ needs.release.outputs.version }} + VERSION: ${{ needs.setup.outputs.version }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} DEB_PATH: ${{ steps.linux-artifacts.outputs.deb }} APPIMAGE_PATH: ${{ steps.linux-artifacts.outputs.appimage }} @@ -542,6 +574,7 @@ jobs: --clobber - name: Upload updater archive to rolling release + if: github.event_name == 'push' run: | gh release upload buzz-desktop-latest \ "$ARCHIVE_PATH" \ @@ -555,7 +588,7 @@ jobs: release-windows: name: Release Windows runs-on: windows-latest - needs: release + needs: setup timeout-minutes: 60 permissions: contents: write @@ -563,7 +596,7 @@ jobs: archive_name: ${{ steps.artifacts.outputs.archive_name }} sig: ${{ steps.read-sig.outputs.sig }} env: - VERSION: ${{ needs.release.outputs.version }} + VERSION: ${{ needs.setup.outputs.version }} TARGET: x86_64-pc-windows-msvc steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -664,6 +697,7 @@ jobs: EXE_PATH: ${{ steps.artifacts.outputs.exe }} - name: Upload updater archive to rolling release + if: github.event_name == 'push' shell: bash run: | gh release upload buzz-desktop-latest \ @@ -677,13 +711,16 @@ jobs: assemble-manifest: name: Assemble multi-platform latest.json + # Only a real tag push assembles latest.json — a branch workflow_dispatch + # skips the rolling-release uploads, so its archive URLs never exist. + if: github.event_name == 'push' runs-on: ubuntu-latest - needs: [release, release-macos-x64, release-linux, release-windows] + needs: [setup, release, release-macos-x64, release-linux, release-windows] timeout-minutes: 10 permissions: contents: write env: - VERSION: ${{ needs.release.outputs.version }} + VERSION: ${{ needs.setup.outputs.version }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -745,9 +782,4 @@ jobs: - name: Upload latest.json to rolling release run: | - gh release create buzz-desktop-latest \ - --prerelease \ - --title "Buzz Desktop Auto-Update" \ - --notes "Rolling release for the Tauri auto-updater. Do not download manually — use the versioned release instead." \ - 2>/dev/null || true gh release upload buzz-desktop-latest latest.json --clobber From 46536d6339198af7914f17baa614291616d69c5b Mon Sep 17 00:00:00 2001 From: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 Date: Sat, 13 Jun 2026 13:15:56 -0400 Subject: [PATCH 3/3] fix(desktop): bundle SQLite so Windows release links After the source-level Windows compile fixes, the release build reached the link stage and failed with LNK1181: cannot open input file 'sqlite3.lib'. rusqlite was declared without the bundled feature, so libsqlite3-sys tried to link a system sqlite3.lib that windows-latest does not provide. Enable rusqlite's bundled feature to compile and statically link SQLite from vendored source, removing the system-library dependency on all platforms. Co-authored-by: Will Pfleger Signed-off-by: Will Pfleger --- desktop/src-tauri/Cargo.lock | 1 + desktop/src-tauri/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index ff71614f9..1919df4e6 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -4213,6 +4213,7 @@ version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" dependencies = [ + "cc", "pkg-config", "vcpkg", ] diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index 143caba46..c0482d28c 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -79,7 +79,7 @@ png = "0.18" zip = "8" sherpa-onnx = "1.12" regex = "1" -rusqlite = "0.37" +rusqlite = { version = "0.37", features = ["bundled"] } axum = "0.8" rodio = "0.22" earshot = "1.0"