chore(dev-env): make .wp-env.json local and add git-worktree tooling#3306
chore(dev-env): make .wp-env.json local and add git-worktree tooling#3306mrabbani wants to merge 1 commit into
Conversation
- Make live .wp-env.json per-machine/per-worktree (gitignore it and .wp-env.override.json); commit .wp-env.json.example as the template. - Example mounts woocommerce + "." + ../dokan-pro, sets ports, and activates Twenty Twenty-Five via an afterStart lifecycle script. - Add .claude/skills/dokan-wp-env-worktrees (SKILL.md + helper scripts create-paired-worktree.sh / worktree-from-pr.sh) and register it in CLAUDE.md.
📝 WalkthroughWalkthroughAdds a Claude skill documenting wp-env usage across git worktrees for dokan-lite/dokan-pro, two bash scripts (create-paired-worktree.sh, worktree-from-pr.sh) to automate paired worktree creation, a Changeswp-env worktree tooling and documentation
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh (1)
104-141: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winSame
dokan-litevsdokanfolder-naming concern ascreate-paired-worktree.sh.This script also creates the lite worktree under
dokan-lite, which SKILL.md documents as breakingphpunit/seed workflows. See the corresponding comment oncreate-paired-worktree.shfor the proposed fix — applies here too.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh around lines 104 - 141, The worktree setup in worktree-from-pr.sh uses the dokan-lite folder name for the lite checkout, which conflicts with the documented dokan folder convention and breaks phpunit/seed workflows. Update the lite worktree destination and related wp-env/plugin references in add_worktree and the wp-env JSON generation so they use the expected dokan naming consistently, matching the paired-worktree script behavior and any symbols like LITE_MAIN, PRO_MOUNT, and $DEST paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.claude/skills/dokan-wp-env-worktrees/create-paired-worktree.sh:
- Around line 42-43: The worktree creation logic in create-paired-worktree.sh is
using a dokan-lite folder name that conflicts with the phpunit/wp-env setup
described in the repo docs. Update add_worktree and the related trailing echo
messages to create and reference a dokan folder instead, so wp-env mounts the
plugin at the expected basename used by npm run phpunit. Keep the dokan-pro path
unchanged and make sure all dokan-lite references in this script are renamed
consistently.
In @.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh:
- Around line 90-102: The fast-forward step in add_worktree is swallowing
failures, so a diverged local branch can silently stay behind the PR head.
Update the git -C "$path" merge --ff-only "origin/$br" path to handle non-zero
status explicitly: keep the fast-forward attempt, but if it fails, emit a
warning with the branch and path instead of suppressing it with 2>/dev/null ||
true. This should be done in add_worktree so the script still mirrors the PR
head behavior without hiding divergence.
- Around line 63-113: The script currently assumes "$DEST/dokan-lite" always
exists before writing .wp-env.json, which breaks pro-only PRs when lite_branch
is empty. Update worktree-from-pr.sh around add_worktree and the final cat >
"$DEST/dokan-lite/.wp-env.json" step so it either skips the write when no lite
worktree was created or falls back to the shared lite checkout path; use the
existing lite_branch, DEST, and add_worktree flow to decide which path should
receive the wp-env config.
---
Duplicate comments:
In @.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh:
- Around line 104-141: The worktree setup in worktree-from-pr.sh uses the
dokan-lite folder name for the lite checkout, which conflicts with the
documented dokan folder convention and breaks phpunit/seed workflows. Update the
lite worktree destination and related wp-env/plugin references in add_worktree
and the wp-env JSON generation so they use the expected dokan naming
consistently, matching the paired-worktree script behavior and any symbols like
LITE_MAIN, PRO_MOUNT, and $DEST paths.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: dc6faf98-65ee-4073-9876-7853a3f09ff0
📒 Files selected for processing (7)
.claude/skills/dokan-wp-env-worktrees/SKILL.md.claude/skills/dokan-wp-env-worktrees/create-paired-worktree.sh.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh.gitignore.wp-env.json.wp-env.json.exampleCLAUDE.md
💤 Files with no reviewable changes (1)
- .wp-env.json
| add_worktree "$LITE_MAIN" "$DEST/dokan-lite" "$BRANCH" "$BASE" | ||
| add_worktree "$PRO_MAIN" "$DEST/dokan-pro" "$BRANCH" "${PRO_BASE:-develop}" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Worktree folder is named dokan-lite, which the project's own docs say breaks phpunit.
SKILL.md (added in this same PR) explicitly calls out that wp-env mounts a local plugin at .../plugins/<folder-basename>, and npm run phpunit hardcodes --env-cwd=wp-content/plugins/dokan, so a dokan-lite folder breaks that workflow. Since this script is what creates the folder, consider naming it dokan here rather than leaving it as a documented "unresolved blocker."
🔧 Proposed fix (rename destination folder)
-add_worktree "$LITE_MAIN" "$DEST/dokan-lite" "$BRANCH" "$BASE"
+add_worktree "$LITE_MAIN" "$DEST/dokan" "$BRANCH" "$BASE"
add_worktree "$PRO_MAIN" "$DEST/dokan-pro" "$BRANCH" "${PRO_BASE:-develop}"
-cat > "$DEST/dokan-lite/.wp-env.json" <<JSON
+cat > "$DEST/dokan/.wp-env.json" <<JSON(and update the remaining $DEST/dokan-lite references in the trailing echo block accordingly.)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/dokan-wp-env-worktrees/create-paired-worktree.sh around lines
42 - 43, The worktree creation logic in create-paired-worktree.sh is using a
dokan-lite folder name that conflicts with the phpunit/wp-env setup described in
the repo docs. Update add_worktree and the related trailing echo messages to
create and reference a dokan folder instead, so wp-env mounts the plugin at the
expected basename used by npm run phpunit. Keep the dokan-pro path unchanged and
make sure all dokan-lite references in this script are renamed consistently.
| other_branch="" | ||
| if [[ -n "$other_num" ]]; then | ||
| other_branch="$( gh pr view "$other_num" --repo "$other_repo" --json headRefName -q .headRefName )" | ||
| echo "Companion PR: $other_repo#$other_num (branch: $other_branch)" | ||
| elif git ls-remote --exit-code --heads "https://github.com/${other_repo}.git" "$this_branch" >/dev/null 2>&1; then | ||
| other_branch="$this_branch" | ||
| echo "No companion PR in body; matched same branch name in $other_repo." | ||
| else | ||
| echo "No companion PR and no matching branch in $other_repo — creating a lite-only env." | ||
| fi | ||
|
|
||
| # --- map to lite/pro branch names --- | ||
| if [[ "$this_side" == "lite" ]]; then | ||
| lite_branch="$this_branch"; pro_branch="$other_branch" | ||
| else | ||
| pro_branch="$this_branch"; lite_branch="$other_branch" | ||
| fi | ||
|
|
||
| # --- resolve main checkouts (dokan-pro expected next to dokan-lite) --- | ||
| LITE_MAIN="$( git rev-parse --show-toplevel )" | ||
| PLUGINS_DIR="$( dirname "$LITE_MAIN" )" | ||
| PRO_MAIN="$PLUGINS_DIR/dokan-pro" | ||
|
|
||
| SLUG="${this_branch//\//-}" | ||
| DEST="${DOKAN_WT_HOME:-$HOME/dokan-wt}/$SLUG" | ||
| mkdir -p "$DEST" | ||
|
|
||
| # add_worktree <repo-main> <path> <branch> [base] | ||
| add_worktree() { | ||
| local main="$1" path="$2" br="$3" base="${4:-develop}" | ||
| git -C "$main" fetch --quiet origin "$br" 2>/dev/null || true | ||
| if git -C "$main" show-ref --verify --quiet "refs/heads/$br"; then | ||
| git -C "$main" worktree add "$path" "$br" | ||
| git -C "$path" merge --ff-only "origin/$br" 2>/dev/null || true # match PR head (no-op if ahead) | ||
| elif git -C "$main" show-ref --verify --quiet "refs/remotes/origin/$br"; then | ||
| git -C "$main" worktree add -b "$br" "$path" "origin/$br" | ||
| else | ||
| git -C "$main" worktree add -b "$br" "$path" "$base" | ||
| fi | ||
| } | ||
|
|
||
| [[ -n "$lite_branch" ]] && add_worktree "$LITE_MAIN" "$DEST/dokan-lite" "$lite_branch" "$this_base" | ||
|
|
||
| if [[ -n "$pro_branch" && -d "$PRO_MAIN/.git" ]]; then | ||
| add_worktree "$PRO_MAIN" "$DEST/dokan-pro" "$pro_branch" develop | ||
| PRO_MOUNT="../dokan-pro" | ||
| else | ||
| PRO_MOUNT="$PRO_MAIN" # lite-only: mount the shared main pro checkout by absolute path | ||
| fi | ||
|
|
||
| cat > "$DEST/dokan-lite/.wp-env.json" <<JSON |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file=".claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh"
# Map the file first
ast-grep outline "$file" --view expanded
# Read the relevant section with line numbers
sed -n '1,180p' "$file" | cat -n
# Search for related mentions of lite-only / pro-only behavior and docs examples
rg -n "lite-only|pro-only|dokan-pro#|dokan-lite#|wp-env.json|add_worktree|this_side|other_branch|lite_branch|pro_branch" .claude/skills/dokan-wp-env-worktrees -SRepository: getdokan/dokan
Length of output: 11336
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file=".claude/skills/dokan-wp-env-worktrees/SKILL.md"
# Show the relevant documented behavior around lite-only / pro-only worktrees
sed -n '120,240p' "$file" | cat -n
# Also inspect the paired worktree helper for comparison
helper=".claude/skills/dokan-wp-env-worktrees/create-paired-worktree.sh"
sed -n '1,140p' "$helper" | cat -nRepository: getdokan/dokan
Length of output: 9963
Pro-only PRs still fail before .wp-env.json is written
In worktree-from-pr.sh, a pro PR with no companion lite branch leaves lite_branch empty, so "$DEST/dokan-lite" is never created, but the script still writes to "$DEST/dokan-lite/.wp-env.json" at the end. That path does not exist, so the script exits early instead of handling the documented getdokan/dokan-pro#5538 case. Guard the write or fall back to the shared lite checkout when no lite worktree is created.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh around lines 63 -
113, The script currently assumes "$DEST/dokan-lite" always exists before
writing .wp-env.json, which breaks pro-only PRs when lite_branch is empty.
Update worktree-from-pr.sh around add_worktree and the final cat >
"$DEST/dokan-lite/.wp-env.json" step so it either skips the write when no lite
worktree was created or falls back to the shared lite checkout path; use the
existing lite_branch, DEST, and add_worktree flow to decide which path should
receive the wp-env config.
| # add_worktree <repo-main> <path> <branch> [base] | ||
| add_worktree() { | ||
| local main="$1" path="$2" br="$3" base="${4:-develop}" | ||
| git -C "$main" fetch --quiet origin "$br" 2>/dev/null || true | ||
| if git -C "$main" show-ref --verify --quiet "refs/heads/$br"; then | ||
| git -C "$main" worktree add "$path" "$br" | ||
| git -C "$path" merge --ff-only "origin/$br" 2>/dev/null || true # match PR head (no-op if ahead) | ||
| elif git -C "$main" show-ref --verify --quiet "refs/remotes/origin/$br"; then | ||
| git -C "$main" worktree add -b "$br" "$path" "origin/$br" | ||
| else | ||
| git -C "$main" worktree add -b "$br" "$path" "$base" | ||
| fi | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Fast-forward failure is silently swallowed.
git merge --ff-only "origin/$br" 2>/dev/null || true discards the exit status entirely. If the local branch has diverged from origin/$br (e.g., stale local branch reused across runs), the worktree silently stays on the old commit instead of the actual PR head, contradicting the script's stated behavior ("fast-forwards each worktree to the PR head" — SKILL.md Line 141). Consider surfacing a warning instead of fully suppressing the failure.
🔧 Proposed fix
- git -C "$path" merge --ff-only "origin/$br" 2>/dev/null || true # match PR head (no-op if ahead)
+ git -C "$path" merge --ff-only "origin/$br" 2>/dev/null || \
+ echo "warning: could not fast-forward $path to origin/$br (diverged?); worktree may not match the PR head" >&2📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # add_worktree <repo-main> <path> <branch> [base] | |
| add_worktree() { | |
| local main="$1" path="$2" br="$3" base="${4:-develop}" | |
| git -C "$main" fetch --quiet origin "$br" 2>/dev/null || true | |
| if git -C "$main" show-ref --verify --quiet "refs/heads/$br"; then | |
| git -C "$main" worktree add "$path" "$br" | |
| git -C "$path" merge --ff-only "origin/$br" 2>/dev/null || true # match PR head (no-op if ahead) | |
| elif git -C "$main" show-ref --verify --quiet "refs/remotes/origin/$br"; then | |
| git -C "$main" worktree add -b "$br" "$path" "origin/$br" | |
| else | |
| git -C "$main" worktree add -b "$br" "$path" "$base" | |
| fi | |
| } | |
| # add_worktree <repo-main> <path> <branch> [base] | |
| add_worktree() { | |
| local main="$1" path="$2" br="$3" base="${4:-develop}" | |
| git -C "$main" fetch --quiet origin "$br" 2>/dev/null || true | |
| if git -C "$main" show-ref --verify --quiet "refs/heads/$br"; then | |
| git -C "$main" worktree add "$path" "$br" | |
| git -C "$path" merge --ff-only "origin/$br" 2>/dev/null || \ | |
| echo "warning: could not fast-forward $path to origin/$br (diverged?); worktree may not match the PR head" >&2 | |
| elif git -C "$main" show-ref --verify --quiet "refs/remotes/origin/$br"; then | |
| git -C "$main" worktree add -b "$br" "$path" "origin/$br" | |
| else | |
| git -C "$main" worktree add -b "$br" "$path" "$base" | |
| fi | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh around lines 90 -
102, The fast-forward step in add_worktree is swallowing failures, so a diverged
local branch can silently stay behind the PR head. Update the git -C "$path"
merge --ff-only "origin/$br" path to handle non-zero status explicitly: keep the
fast-forward attempt, but if it fails, emit a warning with the branch and path
instead of suppressing it with 2>/dev/null || true. This should be done in
add_worktree so the script still mirrors the PR head behavior without hiding
divergence.
Summary
Makes the wp-env config per-machine/per-worktree and adds tooling + docs for running Dokan across git worktrees.
.wp-env.jsonis no longer committed — it holds local ports, plugin mounts, and dependency paths that differ per machine/worktree. It (and.wp-env.override.json) are now gitignored..wp-env.json.exampleis committed as the template — mounts WooCommerce +.(dokan-lite) +../dokan-pro, sets default ports, and activates Twenty Twenty-Five via anafterStartlifecycle script.CLAUDE.md:cp .wp-env.json.example .wp-env.json.dokan-wp-env-worktreesskill (.claude/skills/) documenting how wp-env isolates DBs per worktree, port handling, dependency mounting (lite+pro), paired worktrees for coordinated cross-repo changes, and the install/build order — plus two helper scripts:create-paired-worktree.sh <branch> [base] [port]worktree-from-pr.sh <pr-url|number|owner/repo#N> [port](auto-resolves the companion Pro PR from the body)Why
Every git worktree lives at a different path, so wp-env already gives each its own database automatically — the only real friction is ports and the committed config fighting local edits. Making
.wp-env.jsonlocal removes that friction; the example keeps onboarding one command.Migration for existing clones
.wp-env.jsonis now gitignored. After pulling:cp .wp-env.json.example .wp-env.json # then adjust ports/mounts locallyYour existing local
.wp-env.jsonkeeps working — it just stops being tracked.Notes
npm ciblocker on the private@getdokan/dokan-uigit dependency inside worktrees (honestly recorded, not claimed fixed).Test plan
cp .wp-env.json.example .wp-env.json && npm run env:startbrings up WooCommerce + Dokan Lite + Dokan Pro (if../dokan-propresent) with Twenty Twenty-Five active.git statusno longer shows.wp-env.jsonafter local edits..wp-env.override.jsonoverrides ports without editing the base config.Summary by CodeRabbit
New Features
Documentation
wp-envacross multiple worktrees, including port conflicts, plugin ordering, and shared vs. isolated databases.Chores