Skip to content
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ jobs:
scripts/test-mobile-release-candidate-publisher.sh
- name: Mobile worktree identity contract
run: scripts/test-mobile-worktree-overrides.sh
- name: Desktop dev command contract
run: scripts/test-desktop-dev-command-contract.sh
- name: Codex security review contract
run: just security-review-check
- name: Rust cache contract
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"identifier": "xyz.block.buzz.app",
"build": {
"beforeDevCommand": {
"script": "exec ./node_modules/.bin/vite",
"script": "pnpm exec vite",
"cwd": "..",
"wait": false
},
Expand Down
15 changes: 12 additions & 3 deletions scripts/instance-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,16 @@ if [[ "${BUZZ_RESET_WEBVIEW_STATE:-0}" == "1" ]]; then
DEV_URL="${DEV_URL}?resetDevState=1"
fi

BUZZ_TAURI_CONFIG="{\"build\":{\"devUrl\":\"${DEV_URL}\",\"beforeDevCommand\":\"exec ./node_modules/.bin/vite --port ${BUZZ_VITE_PORT} --strictPort\"},\"identifier\":\"xyz.block.buzz.app.dev\",\"productName\":\"Buzz Dev\"}"
# Tauri runs this through `cmd /C` on Windows, which has no `exec` and cannot
# execute the extensionless `.bin/vite` shim. `pnpm exec` resolves the local
# Vite binary on every platform; elsewhere `exec` still hands the shell's
# process slot to pnpm so Tauri's Ctrl+C reaches the launched command.
case "${BUZZ_TEST_PLATFORM:-$(uname -s)}" in
MINGW*|MSYS*|CYGWIN*) VITE_LAUNCH="pnpm exec vite" ;;
*) VITE_LAUNCH="exec pnpm exec vite" ;;
esac

BUZZ_TAURI_CONFIG="{\"build\":{\"devUrl\":\"${DEV_URL}\",\"beforeDevCommand\":{\"script\":\"${VITE_LAUNCH} --port ${BUZZ_VITE_PORT} --strictPort\",\"cwd\":\"..\",\"wait\":false}},\"identifier\":\"xyz.block.buzz.app.dev\",\"productName\":\"Buzz Dev\"}"
unset VITE_DEV_BRANCH

# In worktrees, extract a label from the branch name and derive a unique app
Expand Down Expand Up @@ -86,10 +95,10 @@ if git rev-parse --is-inside-work-tree &>/dev/null; then
GENERATE_DEV_ICON="$WORKTREE_ROOT/scripts/generate-dev-icon.swift"
BASE_ICON="$WORKTREE_ROOT/desktop/src-tauri/icons/icon.icns"

if swift "$GENERATE_DEV_ICON" "$BASE_ICON" "$DEV_ICON" "$BUZZ_WORKTREE_LABEL"; then
if [[ "$(uname -s)" == Darwin ]] && command -v swift &>/dev/null && swift "$GENERATE_DEV_ICON" "$BASE_ICON" "$DEV_ICON" "$BUZZ_WORKTREE_LABEL"; then
echo "🌳 Worktree: ${BUZZ_WORKTREE_LABEL}"
export VITE_DEV_BRANCH="$BUZZ_WORKTREE_LABEL"
BUZZ_TAURI_CONFIG="{\"build\":{\"devUrl\":\"${DEV_URL}\",\"beforeDevCommand\":\"exec ./node_modules/.bin/vite --port ${BUZZ_VITE_PORT} --strictPort\"},\"identifier\":\"xyz.block.buzz.app.dev.${BUZZ_INSTANCE_SLUG}\",\"productName\":\"Buzz Dev (${BUZZ_WORKTREE_LABEL})\",\"bundle\":{\"icon\":[\"$DEV_ICON\"]}}"
BUZZ_TAURI_CONFIG="{\"build\":{\"devUrl\":\"${DEV_URL}\",\"beforeDevCommand\":{\"script\":\"${VITE_LAUNCH} --port ${BUZZ_VITE_PORT} --strictPort\",\"cwd\":\"..\",\"wait\":false}},\"identifier\":\"xyz.block.buzz.app.dev.${BUZZ_INSTANCE_SLUG}\",\"productName\":\"Buzz Dev (${BUZZ_WORKTREE_LABEL})\",\"bundle\":{\"icon\":[\"$DEV_ICON\"]}}"
fi
fi
fi
Expand Down
88 changes: 88 additions & 0 deletions scripts/test-desktop-dev-command-contract.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env bash
set -euo pipefail

repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)

assert_dev_command() {
node -e '
const config = JSON.parse(process.argv[1]);
const expectedScript = process.argv[2];
const command = config.build.beforeDevCommand;
if (
typeof command !== "object" ||
command.script !== expectedScript ||
command.cwd !== ".." ||
command.wait !== false
) {
console.error("unexpected beforeDevCommand:", JSON.stringify(command));
process.exit(1);
}
' "$1" "$2"
}

config_for_platform() {
local platform=$1
(
cd "$repo_root/desktop"
export BUZZ_TEST_PLATFORM="$platform"
source ../scripts/instance-env.sh >/dev/null 2>&1
printf '%s' "$BUZZ_TAURI_CONFIG"
)
}

port_from_json() {
node -e '
const config = JSON.parse(process.argv[1]);
process.stdout.write(new URL(config.build.devUrl).port);
' "$1"
}

base_config=$(cat "$repo_root/desktop/src-tauri/tauri.conf.json")
assert_dev_command "$base_config" "pnpm exec vite"

windows_config=$(config_for_platform MINGW64_NT-10.0)
windows_port=$(port_from_json "$windows_config")
assert_dev_command "$windows_config" "pnpm exec vite --port ${windows_port} --strictPort"

unix_config=$(config_for_platform Darwin)
unix_port=$(port_from_json "$unix_config")
assert_dev_command "$unix_config" "exec pnpm exec vite --port ${unix_port} --strictPort"

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
mkdir -p "$tmp/bin"
cat > "$tmp/bin/git" <<'MOCK_GIT'
#!/usr/bin/env bash
case "$*" in
"rev-parse --show-toplevel") printf '%s\n' "$TEST_REPO_ROOT" ;;
"rev-parse --is-inside-work-tree") printf '%s\n' true ;;
"rev-parse --git-dir") printf '%s\n' "$TEST_REPO_ROOT/.git/worktrees/windows-test" ;;
"rev-parse --git-common-dir") printf '%s\n' "$TEST_REPO_ROOT/.git" ;;
"rev-parse --abbrev-ref HEAD") printf '%s\n' feature/windows-test ;;
*) exit 1 ;;
esac
MOCK_GIT
cat > "$tmp/bin/uname" <<'MOCK_UNAME'
#!/usr/bin/env bash
printf '%s\n' MINGW64_NT-10.0
MOCK_UNAME
cat > "$tmp/bin/swift" <<'MOCK_SWIFT'
#!/usr/bin/env bash
touch "$SWIFT_CALLED_MARKER"
exit 1
MOCK_SWIFT
chmod +x "$tmp/bin/git" "$tmp/bin/uname" "$tmp/bin/swift"

export TEST_REPO_ROOT="$repo_root"
export SWIFT_CALLED_MARKER="$tmp/swift-called"
(
export PATH="$tmp/bin:$PATH"
cd "$repo_root/desktop"
source ../scripts/instance-env.sh >/dev/null 2>&1
)
if [[ -e "$SWIFT_CALLED_MARKER" ]]; then
echo "expected Windows desktop setup to skip the macOS Swift icon generator" >&2
exit 1
fi

echo "desktop dev command contract test passed"