Skip to content

Commit c1472de

Browse files
authored
feat(dev): autoprovision devenv when making a new git worktree (#109889)
supersedes #108406 and is a more focused version of that after this, `git worktree add ../wherever -b branch` will automatically provision the worktree's env with `devenv sync` which is convenient, pre-commit hooks all work, etc. and `devenv sync` / `direnv allow` now plays nice with worktrees plus a few cleanups here and there
1 parent 2c0d4bf commit c1472de

File tree

6 files changed

+56
-204
lines changed

6 files changed

+56
-204
lines changed

.envrc

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,7 @@ if [ "$(uname -s)" == "Darwin" ] && [ ! -f "/Library/Developer/CommandLineTools/
1616
return 1
1717
fi
1818

19-
SENTRY_ROOT="$(
20-
cd "$(dirname "${BASH_SOURCE[0]}")"
21-
pwd -P
22-
)"
23-
24-
source "${SENTRY_ROOT}/scripts/lib.sh"
19+
source "scripts/lib.sh"
2520

2621
bold="$(tput bold)"
2722
red="$(tput setaf 1)"
@@ -106,9 +101,9 @@ export SENTRY_UI_HOT_RELOAD=1
106101

107102
### You can override the exported variables with a .env file
108103
# All exports should happen before here unless they're safeguarded (see devenv error reporting below)
109-
if [ -f "${SENTRY_ROOT}/.env" ]; then
110-
info "Loading variables from ${SENTRY_ROOT}/.env"
111-
dotenv "${SENTRY_ROOT}/.env"
104+
if [ -f ".env" ]; then
105+
info "Loading variables from .env"
106+
dotenv
112107
fi
113108

114109
## Notify of reporting to Sentry
@@ -133,8 +128,11 @@ PATH_add "/opt/homebrew/bin"
133128

134129
### Python ###
135130

136-
if [ -f .venv/bin/devenv ]; then
137-
DEVENV=.venv/bin/devenv
131+
export VIRTUAL_ENV="${PWD}/.venv"
132+
PATH_add "${VIRTUAL_ENV}/bin"
133+
134+
if [ -f "${VIRTUAL_ENV}/bin/devenv" ]; then
135+
DEVENV="${VIRTUAL_ENV}/bin/devenv"
138136
else
139137
DEVENV=devenv
140138
fi
@@ -148,9 +146,6 @@ https://github.com/getsentry/devenv#install
148146
'
149147
fi
150148

151-
PATH_add .venv/bin
152-
export VIRTUAL_ENV="$PWD/.venv"
153-
154149
if ! require sentry; then
155150
warn "Your virtualenv is activated, but sentry doesn't seem to be installed."
156151
commands_to_run+=("devenv sync")
@@ -169,25 +164,23 @@ if ! require pre-commit; then
169164
fi
170165

171166
### dotagents ###
172-
if [ -f "${SENTRY_ROOT}/agents.toml" ] && [ ! -d "${SENTRY_ROOT}/.agents/skills/commit" ]; then
167+
168+
if [ -f "agents.toml" ] && [ ! -d ".agents/skills/commit" ]; then
173169
warn "Agent skills not installed."
174170
commands_to_run+=("devenv sync")
175171
fi
176172

177-
python3 -m tools.docker_memory_check
178-
179173
### Node ###
180174

181-
# not needed for getsentry
182-
if [ "${PWD##*/}" = "sentry" ]; then
175+
if [ -f ".node-version" ]; then
183176
debug "Checking node..."
184177

185178
if [ "${SENTRY_DEVENV_SKIP_FRONTEND:-}" != "1" ]; then
186179
if ! require node; then
187180
die "You don't seem to have node installed. Please run devenv sync."
188181
fi
189182

190-
read -r node_version < .node-version
183+
read -r node_version < ".node-version"
191184
if [ "v${node_version}" != "$(node --version)" ]; then
192185
die "Unexpected $(command -v node) version. Please run devenv sync."
193186
fi

AGENTS.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,9 @@ CI=true pnpm test <file_path>
168168
CI=true pnpm test components/avatar.spec.tsx
169169
```
170170

171-
> For detailed development patterns, see nested AGENTS.md files:
172-
>
173-
> - **Backend patterns**: `src/AGENTS.md`
174-
> - **Backend testing patterns**: `tests/AGENTS.md`
175-
> - **Frontend patterns**: `static/AGENTS.md`
171+
### Git worktrees
172+
173+
Each worktree has its own `.venv`. When you create a new worktree with `git worktree add`, a post-checkout hook runs `devenv sync` in the new worktree to setup the dev environment. Otherwise run `devenv sync` once in the new worktree, then `direnv allow` to validate and activate the dev environment.
176174

177175
### Context-Aware Loading
178176

config/hooks/post-checkout

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env bash
2+
# When a new worktree is created (git worktree add), run devenv sync to create
3+
# a virtualenv in the new worktree. Git calls this hook with three arguments:
4+
# $1 = previous HEAD ref, $2 = new HEAD ref, $3 = 1 (branch) or 0 (file checkout).
5+
# For a new worktree there is no "previous" commit, so Git passes 40 zeros as $1.
6+
# We only run our logic when $1 is all zeros (new worktree or initial clone).
7+
# Git invokes this hook automatically after checkout (e.g. git clone, checkout, switch, worktree add);
8+
# the hook runs with the worktree root as the current directory.
9+
set -eu
10+
11+
# Only act when $1 is all zeros (no previous HEAD): that happens for worktree add
12+
# and for clone. We only want to run for worktree add; after clone, CI or the
13+
# user runs devenv sync explicitly. In a clone .git is a dir; in a worktree .git
14+
# is a file. So skip unless we're in a worktree to avoid affecting clone/CI.
15+
if [ "$1" != "0000000000000000000000000000000000000000" ]; then
16+
exit 0
17+
fi
18+
WORKTREE_ROOT="${GIT_WORK_TREE:-$PWD}"
19+
# .git is a file in an added worktree, a directory in the main clone; skip if main clone
20+
if [ ! -f "$WORKTREE_ROOT/.git" ]; then
21+
exit 0
22+
fi
23+
24+
# Only run in worktrees that have our devenv setup (sync.py); skip when .venv already exists
25+
if [ ! -d "$WORKTREE_ROOT/.venv" ] && [ -f "$WORKTREE_ROOT/devenv/sync.py" ]; then
26+
if command -v devenv >/dev/null 2>&1; then
27+
echo "New worktree detected. Running devenv sync to create virtualenv..."
28+
if ! (cd "$WORKTREE_ROOT" && devenv sync); then
29+
echo "Warning: devenv sync failed. Run 'cd $WORKTREE_ROOT && devenv sync' manually."
30+
fi
31+
else
32+
echo "New worktree detected. Install devenv and run: cd $WORKTREE_ROOT && devenv sync"
33+
fi
34+
fi

devenv/sync.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ def main(context: dict[str, str]) -> int:
186186

187187
FRONTEND_ONLY = os.environ.get("SENTRY_DEVENV_FRONTEND_ONLY") is not None
188188
SKIP_FRONTEND = os.environ.get("SENTRY_DEVENV_SKIP_FRONTEND") is not None
189+
IN_GIT_WORKTREE = os.path.isfile(f"{reporoot}/.git")
189190

190191
if constants.DARWIN and os.path.exists(f"{constants.root}/bin/colima"):
191192
binroot = f"{reporoot}/.devenv/bin"
@@ -309,7 +310,11 @@ def main(context: dict[str, str]) -> int:
309310
):
310311
print("⚠️ agent skills failed to install (non-fatal)")
311312

312-
fs.ensure_symlink("../../config/hooks/post-merge", f"{reporoot}/.git/hooks/post-merge")
313+
if not IN_GIT_WORKTREE:
314+
fs.ensure_symlink("../../config/hooks/post-merge", f"{reporoot}/.git/hooks/post-merge")
315+
fs.ensure_symlink(
316+
"../../config/hooks/post-checkout", f"{reporoot}/.git/hooks/post-checkout"
317+
)
313318

314319
sentry_conf = os.environ.get("SENTRY_CONF", f"{constants.home}/.sentry")
315320

tests/tools/test_docker_memory_check.py

Lines changed: 0 additions & 106 deletions
This file was deleted.

tools/docker_memory_check.py

Lines changed: 0 additions & 72 deletions
This file was deleted.

0 commit comments

Comments
 (0)