Skip to content
Open
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
50 changes: 28 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@

DDEV add-on for parallel [git worktree](https://git-scm.com/docs/git-worktree) development on Genero Bedrock sites.

Shared MariaDB by default; Caddy (`replace-response`) rewrites browser URLs to `:808x` while PHP/DB keep canonical DDEV hostnames.
**v0.2:** `ddev start` in worktrees — own MariaDB (cloned from canonical on first start, no search-replace), shared uploads via symlinks, Caddy on `:808x` for canonical browser URLs.

## Install

```bash
ddev add-on get generoi/ddev-worktree --version v0.1.3
```

If the add-on registry lookup fails, use the release tarball directly:

```bash
ddev add-on get https://github.com/generoi/ddev-worktree/tarball/v0.1.3
ddev add-on get generoi/ddev-worktree
```

Or from a local checkout while developing the add-on:
Expand All @@ -24,39 +18,49 @@ ddev add-on get /path/to/ddev-worktree

## Project setup (Bedrock)

1. **`.gitignore`** — `.ddev/wt/` (generated Caddyfile + state).
Add to `.gitignore`:

2. **Multisite** — list subsite hostnames in `additional_hostnames` (e.g. `nat.herrfors`).
```
.ddev/wt/
.ddev/config.generoi-worktree.local.yaml
.ddev/generoi-worktree/
.ddev/commands/host/wt-*
.ddev/addon-metadata/generoi-worktree/
```

The add-on installs `config.generoi-worktree.yaml` with the `wt-guard` pre-start hook — no manual `config.yaml` edits.
Multisite: list subsite hostnames in `additional_hostnames` (e.g. `nat.herrfors`).

No Bedrock changes required — Caddy sends `{http.request.host}` (hostname without `:port`) to PHP and rewrites `:808x` back into browser responses.
No Bedrock changes — Caddy sends `{http.request.host}` to PHP and rewrites `:808x` into browser responses.

## Usage

**Canonical checkout:** `ddev start`
**Canonical checkout:**

```bash
ddev start
# https://herrfors.ddev.site
```

**Git worktree:**

```bash
git worktree add ../myproject-feature feature-branch
cd ../myproject-feature
ddev wt-up
ddev start
# https://herrfors.ddev.site:808x (Caddy proxy; own DB forked from canonical on first start)
ddev wt-port
ddev wt-down
ddev stop
```

| Command | Description |
|---------|-------------|
| `ddev wt-up` | Shared DB + Caddy on `:808x` |
| `ddev wt-up --port=8083` | Pin host port |
| `ddev wt-up --no-deps` | Skip composer/pnpm |
| `ddev start` | Worktree: full DDEV + Caddy `:808x` + DB seed (first time) |
| `ddev wt-port` | Print `WT_URL` / `WT_PORT` |
| `ddev wt-wp …` | WP-CLI in sidecar |
| `ddev wt-list` | Running sidecars |
| `ddev wt-down` | Stop sidecar + Caddy |
| `ddev wt-sync-db` | Re-clone DB from canonical (manual) |
| `ddev wt-list` | Running Caddy proxies |
| `ddev wt-down` | Stop Caddy only (web/db keep running) |

See [generoi-worktree/README.md](generoi-worktree/README.md) for architecture details.
Removed in v0.2: `wt-up`, `wt-guard`, `wt-wp` — use `ddev start` and `ddev wp`.

## Acceptance tests

Expand All @@ -65,3 +69,5 @@ From a git worktree checkout (canonical DDEV running):
```bash
bash .ddev/generoi-worktree/test-acceptance.sh
```

See [generoi-worktree/README.md](generoi-worktree/README.md) for architecture details.
4 changes: 2 additions & 2 deletions commands/host/wt-down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Stop this worktree's sidecar container
## Description: Stop Caddy proxy (DDEV web/db keep running)
## Usage: wt-down
## Example: "ddev wt-down"
## OSTypes: linux,darwin
Expand All @@ -14,4 +14,4 @@ source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-wor

wt_require docker
wt_ensure_ddev_project
wt_sidecar_stop
wt_caddy_stop
22 changes: 0 additions & 22 deletions commands/host/wt-guard

This file was deleted.

4 changes: 2 additions & 2 deletions commands/host/wt-list
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: List generoi worktree sidecars for this canonical project
## Description: List generoi worktree Caddy proxies for this canonical project
## Usage: wt-list
## Example: "ddev wt-list"
## OSTypes: linux,darwin
Expand All @@ -17,6 +17,6 @@ wt_ensure_ddev_project

name=$(wt_canonical_name)
docker ps -a \
--filter "label=com.generoi.worktree=true" \
--filter "label=com.generoi.worktree-proxy=caddy" \
--filter "label=com.generoi.canonical=${name}" \
--format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}\t{{.Label "com.generoi.approot"}}'
4 changes: 2 additions & 2 deletions commands/host/wt-port
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Print this worktree sidecar URL (WT_URL)
## Description: Print worktree browse URL (WT_URL on :808x)
## Usage: wt-port
## Example: "ddev wt-port"
## OSTypes: linux,darwin
Expand All @@ -15,7 +15,7 @@ source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-wor
wt_ensure_ddev_project

if ! wt_read_state >/dev/null 2>&1; then
echo "generoi-worktree: no active sidecar (run ddev wt-up)" >&2
echo "generoi-worktree: no Caddy proxy state (run ddev start in this worktree)" >&2
exit 1
fi

Expand Down
13 changes: 13 additions & 0 deletions commands/host/wt-post-start
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Start Caddy proxy and seed DB on first worktree start
## Usage: (internal) wt-post-start
## OSTypes: linux,darwin

set -euo pipefail

# shellcheck disable=SC1091
source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-worktree/lib.sh"

wt_post_start
13 changes: 13 additions & 0 deletions commands/host/wt-pre-stop
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Stop Caddy proxy before DDEV stops
## Usage: (internal) wt-pre-stop
## OSTypes: linux,darwin

set -euo pipefail

# shellcheck disable=SC1091
source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-worktree/lib.sh"

wt_pre_stop
13 changes: 13 additions & 0 deletions commands/host/wt-prepare
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Prepare git worktree DDEV project (unique name, bootstrap links)
## Usage: (internal) wt-prepare
## OSTypes: linux,darwin

set -euo pipefail

# shellcheck disable=SC1091
source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-worktree/lib.sh"

wt_prepare
17 changes: 17 additions & 0 deletions commands/host/wt-sync-db
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Re-clone database from canonical (worktrees only)
## Usage: wt-sync-db
## Example: "ddev wt-sync-db"
## OSTypes: linux,darwin
## ProjectTypes: php,wordpress

set -euo pipefail

# shellcheck disable=SC1091
source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-worktree/lib.sh"

wt_require ddev
wt_ensure_ddev_project
wt_sync_db
51 changes: 4 additions & 47 deletions commands/host/wt-up
Original file line number Diff line number Diff line change
@@ -1,57 +1,14 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Start a worktree sidecar (shared DB + Caddy URL rewrite)
## Usage: wt-up [--port=808x] [--no-deps]
## Example: "ddev wt-up" or "ddev wt-up --port=8083 --no-deps"
## Description: (removed) use ddev start in git worktrees
## Usage: wt-up
## OSTypes: linux,darwin
## ProjectTypes: php,wordpress

set -euo pipefail

APPROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)
# shellcheck disable=SC1091
source "$APPROOT/.ddev/generoi-worktree/lib.sh"
source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-worktree/lib.sh"

SKIP_DEPS=false
WT_PORT=""

for arg in "$@"; do
case "$arg" in
--port=*) WT_PORT="${arg#*=}" ;;
--no-deps) SKIP_DEPS=true ;;
--db=*)
echo "generoi-worktree: --db= is no longer supported (always shared DB + Caddy :port)" >&2
exit 1
;;
-h|--help)
echo "Usage: ddev wt-up [--port=808x] [--no-deps]"
exit 0
;;
*)
echo "Unknown argument: $arg" >&2
exit 1
;;
esac
done

wt_require docker
wt_require jq
wt_ensure_ddev_project

if wt_is_canonical_checkout; then
echo "generoi-worktree: you are on the canonical checkout; use 'ddev start' for daily dev." >&2
echo "generoi-worktree: create a git worktree first, then run 'ddev wt-up' there." >&2
exit 1
fi

wt_ensure_canonical_running
wt_bootstrap_links

if [[ "$SKIP_DEPS" == false ]]; then
wt_install_deps
fi

wt_sidecar_start "$WT_PORT"

echo "generoi-worktree: ready"
wt_sidecar_start
28 changes: 5 additions & 23 deletions commands/host/wt-wp
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
#!/usr/bin/env bash

## #ddev-generated: If you want to edit and own this file, remove this line.
## Description: Run wp-cli in this worktree's sidecar
## Usage: wt-wp [flags] [args]
## Example: "ddev wt-wp plugin list" or "ddev wt-wp --url=https://nat.herrfors.ddev.site option get home"
## Description: (removed) use ddev wp in worktrees
## Usage: wt-wp
## Example: "ddev wt-wp plugin list"
## OSTypes: linux,darwin
## ProjectTypes: php,wordpress

set -euo pipefail

# shellcheck disable=SC1091
source "$(git rev-parse --show-toplevel 2>/dev/null || pwd -P)/.ddev/generoi-worktree/lib.sh"

wt_require docker
wt_ensure_ddev_project

if ! wt_sidecar_running; then
echo "generoi-worktree: sidecar is not running (run ddev wt-up)" >&2
exit 1
fi

container=$(wt_container_name)
quoted=$(printf '%q ' "$@")
exec_cmd=(bash -lc "cd /var/www/html && wp --path=web/wp ${quoted}")

if [[ -t 0 ]]; then
docker exec -it "$container" "${exec_cmd[@]}"
else
docker exec -i "$container" "${exec_cmd[@]}"
fi
echo "generoi-worktree: wt-wp was removed in v0.2; use 'ddev wp' in this worktree." >&2
exit 1
8 changes: 6 additions & 2 deletions config.generoi-worktree.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# #ddev-generated
# generoi-worktree: block ddev start in git worktrees (use ddev wt-up).
# generoi-worktree: git worktree support (unique name, Caddy :808x, forked DB).
hooks:
pre-start:
- exec-host: "bash .ddev/commands/host/wt-guard"
- exec-host: "bash .ddev/commands/host/wt-prepare"
post-start:
- exec-host: "bash .ddev/commands/host/wt-post-start"
pre-stop:
- exec-host: "bash .ddev/commands/host/wt-pre-stop"
45 changes: 27 additions & 18 deletions generoi-worktree/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,31 @@

Install: `ddev add-on get generoi/ddev-worktree`

Worktree sidecars for Bedrock sites: reuse the canonical DDEV web image + **shared
MariaDB**, browse on `https://<canonical-host>:808x` while PHP/DB keep canonical
hostnames.
## v0.2 architecture

**Caddy** strips `:port` from `Host` before PHP (`header_up Host {http.request.host}`),
then `replace-response` adds `:808x` back in browser URLs. No Bedrock changes.
**Canonical:** normal `ddev start` — one MariaDB, Traefik URL.

**Git worktree:** `ddev start` — full DDEV project with a unique name (`herrfors-wt-<suffix>`), own MariaDB, Caddy on `:808x`.

```
Browser ──► Caddy (:808x) ──► ddev-<wt-project>-web:80
└── ddev-<wt-project>-db (forked from canonical)
```

**Caddy** strips `:port` from `Host` before PHP (`header_up Host {http.request.host}`), then `replace-response` adds `:808x` back in browser URLs.

**Database:** first `ddev start` in a worktree exports canonical `db` and imports into the worktree DB (no search-replace). Refresh manually with `ddev wt-sync-db`.

**Uploads / .env:** symlinked from canonical checkout on `wt-prepare` (shared on host).

## Hooks

| Hook | Action |
|------|--------|
| `pre-start` | `wt-prepare` — unique project name, bootstrap symlinks |
| `post-start` | `wt-post-start` — seed DB if empty, start Caddy |
| `pre-stop` | `wt-pre-stop` — stop Caddy |

## Usage

Expand All @@ -16,18 +35,8 @@ then `replace-response` adds `:808x` back in browser URLs. No Bedrock changes.
**Worktree:**

```bash
ddev wt-up
ddev start
ddev wt-port
ddev wt-down
ddev wt-sync-db # optional: refresh DB from canonical
ddev stop
```

| Flag | Description |
|------|-------------|
| `--port=808x` | Pin host port (default: first free 8081–8099) |
| `--no-deps` | Skip composer/pnpm install |

## Bootstrap

Symlinks from canonical: `.env`, uploads, theme `public/` dirs.

Local per worktree: `composer install`, `pnpm install` (or npm/yarn from lockfile).
Loading