@haus-tech/haus-workflow 0.24.1 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -33,4 +33,7 @@ Clone a whole **workspace** from its manifest. Workspace-only (a `repos.manifest
|
|
|
33
33
|
- **Cancel** — do nothing.
|
|
34
34
|
5. Show the concrete plan before touching anything: list which repos will be cloned (and into which `folder`) and which will be reused/skipped. Get a final go-ahead.
|
|
35
35
|
6. For each repo to clone, run (quoting it first): `haus clone <repo-url> <folder>` from the workspace root. Offer `--dry-run` first if the user wants a preview. If one repo fails, report it and continue to the next.
|
|
36
|
+
|
|
37
|
+
**Transport fallback.** Manifest URLs may be SSH (`git@github.com:org/repo.git` or `ssh://…`). Probe SSH connectivity once up front (`ssh -T git@github.com`); if it fails, **auto-fall back to the HTTPS URL** (`https://github.com/org/repo.git`) using your `gh auth` credentials, clone over HTTPS, and **report that you switched transport** so the user knows their SSH is down. Don't halt the run for an SSH outage when HTTPS works.
|
|
38
|
+
|
|
36
39
|
7. After the loop, report which repos were cloned, reused (local), skipped (already present), and failed. Remind the user that installing dependencies and configuring each repo (`.env`, services) is still a manual step for now.
|
|
@@ -6,16 +6,23 @@ Clone a project's repos **and** set each one up for local development — node v
|
|
|
6
6
|
|
|
7
7
|
Run the full `project:clone` flow by following `~/.claude/commands/haus-clone.md` end to end (name → one repo; no name → workspace repos from `repos.manifest.json`). Carry the resulting repo list into Step 2.
|
|
8
8
|
|
|
9
|
-
## Step 2 —
|
|
9
|
+
## Step 2 — Prerequisite gate (one consolidated check)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
Before any setup work, probe **everything** the workspace will need and surface **all** gaps in a single prompt — never discover them piecemeal mid-flow. For the repos being set up, check:
|
|
12
|
+
|
|
13
|
+
- **Auth tokens** — `NODE_AUTH_TOKEN` exported (private `@`-scoped npm packages fail without it); `~/.composer/auth.json` (or a repo-local `auth.json`) present if any repo has private composer deps.
|
|
14
|
+
- **Docker daemon** — running (`docker info`); required for any repo's `needs:` services.
|
|
15
|
+
- **PHP environment** — `valet`, `herd`, `ddev`, or `php` on PATH, if any repo is a PHP/WordPress site.
|
|
16
|
+
- **WP-CLI** — `wp --version`, if any repo's `seed:` pulls a WordPress DB.
|
|
17
|
+
- **Node versions** — the versions named in each repo's `.nvmrc` / `engines.node` are installable via `nvm`.
|
|
18
|
+
|
|
19
|
+
Then list the repos and what each will run (node, deps, localdev steps), **report every gap at once**, and get a single go-ahead. For **reused** local clones, ask whether to re-run setup. For each gap, name what it blocks; the user decides whether to fix it now (**ask before any global/system install**) or proceed and skip the affected steps. Don't begin per-repo work until this gate is acknowledged.
|
|
13
20
|
|
|
14
21
|
## Step 3 — Per-repo dependency pass
|
|
15
22
|
|
|
16
23
|
For each repo, in its own directory, detect and install from the repo's own files (read its `docs/setup.md` / `CLAUDE.md` / `README.md` first — they win). Select node from `.nvmrc`/`engines.node` (`nvm install`), enable the pinned package manager (`corepack enable`), install JS deps (`yarn`/`pnpm`/`npm` by lockfile), composer deps if `composer.json` + `composer` present. Run each repo's steps in one login shell so the node version stays active. Per-repo failure is reported and skipped, not fatal.
|
|
17
24
|
|
|
18
|
-
**
|
|
25
|
+
**Leave `.env` to Step 4 → "Env".** The dependency pass installs only; the env phase writes each repo's `.env` deterministically once services, links, and values are in place.
|
|
19
26
|
|
|
20
27
|
## Step 4 — Local-dev orchestration
|
|
21
28
|
|
|
@@ -27,7 +34,7 @@ Specify the least. Infer the rest from the repo's stack + these conventions, and
|
|
|
27
34
|
|
|
28
35
|
- **IMPORTANT — never install anything without asking first; global/system tools especially** (Homebrew, Docker, Laravel Herd, global `npm`/`composer` packages). Detect what's already present; if something required is missing, name it, say why it's needed, and get an explicit **yes** before installing. Prefer the least-invasive option, and don't switch or override tools the dev already has.
|
|
29
36
|
- **PHP / WordPress sites are served by the developer's own PHP environment.** If they already have one — detect `valet`, `herd`, `ddev`, or `php` on PATH — **use it**: just satisfy the env contract (docroot → the repo's `web/`, HTTPS) and report the URL; never override what they already run. **Only when no local PHP environment exists** (a completely fresh machine) suggest installing **[Laravel Herd](https://herd.laravel.com)** as the default (asking first) and point its docroot at `web/` + `herd secure`.
|
|
30
|
-
- **Databases and other services (a repo's `needs:`) run in Docker.** **If Docker isn't installed
|
|
37
|
+
- **Databases and other services (a repo's `needs:`) run in Docker as standalone containers.** Bring each up with a **clean `docker run`** — image, host port, and env from the house convention for that service (e.g. `mysql` → `mysql:8` on `127.0.0.1:3306`, root password from generated secrets; `postgres` → `postgres:16` on `5432`). **Do not provision a `needs:` service from the repo's own `docker-compose.yml` when that compose bind-mounts repo-relative init files** (e.g. `./seed.sql`, `./docker-entrypoint-initdb.d/`): those mounts need files the guard won't let us create, and they conflate bring-up with seeding (which is the separate `seed:` step). **If Docker isn't installed** it's a prerequisite (surfaced in the Step 2 gate) — **ask before installing it** (global install). **Port-conflict caveat:** if the conventional host port is already taken, pick the next free port, use it, and **record the chosen port in the workspace `localdev.yml` `env` map** so sink repos point at the right place. A `needs:` service comes up **empty** — populating it is always the separate `seed:` step.
|
|
31
38
|
- **Dependencies** install from the lockfile (Step 3).
|
|
32
39
|
- A repo's `localdev.yml` carries **only what can't be inferred** — its `needs`, repo-specific `build`/`seed` commands, env keys, and URL. Detect the stack (e.g. Bedrock = `composer.json` + `web/` docroot + `wp-cli.yml`; Vendure/Node = `docker-compose.yml` + `@vendure/*`) and apply the matching convention.
|
|
33
40
|
|
|
@@ -57,6 +64,8 @@ steps: # optional escape hatch: explicit ordered shell steps when intent isn't e
|
|
|
57
64
|
|
|
58
65
|
**Workspace — `<workspace>/.haus-workflow/localdev.yml`** (the glue BETWEEN repos):
|
|
59
66
|
|
|
67
|
+
The workspace `env` map is the **single source of truth for cross-repo values** — DB names, ports, host URLs are chosen once and recorded here as literals. The env phase reads values **from here** and writes them into each repo's `.env`. Recording them here (not only in a repo's `.env`) means a later `seed:` / `db:pull` step can find them without depending on env-file load order.
|
|
68
|
+
|
|
60
69
|
```yaml
|
|
61
70
|
order: [repo-a, repo-b] # setup/startup order, by manifest id
|
|
62
71
|
links:
|
|
@@ -64,9 +73,10 @@ links:
|
|
|
64
73
|
- { type: composer-path, in: <repo>, dep: <sibling-repo> }
|
|
65
74
|
- { type: yarn-link, in: [<repo>, ...], dep: <sibling-package-repo> }
|
|
66
75
|
env:
|
|
67
|
-
-
|
|
76
|
+
- value: 'app_local' # a chosen literal — the recorded source of truth, OR …
|
|
77
|
+
# source: { repo: <repo>, provides: '<value>' } # … a value produced by another repo
|
|
68
78
|
sinks:
|
|
69
|
-
- { repo: <repo>, key:
|
|
79
|
+
- { repo: <repo>, key: DB_NAME } # written under `key` into each sink's .env
|
|
70
80
|
```
|
|
71
81
|
|
|
72
82
|
### Run order
|
|
@@ -74,23 +84,46 @@ env:
|
|
|
74
84
|
1. **Discover** `.haus-workflow/localdev.yml` in the workspace root and each repo.
|
|
75
85
|
2. **Resolve order** from the workspace `order` (repos not listed run last, in manifest order). No workspace file → manifest order.
|
|
76
86
|
3. **Per repo, in order**, apply intent via the conventions:
|
|
77
|
-
- **`needs`** →
|
|
87
|
+
- **`needs`** → bring up each service as a **standalone `docker run`** (image/port/env from conventions; **not** the repo's compose when it bind-mounts repo-relative init files) if not already running. The service comes up **empty**; record its values in the workspace `localdev.yml` `env` map. No data is created here, so no overwrite prompt at this step — data lands in `seed:`.
|
|
78
88
|
- **`build`** → run it (honor any node version the repo's docs note).
|
|
79
89
|
- **`serve`** → for `via: herd` / PHP envs, install nothing — verify the dev's environment serves `web/`, and report the URL.
|
|
80
|
-
- **`seed`** →
|
|
90
|
+
- **`seed`** → populate the empty datastore. **Always a distinct, confirm-gated step, separate from `needs:` bring-up** (don't conflate "DB up" with "DB has data"). Before running, **check its prerequisites and report any gap instead of running blind** — e.g. WP-CLI present (for `wp` / `db:pull` seeds), the target repo's **`.env` written** (the seed reads connection values from it — done in the Env step above), the **SSH alias resolves** (for remote pulls like `dep db:pull staging-oderland`). **Confirm first** for every remote (SSH) or destructive (overwrites data) seed — every run, even on re-run. Missing prerequisite → skip with a clear message, don't guess.
|
|
81
91
|
- **`steps`** (escape hatch) → run in order, selecting `node:` per step, `optional:` failures continue, **confirming before any `remote:`/`destructive:` step** — every run, even on re-run.
|
|
82
92
|
4. **Links** (workspace-owned, performed generically — do NOT call a repo's own `setup-dev-mode.sh`, which is deprecated):
|
|
83
93
|
- `symlink` → `ln -s <from> <to>`; replace an existing symlink, but never clobber a real directory without confirmation.
|
|
84
94
|
- `composer-path` → in `in`'s `composer.json`, set the `dep`'s require to `{ "type": "path", "url": "../<dep-folder>", "options": { "symlink": true } }`, then `composer update <vendor/dep>`.
|
|
85
95
|
- `yarn-link` → `yarn link` in the `dep` repo, then `yarn link <pkg-name>` in each `in` repo (read `<pkg-name>` from the dep's `package.json`).
|
|
86
|
-
5. **Env:**
|
|
96
|
+
5. **Env (deterministic):** write each repo's `.env` from known values — no improvising.
|
|
97
|
+
1. **Compute** each repo's values, in this precedence: the workspace `localdev.yml` `env` map (chosen literals + cross-repo `source` values — the single source of truth) → generated secrets (DB passwords/tokens minted this run) → the **dev-defaults table** below for anything still unset.
|
|
98
|
+
2. **Write** them into each repo's `.env` (create it if absent; **upsert** keys, never clobbering a value the user already set). These are local dev files — write them directly.
|
|
99
|
+
3. **Real secrets the generator can't mint** (third-party API keys, prod credentials) go in as clearly-marked `KEY=` blanks for the user to fill; report exactly which keys are still blank.
|
|
100
|
+
|
|
101
|
+
**Dev-defaults table** — used only when neither `localdev.yml` nor a generated secret supplies the value:
|
|
102
|
+
|
|
103
|
+
| Key | Default |
|
|
104
|
+
| -------------------------------- | ------------------------------------------------------------------- |
|
|
105
|
+
| `DB_HOST` | `127.0.0.1` |
|
|
106
|
+
| `DB_PORT` | `3306` (mysql) / `5432` (postgres) — or the port chosen on conflict |
|
|
107
|
+
| `DB_USER` / `DB_PASSWORD` | `root` / a generated secret |
|
|
108
|
+
| `WP_HOME`, `WP_SITEURL`, `*_URL` | the repo's `serve.url` |
|
|
109
|
+
| `WP_ENV` / `APP_ENV` | `development` |
|
|
110
|
+
|
|
87
111
|
6. **Report, then offer to start.** Give the per-repo summary, then **ask the user whether to start everything now.**
|
|
88
112
|
- **Yes** → start each repo in the workspace `order` (its `serve.start`, e.g. `yarn dev`; bring up any remaining foreground services), run any follow-ups (e.g. `wp sync-products sync`), then **print the live URLs** (each repo's `serve.url`).
|
|
89
113
|
- **No** → just print the ordered start commands + follow-ups as next steps; start nothing.
|
|
90
114
|
|
|
91
|
-
**Default is "ready to run" (D2):** the preparation — datastores up (`docker
|
|
115
|
+
**Default is "ready to run" (D2):** the preparation — datastores up (standalone `docker run`), seeds applied (confirm-gated), links, builds, each repo's `.env` written — always happens. Starting the **foreground** dev servers and the initial product sync happen **only if the user says yes** to the start prompt above; otherwise they're printed, not run.
|
|
116
|
+
|
|
117
|
+
## Step 5 — Report and define "done"
|
|
118
|
+
|
|
119
|
+
**"Done" is an explicit terminal state**, not "looks set up". The preparation reaches:
|
|
120
|
+
|
|
121
|
+
- datastores up (standalone containers),
|
|
122
|
+
- dependencies installed and builds green,
|
|
123
|
+
- links wired,
|
|
124
|
+
- each repo's `.env` written from known values.
|
|
92
125
|
|
|
93
|
-
|
|
126
|
+
From there, **live URLs are reachable only if** every required secret is satisfiable **and** the user starts the servers. If a secret can't be minted (a third-party key, a prod credential), say exactly which keys are still blank and what the user must fill — don't imply links a missing secret will quietly break.
|
|
94
127
|
|
|
95
128
|
Summarise per repo (node, deps, localdev steps, links, env). Then **ask whether to start everything now**:
|
|
96
129
|
|