mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
## Summary Carl, an automated agent, implementing on Wes's request. Fix ordinary Desktop dev checkouts being misclassified as linked worktrees when launched through `just production`, `staging`, or other recipes that source `instance-env.sh` from `desktop/`. From the repository root, Git reports both directories as `.git`. From `desktop/`, it can report an absolute `--git-dir` and `../.git` for `--git-common-dir`. The textual comparison treats them as different and chooses a branch-suffixed app profile (for example `.dev.main`) instead of the canonical `.dev` profile populated by the agent-adoption script. - Request `--path-format=absolute` for both paths. Actual linked worktrees still have distinct Git/common directories and retain their existing isolated app identities. - Add eight isolated fixture cases executing the real environment script with real Git: ordinary root/subdirectory on main and feature branches, linked root/subdirectory, detached linked subdirectory, and symlinked ordinary subdirectory. Paths contain spaces. Only native icon generation is stubbed; no user profile, keychain, app, or relay is accessed. - Run the regression in the existing always-run CI contract job. No agent migration, global-settings copy, keychain changes, profile merging, branch-label redesign, or packaged-release behavior changes. Existing Git `--path-format` support is required (Git 2.31+). ### Related issue Searched open PRs for `instance-env` and worktree titles, and open issues for dev-profile/adoption reports. No matching path-normalization fix found. - #7142 touches `instance-env.sh` for descriptive labels. This fix is independent; it uses a distinct test filename to avoid colliding with that PR's new `test-instance-env.sh`. - #6915 proposes a separate release-profile launch recipe; this fix preserves the current dev-profile contract instead. ### Testing At exact head `0a09a2f3716b0378546b66be2302b750ed4330b9`: - `scripts/test-desktop-instance-detection.sh`: **8/8 passed**. - Before the production change, the same regression failed on the ordinary checkout's `desktop/` case: actual `xyz.block.buzz.app.dev.main`, expected `xyz.block.buzz.app.dev`. - `bash -n scripts/instance-env.sh scripts/test-desktop-instance-detection.sh`: passed. - `git diff --check`: passed before commit; pre-commit and commit-msg hooks completed. - Applicable pre-push gates passed: branch-skew, push-head-scope, and file-size policy (6 tests plus all three entrypoints). Rust/Desktop/Mobile package lanes were correctly inapplicable to this shell/CI-only diff. No native app launch or first-boot key import was performed. The validated boundary is the generated launch environment/profile identity, not successful agent startup. Hosted CI has not been checked or represented as green. Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <32a2e2c9d428ee08902cab75d956da2c1d235a22d4766b0dd4138bf6e2e5db1d@buzz.block.builderlab.xyz>
100 lines
5.4 KiB
Bash
Executable File
100 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Computes the full multi-instance desktop dev environment.
|
|
# Source this file from desktop dev commands; it exports:
|
|
# BUZZ_VITE_PORT, BUZZ_HMR_PORT, VITE_PORT, VITE_HMR_PORT
|
|
# BUZZ_RELAY_PORT, BUZZ_RELAY_URL
|
|
# BUZZ_INSTANCE_SLUG, BUZZ_WORKTREE_LABEL, VITE_DEV_BRANCH (worktrees only)
|
|
# BUZZ_TAURI_CONFIG
|
|
# BUZZ_PRIVATE_KEY (worktrees only, when BUZZ_SHARE_IDENTITY=1)
|
|
|
|
WORKTREE_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
|
|
# Derive a stable base port from the worktree root so the same worktree always
|
|
# gets the same ports. This keeps the Tauri dev config stable between runs and
|
|
# preserves Cargo's build cache.
|
|
BASE_PORT=$(python3 -c "import hashlib,sys; h=int(hashlib.sha256(sys.argv[1].encode()).hexdigest(), 16); print(10000 + h % 55000)" "$WORKTREE_ROOT")
|
|
export BUZZ_VITE_PORT=$BASE_PORT
|
|
export BUZZ_HMR_PORT=$((BASE_PORT + 1))
|
|
export BUZZ_RELAY_PORT=3000
|
|
export VITE_PORT="$BUZZ_VITE_PORT"
|
|
export VITE_HMR_PORT="$BUZZ_HMR_PORT"
|
|
export BUZZ_RELAY_URL="${BUZZ_RELAY_URL:-ws://localhost:3000}"
|
|
|
|
DEV_URL="http://localhost:${BUZZ_VITE_PORT}"
|
|
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\"}"
|
|
unset VITE_DEV_BRANCH
|
|
|
|
# In worktrees, extract a label from the branch name and derive a unique app
|
|
# identity and icon so multiple local desktop instances can run side by side.
|
|
#
|
|
# Worktree detection: compare --git-dir to --git-common-dir. In the main
|
|
# working tree these identify the same directory; in any linked worktree
|
|
# (whether under .worktrees/, .claude/worktrees/, or elsewhere) they differ.
|
|
# Normalize both paths: callers run from desktop/, where Git can otherwise
|
|
# return an absolute --git-dir but a relative --git-common-dir for the same .git.
|
|
if git rev-parse --is-inside-work-tree &>/dev/null; then
|
|
GIT_DIR=$(git rev-parse --path-format=absolute --git-dir)
|
|
GIT_COMMON_DIR=$(git rev-parse --path-format=absolute --git-common-dir 2>/dev/null)
|
|
if [[ -n "$GIT_COMMON_DIR" && "$GIT_DIR" != "$GIT_COMMON_DIR" ]]; then
|
|
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
|
|
export BUZZ_WORKTREE_LABEL="${BRANCH_NAME##*/}"
|
|
export BUZZ_INSTANCE_SLUG=$(echo "$BRANCH_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//')
|
|
|
|
# BUZZ_SHARE_IDENTITY=1: reuse the main dev checkout's Nostr key so
|
|
# worktrees skip onboarding and share the same identity. The per-worktree
|
|
# identifier is kept so concurrent instances don't collide on
|
|
# tauri-plugin-single-instance or the app data directory.
|
|
if [[ "${BUZZ_SHARE_IDENTITY:-0}" == "1" ]]; then
|
|
KEYRING_SERVICE="buzz-desktop-dev"
|
|
KEYRING_BLOB=""
|
|
case "$(uname -s)" in
|
|
Darwin)
|
|
if command -v security &>/dev/null; then
|
|
KEYRING_BLOB="$(security find-generic-password -s "$KEYRING_SERVICE" -a secrets -w 2>/dev/null || true)"
|
|
fi
|
|
;;
|
|
Linux)
|
|
if command -v secret-tool &>/dev/null; then
|
|
KEYRING_BLOB="$(secret-tool lookup service "$KEYRING_SERVICE" username secrets target default 2>/dev/null || true)"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
KEYRING_IDENTITY="$(printf '%s' "$KEYRING_BLOB" | python3 -c 'import json, sys; value = json.load(sys.stdin).get("identity", ""); print(value if isinstance(value, str) else "")' 2>/dev/null || true)"
|
|
CANONICAL_KEY="$HOME/Library/Application Support/xyz.block.buzz.app.dev/identity.key"
|
|
LEGACY_CANONICAL_KEY="$HOME/Library/Application Support/xyz.block.sprout.app.dev/identity.key"
|
|
|
|
SHARED_IDENTITY="$KEYRING_IDENTITY"
|
|
if [[ -z "$SHARED_IDENTITY" && -f "$CANONICAL_KEY" ]]; then
|
|
SHARED_IDENTITY="$(cat "$CANONICAL_KEY")"
|
|
elif [[ -z "$SHARED_IDENTITY" && -f "$LEGACY_CANONICAL_KEY" ]]; then
|
|
SHARED_IDENTITY="$(cat "$LEGACY_CANONICAL_KEY")"
|
|
fi
|
|
|
|
if [[ -n "$SHARED_IDENTITY" ]]; then
|
|
export BUZZ_PRIVATE_KEY="$SHARED_IDENTITY"
|
|
else
|
|
echo "⚠ BUZZ_SHARE_IDENTITY=1 but no identity found in keyring service $KEYRING_SERVICE, at $CANONICAL_KEY, or at $LEGACY_CANONICAL_KEY — run Buzz from repo root first" >&2
|
|
fi
|
|
fi
|
|
|
|
ICON_DIR="$WORKTREE_ROOT/desktop/src-tauri/target/dev-icons"
|
|
mkdir -p "$ICON_DIR"
|
|
DEV_ICON="$ICON_DIR/icon.icns"
|
|
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
|
|
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\"]}}"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
export BUZZ_TAURI_CONFIG
|