From e93b29d921fe2362469ade6140ed2a89a0bc8484 Mon Sep 17 00:00:00 2001 From: Yuval Hayke Date: Thu, 9 Jul 2026 18:39:50 +0300 Subject: [PATCH] chore(demo): fix screenshot mode leaking pinned repos, add worktree fixture FLEET_DEMO_PREFIX filtered sessions but never pinned repos, so every real pinned repo still rendered as a sidebar header in a demo/screenshot run. Route the session filter and the pinned-repo load through a shared demoPathVisible() helper so the two can't drift apart again. Also enrich the demo fixture: api-server gets a fake origin remote plus a linked worktree on feat/auth, so the sidebar shows a real "origin -> main repo + worktree" grouping (main clone stays clean, the worktree carries the dirty edit + approved PR badge). Add make demo / demo-setup / demo-clean targets so launching the demo isn't a remembered env-var incantation. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01W2kWH9hdd7ZN8NF1rxh42U --- Makefile | 19 ++++++++++++++++++- demo/setup.sh | 19 +++++++++++++++---- internal/ui/app.go | 19 ++++++++++++++++--- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 97349dc5..77db26a1 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,9 @@ BINARY := fleet BUILD_DIR := build VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") -.PHONY: build run clean test fmt install lint coverage deps vet setup +.PHONY: build run clean test fmt install lint coverage deps vet setup demo demo-setup demo-clean + +DEMO_PREFIX := /tmp/fleet-demo build: go build -v -ldflags "-s -w -X main.version=$(VERSION)" -o $(BUILD_DIR)/$(BINARY) ./cmd/fleet @@ -44,3 +46,18 @@ install: build setup: pre-commit install + +# --- Demo / screenshot mode ------------------------------------------------- +# demo-setup builds a throwaway fleet under $(DEMO_PREFIX): fake repos, one +# worktree grouped under its origin, and 5 sessions. `make demo` then launches +# fleet filtered to just those repos (FLEET_DEMO_PREFIX) with the fake gh on +# PATH so PR badges render. `make demo-clean` tears it all down. +# Typical flow: make demo-setup (wait ~30s) make demo +demo-setup: + bash demo/setup.sh + +demo: build + FLEET_DEMO_PREFIX=$(DEMO_PREFIX) PATH="$(CURDIR)/demo:$$PATH" $(BUILD_DIR)/$(BINARY) + +demo-clean: + bash demo/cleanup.sh diff --git a/demo/setup.sh b/demo/setup.sh index 174ff508..d0bff74c 100755 --- a/demo/setup.sh +++ b/demo/setup.sh @@ -66,8 +66,19 @@ type User struct { // TODO: add authentication middleware EOF git add -A && git commit -q -m "init: basic Go web API" -git checkout -q -b feat/auth -echo "// wip" >> internal/handlers/users.go + +# Fake remote so the main clone and its worktree share ONE origin in fleet's +# sidebar. Origin identity comes from remote.origin.url (git.GetOriginKey); +# without a remote each folder falls back to a distinct local: and +# the two checkouts split into separate groups instead of grouping together. +git remote add origin https://github.com/example/api-server.git + +# Feature work lives in a linked worktree (the real fleet flow), not the main +# checkout — this is what yields the "origin → main repo + worktree" grouping. +# Main stays on `main` (clean); the worktree holds feat/auth (dirty + PR #42). +WT1="$DEMO_DIR/api-server-feat-auth" +git worktree add -q "$WT1" -b feat/auth +echo "// wip" >> "$WT1/internal/handlers/users.go" # Repo 2: React dashboard REPO2="$DEMO_DIR/dashboard-ui" @@ -233,10 +244,10 @@ PROMPTS=( "What does this project do? Summarize in one sentence." "Implement the full training pipeline: data preprocessing with missing value handling, model training with scikit-learn, cross-validation, and evaluation metrics" ) -REPOS=("$REPO1" "$REPO1" "$REPO2" "$REPO2" "$REPO3") +REPOS=("$REPO1" "$WT1" "$REPO2" "$REPO2" "$REPO3") LABELS=( "api-server: architecture review" - "api-server: add auth middleware" + "api-server (feat/auth worktree): add auth middleware" "dashboard-ui: analytics component" "dashboard-ui: quick question" "ml-pipeline: implement training" diff --git a/internal/ui/app.go b/internal/ui/app.go index c9368c2d..1be0923f 100644 --- a/internal/ui/app.go +++ b/internal/ui/app.go @@ -1384,9 +1384,13 @@ func (h *Home) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } } } - // Load pinned repos from storage. + // Load pinned repos from storage. Honor the demo screenshot filter so + // pinned-but-empty regular repos don't leak into a FLEET_DEMO_PREFIX run. if pinnedPaths, err := h.storage.LoadPinnedRepos(); err == nil { for _, p := range pinnedPaths { + if !demoPathVisible(p) { + continue + } h.pinnedRepos[p] = true } } @@ -6093,6 +6097,15 @@ func (h *Home) syncViewport() { } } +// demoPathVisible reports whether a repo/session path should be shown given the +// optional FLEET_DEMO_PREFIX screenshot filter. An empty prefix (the default) +// shows everything. Shared by the session filter and the pinned-repo load so the +// two can't drift and leak regular repos into a demo run. +func demoPathVisible(path string) bool { + prefix := os.Getenv("FLEET_DEMO_PREFIX") + return prefix == "" || strings.HasPrefix(path, prefix) +} + func (h *Home) loadSessions() tea.Msg { rows, err := h.storage.LoadSessions() if err != nil { @@ -6106,10 +6119,10 @@ func (h *Home) loadSessions() tea.Msg { } // Demo mode: only show sessions under the specified path prefix. - if prefix := os.Getenv("FLEET_DEMO_PREFIX"); prefix != "" { + if os.Getenv("FLEET_DEMO_PREFIX") != "" { filtered := make([]*session.Session, 0, len(sessions)) for _, s := range sessions { - if strings.HasPrefix(s.ProjectPath, prefix) { + if demoPathVisible(s.ProjectPath) { filtered = append(filtered, s) } }