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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: doploy-cli
3
- Version: 0.2.1
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>` | Recent builds for a project. `--type development\|staging\|production`, `--limit` |
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>` | Recent builds for a project. `--type development\|staging\|production`, `--limit` |
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 > MCP Connections.')
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 > MCP Connections to kill the session server-side)')
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', 'commit_sha', 'created'])
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'] == 'WARNING' and not args.warnings:
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
- print(f"\n[{r['error_type']}] {r['module']}.{r['test']}")
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 data.get('truncated'):
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.1
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>` | Recent builds for a project. `--type development\|staging\|production`, `--limit` |
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 |
@@ -1,6 +1,7 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
+ doploy_cli/SKILL.md
4
5
  doploy_cli/__init__.py
5
6
  doploy_cli/main.py
6
7
  doploy_cli.egg-info/PKG-INFO
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "doploy-cli"
7
- version = "0.2.1"
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