doploy-cli 0.2.1__tar.gz → 0.2.3__tar.gz
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.
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/PKG-INFO +14 -2
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/README.md +13 -1
- doploy_cli-0.2.3/doploy_cli/SKILL.md +63 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli/main.py +93 -11
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli.egg-info/PKG-INFO +14 -2
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli.egg-info/SOURCES.txt +1 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/pyproject.toml +4 -1
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/LICENSE +0 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli/__init__.py +0 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli.egg-info/dependency_links.txt +0 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli.egg-info/entry_points.txt +0 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli.egg-info/requires.txt +0 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/doploy_cli.egg-info/top_level.txt +0 -0
- {doploy_cli-0.2.1 → doploy_cli-0.2.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: doploy-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: doploy CLI: watch builds, read logs, and drive Odoo deployments from a terminal
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://doploy.io
|
|
@@ -55,6 +55,16 @@ uv tool install doploy-cli
|
|
|
55
55
|
|
|
56
56
|
Requires Python 3.10 or newer.
|
|
57
57
|
|
|
58
|
+
## Using it from a coding agent
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
doploy skill install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Installs a skill file so Claude Code knows when to use `doploy`, how to find ids, and the
|
|
65
|
+
push → build → read failures → fix loop. `doploy skill print >> AGENTS.md` does the same for
|
|
66
|
+
Codex and other agents.
|
|
67
|
+
|
|
58
68
|
## Sign in
|
|
59
69
|
|
|
60
70
|
```bash
|
|
@@ -83,9 +93,11 @@ doploy logs <build-id> --source test -f # follow the test log until the bui
|
|
|
83
93
|
| Command | Description |
|
|
84
94
|
|---|---|
|
|
85
95
|
| `login` | Sign in with your browser |
|
|
96
|
+
| `skill install` | Teach Claude Code to use doploy (`skill print` for AGENTS.md) |
|
|
86
97
|
| `logout` | Forget the saved session |
|
|
87
98
|
| `projects` | List your projects |
|
|
88
|
-
| `builds <project>` |
|
|
99
|
+
| `builds <project>` | Live builds for a project. `--type development\|staging\|production`, `--limit`, `--all` |
|
|
100
|
+
| `branches <project>` | Live branches with their ids |
|
|
89
101
|
| `build <id>` | One build: status, commit, versions, error summary |
|
|
90
102
|
| `tests <build>` | Test failures for a build. `--details` prints tracebacks, `--warnings` includes warnings |
|
|
91
103
|
| `logs <build>` | Tail logs. `--source build\|test\|odoo`, `--lines`, `--filter TEXT`, `-f` to follow |
|
|
@@ -33,6 +33,16 @@ uv tool install doploy-cli
|
|
|
33
33
|
|
|
34
34
|
Requires Python 3.10 or newer.
|
|
35
35
|
|
|
36
|
+
## Using it from a coding agent
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
doploy skill install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Installs a skill file so Claude Code knows when to use `doploy`, how to find ids, and the
|
|
43
|
+
push → build → read failures → fix loop. `doploy skill print >> AGENTS.md` does the same for
|
|
44
|
+
Codex and other agents.
|
|
45
|
+
|
|
36
46
|
## Sign in
|
|
37
47
|
|
|
38
48
|
```bash
|
|
@@ -61,9 +71,11 @@ doploy logs <build-id> --source test -f # follow the test log until the bui
|
|
|
61
71
|
| Command | Description |
|
|
62
72
|
|---|---|
|
|
63
73
|
| `login` | Sign in with your browser |
|
|
74
|
+
| `skill install` | Teach Claude Code to use doploy (`skill print` for AGENTS.md) |
|
|
64
75
|
| `logout` | Forget the saved session |
|
|
65
76
|
| `projects` | List your projects |
|
|
66
|
-
| `builds <project>` |
|
|
77
|
+
| `builds <project>` | Live builds for a project. `--type development\|staging\|production`, `--limit`, `--all` |
|
|
78
|
+
| `branches <project>` | Live branches with their ids |
|
|
67
79
|
| `build <id>` | One build: status, commit, versions, error summary |
|
|
68
80
|
| `tests <build>` | Test failures for a build. `--details` prints tracebacks, `--warnings` includes warnings |
|
|
69
81
|
| `logs <build>` | Tail logs. `--source build\|test\|odoo`, `--lines`, `--filter TEXT`, `-f` to follow |
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doploy
|
|
3
|
+
description: Use the `doploy` CLI to watch Odoo builds, read test failures and logs, and update modules on doploy-hosted deployments. Use when the repo is an Odoo project deployed on doploy, when a build or test run needs checking, or when the user asks to deploy, update modules, or look at logs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# doploy
|
|
7
|
+
|
|
8
|
+
`doploy` is the command line for doploy, which builds and hosts Odoo projects from a GitHub
|
|
9
|
+
repo. Every branch push produces a development build with a full Odoo test run. Production and
|
|
10
|
+
staging are long-lived deployments that update in place.
|
|
11
|
+
|
|
12
|
+
Check it is installed and signed in with `doploy projects`. If that fails, tell the user to run
|
|
13
|
+
`pipx install doploy-cli && doploy login` (it opens a browser; do not try to sign in for them).
|
|
14
|
+
|
|
15
|
+
## Finding ids
|
|
16
|
+
|
|
17
|
+
Ids are stable and worth reusing within a session.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
doploy projects # project id (short string, e.g. Bx2Nx)
|
|
21
|
+
doploy builds <project> --type development --limit 5 # build ids, newest first
|
|
22
|
+
doploy branches <project> # branch ids, for `branch create --from`
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Prefer `--json` when you need to parse output.
|
|
26
|
+
|
|
27
|
+
## The loop after pushing code
|
|
28
|
+
|
|
29
|
+
1. Push the commit. doploy builds the branch automatically.
|
|
30
|
+
2. `doploy builds <project> --type development --limit 3` until the newest build for your
|
|
31
|
+
commit leaves `Building`. Poll every 30 seconds or so; builds take several minutes.
|
|
32
|
+
3. On `Error` or `Active Error`: `doploy tests <build> --details` shows every failing test with
|
|
33
|
+
its traceback. `doploy logs <build> --source test --filter ERROR` shows the surrounding log.
|
|
34
|
+
4. Fix, push, repeat. On `Success`, open the pull request.
|
|
35
|
+
|
|
36
|
+
Do not create a new build by hand for a branch you already pushed; the push did it.
|
|
37
|
+
|
|
38
|
+
## Logs
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
doploy logs <build> --source test -f # follow the test run until the build settles
|
|
42
|
+
doploy logs <build> --source odoo --filter Traceback # the running container (staging/prod)
|
|
43
|
+
doploy logs <build> --source build # doploy's own deploy log
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## After a merge to staging or production
|
|
47
|
+
|
|
48
|
+
Code updates land in place. The changed modules still need `odoo-bin -u`:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
doploy update-modules <build> --wait # exactly the modules doploy saw change
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`--wait` exits non-zero if the update failed; print the tail it shows. Add `--theme` when a
|
|
55
|
+
website theme changed and the user says so.
|
|
56
|
+
|
|
57
|
+
## Rules
|
|
58
|
+
|
|
59
|
+
- Anything aimed at production needs `--confirm`. Ask the user before adding it.
|
|
60
|
+
- `doploy backup <build> --confirm --wait` before risky production updates.
|
|
61
|
+
- The CLI cannot delete, restore, or change domains. Do not look for a way around that.
|
|
62
|
+
- Deploy commands may return "Deploy actions are not enabled". The user turns that on in
|
|
63
|
+
doploy under Settings → Connected apps. Do not retry until they say it is done.
|
|
@@ -232,7 +232,7 @@ def cmd_login(args):
|
|
|
232
232
|
_browser_login(base)
|
|
233
233
|
projects = _client(argparse.Namespace(token=None, base=base)).request('GET', '/projects')
|
|
234
234
|
print(f'logged in; {len(projects["projects"])} project(s) visible; config saved to {CONFIG_PATH}')
|
|
235
|
-
print('Deploy actions: toggle "Allow deploy actions" in Settings >
|
|
235
|
+
print('Deploy actions: toggle "Allow deploy actions" in Settings > Connected apps.')
|
|
236
236
|
|
|
237
237
|
|
|
238
238
|
def cmd_logout(args):
|
|
@@ -240,7 +240,7 @@ def cmd_logout(args):
|
|
|
240
240
|
for k in ('token', 'access_token', 'refresh_token', 'client_id', 'expires_at'):
|
|
241
241
|
cfg.pop(k, None)
|
|
242
242
|
_save_config(cfg)
|
|
243
|
-
print('logged out (revoke the grant in Settings >
|
|
243
|
+
print('logged out (revoke the grant in Settings > Connected apps to kill the session server-side)')
|
|
244
244
|
|
|
245
245
|
|
|
246
246
|
def cmd_projects(args):
|
|
@@ -251,15 +251,39 @@ def cmd_projects(args):
|
|
|
251
251
|
_table(data['projects'], ['id', 'name', 'odoo_version'])
|
|
252
252
|
|
|
253
253
|
|
|
254
|
+
def _short(rows: list[dict]) -> list[dict]:
|
|
255
|
+
"""Table-friendly copies: 7-char commit, minute-precision timestamps."""
|
|
256
|
+
out = []
|
|
257
|
+
for r in rows:
|
|
258
|
+
r = dict(r)
|
|
259
|
+
if r.get('commit_sha'):
|
|
260
|
+
r['commit'] = r['commit_sha'][:7]
|
|
261
|
+
if r.get('created'):
|
|
262
|
+
r['created'] = r['created'][:16].replace('T', ' ')
|
|
263
|
+
out.append(r)
|
|
264
|
+
return out
|
|
265
|
+
|
|
266
|
+
|
|
254
267
|
def cmd_builds(args):
|
|
255
268
|
params = {'limit': str(args.limit)}
|
|
256
269
|
if args.type:
|
|
257
270
|
params['type'] = args.type
|
|
271
|
+
if args.all:
|
|
272
|
+
params['all'] = '1'
|
|
258
273
|
data = _client(args).request('GET', f'/projects/{args.project}/builds', params=params)
|
|
259
274
|
if args.json:
|
|
260
275
|
print(json.dumps(data, indent=2))
|
|
261
276
|
return
|
|
262
|
-
_table(data['builds'], ['id', 'type', 'status', 'fqdn', '
|
|
277
|
+
_table(_short(data['builds']), ['id', 'type', 'status', 'fqdn', 'commit', 'created'])
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def cmd_branches(args):
|
|
281
|
+
params = {'all': '1'} if args.all else None
|
|
282
|
+
data = _client(args).request('GET', f'/projects/{args.project}/branches', params=params)
|
|
283
|
+
if args.json:
|
|
284
|
+
print(json.dumps(data, indent=2))
|
|
285
|
+
return
|
|
286
|
+
_table(data['branches'], ['id', 'name', 'type'])
|
|
263
287
|
|
|
264
288
|
|
|
265
289
|
def cmd_build(args):
|
|
@@ -275,12 +299,20 @@ def cmd_tests(args):
|
|
|
275
299
|
c = data['counts']
|
|
276
300
|
print(f"build {data['build_id']} [{data['build_status']}] — "
|
|
277
301
|
f"{c['error']} errors, {c['fail']} failures, {c['warning']} warnings")
|
|
302
|
+
loader_rows = 0
|
|
278
303
|
for r in data['results']:
|
|
279
|
-
if r['error_type']
|
|
304
|
+
if r['error_type'] not in ('ERROR', 'FAIL') and not args.warnings:
|
|
305
|
+
continue
|
|
306
|
+
is_test = bool(r.get('test')) and r['test'] != 'Unknown'
|
|
307
|
+
if not is_test and not args.details:
|
|
308
|
+
loader_rows += 1 # module-loading summaries: only interesting with --details
|
|
280
309
|
continue
|
|
281
|
-
|
|
310
|
+
where = f"{r['module']}.{r['test']}" if is_test else '(module loading)'
|
|
311
|
+
print(f"\n[{r['error_type']}] {where}")
|
|
282
312
|
if args.details:
|
|
283
313
|
print(r['details'])
|
|
314
|
+
if loader_rows:
|
|
315
|
+
print(f"\n(+{loader_rows} module-loading message(s); use --details to see them)")
|
|
284
316
|
|
|
285
317
|
|
|
286
318
|
def cmd_rebuild(args):
|
|
@@ -329,15 +361,21 @@ def cmd_logs(args):
|
|
|
329
361
|
if args.source == 'build':
|
|
330
362
|
if data.get('error_summary'):
|
|
331
363
|
print(f"error summary: {data['error_summary']}\n")
|
|
332
|
-
for t in data.get('tasks') or []:
|
|
333
|
-
print(f"task {t['id']} [{t['status']}] {t['title']}")
|
|
334
|
-
if data.get('tasks'):
|
|
335
|
-
print()
|
|
336
364
|
shown = data['lines']
|
|
337
365
|
for ln in shown:
|
|
338
366
|
print(ln)
|
|
339
367
|
if not args.follow:
|
|
340
|
-
if
|
|
368
|
+
if args.filter:
|
|
369
|
+
searched = data.get('searched_lines')
|
|
370
|
+
total = data.get('total_lines')
|
|
371
|
+
if searched and total and total > searched:
|
|
372
|
+
scope = f"the last {searched} of {total} lines"
|
|
373
|
+
elif searched or total:
|
|
374
|
+
scope = f"all {total or searched} lines"
|
|
375
|
+
else:
|
|
376
|
+
scope = 'the recent log'
|
|
377
|
+
print(f"... ({len(shown)} matching line(s) in {scope})", file=sys.stderr)
|
|
378
|
+
elif data.get('truncated'):
|
|
341
379
|
print(f"... (showing last {len(shown)} lines; use --lines to see more)", file=sys.stderr)
|
|
342
380
|
return
|
|
343
381
|
# Follow: poll and print only what is new. Build and test logs end when
|
|
@@ -443,6 +481,34 @@ def cmd_backup(args):
|
|
|
443
481
|
sys.exit(1)
|
|
444
482
|
|
|
445
483
|
|
|
484
|
+
# --- agent skill ------------------------------------------------------------
|
|
485
|
+
#
|
|
486
|
+
# The skill ships inside the package (doploy_cli/SKILL.md) so no public repo
|
|
487
|
+
# is needed. `doploy skill install` drops it where Claude Code discovers it;
|
|
488
|
+
# `doploy skill print` gives the same text for AGENTS.md / other agents.
|
|
489
|
+
|
|
490
|
+
def _skill_text() -> str:
|
|
491
|
+
from importlib import resources
|
|
492
|
+
return resources.files('doploy_cli').joinpath('SKILL.md').read_text(encoding='utf-8')
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
def _skill_target(project: bool) -> Path:
|
|
496
|
+
base = Path.cwd() if project else Path.home()
|
|
497
|
+
return base / '.claude' / 'skills' / 'doploy' / 'SKILL.md'
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def cmd_skill(args):
|
|
501
|
+
if args.skill_command == 'print':
|
|
502
|
+
print(_skill_text(), end='')
|
|
503
|
+
return
|
|
504
|
+
target = _skill_target(args.project)
|
|
505
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
506
|
+
target.write_text(_skill_text(), encoding='utf-8')
|
|
507
|
+
scope = 'this project' if args.project else 'all projects'
|
|
508
|
+
print(f'installed doploy skill for Claude Code ({scope}): {target}')
|
|
509
|
+
print('Other agents: `doploy skill print >> AGENTS.md`')
|
|
510
|
+
|
|
511
|
+
|
|
446
512
|
def main(argv=None):
|
|
447
513
|
p = argparse.ArgumentParser(prog='doploy', description=__doc__.splitlines()[0])
|
|
448
514
|
p.add_argument('--token', help=argparse.SUPPRESS)
|
|
@@ -457,17 +523,33 @@ def main(argv=None):
|
|
|
457
523
|
sp = sub.add_parser('logout', help='forget saved credentials')
|
|
458
524
|
sp.set_defaults(func=cmd_logout)
|
|
459
525
|
|
|
526
|
+
sp = sub.add_parser('skill', help='teach coding agents how to use doploy')
|
|
527
|
+
ssub = sp.add_subparsers(dest='skill_command', required=True)
|
|
528
|
+
ip = ssub.add_parser('install', help='install the Claude Code skill (~/.claude/skills/doploy)')
|
|
529
|
+
ip.add_argument('--project', action='store_true',
|
|
530
|
+
help='install into ./.claude/skills instead of your home directory')
|
|
531
|
+
ip.set_defaults(func=cmd_skill)
|
|
532
|
+
pp = ssub.add_parser('print', help='print the skill text, e.g. for AGENTS.md')
|
|
533
|
+
pp.set_defaults(func=cmd_skill)
|
|
534
|
+
|
|
460
535
|
sp = sub.add_parser('projects', help='list your projects')
|
|
461
536
|
sp.add_argument('--json', action='store_true')
|
|
462
537
|
sp.set_defaults(func=cmd_projects)
|
|
463
538
|
|
|
464
|
-
sp = sub.add_parser('builds', help='list builds for a project')
|
|
539
|
+
sp = sub.add_parser('builds', help='list live builds for a project')
|
|
465
540
|
sp.add_argument('project', help='project id (from `doploy projects`)')
|
|
466
541
|
sp.add_argument('--type', choices=['development', 'staging', 'production'])
|
|
467
542
|
sp.add_argument('--limit', type=int, default=20)
|
|
543
|
+
sp.add_argument('--all', action='store_true', help='include torn-down builds')
|
|
468
544
|
sp.add_argument('--json', action='store_true')
|
|
469
545
|
sp.set_defaults(func=cmd_builds)
|
|
470
546
|
|
|
547
|
+
sp = sub.add_parser('branches', help='list live branches for a project')
|
|
548
|
+
sp.add_argument('project', help='project id (from `doploy projects`)')
|
|
549
|
+
sp.add_argument('--all', action='store_true', help='include branches whose git ref is gone')
|
|
550
|
+
sp.add_argument('--json', action='store_true')
|
|
551
|
+
sp.set_defaults(func=cmd_branches)
|
|
552
|
+
|
|
471
553
|
sp = sub.add_parser('build', help='show one build')
|
|
472
554
|
sp.add_argument('build_id', type=int)
|
|
473
555
|
sp.set_defaults(func=cmd_build)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: doploy-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: doploy CLI: watch builds, read logs, and drive Odoo deployments from a terminal
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://doploy.io
|
|
@@ -55,6 +55,16 @@ uv tool install doploy-cli
|
|
|
55
55
|
|
|
56
56
|
Requires Python 3.10 or newer.
|
|
57
57
|
|
|
58
|
+
## Using it from a coding agent
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
doploy skill install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Installs a skill file so Claude Code knows when to use `doploy`, how to find ids, and the
|
|
65
|
+
push → build → read failures → fix loop. `doploy skill print >> AGENTS.md` does the same for
|
|
66
|
+
Codex and other agents.
|
|
67
|
+
|
|
58
68
|
## Sign in
|
|
59
69
|
|
|
60
70
|
```bash
|
|
@@ -83,9 +93,11 @@ doploy logs <build-id> --source test -f # follow the test log until the bui
|
|
|
83
93
|
| Command | Description |
|
|
84
94
|
|---|---|
|
|
85
95
|
| `login` | Sign in with your browser |
|
|
96
|
+
| `skill install` | Teach Claude Code to use doploy (`skill print` for AGENTS.md) |
|
|
86
97
|
| `logout` | Forget the saved session |
|
|
87
98
|
| `projects` | List your projects |
|
|
88
|
-
| `builds <project>` |
|
|
99
|
+
| `builds <project>` | Live builds for a project. `--type development\|staging\|production`, `--limit`, `--all` |
|
|
100
|
+
| `branches <project>` | Live branches with their ids |
|
|
89
101
|
| `build <id>` | One build: status, commit, versions, error summary |
|
|
90
102
|
| `tests <build>` | Test failures for a build. `--details` prints tracebacks, `--warnings` includes warnings |
|
|
91
103
|
| `logs <build>` | Tail logs. `--source build\|test\|odoo`, `--lines`, `--filter TEXT`, `-f` to follow |
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "doploy-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "doploy CLI: watch builds, read logs, and drive Odoo deployments from a terminal"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -31,3 +31,6 @@ doploy = "doploy_cli.main:main"
|
|
|
31
31
|
|
|
32
32
|
[tool.setuptools.packages.find]
|
|
33
33
|
include = ["doploy_cli*"]
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.package-data]
|
|
36
|
+
doploy_cli = ["SKILL.md"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|