Skip to content

chore(dev-env): make .wp-env.json local and add git-worktree tooling#3306

Open
mrabbani wants to merge 1 commit into
developfrom
feat/wp-env-worktree-config
Open

chore(dev-env): make .wp-env.json local and add git-worktree tooling#3306
mrabbani wants to merge 1 commit into
developfrom
feat/wp-env-worktree-config

Conversation

@mrabbani

@mrabbani mrabbani commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

Makes the wp-env config per-machine/per-worktree and adds tooling + docs for running Dokan across git worktrees.

  • .wp-env.json is 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.example is committed as the template — mounts WooCommerce + . (dokan-lite) + ../dokan-pro, sets default ports, and activates Twenty Twenty-Five via an afterStart lifecycle script.
  • First-run instruction added to CLAUDE.md: cp .wp-env.json.example .wp-env.json.
  • New dokan-wp-env-worktrees skill (.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.json local removes that friction; the example keeps onboarding one command.

Migration for existing clones

.wp-env.json is now gitignored. After pulling:

cp .wp-env.json.example .wp-env.json   # then adjust ports/mounts locally

Your existing local .wp-env.json keeps working — it just stops being tracked.

Notes

  • Docs-only + dev-env config; no plugin runtime code changes.
  • The skill's SKILL.md documents a known, still-unresolved npm ci blocker on the private @getdokan/dokan-ui git dependency inside worktrees (honestly recorded, not claimed fixed).

Test plan

  • Fresh clone: cp .wp-env.json.example .wp-env.json && npm run env:start brings up WooCommerce + Dokan Lite + Dokan Pro (if ../dokan-pro present) with Twenty Twenty-Five active.
  • git status no longer shows .wp-env.json after local edits.
  • .wp-env.override.json overrides ports without editing the base config.

Summary by CodeRabbit

  • New Features

    • Added scripts to create paired WordPress worktrees for Dokan Lite and Pro from either a branch or a PR reference.
    • Added a sample WordPress environment configuration for local setup with custom ports and theme activation.
  • Documentation

    • Expanded setup guidance for using wp-env across multiple worktrees, including port conflicts, plugin ordering, and shared vs. isolated databases.
    • Updated onboarding notes to explain first-time local configuration and the new worktree workflow.
  • Chores

    • Ignored generated WordPress environment config files in version control.

- 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.
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds 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 .wp-env.json.example config, .gitignore entries for generated wp-env files, removal of the committed .wp-env.json, and CLAUDE.md updates.

Changes

wp-env worktree tooling and documentation

Layer / File(s) Summary
Worktree/wp-env conceptual documentation
.claude/skills/dokan-wp-env-worktrees/SKILL.md
Documents instance identity via md5 hashing, port-conflict handling, plugin configuration order, paired-worktree conventions, PR/branch-based workflows, bootstrap steps with an unresolved npm ci blocker, isolated vs shared database modes, and operational gotchas.
create-paired-worktree.sh script
.claude/skills/dokan-wp-env-worktrees/create-paired-worktree.sh
New script creates side-by-side lite/pro worktrees for a given branch, writes .wp-env.json/.wp-env.override.json, and prints setup/teardown instructions.
worktree-from-pr.sh script
.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh
New script resolves paired lite/pro branches from a GitHub PR via gh/jq, adds matching git worktrees, writes wp-env config/override files, and prints follow-up commands.
wp-env config files and repo docs update
.wp-env.json.example, .wp-env.json, .gitignore, CLAUDE.md
Adds an example wp-env config, deletes the committed .wp-env.json, ignores generated wp-env config files, and updates CLAUDE.md's skills list and environment setup instructions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • getdokan/dokan#3113: Extends the same CLAUDE.md/Claude Code skills system by adding this new dokan-wp-env-worktrees skill alongside the skills introduced there.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main dev-env and git-worktree tooling changes.
Description check ✅ Passed The PR description covers summary, rationale, migration, notes, and test plan, but omits several template sections like related PRs, changelog, and before/after.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/wp-env-worktree-config

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
.claude/skills/dokan-wp-env-worktrees/worktree-from-pr.sh (1)

104-141: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Same dokan-lite vs dokan folder-naming concern as create-paired-worktree.sh.

This script also creates the lite worktree under dokan-lite, which SKILL.md documents as breaking phpunit/seed workflows. See the corresponding comment on create-paired-worktree.sh for 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

📥 Commits

Reviewing files that changed from the base of the PR and between 4338fe1 and 66faaa6.

📒 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.example
  • CLAUDE.md
💤 Files with no reviewable changes (1)
  • .wp-env.json

Comment on lines +42 to +43
add_worktree "$LITE_MAIN" "$DEST/dokan-lite" "$BRANCH" "$BASE"
add_worktree "$PRO_MAIN" "$DEST/dokan-pro" "$BRANCH" "${PRO_BASE:-develop}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.

Comment on lines +63 to +113
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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 -S

Repository: 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 -n

Repository: 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.

Comment on lines +90 to +102
# 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
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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.

Suggested change
# 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant