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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/quiet-tools-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---

---

Run T3 worktree dependency preparation asynchronously while retaining portable Git hook setup.
7 changes: 7 additions & 0 deletions .githooks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ source-identity key.
Records package/lockfile state under `node_modules` so T3 handoff does not
repeat an install Git already completed.

When T3 launches the configured worktree setup script, it sets
`T3CODE_DEFER_DEPENDENCY_INSTALL=1`. Cleanup still runs synchronously, while the
setup terminal installs dependencies asynchronously with hardlink imports from
the shared pnpm store. Raw Git worktrees still install during checkout. Their
install failure is best-effort; T3 can request the real exit status with
`T3CODE_WORKTREE_PREPARATION_STRICT=1` without removing the created worktree.

## `pre-commit` / `pre-push`

lint-staged on commit; agent ship gate on push (see repo AGENTS.md).
20 changes: 18 additions & 2 deletions .githooks/post-checkout
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ clean_ts_project_emit() {

clean_ts_project_emit "$wt_root"

# T3 launches the configured worktree setup command in a visible terminal. Keep
# cleanup synchronous, but leave dependency installation to that async setup.
if [ "${T3CODE_DEFER_DEPENDENCY_INSTALL:-0}" = "1" ]; then
echo "post-checkout: dependency installation deferred to T3 workspace initialization" >&2
exit 0
fi

# --- pnpm install when lockfile / package.json changed -----------------------
[ -f "$wt_root/pnpm-lock.yaml" ] || exit 0
state_file="$wt_root/node_modules/.pnpm-checkout-state"
Expand All @@ -78,5 +85,14 @@ command -v pnpm >/dev/null 2>&1 || {
export CI=1
echo "post-checkout: pnpm install in $wt_root" >&2
cd "$wt_root" || exit 1
pnpm install --frozen-lockfile --prefer-offline --config.confirmModulesPurge=false || exit $?
printf '%s\n' "$state" >"$state_file"
if pnpm install --frozen-lockfile --prefer-offline \
--config.package-import-method=hardlink \
--config.confirmModulesPurge=false
then
printf '%s\n' "$state" >"$state_file"
else
status=$?
echo "post-checkout: dependency preparation failed (exit $status); worktree remains usable but degraded" >&2
[ "${T3CODE_WORKTREE_PREPARATION_STRICT:-0}" = "1" ] && exit "$status"
exit 0
fi
22 changes: 21 additions & 1 deletion scripts/hooks/post-checkout.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mkdir -p .githooks "$work/fake-home/.local/bin"
install -m 0755 "$hook" .githooks/post-checkout
printf '{}\n' >package.json
printf 'lockfileVersion: 9\n' >pnpm-lock.yaml
printf '#!/bin/sh\nroot=$(git rev-parse --show-toplevel)\nmkdir -p "$root/node_modules"\ntouch "$root/node_modules/.modules.yaml"\nprintf x >>"$root/.pnpm-runs"\n' >"$work/fake-home/.local/bin/pnpm"
printf '#!/bin/sh\nroot=$(git rev-parse --show-toplevel)\nmkdir -p "$root/node_modules"\ntouch "$root/node_modules/.modules.yaml"\nprintf x >>"$root/.pnpm-runs"\nprintf "%%s\\n" "$*" >"$root/.pnpm-args"\n' >"$work/fake-home/.local/bin/pnpm"
chmod +x "$work/fake-home/.local/bin/pnpm"
git add .githooks package.json pnpm-lock.yaml
git commit -q -m init
Expand All @@ -24,6 +24,7 @@ ref=$(git -C "$work/idempotent-linked" rev-parse HEAD)
HOME="$work/fake-home" git -C "$work/idempotent-linked" -c core.hooksPath=.githooks \
hook run post-checkout -- "$ref" "$ref" 1
test "$(wc -c <"$work/idempotent-linked/.pnpm-runs")" = 1
grep -q -- '--config.package-import-method=hardlink' "$work/idempotent-linked/.pnpm-args"

# Branch checkout must wipe packages/*/dist.
git init -q "$work/ts-clean-main"
Expand Down Expand Up @@ -61,4 +62,23 @@ HOME="$work/fake-home" git -c core.hooksPath=.githooks \
hook run post-checkout -- "$ref" "$ref" 0
test -f packages/effect-app/dist/keep.d.ts

# T3 may defer installation to its setup terminal. Normal Git preparation is
# best-effort, while T3's explicit strict pass can still observe the exit code.
printf '#!/bin/sh\ntouch "$(git rev-parse --show-toplevel)/.pnpm-attempt"\nexit 17\n' >"$work/fake-home/.local/bin/pnpm"
chmod +x "$work/fake-home/.local/bin/pnpm"
rm -f node_modules/.pnpm-checkout-state .pnpm-attempt
deferred_out="$(HOME="$work/fake-home" T3CODE_DEFER_DEPENDENCY_INSTALL=1 T3CODE_WORKTREE_PREPARATION_STRICT=1 sh .githooks/post-checkout HEAD HEAD 1 2>&1)"
case "$deferred_out" in
*"dependency installation deferred to T3 workspace initialization"*) ;;
*) exit 1 ;;
esac
test ! -f .pnpm-attempt
HOME="$work/fake-home" sh .githooks/post-checkout HEAD HEAD 1 >/dev/null 2>&1
test -f .pnpm-attempt
set +e
HOME="$work/fake-home" T3CODE_WORKTREE_PREPARATION_STRICT=1 sh .githooks/post-checkout HEAD HEAD 1 >/dev/null 2>&1
strict_status=$?
set -e
test "$strict_status" = 17

echo "portable worktree hooks passed"
10 changes: 10 additions & 0 deletions t3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://t3.codes/schema/t3.json",
"scripts": [
{
"name": "Setup Worktree",
"command": "pnpm install --frozen-lockfile --prefer-offline --config.package-import-method=hardlink --config.confirmModulesPurge=false",
"runOnWorktreeCreate": true
}
]
}
Loading