@mriekki/lean 0.1.0 → 0.2.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.
Files changed (41) hide show
  1. package/README.md +71 -67
  2. package/assets/components.json +33 -33
  3. package/assets/core/distribution.json +52 -51
  4. package/assets/deployment/distribution.json +34 -34
  5. package/assets/generated/ASSEMBLY.json +38 -33
  6. package/assets/generated/core/core/skills/core-sync/SKILL.md +78 -120
  7. package/assets/generated/core/core/skills/deploy/SKILL.md +74 -91
  8. package/assets/generated/core/core/skills/lean-update/SKILL.md +189 -0
  9. package/assets/generated/core/core/skills/upstream-fix/SKILL.md +91 -76
  10. package/assets/generated/deployment/distribution/lean-poc-deploy.py +8 -8
  11. package/assets/generated/deployment/src/lean_poc_deployment/__init__.py +3 -3
  12. package/assets/generated/deployment/src/lean_poc_deployment/__main__.py +3 -3
  13. package/assets/generated/deployment/src/lean_poc_deployment/app_cli.py +140 -140
  14. package/assets/generated/deployment/src/lean_poc_deployment/app_runtime.py +455 -455
  15. package/assets/generated/deployment/src/lean_poc_deployment/app_runtime_remote.py +415 -415
  16. package/assets/generated/deployment/src/lean_poc_deployment/box_platform.py +208 -208
  17. package/assets/generated/deployment/src/lean_poc_deployment/box_platform_assets.py +100 -100
  18. package/assets/generated/deployment/src/lean_poc_deployment/box_platform_remote.py +271 -271
  19. package/assets/generated/deployment/src/lean_poc_deployment/cli.py +437 -437
  20. package/assets/generated/deployment/src/lean_poc_deployment/doctor.py +121 -121
  21. package/assets/generated/deployment/src/lean_poc_deployment/entrypoint.py +25 -25
  22. package/assets/generated/deployment/src/lean_poc_deployment/errors.py +5 -5
  23. package/assets/generated/deployment/src/lean_poc_deployment/keys.py +171 -171
  24. package/assets/generated/deployment/src/lean_poc_deployment/profiles.py +204 -204
  25. package/assets/generated/deployment/src/lean_poc_deployment/route_registry.py +367 -367
  26. package/assets/generated/deployment/src/lean_poc_deployment/route_registry_remote.py +443 -443
  27. package/assets/generated/deployment/src/lean_poc_deployment/security.py +290 -290
  28. package/assets/generated/deployment/src/lean_poc_deployment/sqlite_adapter.py +334 -334
  29. package/assets/generated/deployment/src/lean_poc_deployment/sqlite_adapter_remote.py +339 -339
  30. package/assets/generated/deployment/src/lean_poc_deployment/sqlite_cli.py +85 -85
  31. package/assets/generated/deployment/src/lean_poc_deployment/sqlite_import_recovery.py +437 -437
  32. package/assets/generated/deployment/src/lean_poc_deployment/ssh.py +118 -118
  33. package/assets/generated/deployment/src/lean_poc_deployment/teardown.py +286 -286
  34. package/assets/generated/deployment/src/lean_poc_deployment/teardown_cli.py +120 -120
  35. package/assets/generated/deployment/src/lean_poc_deployment/teardown_remote.py +100 -100
  36. package/assets/generated/deployment/src/lean_poc_deployment/trust.py +278 -278
  37. package/bin/lean.mjs +9 -9
  38. package/package.json +33 -33
  39. package/src/cli.mjs +131 -131
  40. package/src/engine.mjs +243 -243
  41. package/src/package-data.mjs +18 -18
@@ -1,86 +1,86 @@
1
- """CLI for the SQLite persistence adapter."""
2
- from __future__ import annotations
3
- import argparse, json, sys
4
- from typing import Any
5
- from .errors import DeploymentKitError
6
- from .sqlite_adapter import authorization_phrase, apply_sqlite_operation, normalize_sqlite_request, plan_sqlite_operation, sqlite_inventory
7
- from .sqlite_import_recovery import (
8
- apply_sqlite_import_recovery,
9
- authorization_phrase as recovery_authorization_phrase,
10
- plan_sqlite_import_recovery,
11
- )
12
-
13
-
14
- def _print(value: Any, *, as_json: bool) -> None:
15
- if as_json:
16
- print(json.dumps(value, indent=2, sort_keys=True)); return
17
- if isinstance(value, dict):
18
- for key, item in value.items():
19
- print(f"{key}: {json.dumps(item, sort_keys=True) if isinstance(item,(dict,list)) else item}")
20
- else: print(value)
21
-
22
-
23
- def _parse_env(items: list[str]) -> list[tuple[str,str]]:
24
- out=[]
25
- for item in items:
26
- if '=' not in item: raise DeploymentKitError("--maintenance-env entries must use NAME=value form.")
27
- out.append(tuple(item.split('=',1)))
28
- return out
29
-
30
-
31
- def _confirm(args: argparse.Namespace, phrase: str, action: str) -> None:
32
- if args.yes: return
33
- if input(f"Type {phrase} to {action}: ").strip() != phrase:
34
- raise DeploymentKitError(f"{action.capitalize()} was not authorized.")
35
-
36
-
37
- def _common(parser: argparse.ArgumentParser) -> None:
38
- parser.add_argument('name')
39
- parser.add_argument('--owner-repo', required=True)
40
- parser.add_argument('--environment', required=True)
41
- parser.add_argument('--app-slug', required=True)
42
- parser.add_argument('--image', required=True)
43
- parser.add_argument('--maintenance-env', action='append', default=[], help='Non-secret image maintenance environment value in NAME=value form; repeat as needed')
44
- parser.add_argument('--json', action='store_true')
45
- parser.add_argument('--yes', action='store_true')
46
-
47
-
48
- def _import_args(parser: argparse.ArgumentParser) -> None:
49
- parser.add_argument('--run-as', required=True)
50
- parser.add_argument('--database-file', required=True)
51
- parser.add_argument('--source-database', required=True)
52
-
53
-
54
- def build_parser() -> argparse.ArgumentParser:
55
- parser=argparse.ArgumentParser(prog='lean-poc-deploy sqlite')
56
- sub=parser.add_subparsers(dest='command',required=True)
57
- inv=sub.add_parser('inventory',help='Read SQLite persistence reservations without writes'); inv.add_argument('name'); inv.add_argument('--json',action='store_true')
58
- imp=sub.add_parser('import',help='Import an existing SQLite DB via the exact image online-backup contract'); _common(imp); _import_args(imp)
59
- recover=sub.add_parser('recover-import',help='Recover a verified failed import without overwriting or recopying the database'); _common(recover); _import_args(recover)
60
- backup=sub.add_parser('backup',help='Create a verified SQLite backup with the exact image'); _common(backup)
61
- migrate=sub.add_parser('migrate',help='Create required backup and run exact-image SQLite migration'); _common(migrate)
62
- migrate.add_argument('--first-install',action='store_true'); migrate.add_argument('--run-as'); migrate.add_argument('--database-file')
63
- check=sub.add_parser('rollback-check',help='Verify that an exact rollback image accepts the current SQLite state'); _common(check)
64
- return parser
65
-
66
-
67
- def main(argv: list[str]|None=None) -> int:
68
- args=build_parser().parse_args(argv)
69
- try:
70
- if args.command=='inventory': _print(sqlite_inventory(args.name),as_json=args.json); return 0
71
- request=normalize_sqlite_request(owner_repo=args.owner_repo,environment=args.environment,app_slug=args.app_slug,image=args.image,
72
- maintenance_environment=_parse_env(args.maintenance_env),run_as=getattr(args,'run_as',None),database_file=getattr(args,'database_file',None),
73
- source_database=getattr(args,'source_database',None),first_install=getattr(args,'first_install',False))
74
- if args.command=='recover-import':
75
- plan=plan_sqlite_import_recovery(args.name,request)
76
- _print({k:v for k,v in plan.items() if k!='request'},as_json=False)
77
- phrase=recovery_authorization_phrase(plan)
78
- _confirm(args,phrase,f"recover SQLite import for {plan['appSlug']} ({plan['environment']}) on target {args.name}")
79
- _print(apply_sqlite_import_recovery(plan),as_json=args.json); return 0
80
- plan=plan_sqlite_operation(args.name,args.command,request)
81
- _print({k:v for k,v in plan.items() if k!='spec'},as_json=False)
82
- phrase=authorization_phrase(plan)
83
- _confirm(args,phrase,f"run SQLite {args.command} for {plan['appSlug']} ({plan['environment']}) on target {args.name}")
84
- _print(apply_sqlite_operation(plan),as_json=args.json); return 0
85
- except DeploymentKitError as error:
1
+ """CLI for the SQLite persistence adapter."""
2
+ from __future__ import annotations
3
+ import argparse, json, sys
4
+ from typing import Any
5
+ from .errors import DeploymentKitError
6
+ from .sqlite_adapter import authorization_phrase, apply_sqlite_operation, normalize_sqlite_request, plan_sqlite_operation, sqlite_inventory
7
+ from .sqlite_import_recovery import (
8
+ apply_sqlite_import_recovery,
9
+ authorization_phrase as recovery_authorization_phrase,
10
+ plan_sqlite_import_recovery,
11
+ )
12
+
13
+
14
+ def _print(value: Any, *, as_json: bool) -> None:
15
+ if as_json:
16
+ print(json.dumps(value, indent=2, sort_keys=True)); return
17
+ if isinstance(value, dict):
18
+ for key, item in value.items():
19
+ print(f"{key}: {json.dumps(item, sort_keys=True) if isinstance(item,(dict,list)) else item}")
20
+ else: print(value)
21
+
22
+
23
+ def _parse_env(items: list[str]) -> list[tuple[str,str]]:
24
+ out=[]
25
+ for item in items:
26
+ if '=' not in item: raise DeploymentKitError("--maintenance-env entries must use NAME=value form.")
27
+ out.append(tuple(item.split('=',1)))
28
+ return out
29
+
30
+
31
+ def _confirm(args: argparse.Namespace, phrase: str, action: str) -> None:
32
+ if args.yes: return
33
+ if input(f"Type {phrase} to {action}: ").strip() != phrase:
34
+ raise DeploymentKitError(f"{action.capitalize()} was not authorized.")
35
+
36
+
37
+ def _common(parser: argparse.ArgumentParser) -> None:
38
+ parser.add_argument('name')
39
+ parser.add_argument('--owner-repo', required=True)
40
+ parser.add_argument('--environment', required=True)
41
+ parser.add_argument('--app-slug', required=True)
42
+ parser.add_argument('--image', required=True)
43
+ parser.add_argument('--maintenance-env', action='append', default=[], help='Non-secret image maintenance environment value in NAME=value form; repeat as needed')
44
+ parser.add_argument('--json', action='store_true')
45
+ parser.add_argument('--yes', action='store_true')
46
+
47
+
48
+ def _import_args(parser: argparse.ArgumentParser) -> None:
49
+ parser.add_argument('--run-as', required=True)
50
+ parser.add_argument('--database-file', required=True)
51
+ parser.add_argument('--source-database', required=True)
52
+
53
+
54
+ def build_parser() -> argparse.ArgumentParser:
55
+ parser=argparse.ArgumentParser(prog='lean-poc-deploy sqlite')
56
+ sub=parser.add_subparsers(dest='command',required=True)
57
+ inv=sub.add_parser('inventory',help='Read SQLite persistence reservations without writes'); inv.add_argument('name'); inv.add_argument('--json',action='store_true')
58
+ imp=sub.add_parser('import',help='Import an existing SQLite DB via the exact image online-backup contract'); _common(imp); _import_args(imp)
59
+ recover=sub.add_parser('recover-import',help='Recover a verified failed import without overwriting or recopying the database'); _common(recover); _import_args(recover)
60
+ backup=sub.add_parser('backup',help='Create a verified SQLite backup with the exact image'); _common(backup)
61
+ migrate=sub.add_parser('migrate',help='Create required backup and run exact-image SQLite migration'); _common(migrate)
62
+ migrate.add_argument('--first-install',action='store_true'); migrate.add_argument('--run-as'); migrate.add_argument('--database-file')
63
+ check=sub.add_parser('rollback-check',help='Verify that an exact rollback image accepts the current SQLite state'); _common(check)
64
+ return parser
65
+
66
+
67
+ def main(argv: list[str]|None=None) -> int:
68
+ args=build_parser().parse_args(argv)
69
+ try:
70
+ if args.command=='inventory': _print(sqlite_inventory(args.name),as_json=args.json); return 0
71
+ request=normalize_sqlite_request(owner_repo=args.owner_repo,environment=args.environment,app_slug=args.app_slug,image=args.image,
72
+ maintenance_environment=_parse_env(args.maintenance_env),run_as=getattr(args,'run_as',None),database_file=getattr(args,'database_file',None),
73
+ source_database=getattr(args,'source_database',None),first_install=getattr(args,'first_install',False))
74
+ if args.command=='recover-import':
75
+ plan=plan_sqlite_import_recovery(args.name,request)
76
+ _print({k:v for k,v in plan.items() if k!='request'},as_json=False)
77
+ phrase=recovery_authorization_phrase(plan)
78
+ _confirm(args,phrase,f"recover SQLite import for {plan['appSlug']} ({plan['environment']}) on target {args.name}")
79
+ _print(apply_sqlite_import_recovery(plan),as_json=args.json); return 0
80
+ plan=plan_sqlite_operation(args.name,args.command,request)
81
+ _print({k:v for k,v in plan.items() if k!='spec'},as_json=False)
82
+ phrase=authorization_phrase(plan)
83
+ _confirm(args,phrase,f"run SQLite {args.command} for {plan['appSlug']} ({plan['environment']}) on target {args.name}")
84
+ _print(apply_sqlite_operation(plan),as_json=args.json); return 0
85
+ except DeploymentKitError as error:
86
86
  print(f"ERROR: {error}",file=sys.stderr); return 2