@wpmoo/toolkit 0.9.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/LICENSE +22 -0
- package/README.md +519 -0
- package/dist/addons-yaml.js +59 -0
- package/dist/args.js +259 -0
- package/dist/cli.js +1039 -0
- package/dist/cockpit/command-palette.js +23 -0
- package/dist/cockpit/command-registry.js +91 -0
- package/dist/cockpit/daily-prompts.js +177 -0
- package/dist/cockpit/menu.js +99 -0
- package/dist/cockpit/safety.js +22 -0
- package/dist/compose-layout.js +118 -0
- package/dist/daily-actions.js +190 -0
- package/dist/doctor.js +519 -0
- package/dist/environment-context.js +10 -0
- package/dist/environment-version.js +5 -0
- package/dist/environment.js +136 -0
- package/dist/external-assets.js +153 -0
- package/dist/external-templates.js +86 -0
- package/dist/git.js +98 -0
- package/dist/github.js +87 -0
- package/dist/help.js +157 -0
- package/dist/menu-navigation.js +67 -0
- package/dist/module-actions.js +114 -0
- package/dist/odoo-versions.js +1 -0
- package/dist/path-validation.js +50 -0
- package/dist/prompt-copy.js +8 -0
- package/dist/prompt-repositories.js +34 -0
- package/dist/prompts/index.js +174 -0
- package/dist/repo-actions.js +158 -0
- package/dist/repo-url.js +27 -0
- package/dist/repository-preflight.js +46 -0
- package/dist/safe-reset.js +217 -0
- package/dist/scaffold.js +161 -0
- package/dist/source-actions.js +65 -0
- package/dist/source-manifest.js +338 -0
- package/dist/status.js +239 -0
- package/dist/templates.js +758 -0
- package/dist/types.js +1 -0
- package/dist/update-check.js +106 -0
- package/dist/version.js +19 -0
- package/docs/assets/patreon-donate.png +0 -0
- package/docs/assets/wpmoo-banner.png +0 -0
- package/docs/external-resources.md +136 -0
- package/docs/generated-environment-verification.md +140 -0
- package/docs/handoff.md +29 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WPMoo.org
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
[](https://github.com/wpmoo-org/wpmoo-toolkit/actions/workflows/ci.yml) [](https://github.com/wpmoo-org/wpmoo-toolkit) [](https://www.npmjs.com/package/@wpmoo/toolkit) [](https://codecov.io/gh/wpmoo-org/wpmoo-toolkit) [](LICENSE) [](https://github.com/wpmoo-org/wpmoo-toolkit) [](https://www.buymeacoffee.com/cangir) [](https://www.patreon.com/wpmoo)
|
|
4
|
+
|
|
5
|
+
# WPMoo Toolkit
|
|
6
|
+
|
|
7
|
+
WPMoo Toolkit is a development-first CLI for creating and operating Docker Compose based environments for Odoo, with source repositories managed as Git submodules.
|
|
8
|
+
|
|
9
|
+
It gives Odoo teams a repeatable environment layout, a guided cockpit for daily work, direct commands for automation, and recovery tools that refresh generated files without touching product source code.
|
|
10
|
+
|
|
11
|
+
WPMoo Toolkit is an independent project and is not affiliated with, endorsed by, or sponsored by Odoo S.A. Odoo is a trademark of Odoo S.A.
|
|
12
|
+
|
|
13
|
+
## Development Status
|
|
14
|
+
|
|
15
|
+
> [!IMPORTANT]
|
|
16
|
+
> **Pre-1.0 active development:** WPMoo Toolkit has not reached `1.0.0` yet. Until the `1.0.0` release, use it as a preview tool for evaluation, local trials, and feedback rather than a dependency for critical production workflows. Setup conventions and command behavior may still change between pre-1.0 releases.
|
|
17
|
+
|
|
18
|
+
## Why WPMoo Toolkit
|
|
19
|
+
|
|
20
|
+
- Create a local Odoo development environment from a dev repository and one or more source repositories.
|
|
21
|
+
- Keep product source repositories under `odoo/custom/src/private`, `odoo/custom/src/oca`, or `odoo/custom/src/external` as Git submodules pinned to the selected Odoo branch.
|
|
22
|
+
- Copy Docker Compose resources from the standalone `wpmoo-org/odoo-docker-compose` resource instead of embedding large runtime assets in the TypeScript package.
|
|
23
|
+
- Optionally copy project-local Agent Skills from `wpmoo-org/odoo-skills` into generated environments.
|
|
24
|
+
- Use either a guided terminal cockpit or direct CLI commands for the same lifecycle tasks.
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- Node.js `>=20.17`
|
|
29
|
+
- Git
|
|
30
|
+
- Docker and Docker Compose for generated environment runtime commands
|
|
31
|
+
- GitHub CLI (`gh`) is optional. Use it for repository discovery, repository creation, and deeper diagnostics.
|
|
32
|
+
|
|
33
|
+
The wizard currently offers Odoo `19.0`, `18.0`, `17.0`, and `16.0`. Generated
|
|
34
|
+
environments now use the compact compose layout (`compose.yaml` with
|
|
35
|
+
`compose/<env>.yaml` overlays). Legacy root-level
|
|
36
|
+
`docker-compose_<version>.yml` layouts are still supported for compatibility.
|
|
37
|
+
|
|
38
|
+
Set up GitHub CLI only when you want WPMoo to discover your personal account and organizations or create missing repositories from the interactive wizard:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
brew install gh
|
|
42
|
+
gh auth login
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
Run the guided wizard from a workspace directory:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx @wpmoo/toolkit
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Short alias:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx wpmoo
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Legacy package paths `npx @wpmoo/odoo` and `npx @wpmoo/odoo-dev` remain
|
|
60
|
+
available as compatibility redirects to `@wpmoo/toolkit`.
|
|
61
|
+
|
|
62
|
+
If the current directory is not already a WPMoo environment, the CLI opens the create flow. It asks for the product slug, Odoo version, and environment folder. Choose any environment folder; the default is `./<product>_dev`.
|
|
63
|
+
|
|
64
|
+
After folder selection, connect Git/GitHub to use repository URLs. Choose local-only setup to skip Git/GitHub connection and source repo prompts. Add source repositories later from the cockpit (`Repositories` -> `add-repo`) or `npx @wpmoo/toolkit add-repo`.
|
|
65
|
+
|
|
66
|
+
For non-interactive usage with repository URLs:
|
|
67
|
+
|
|
68
|
+
Direct `create` commands keep the existing repo URL options; use `--target <path>` to choose a custom folder.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npx @wpmoo/toolkit create \
|
|
72
|
+
--product odoo_sample_module \
|
|
73
|
+
--odoo-version 19.0 \
|
|
74
|
+
--dev-repo-url https://github.com/example-org/odoo_sample_module_dev.git \
|
|
75
|
+
--source-repo-url https://github.com/example-org/odoo_sample_module.git \
|
|
76
|
+
--init-empty-repos
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Add multiple source repositories by repeating `--source-repo-url`:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx @wpmoo/toolkit create \
|
|
83
|
+
--product odoo_sample_module \
|
|
84
|
+
--dev-repo-url https://github.com/example-org/odoo_sample_module_dev.git \
|
|
85
|
+
--source-repo-url https://github.com/example-org/odoo_sample_module.git \
|
|
86
|
+
--source-addons odoo_sample_module,odoo_sample_module_portal \
|
|
87
|
+
--source-repo-url git@github.com:example-org/odoo_sample_module_reports.git \
|
|
88
|
+
--source-path odoo_sample_module_reports \
|
|
89
|
+
--source-addons odoo_sample_module_reports
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Preview planned files and commands without writing:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npx @wpmoo/toolkit create \
|
|
96
|
+
--product odoo_sample_module \
|
|
97
|
+
--dev-repo-url https://github.com/example-org/odoo_sample_module_dev.git \
|
|
98
|
+
--source-repo-url https://github.com/example-org/odoo_sample_module.git \
|
|
99
|
+
--dry-run
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## The Cockpit
|
|
103
|
+
|
|
104
|
+
Run the package with no command inside a generated environment:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npx @wpmoo/toolkit
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The cockpit starts with a fast environment status summary, then opens a compact menu designed for repeated local work:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
Command palette /
|
|
114
|
+
Services
|
|
115
|
+
Modules
|
|
116
|
+
Database
|
|
117
|
+
Diagnostics
|
|
118
|
+
Repositories
|
|
119
|
+
Maintenance
|
|
120
|
+
Exit
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The UI is intentionally practical rather than decorative:
|
|
124
|
+
|
|
125
|
+
- `Command palette /` searches slash commands such as `/test`, `/logs`, `/doctor`, and `/safe-reset`.
|
|
126
|
+
- Category menus group related tasks for scanability: services, modules, database, diagnostics, repositories, and maintenance.
|
|
127
|
+
- `Esc` returns from category menus to the top-level cockpit.
|
|
128
|
+
- Empty states explain the next action, such as adding a source repo before selecting a module.
|
|
129
|
+
- Risky commands such as stopping services, resetting databases, restoring snapshots, removing repos, removing modules, and safe reset ask for explicit confirmation.
|
|
130
|
+
- Guided prompts collect common arguments for daily actions, including module names, database names, test modes, tags, snapshot names, and POT output paths.
|
|
131
|
+
|
|
132
|
+
## Cockpit Command Map
|
|
133
|
+
|
|
134
|
+
| Category | Commands |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| Services | `start`, `stop`, `restart`, `logs`, `shell` |
|
|
137
|
+
| Modules | `install`, `update`, `test`, `lint`, `pot`, `add-module`, `remove-module` |
|
|
138
|
+
| Database | `psql`, `snapshot`, `restore-snapshot`, `resetdb` |
|
|
139
|
+
| Diagnostics | `status`, `doctor` |
|
|
140
|
+
| Repositories | `add-repo`, `remove-repo` |
|
|
141
|
+
| Maintenance | `safe-reset` |
|
|
142
|
+
|
|
143
|
+
Every cockpit action maps to a direct command, or to an equivalent management command such as `/safe-reset` mapping to `reset`, for scripting and repeatable terminal workflows.
|
|
144
|
+
|
|
145
|
+
## Direct Commands
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx @wpmoo/toolkit --help
|
|
149
|
+
npx @wpmoo/toolkit --version
|
|
150
|
+
|
|
151
|
+
npx @wpmoo/toolkit status
|
|
152
|
+
npx @wpmoo/toolkit status --json
|
|
153
|
+
npx @wpmoo/toolkit doctor
|
|
154
|
+
npx @wpmoo/toolkit doctor --json
|
|
155
|
+
npx @wpmoo/toolkit doctor --fix
|
|
156
|
+
npx @wpmoo/toolkit source list --json
|
|
157
|
+
npx @wpmoo/toolkit add-repo --repo-url https://github.com/example-org/odoo_sample_module_reports.git
|
|
158
|
+
npx @wpmoo/toolkit remove-repo --repo odoo_sample_module_reports
|
|
159
|
+
npx @wpmoo/toolkit add-module --repo odoo_sample_module --module odoo_sample_module_base --source-type private
|
|
160
|
+
npx @wpmoo/toolkit remove-module --repo odoo_sample_module --module odoo_sample_module_base --source-type private
|
|
161
|
+
npx @wpmoo/toolkit reset --dry-run
|
|
162
|
+
npx @wpmoo/toolkit reset
|
|
163
|
+
|
|
164
|
+
npx @wpmoo/toolkit start
|
|
165
|
+
npx @wpmoo/toolkit stop
|
|
166
|
+
npx @wpmoo/toolkit restart
|
|
167
|
+
npx @wpmoo/toolkit logs odoo
|
|
168
|
+
npx @wpmoo/toolkit shell
|
|
169
|
+
npx @wpmoo/toolkit psql postgres
|
|
170
|
+
|
|
171
|
+
npx @wpmoo/toolkit install sale devel
|
|
172
|
+
npx @wpmoo/toolkit update sale devel
|
|
173
|
+
npx @wpmoo/toolkit test sale --db devel --mode update --tags /sale
|
|
174
|
+
npx @wpmoo/toolkit lint
|
|
175
|
+
npx @wpmoo/toolkit pot sale devel i18n/sale.pot
|
|
176
|
+
|
|
177
|
+
npx @wpmoo/toolkit resetdb devel sale
|
|
178
|
+
npx @wpmoo/toolkit snapshot devel before-update
|
|
179
|
+
npx @wpmoo/toolkit restore-snapshot --dry-run before-update devel
|
|
180
|
+
npx @wpmoo/toolkit restore-snapshot before-update devel
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Daily action commands must be run from a generated environment root containing `.wpmoo/odoo.json`. They delegate to fixed scripts under `./scripts`; they do not search parent directories or run arbitrary script names.
|
|
184
|
+
|
|
185
|
+
## Generated Environment Layout
|
|
186
|
+
|
|
187
|
+
A generated environment is a separate Git repository, usually named `<product>_dev`, but the wizard and `--target` can use any folder. Product source code stays in child source repositories.
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
odoo_sample_module_dev/
|
|
191
|
+
|-- .wpmoo/
|
|
192
|
+
| `-- odoo.json
|
|
193
|
+
|-- .env.example
|
|
194
|
+
|-- AGENTS.md
|
|
195
|
+
|-- README.md
|
|
196
|
+
|-- compose.yaml
|
|
197
|
+
|-- compose/
|
|
198
|
+
| |-- dev.yaml
|
|
199
|
+
| |-- stage.yaml
|
|
200
|
+
| `-- prod.yaml
|
|
201
|
+
|-- config/
|
|
202
|
+
| `-- odoo/
|
|
203
|
+
| `-- odoo.conf
|
|
204
|
+
|-- docs/
|
|
205
|
+
| |-- appstore-release.md
|
|
206
|
+
| `-- compose.md
|
|
207
|
+
|-- resources/
|
|
208
|
+
| `-- odoo/
|
|
209
|
+
| `-- entrypoint.sh
|
|
210
|
+
|-- moo
|
|
211
|
+
|-- odoo/
|
|
212
|
+
| `-- custom/
|
|
213
|
+
| `-- src/
|
|
214
|
+
| |-- private/
|
|
215
|
+
| |-- oca/
|
|
216
|
+
| `-- external/
|
|
217
|
+
`-- scripts/
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Development uses `compose.yaml` plus `compose/dev.yaml` by default. Set
|
|
221
|
+
`WPMOO_ENV=stage` or `WPMOO_ENV=prod` only after providing production-grade
|
|
222
|
+
secrets and volumes.
|
|
223
|
+
|
|
224
|
+
The metadata file `.wpmoo/odoo.json` records the product slug, selected Odoo version, dev repo URL, source repos, engine, external resource refs, ports, and template configuration. Status, doctor, daily actions, and safe reset use that metadata instead of guessing from the filesystem.
|
|
225
|
+
|
|
226
|
+
## Daily `./moo` Commands
|
|
227
|
+
|
|
228
|
+
Generated environments include a local `./moo` dispatcher. It is the shortest path for everyday Compose and Odoo work:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
cp .env.example .env
|
|
232
|
+
|
|
233
|
+
./moo start
|
|
234
|
+
./moo logs odoo
|
|
235
|
+
./moo shell
|
|
236
|
+
./moo psql postgres
|
|
237
|
+
./moo restart
|
|
238
|
+
./moo stop
|
|
239
|
+
|
|
240
|
+
./moo install sale devel
|
|
241
|
+
./moo update sale devel
|
|
242
|
+
./moo test sale --db devel --mode update --tags /sale
|
|
243
|
+
./moo lint
|
|
244
|
+
./moo pot sale devel i18n/sale.pot
|
|
245
|
+
|
|
246
|
+
./moo snapshot devel before-update
|
|
247
|
+
./moo restore-snapshot --dry-run before-update devel
|
|
248
|
+
./moo restore-snapshot before-update devel
|
|
249
|
+
./moo resetdb devel sale
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`restore-snapshot --dry-run` validates the selected snapshot and prints the
|
|
253
|
+
restore plan without changing the database or filestore. Generated environments
|
|
254
|
+
also support `WPMOO_SNAPSHOT_RETENTION_COUNT` for pruning old snapshot files.
|
|
255
|
+
When `WPMOO_ENV=stage` or `WPMOO_ENV=prod`, destructive database actions such
|
|
256
|
+
as `resetdb` and real `restore-snapshot` require `WPMOO_ALLOW_DESTRUCTIVE=1`.
|
|
257
|
+
|
|
258
|
+
Use `npx @wpmoo/toolkit ...` for package/operator commands such as `create`, `add-repo`, `remove-repo`, `add-module`, `remove-module`, `status`, `doctor`, and `reset`. Use `./moo ...` inside a generated environment for local daily Compose commands.
|
|
259
|
+
|
|
260
|
+
## Repository and Module Management
|
|
261
|
+
|
|
262
|
+
Add a source repository after local-only setup from the cockpit or direct command:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
npx @wpmoo/toolkit add-repo \
|
|
266
|
+
--repo-url https://github.com/example-org/odoo_sample_module_reports.git \
|
|
267
|
+
--init-empty-repos
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Pin source repositories to dedicated source directories:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npx @wpmoo/toolkit add-repo \
|
|
274
|
+
--repo-url https://github.com/OCA/sale-workflow.git \
|
|
275
|
+
--source-type oca
|
|
276
|
+
|
|
277
|
+
npx @wpmoo/toolkit add-repo \
|
|
278
|
+
--repo-url https://github.com/example-org/odoo_external_tool.git \
|
|
279
|
+
--source-type external
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
GitHub CLI is optional for repository setup. When it is available and authenticated, the interactive flow can:
|
|
283
|
+
|
|
284
|
+
- detect the owner or organization from the current environment;
|
|
285
|
+
- suggest repository URLs;
|
|
286
|
+
- check whether the repository is accessible;
|
|
287
|
+
- create inaccessible repositories after confirmation;
|
|
288
|
+
- initialize empty repositories with the selected Odoo branch.
|
|
289
|
+
|
|
290
|
+
Add a minimal Odoo module skeleton to a source repository:
|
|
291
|
+
|
|
292
|
+
For module actions, `--source-type` selects the source directory (`private`, `oca`, or `external`). Default is `private`.
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
npx @wpmoo/toolkit add-module \
|
|
296
|
+
--repo odoo_sample_module \
|
|
297
|
+
--module odoo_sample_module_base \
|
|
298
|
+
--source-type oca
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Remove a module registration while keeping files:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
npx @wpmoo/toolkit remove-module \
|
|
305
|
+
--repo odoo_sample_module \
|
|
306
|
+
--module odoo_sample_module_base \
|
|
307
|
+
--source-type oca
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Delete module files as well:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
npx @wpmoo/toolkit remove-module \
|
|
314
|
+
--repo odoo_sample_module \
|
|
315
|
+
--module odoo_sample_module_base \
|
|
316
|
+
--delete-files
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Remove a source repository submodule:
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
npx @wpmoo/toolkit remove-repo --repo odoo_sample_module_reports
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
WPMoo refuses to remove a source repo submodule when that submodule has uncommitted changes.
|
|
326
|
+
|
|
327
|
+
Generated environments also keep a deterministic source manifest at
|
|
328
|
+
`odoo/custom/manifests/sources.yaml`. It mirrors source submodules from
|
|
329
|
+
`.wpmoo/odoo.json` and `.gitmodules`, including source type, path, URL, branch,
|
|
330
|
+
and addon boundaries.
|
|
331
|
+
|
|
332
|
+
Inspect configured sources:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
npx @wpmoo/toolkit source list
|
|
336
|
+
npx @wpmoo/toolkit source list --json
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Regenerate the manifest and metadata from the current metadata/gitmodule state:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
npx @wpmoo/toolkit source sync
|
|
343
|
+
npx @wpmoo/toolkit source sync --json
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
`source add` and `source remove` are direct aliases for the same repository
|
|
347
|
+
operations:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
npx @wpmoo/toolkit source add \
|
|
351
|
+
--repo-url https://github.com/OCA/server-tools.git \
|
|
352
|
+
--source-type oca
|
|
353
|
+
|
|
354
|
+
npx @wpmoo/toolkit source remove --repo server-tools --source-type oca
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Status, Doctor, and Recovery
|
|
358
|
+
|
|
359
|
+
`status` is fast and offline. It reads local metadata and files only:
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
npx @wpmoo/toolkit status
|
|
363
|
+
npx @wpmoo/toolkit status --json
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
It reports whether the environment is detected, which Odoo version is selected, how many source repos are configured, how many module candidates are present, which core files are missing, and the recommended next action.
|
|
367
|
+
|
|
368
|
+
For automation and VS Code cockpit integration, all of these commands also support
|
|
369
|
+
`--json`:
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
npx @wpmoo/toolkit status --json
|
|
373
|
+
npx @wpmoo/toolkit source list --json
|
|
374
|
+
npx @wpmoo/toolkit source sync --json
|
|
375
|
+
npx @wpmoo/toolkit doctor --json
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
JSON output is optional; human-readable output remains the default.
|
|
379
|
+
|
|
380
|
+
`doctor` performs deeper checks:
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
npx @wpmoo/toolkit doctor
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
It validates metadata, engine support, selected compose files, source repo paths,
|
|
387
|
+
source manifest consistency, daily scripts, `.env` settings, Docker CLI access,
|
|
388
|
+
Docker Compose access, GitHub CLI authentication when available, and PostgreSQL
|
|
389
|
+
18 compatibility in compose mount targets (for mounts to
|
|
390
|
+
`/var/lib/postgresql/data` or `/var/lib/postgresql/18/docker`).
|
|
391
|
+
|
|
392
|
+
Use `doctor --fix` for safe file-level repairs. It can normalize PostgreSQL 18
|
|
393
|
+
mount targets and regenerate `odoo/custom/manifests/sources.yaml` from
|
|
394
|
+
metadata plus `.gitmodules`, then it runs doctor again and reports any remaining
|
|
395
|
+
manual issues.
|
|
396
|
+
|
|
397
|
+
Safe reset refreshes generated environment files without deleting product source code:
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
npx @wpmoo/toolkit reset --dry-run
|
|
401
|
+
npx @wpmoo/toolkit reset
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Safe reset updates generated files such as `.wpmoo/odoo.json`, `moo`,
|
|
405
|
+
`.gitignore`, `.env.example`, generated docs, compose assets, and optional
|
|
406
|
+
Agent Skills. Compose overlays like `compose.yaml` and `compose/dev.yaml` are
|
|
407
|
+
also refreshed from the current compose template source.
|
|
408
|
+
|
|
409
|
+
Use `reset --dry-run` first when you want a deterministic preview of refreshed
|
|
410
|
+
files and cleanup warnings without writing to the environment.
|
|
411
|
+
|
|
412
|
+
It does not touch source repo folders under
|
|
413
|
+
`odoo/custom/src/private`, module source code, Git history, remotes, or
|
|
414
|
+
branches. It also preserves local runtime artifacts and custom source layout
|
|
415
|
+
content:
|
|
416
|
+
|
|
417
|
+
- `.env`, `data`, and `backups`
|
|
418
|
+
- `odoo/custom/src/oca`, `odoo/custom/src/external`, `odoo/custom/patches`,
|
|
419
|
+
`odoo/custom/manifests`, and their existing contents
|
|
420
|
+
|
|
421
|
+
Legacy compose template paths from older scaffolds can remain
|
|
422
|
+
(`docs/assets/`, `test/`, `.github/`) until you remove them manually.
|
|
423
|
+
|
|
424
|
+
Recommended recovery pattern:
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
./moo snapshot devel before-reset
|
|
428
|
+
npx @wpmoo/toolkit reset --dry-run
|
|
429
|
+
npx @wpmoo/toolkit reset
|
|
430
|
+
npx @wpmoo/toolkit doctor --fix
|
|
431
|
+
./moo restore-snapshot --dry-run before-reset devel
|
|
432
|
+
./moo restore-snapshot before-reset devel
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## External Resources
|
|
436
|
+
|
|
437
|
+
WPMoo Toolkit keeps the package small by copying external resources into generated environments:
|
|
438
|
+
|
|
439
|
+
```text
|
|
440
|
+
gh:wpmoo-org/odoo-docker-compose
|
|
441
|
+
gh:wpmoo-org/odoo-skills
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Use the default resources:
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
npx @wpmoo/toolkit create \
|
|
448
|
+
--product odoo_sample_module \
|
|
449
|
+
--source-repo-url https://github.com/example-org/odoo_sample_module.git \
|
|
450
|
+
--agent-skills-template
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
Pin external resource refs:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
npx @wpmoo/toolkit create \
|
|
457
|
+
--product odoo_sample_module \
|
|
458
|
+
--source-repo-url https://github.com/example-org/odoo_sample_module.git \
|
|
459
|
+
--compose-template-ref v0.1.0 \
|
|
460
|
+
--agent-skills-template \
|
|
461
|
+
--agent-skills-template-ref v0.1.0
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Use local resource clones while developing the resource packages:
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
git clone https://github.com/wpmoo-org/odoo-docker-compose ../odoo-docker-compose
|
|
468
|
+
git clone https://github.com/wpmoo-org/odoo-skills ../odoo-skills
|
|
469
|
+
|
|
470
|
+
npx @wpmoo/toolkit create \
|
|
471
|
+
--engine compose \
|
|
472
|
+
--compose-template-url ../odoo-docker-compose \
|
|
473
|
+
--agent-skills-template \
|
|
474
|
+
--agent-skills-template-url ../odoo-skills \
|
|
475
|
+
--product odoo_sample_module \
|
|
476
|
+
--source-repo-url https://github.com/example-org/odoo_sample_module.git
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
More detail: [External Resources](docs/external-resources.md).
|
|
480
|
+
|
|
481
|
+
## Verification
|
|
482
|
+
|
|
483
|
+
Run local package checks from the repository root:
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
npm run typecheck
|
|
487
|
+
npm test
|
|
488
|
+
npm run test:coverage
|
|
489
|
+
npm run build
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Generated environment behavior is covered by the operator-facing matrix in [Generated Environment Verification](docs/generated-environment-verification.md).
|
|
493
|
+
|
|
494
|
+
## Release
|
|
495
|
+
|
|
496
|
+
The normal release path uses the repository helper and GitHub Actions trusted publishing:
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
npm run release:check
|
|
500
|
+
npm run typecheck
|
|
501
|
+
npm test
|
|
502
|
+
npm run build
|
|
503
|
+
VERSION="$(node -p "require('./package.json').version")"
|
|
504
|
+
git tag -a "v$VERSION" -m "Release v$VERSION"
|
|
505
|
+
git push origin "v$VERSION"
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
If `npm run release:check` bumps `package.json` and `package-lock.json`, commit and push that version bump first, then rerun the release check before tagging. Publishing is handled by the `Publish` workflow after the tag is pushed.
|
|
509
|
+
|
|
510
|
+
## Sponsoring
|
|
511
|
+
|
|
512
|
+
Support ongoing WPMoo development through recurring or one-time sponsorship:
|
|
513
|
+
|
|
514
|
+
<a href="https://www.buymeacoffee.com/cangir">
|
|
515
|
+
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me a Coffee" width="250">
|
|
516
|
+
</a>
|
|
517
|
+
<a href="https://www.patreon.com/wpmoo">
|
|
518
|
+
<img src="docs/assets/patreon-donate.png" alt="Support WPMoo on Patreon" width="250">
|
|
519
|
+
</a>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function escapeRegExp(value) {
|
|
2
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3
|
+
}
|
|
4
|
+
function ensureFinalNewline(value) {
|
|
5
|
+
return value.endsWith('\n') ? value : `${value}\n`;
|
|
6
|
+
}
|
|
7
|
+
function yamlList(items) {
|
|
8
|
+
return items.map((item) => ` - ${item}`).join('\n');
|
|
9
|
+
}
|
|
10
|
+
function renderSourceRepoBlock(repo) {
|
|
11
|
+
return `private/${repo.path}:\n${yamlList(repo.addons)}\n`;
|
|
12
|
+
}
|
|
13
|
+
export function addSourceRepoToAddonsYaml(content, repo) {
|
|
14
|
+
const blockPattern = new RegExp(`^private/${escapeRegExp(repo.path)}:\\s*$`, 'm');
|
|
15
|
+
if (blockPattern.test(content)) {
|
|
16
|
+
return content;
|
|
17
|
+
}
|
|
18
|
+
const base = ensureFinalNewline(content.trimEnd());
|
|
19
|
+
return `${base}\n${renderSourceRepoBlock(repo)}`;
|
|
20
|
+
}
|
|
21
|
+
export function removeSourceRepoFromAddonsYaml(content, repoPath) {
|
|
22
|
+
const blockPattern = new RegExp(`(^|\\n)private/${escapeRegExp(repoPath)}:\\n(?:[ \\t].*(?:\\n|$))*`, 'g');
|
|
23
|
+
const updated = content
|
|
24
|
+
.replace(blockPattern, (match, prefix) => (prefix === '\n' && match.endsWith('\n') ? '\n' : ''))
|
|
25
|
+
.replace(/\n{3,}/g, '\n\n');
|
|
26
|
+
return ensureFinalNewline(updated.trimEnd());
|
|
27
|
+
}
|
|
28
|
+
function sourceRepoBlockPattern(repoPath) {
|
|
29
|
+
return new RegExp(`(^private/${escapeRegExp(repoPath)}:\\n)((?:[ \\t].*(?:\\n|$))*)`, 'm');
|
|
30
|
+
}
|
|
31
|
+
function parseYamlListItems(blockBody) {
|
|
32
|
+
return blockBody
|
|
33
|
+
.split('\n')
|
|
34
|
+
.map((line) => line.trim().match(/^-\s+(.+)$/)?.[1]?.trim())
|
|
35
|
+
.filter((item) => Boolean(item));
|
|
36
|
+
}
|
|
37
|
+
export function addModuleToSourceRepoInAddonsYaml(content, repoPath, moduleName) {
|
|
38
|
+
const blockPattern = sourceRepoBlockPattern(repoPath);
|
|
39
|
+
const match = content.match(blockPattern);
|
|
40
|
+
if (!match) {
|
|
41
|
+
return addSourceRepoToAddonsYaml(content, { path: repoPath, addons: [moduleName] });
|
|
42
|
+
}
|
|
43
|
+
const addons = parseYamlListItems(match[2]);
|
|
44
|
+
if (addons.includes(moduleName)) {
|
|
45
|
+
return content;
|
|
46
|
+
}
|
|
47
|
+
const replacement = `${match[1]}${yamlList([...addons, moduleName])}\n`;
|
|
48
|
+
return content.replace(blockPattern, replacement);
|
|
49
|
+
}
|
|
50
|
+
export function removeModuleFromSourceRepoInAddonsYaml(content, repoPath, moduleName) {
|
|
51
|
+
const blockPattern = sourceRepoBlockPattern(repoPath);
|
|
52
|
+
const match = content.match(blockPattern);
|
|
53
|
+
if (!match) {
|
|
54
|
+
return content;
|
|
55
|
+
}
|
|
56
|
+
const addons = parseYamlListItems(match[2]).filter((addon) => addon !== moduleName);
|
|
57
|
+
const replacement = `${match[1]}${addons.length ? `${yamlList(addons)}\n` : ''}`;
|
|
58
|
+
return ensureFinalNewline(content.replace(blockPattern, replacement).trimEnd());
|
|
59
|
+
}
|