@haus-tech/haus-workflow 6.2.0 → 6.3.0
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.
- package/CHANGELOG.md +11 -0
- package/dist/cli.js +15453 -9507
- package/library/global/skills/haus-workflow/references/clone.md +136 -0
- package/library/schemas/localdev.v2.schema.json +369 -0
- package/package.json +3 -1
|
@@ -202,6 +202,142 @@ seeds: # optional: data sources NOT owned by a manifest repo (e.g. a shared Word
|
|
|
202
202
|
login: 'Add your SSH key to the host (ssh-add …) / request access — or skip the pull.'
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
+
**Workspace, format v2: the `instance:` section (per-worktree environments, ADR-0163).**
|
|
206
|
+
A workspace that runs features in parallel worktrees adds `version: 2` and an `instance:`
|
|
207
|
+
section, and sets `worktree.env: true` in `haus.workspace.yaml`. Unlike the rest of this
|
|
208
|
+
file, `instance:` is parsed and validated strictly by the CLI (`haus doctor`; schema
|
|
209
|
+
`library/schemas/localdev.v2.schema.json`); unknown keys are errors. A v1 file simply has
|
|
210
|
+
no instance support.
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
version: 2
|
|
214
|
+
instance:
|
|
215
|
+
ports: # name -> main-checkout port; a worktree gets <leased block> + offset, in this order
|
|
216
|
+
vendure: 3000
|
|
217
|
+
admin-ui: 4200
|
|
218
|
+
datastores: # shared engines; a worktree is isolated INSIDE them, never by its own container
|
|
219
|
+
mariadb: { engine: mariadb, compose: { project: shop-workspace, service: mariadb }, port: 3318 }
|
|
220
|
+
# compose.file: the compose file (workspace-relative) when its name is not a default one,
|
|
221
|
+
# e.g. compose: { project: shop-workspace, service: pg, file: docker-compose.local.yml }
|
|
222
|
+
redis: { engine: redis, compose: { project: shop-workspace, service: redis }, port: 6381 } # needs --databases 64
|
|
223
|
+
search:
|
|
224
|
+
{
|
|
225
|
+
engine: elasticsearch,
|
|
226
|
+
compose: { project: shop-workspace, service: es },
|
|
227
|
+
port: 9201,
|
|
228
|
+
prefix: 'vendure-',
|
|
229
|
+
}
|
|
230
|
+
databases: # one database per worktree: <name>_wt_<slug>, cloned from <name>_tpl (or <name>)
|
|
231
|
+
ecom: { on: mariadb, name: shop_ecom, perWorktree: clone } # or perWorktree: empty
|
|
232
|
+
sites: # one Herd site per worktree on a copy-on-write docroot clone
|
|
233
|
+
wordpress:
|
|
234
|
+
kind: herd
|
|
235
|
+
root: shop.se # workspace-relative docroot
|
|
236
|
+
host: '{{slug}}.shop.se' # served at http://<slug>.shop.se.test
|
|
237
|
+
share: [wp-content/uploads] # symlinked to the main docroot, not copied
|
|
238
|
+
plugins: { ecom-widgets: shop-ecom-widgets } # plugin dir -> member repo in this worktree
|
|
239
|
+
config:
|
|
240
|
+
{
|
|
241
|
+
kind: wp-config-override,
|
|
242
|
+
defines: { DB_NAME: '{{db.wp}}', WP_HOME: '{{site.wordpress.url}}' },
|
|
243
|
+
}
|
|
244
|
+
after: ['wp search-replace http://shop.se.test {{site.wordpress.url}} --skip-columns=guid']
|
|
245
|
+
processes: # what `env start <name>` runs, from that member repo, on its leased port
|
|
246
|
+
vendure: { repo: shop-ecom, start: 'yarn dev', port: vendure, health: '/health' }
|
|
247
|
+
copyLocal: # extra machine-local files copied from the main checkout (mode 600)
|
|
248
|
+
- { repo: shop-ecom, path: auth.json }
|
|
249
|
+
teardown: # shell commands `env down --destroy` / `env gc --write` run before dropping databases
|
|
250
|
+
- 'docker compose -p shop-ecom-e2e-{{slug}} down -v --remove-orphans'
|
|
251
|
+
env: # the same map as v1; values may now use templates
|
|
252
|
+
- value: '{{port.vendure}}'
|
|
253
|
+
sinks: [{ repo: shop-ecom, key: API_PORT }]
|
|
254
|
+
- value: '{{db.ecom}}'
|
|
255
|
+
sinks: [{ repo: shop-ecom, key: DB_NAME }]
|
|
256
|
+
- value: '{{redis.redis.db}}'
|
|
257
|
+
sinks: [{ repo: shop-ecom, key: REDIS_DB }]
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Templates: `{{slug}}`, `{{port.<name>}}`, `{{db.<name>}}`, `{{redis.<name>.db}}`,
|
|
261
|
+
`{{search.<name>.prefix}}`, `{{site.<name>.url|host|root}}`. In the main checkout they
|
|
262
|
+
resolve to today's values (the main ports and database names, Redis DB 0, the main
|
|
263
|
+
prefix), so one manifest serves both; only a worktree gets new ones. Only keys fed by a
|
|
264
|
+
templated entry are instance-owned; every other key in a repo's `.env` is copied as it is.
|
|
265
|
+
`teardown` (workspace file only) cleans up per-worktree resources the CLI does not track,
|
|
266
|
+
such as a compose project an app's own test harness starts; keep each command idempotent.
|
|
267
|
+
`after` (workspace file only) is its counterpart for `env up`: commands that run once per
|
|
268
|
+
environment in the worktree root, after the `.env` files and `.haus-env.json` exist, such as
|
|
269
|
+
copying the main bucket into a per-worktree one (`mc mirror local/assets
|
|
270
|
+
local/assets-wt-{{slug}}`); a failed one is retried by the next `env up`.
|
|
271
|
+
|
|
272
|
+
**Single-repo projects** (a plain repo with Claude Code worktrees, ADR-0167): the repo's own
|
|
273
|
+
`.haus-workflow/localdev.yml` takes the whole `instance:` section, the flag is
|
|
274
|
+
`"worktree": { "env": true }` in `.haus-workflow/haus.config.json`, and `repo:` in sinks,
|
|
275
|
+
processes and `copyLocal` names a folder inside the repo (`.` for the root, `apps/server`
|
|
276
|
+
for an app).
|
|
277
|
+
|
|
278
|
+
**Other engines and site kinds.** The same section covers the other client stacks:
|
|
279
|
+
|
|
280
|
+
```yaml
|
|
281
|
+
instance:
|
|
282
|
+
datastores:
|
|
283
|
+
# An engine on the host (DBngin, Homebrew), not in Docker: haus never starts it and
|
|
284
|
+
# connects with the host's mysql/mariadb client. Credentials: export MYSQL_USER and
|
|
285
|
+
# MYSQL_PWD, or use ~/.my.cnf. `port` defaults to native.port. Supported for mariadb,
|
|
286
|
+
# mysql, elasticsearch and opensearch.
|
|
287
|
+
mysql: { engine: mysql, native: { host: 127.0.0.1, port: 3306 } }
|
|
288
|
+
# native: { host: 127.0.0.1, port: 3306, client: /Users/Shared/DBngin/mysql/8.0.33/bin/mysql }
|
|
289
|
+
# SQL Server: database isolation (BACKUP / RESTORE WITH MOVE into <name>_wt_<slug>).
|
|
290
|
+
# azure-sql-edge has no sqlcmd; haus then runs mcr.microsoft.com/mssql-tools (amd64) on
|
|
291
|
+
# the engine's network. The SA password stays in the engine container's env.
|
|
292
|
+
mssql: { engine: mssql, compose: { project: vafab-workspace, service: mssql }, port: 49760 }
|
|
293
|
+
sites:
|
|
294
|
+
cms: # Bedrock: the root is a member repo, its .env gets the defines (copy: none is the default)
|
|
295
|
+
kind: herd
|
|
296
|
+
root: bad-varme.se
|
|
297
|
+
host: '{{slug}}.bad-varme.se'
|
|
298
|
+
php: '8.2'
|
|
299
|
+
share: [web/app/uploads]
|
|
300
|
+
config:
|
|
301
|
+
kind: bedrock-env
|
|
302
|
+
defines:
|
|
303
|
+
DB_NAME: '{{db.wp}}'
|
|
304
|
+
WP_HOME: '{{site.cms.url}}'
|
|
305
|
+
WP_SITEURL: '{{site.cms.url}}/wp'
|
|
306
|
+
app: # Laravel on Herd: same, with Laravel's keys
|
|
307
|
+
kind: herd
|
|
308
|
+
root: app.example.se
|
|
309
|
+
host: '{{slug}}.app.example.se'
|
|
310
|
+
secure: true
|
|
311
|
+
config:
|
|
312
|
+
kind: laravel-env
|
|
313
|
+
defines: { APP_URL: '{{site.app.url}}', DB_DATABASE: '{{db.api}}' }
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
`bedrock-env` and `laravel-env` write no PHP file and need no `patch-wp-config`: the
|
|
317
|
+
defines become instance-owned keys of the member's `.env`, next to any `env:` sinks for
|
|
318
|
+
that repo, and the rest of the main checkout's `.env` is copied as it is. Teardown unlinks
|
|
319
|
+
the Herd site and never deletes the member repo.
|
|
320
|
+
|
|
321
|
+
**How this relates to the clone flow.** This procedure sets up the **main checkout**: it
|
|
322
|
+
brings the shared engines up, seeds the main databases and writes each repo's `.env`. It
|
|
323
|
+
never touches `instance:`. A worktree then gets its own environment from that main
|
|
324
|
+
checkout with one command, run inside the worktree:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
haus workspace worktree env snapshot ecom # once, and whenever fresh data is wanted: <name>_tpl from the main DB
|
|
328
|
+
haus workspace worktree env up # lease ports, clone DBs, Redis index, prefix, site, .env files
|
|
329
|
+
haus workspace worktree env start vendure # runs on the worktree's own port
|
|
330
|
+
haus workspace worktree env status # ports, URLs, databases
|
|
331
|
+
haus workspace worktree env down --destroy # or just `worktree remove`, which runs it first
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
`env up` copies each repo's `.env` from the main checkout (secrets included, never printed)
|
|
335
|
+
and replaces only the instance-owned keys, so the main checkout's `.env` must exist first:
|
|
336
|
+
that is exactly what this clone flow produces. Agents never read a `.env`; they use
|
|
337
|
+
`haus workspace worktree env get <key>` or `.haus-env.json`. For a WordPress site with
|
|
338
|
+
`config.kind: wp-config-override`, run `haus workspace worktree env patch-wp-config <site>`
|
|
339
|
+
once in the main checkout (it backs the file up and never prints it).
|
|
340
|
+
|
|
205
341
|
#### Run order
|
|
206
342
|
|
|
207
343
|
1. **Discover** `.haus-workflow/localdev.yml` in the workspace root and each repo.
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/WeAreHausTech/haus-workflow/library/schemas/localdev.v2.schema.json",
|
|
4
|
+
"title": "haus localdev.yml (version 2)",
|
|
5
|
+
"description": "The CLI-parsed part of .haus-workflow/localdev.yml (ADR-0163). Only `version`, `instance` and the templates in `env` are validated by the CLI (src/workspace/env/manifest.ts, which is the enforcement); every other top-level key is agent-interpreted by the clone skill and left open here. Templates: {{slug}}, {{port.<name>}}, {{db.<name>}}, {{redis.<name>.db}}, {{search.<name>.prefix}}, {{site.<name>.url|host|root}}.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"version": {
|
|
9
|
+
"enum": [1, 2]
|
|
10
|
+
},
|
|
11
|
+
"instance": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"description": "Per-worktree environment. A repo file may declare only ports and processes.",
|
|
15
|
+
"properties": {
|
|
16
|
+
"ports": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"propertyNames": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$"
|
|
21
|
+
},
|
|
22
|
+
"additionalProperties": {
|
|
23
|
+
"type": "integer",
|
|
24
|
+
"minimum": 1,
|
|
25
|
+
"maximum": 65535
|
|
26
|
+
},
|
|
27
|
+
"maxProperties": 20,
|
|
28
|
+
"description": "name -> main-checkout port; a worktree gets lease base + declaration index"
|
|
29
|
+
},
|
|
30
|
+
"datastores": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"propertyNames": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$"
|
|
35
|
+
},
|
|
36
|
+
"additionalProperties": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"required": ["engine"],
|
|
40
|
+
"properties": {
|
|
41
|
+
"engine": {
|
|
42
|
+
"enum": [
|
|
43
|
+
"mariadb",
|
|
44
|
+
"mysql",
|
|
45
|
+
"postgres",
|
|
46
|
+
"redis",
|
|
47
|
+
"elasticsearch",
|
|
48
|
+
"opensearch",
|
|
49
|
+
"mssql"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"compose": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"required": ["project", "service"],
|
|
56
|
+
"properties": {
|
|
57
|
+
"project": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"minLength": 1
|
|
60
|
+
},
|
|
61
|
+
"service": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"minLength": 1
|
|
64
|
+
},
|
|
65
|
+
"file": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"minLength": 1,
|
|
68
|
+
"description": "Compose file, relative to the workspace root, passed as -f when env up has to create the engine (for a non-default name such as docker-compose.local.yml)."
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"native": {
|
|
73
|
+
"type": "object",
|
|
74
|
+
"additionalProperties": false,
|
|
75
|
+
"required": ["host", "port"],
|
|
76
|
+
"description": "An engine on the host, outside Docker (mariadb, mysql, elasticsearch, opensearch). haus never starts it; SQL credentials come only from MYSQL_USER / MYSQL_PWD or ~/.my.cnf.",
|
|
77
|
+
"properties": {
|
|
78
|
+
"host": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"pattern": "^[A-Za-z0-9._:-]+$"
|
|
81
|
+
},
|
|
82
|
+
"port": {
|
|
83
|
+
"type": "integer",
|
|
84
|
+
"minimum": 1,
|
|
85
|
+
"maximum": 65535
|
|
86
|
+
},
|
|
87
|
+
"client": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"pattern": "^[A-Za-z0-9._/+-]+$",
|
|
90
|
+
"description": "mysql/mariadb client: a command on PATH or an absolute path (default: mysql or mariadb on PATH)"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"port": {
|
|
95
|
+
"type": "integer",
|
|
96
|
+
"minimum": 1,
|
|
97
|
+
"maximum": 65535,
|
|
98
|
+
"description": "The engine port. Optional with native: (defaults to native.port)."
|
|
99
|
+
},
|
|
100
|
+
"isolation": {
|
|
101
|
+
"enum": ["database", "db-index", "key-prefix", "prefix", "container"],
|
|
102
|
+
"description": "Default per engine: database (SQL, mssql included), db-index (redis), prefix (search). container has no driver yet."
|
|
103
|
+
},
|
|
104
|
+
"prefix": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"description": "The main checkout's index or key prefix (default empty)."
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"oneOf": [
|
|
110
|
+
{
|
|
111
|
+
"required": ["compose", "port"]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"required": ["native"]
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"databases": {
|
|
120
|
+
"type": "object",
|
|
121
|
+
"propertyNames": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$"
|
|
124
|
+
},
|
|
125
|
+
"additionalProperties": {
|
|
126
|
+
"type": "object",
|
|
127
|
+
"additionalProperties": false,
|
|
128
|
+
"required": ["on", "name"],
|
|
129
|
+
"properties": {
|
|
130
|
+
"on": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"description": "A datastore name"
|
|
133
|
+
},
|
|
134
|
+
"name": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"minLength": 1
|
|
137
|
+
},
|
|
138
|
+
"perWorktree": {
|
|
139
|
+
"enum": ["clone", "empty"],
|
|
140
|
+
"default": "clone"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"sites": {
|
|
146
|
+
"type": "object",
|
|
147
|
+
"propertyNames": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$"
|
|
150
|
+
},
|
|
151
|
+
"additionalProperties": {
|
|
152
|
+
"type": "object",
|
|
153
|
+
"additionalProperties": false,
|
|
154
|
+
"required": ["kind", "root", "host"],
|
|
155
|
+
"properties": {
|
|
156
|
+
"kind": {
|
|
157
|
+
"const": "herd"
|
|
158
|
+
},
|
|
159
|
+
"mode": {
|
|
160
|
+
"enum": ["per-worktree", "shared-lock"],
|
|
161
|
+
"default": "per-worktree"
|
|
162
|
+
},
|
|
163
|
+
"root": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"minLength": 1,
|
|
166
|
+
"description": "Relative path inside the repo; no leading / and no .."
|
|
167
|
+
},
|
|
168
|
+
"host": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"minLength": 1,
|
|
171
|
+
"description": "May use templates, e.g. {{slug}}.shop.se"
|
|
172
|
+
},
|
|
173
|
+
"mainHost": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"description": "The main checkout's host (default: basename of root)"
|
|
176
|
+
},
|
|
177
|
+
"secure": {
|
|
178
|
+
"type": "boolean",
|
|
179
|
+
"default": false
|
|
180
|
+
},
|
|
181
|
+
"php": {
|
|
182
|
+
"type": ["string", "number"]
|
|
183
|
+
},
|
|
184
|
+
"copy": {
|
|
185
|
+
"enum": ["cow", "none"],
|
|
186
|
+
"description": "cow clones the main docroot; none uses the worktree folder as it is (the default, and required, for bedrock-env and laravel-env, whose root is a member repo)."
|
|
187
|
+
},
|
|
188
|
+
"share": {
|
|
189
|
+
"type": "array",
|
|
190
|
+
"items": {
|
|
191
|
+
"type": "string",
|
|
192
|
+
"minLength": 1
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
"plugins": {
|
|
196
|
+
"type": "object",
|
|
197
|
+
"additionalProperties": {
|
|
198
|
+
"type": "string",
|
|
199
|
+
"minLength": 1
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"config": {
|
|
203
|
+
"type": "object",
|
|
204
|
+
"additionalProperties": false,
|
|
205
|
+
"required": ["kind"],
|
|
206
|
+
"properties": {
|
|
207
|
+
"kind": {
|
|
208
|
+
"enum": ["wp-config-override", "bedrock-env", "laravel-env"],
|
|
209
|
+
"description": "wp-config-override writes wp-config.haus-instance.php; bedrock-env and laravel-env write the defines into the site repo's .env (instance-owned keys)."
|
|
210
|
+
},
|
|
211
|
+
"defines": {
|
|
212
|
+
"type": "object",
|
|
213
|
+
"propertyNames": {
|
|
214
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
|
|
215
|
+
},
|
|
216
|
+
"additionalProperties": {
|
|
217
|
+
"type": "string"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"after": {
|
|
223
|
+
"type": "array",
|
|
224
|
+
"items": {
|
|
225
|
+
"type": "string",
|
|
226
|
+
"minLength": 1
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"processes": {
|
|
233
|
+
"type": "object",
|
|
234
|
+
"propertyNames": {
|
|
235
|
+
"type": "string",
|
|
236
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$"
|
|
237
|
+
},
|
|
238
|
+
"additionalProperties": {
|
|
239
|
+
"type": "object",
|
|
240
|
+
"additionalProperties": false,
|
|
241
|
+
"required": ["start"],
|
|
242
|
+
"properties": {
|
|
243
|
+
"repo": {
|
|
244
|
+
"type": "string",
|
|
245
|
+
"description": "Required in the workspace file; defaults to the owning repo in a repo file. In a single-repo project (ADR-0167), the folder inside the repo the process runs in (`.` for the root)"
|
|
246
|
+
},
|
|
247
|
+
"start": {
|
|
248
|
+
"type": "string",
|
|
249
|
+
"minLength": 1
|
|
250
|
+
},
|
|
251
|
+
"port": {
|
|
252
|
+
"type": "string",
|
|
253
|
+
"description": "A name from instance.ports"
|
|
254
|
+
},
|
|
255
|
+
"health": {
|
|
256
|
+
"type": "string"
|
|
257
|
+
},
|
|
258
|
+
"healthTimeoutSec": {
|
|
259
|
+
"type": "number",
|
|
260
|
+
"exclusiveMinimum": 0,
|
|
261
|
+
"default": 120
|
|
262
|
+
},
|
|
263
|
+
"optional": {
|
|
264
|
+
"type": "boolean",
|
|
265
|
+
"default": false
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
"copyLocal": {
|
|
271
|
+
"type": "array",
|
|
272
|
+
"items": {
|
|
273
|
+
"type": "object",
|
|
274
|
+
"additionalProperties": false,
|
|
275
|
+
"required": ["repo", "path"],
|
|
276
|
+
"properties": {
|
|
277
|
+
"repo": {
|
|
278
|
+
"type": "string",
|
|
279
|
+
"minLength": 1
|
|
280
|
+
},
|
|
281
|
+
"path": {
|
|
282
|
+
"type": "string",
|
|
283
|
+
"minLength": 1,
|
|
284
|
+
"description": "Relative path inside the repo; no leading / and no .."
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"teardown": {
|
|
290
|
+
"type": "array",
|
|
291
|
+
"items": {
|
|
292
|
+
"type": "string",
|
|
293
|
+
"minLength": 1
|
|
294
|
+
},
|
|
295
|
+
"description": "Shell commands (templated) env down --destroy and env gc --write run after stopping processes and before dropping databases; workspace file only, must be idempotent"
|
|
296
|
+
},
|
|
297
|
+
"after": {
|
|
298
|
+
"type": "array",
|
|
299
|
+
"items": {
|
|
300
|
+
"type": "string",
|
|
301
|
+
"minLength": 1
|
|
302
|
+
},
|
|
303
|
+
"description": "Shell commands (templated) env up runs once per environment in the worktree root, after the .env files and .haus-env.json are written (for example seeding a per-worktree bucket from the main one, ADR-0167); a failed one is retried by the next env up; workspace file only, must be idempotent"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
"env": {
|
|
308
|
+
"type": "array",
|
|
309
|
+
"items": {
|
|
310
|
+
"type": "object",
|
|
311
|
+
"required": ["sinks"],
|
|
312
|
+
"properties": {
|
|
313
|
+
"value": {
|
|
314
|
+
"type": ["string", "number"]
|
|
315
|
+
},
|
|
316
|
+
"source": {
|
|
317
|
+
"type": "object",
|
|
318
|
+
"required": ["provides"],
|
|
319
|
+
"properties": {
|
|
320
|
+
"repo": {
|
|
321
|
+
"type": "string"
|
|
322
|
+
},
|
|
323
|
+
"provides": {
|
|
324
|
+
"type": "string"
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
"sinks": {
|
|
329
|
+
"type": "array",
|
|
330
|
+
"items": {
|
|
331
|
+
"type": "object",
|
|
332
|
+
"required": ["repo", "key"],
|
|
333
|
+
"properties": {
|
|
334
|
+
"repo": {
|
|
335
|
+
"type": "string",
|
|
336
|
+
"minLength": 1,
|
|
337
|
+
"description": "A member repo (id or folder) in a workspace; in a single-repo project (ADR-0167) a folder inside the repo in canonical form, `.` for the root or `apps/server` for a monorepo app, whose .env receives the key"
|
|
338
|
+
},
|
|
339
|
+
"key": {
|
|
340
|
+
"type": "string",
|
|
341
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"anyOf": [
|
|
348
|
+
{
|
|
349
|
+
"required": ["value"]
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"required": ["source"]
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
"if": {
|
|
359
|
+
"required": ["instance"]
|
|
360
|
+
},
|
|
361
|
+
"then": {
|
|
362
|
+
"properties": {
|
|
363
|
+
"version": {
|
|
364
|
+
"const": 2
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
"required": ["version"]
|
|
368
|
+
}
|
|
369
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haus-tech/haus-workflow",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "Haus AI workflow CLI for Claude Code.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"scripts/postinstall.mjs",
|
|
17
17
|
"library/global",
|
|
18
18
|
"library/catalog",
|
|
19
|
+
"library/schemas",
|
|
19
20
|
"README.md",
|
|
20
21
|
"CHANGELOG.md",
|
|
21
22
|
"docs/before-you-start.md",
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"test:quick": "node scripts/test-fast.mjs --quick",
|
|
29
30
|
"test:full": "node scripts/run-tests.mjs tests/**/*.test.js",
|
|
30
31
|
"test:coverage": "c8 yarn test:full",
|
|
32
|
+
"test:integration": "HAUS_INTEGRATION=1 node scripts/run-tests.mjs tests/integration/*.int.test.js",
|
|
31
33
|
"coverage:check": "c8 --check-coverage yarn test:full",
|
|
32
34
|
"lint": "eslint src --cache --cache-location .eslintcache",
|
|
33
35
|
"format:check": "prettier --check --cache --cache-location .prettiercache .",
|