Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
69 changes: 33 additions & 36 deletions .github/workflows/desktop-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,26 +75,20 @@ jobs:
EVENT_NAME: ${{ github.event_name }}
GIT_REF: ${{ github.ref }}
run: |
# Keep one artifact per OS to stay under the repo's tight artifact quota.
# macOS arm64 only - Apple Silicon covers current Macs. The Intel (macos-13)
# runner is queue-starved and the x64 cross-compile is unreliable, so it is dropped.
mac='{"host":"macos-14","target":"darwin-arm64","platform_flag":"--mac dmg zip --arm64","group":"mac"}'
mac_arm64='{"host":"macos-14","target":"darwin-arm64","platform_flag":"--mac dmg zip --arm64","group":"mac"}'
mac_x64='{"host":"macos-26-intel","target":"darwin-x64","platform_flag":"--mac dmg zip --x64","group":"mac"}'
linux='{"host":"ubuntu-24.04","target":"linux-amd64","platform_flag":"--linux deb --x64","group":"linux"}'
# W-01 §2.2.6 win-arm64: both Windows arches are packaged in ONE electron-builder
# invocation so a single latest.yml lists both installers — electron-updater then
# serves x64 and arm64 machines from the same feed (a per-arch matrix split would
# produce two latest.yml files and silently drop one arch from the update feed).
win='{"host":"windows-2025","target":"win-x64-arm64","platform_flag":"--win nsis --x64 --arm64","group":"win"}'
win='{"host":"windows-2025","target":"win-x64","platform_flag":"--win nsis --x64","group":"win"}'
# Dev mainline pushes exercise only the Windows packaging path (the newest and
# least-runner-covered one); everything else follows the platforms selection.
if [ "$EVENT_NAME" = "push" ] && [ "$GIT_REF" = "refs/heads/dev" ]; then
items="$win"
else
case "$PLATFORMS" in
mac) items="$mac" ;;
mac) items="$mac_arm64,$mac_x64" ;;
linux) items="$linux" ;;
windows) items="$win" ;;
*) items="$mac,$linux,$win" ;;
*) items="$mac_arm64,$mac_x64,$linux,$win" ;;
esac
fi
echo "matrix={\"include\":[$items]}" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -149,18 +143,6 @@ jobs:
tenant-id: ${{ secrets.AZURE_TRUSTED_SIGNING_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_TRUSTED_SIGNING_SUBSCRIPTION_ID }}

# Cross-arch packaging: bun only installs the runner's own platform binaries,
# so the arm64 app asar would silently miss its prebuilt native modules
# (@lydell/node-pty-win32-arm64 for the terminal, @parcel/watcher-win32-arm64
# for file watching). electron-builder filters node_modules by the target
# os/cpu when copying, so installing both here yields each artifact its
# matching set. Versions must match packages/desktop/package.json
# optionalDependencies.
- name: Install arm64 Windows platform packages
if: matrix.group == 'win'
shell: pwsh
run: npm install --no-save --no-package-lock --no-audit --no-fund "@lydell/node-pty-win32-arm64@1.2.0-beta.12" "@parcel/watcher-win32-arm64@2.5.1"

# bun run build invokes the package prebuild lifecycle before electron-vite.
- name: Build renderer
working-directory: packages/desktop
Expand Down Expand Up @@ -192,25 +174,21 @@ jobs:
AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE: ${{ secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }}
run: npx electron-builder ${{ matrix.platform_flag }} --publish never --config electron-builder.config.ts

# W-01 §2.2.6 Windows smoke floor: the packaged exe launch below proves the
# x64 app boots, but NSIS-specific regressions (installer script, per-arch
# payload, signing hook) would otherwise only surface on a physical machine.
# Assert both per-arch installers exist, and when Trusted Signing ran,
# assert the installer signature actually validates on Windows.
# Assert that packaging produced the supported x64 installer and, when
# Trusted Signing ran, that its signature validates on Windows.
- name: Assert NSIS installers and signatures
if: matrix.group == 'win'
working-directory: packages/desktop
shell: pwsh
run: |
$installers = Get-ChildItem -Path dist -Filter "deepagent-code-desktop-win-*.exe" -File
$x64 = $installers | Where-Object { $_.Name -eq "deepagent-code-desktop-win-x64.exe" }
$arm64 = $installers | Where-Object { $_.Name -eq "deepagent-code-desktop-win-arm64.exe" }
if (-not $x64 -or -not $arm64) {
Write-Error "NSIS installers missing: expected win-x64 and win-arm64, found: $($installers.Name -join ', ')"
if (-not $x64 -or $installers.Count -ne 1) {
Write-Error "NSIS installers mismatch: expected only win-x64, found: $($installers.Name -join ', ')"
exit 1
}
if ($env:HAS_TRUSTED_SIGNING -eq "true") {
foreach ($installer in @($x64, $arm64)) {
foreach ($installer in @($x64)) {
$signature = Get-AuthenticodeSignature -FilePath $installer.FullName
if ($signature.Status -ne "Valid") {
Write-Error "$($installer.Name) signature status '$($signature.Status)': $($signature.StatusMessage)"
Expand All @@ -226,7 +204,7 @@ jobs:
if: matrix.group == 'mac'
working-directory: packages/desktop
run: |
executable=$(find dist/mac-arm64 -maxdepth 4 -type f -path '*/Contents/MacOS/DeepAgent Code*' -perm +111 -print -quit)
executable=$(find dist -maxdepth 5 -type f -path '*/Contents/MacOS/DeepAgent Code*' -perm +111 -print -quit)
test -n "$executable"
DEEPAGENT_CODE_DESKTOP_EXECUTABLE="$executable" bun run test:subagents-cold-start

Expand All @@ -241,9 +219,7 @@ jobs:
working-directory: packages/desktop
shell: pwsh
run: |
# win-unpacked holds the x64 app (the arch the x64 runner can execute;
# arm64 lands in win-arm64-unpacked and is covered by the installer
# assertion above). Wildcard matches both prod ("DeepAgent Code.exe")
# win-unpacked holds the x64 app. Wildcard matches both prod ("DeepAgent Code.exe")
# and beta ("DeepAgent Code Beta.exe") artifact names so the beta build
# cannot silently fail this smoke because of an exact name filter.
$exe = Get-ChildItem -Path "dist/win-unpacked" -Filter "*DeepAgent Code*.exe" -Recurse -File | Select-Object -First 1
Expand Down Expand Up @@ -277,12 +253,26 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: package.json

- uses: actions/download-artifact@v4
with:
pattern: deepagent-code-desktop-*
path: release-assets
merge-multiple: true

- uses: actions/download-artifact@v4
with:
name: deepagent-code-desktop-darwin-arm64
path: /tmp/latest-yml-aarch64-apple-darwin

- uses: actions/download-artifact@v4
with:
name: deepagent-code-desktop-darwin-x64
path: /tmp/latest-yml-x86_64-apple-darwin

- name: Publish latest desktop release
env:
GH_TOKEN: ${{ github.token }}
Expand All @@ -293,6 +283,13 @@ jobs:
version=$(node -p 'require("./packages/desktop/package.json").version.replace(/-.*/, "")')
tag="app-v${version}-main.${GITHUB_RUN_NUMBER}"

# The two native Mac jobs each write latest-mac.yml; publish one feed
# containing both supported architectures instead of whichever artifact
# happened to win the merge-multiple download.
LATEST_YML_DIR=/tmp GH_REPO="$REPOSITORY" DEEPAGENT_CODE_VERSION="$version" \
RUNNER_TEMP="$RUNNER_TEMP" bun packages/desktop/scripts/finalize-latest-yml.ts --dry-run
cp "$RUNNER_TEMP/latest-mac.yml" release-assets/latest-mac.yml

mapfile -t assets < <(find release-assets -type f \( -name 'latest*.yml' -o -name '*.blockmap' -o -name '*.dmg' -o -name '*.zip' -o -name '*.deb' -o -name '*.exe' \) | sort)
if [ "${#assets[@]}" -eq 0 ]; then
echo "No desktop release assets found"
Expand Down
Loading
Loading