graphcore-distro 0.1.0__py3-none-any.whl

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 (108) hide show
  1. doc_topics.py +75 -0
  2. graphcore_cli/__init__.py +397 -0
  3. graphcore_cli/api_cmd.py +504 -0
  4. graphcore_cli/apps_cmd.py +26 -0
  5. graphcore_cli/db_cmd.py +90 -0
  6. graphcore_cli/docker_cmd.py +273 -0
  7. graphcore_cli/docs_cmd.py +90 -0
  8. graphcore_cli/frontend_cmd.py +460 -0
  9. graphcore_cli/identity_cmd.py +17 -0
  10. graphcore_cli/infra_cmd.py +56 -0
  11. graphcore_cli/scaffold_cmd.py +305 -0
  12. graphcore_cli/skills_cmd.py +65 -0
  13. graphcore_cli/tests/__init__.py +0 -0
  14. graphcore_cli/tests/test_api_cmd.py +568 -0
  15. graphcore_cli/tests/test_cli.py +735 -0
  16. graphcore_cli/tests/test_createadmin_cmd.py +46 -0
  17. graphcore_cli/tests/test_dev_reset.py +64 -0
  18. graphcore_cli/tests/test_docker_cmd.py +151 -0
  19. graphcore_cli/tests/test_docs_cmd.py +103 -0
  20. graphcore_cli/tests/test_frontend_cmd.py +589 -0
  21. graphcore_cli/tests/test_infra_cmd.py +105 -0
  22. graphcore_cli/tests/test_migrate.py +143 -0
  23. graphcore_cli/tests/test_packaging.py +72 -0
  24. graphcore_cli/tests/test_policy_cmd.py +46 -0
  25. graphcore_cli/tests/test_skills_cmd.py +111 -0
  26. graphcore_cli/tests/test_status_cmd.py +37 -0
  27. graphcore_distro-0.1.0.dist-info/METADATA +78 -0
  28. graphcore_distro-0.1.0.dist-info/RECORD +108 -0
  29. graphcore_distro-0.1.0.dist-info/WHEEL +5 -0
  30. graphcore_distro-0.1.0.dist-info/entry_points.txt +6 -0
  31. graphcore_distro-0.1.0.dist-info/licenses/LICENSE +202 -0
  32. graphcore_distro-0.1.0.dist-info/licenses/NOTICE +2 -0
  33. graphcore_distro-0.1.0.dist-info/top_level.txt +5 -0
  34. graphcore_project/__init__.py +28 -0
  35. graphcore_project/http.py +66 -0
  36. graphcore_project/identity.py +664 -0
  37. graphcore_project/keycloak_admin.py +152 -0
  38. graphcore_project/locate.py +75 -0
  39. graphcore_project/runner.py +382 -0
  40. graphcore_project/tests/__init__.py +0 -0
  41. graphcore_project/tests/test_identity.py +641 -0
  42. graphcore_project/tests/test_keycloak_admin.py +109 -0
  43. graphcore_project/tests/test_locate.py +125 -0
  44. graphcore_project/tests/test_runner.py +216 -0
  45. graphcore_project_kit/__init__.py +1 -0
  46. graphcore_project_kit/infra/docker-compose.yml +84 -0
  47. graphcore_project_kit/infra/realm/README.md +5 -0
  48. graphcore_project_kit/infra/realm/template-realm.json +2779 -0
  49. graphcore_project_kit/infra/themes/graphcore/login/template.ftl +268 -0
  50. graphcore_project_kit/infra/themes/graphcore/login/theme.properties +3 -0
  51. graphcore_project_kit/scaffold/app_template/backend/app_name/__init__.py-tpl +0 -0
  52. graphcore_project_kit/scaffold/app_template/backend/app_name/apps.py-tpl +17 -0
  53. graphcore_project_kit/scaffold/app_template/backend/app_name/authorization.py-tpl +16 -0
  54. graphcore_project_kit/scaffold/app_template/backend/app_name/entities/__init__.py-tpl +11 -0
  55. graphcore_project_kit/scaffold/app_template/backend/app_name/migrations/__init__.py-tpl +0 -0
  56. graphcore_project_kit/scaffold/app_template/backend/app_name/models.py-tpl +14 -0
  57. graphcore_project_kit/scaffold/app_template/backend/app_name/persistence.py-tpl +13 -0
  58. graphcore_project_kit/scaffold/app_template/backend/app_name/routes.py-tpl +3 -0
  59. graphcore_project_kit/scaffold/app_template/backend/app_name/strategies/__init__.py-tpl +11 -0
  60. graphcore_project_kit/scaffold/app_template/backend/app_name/test_settings.py-tpl +6 -0
  61. graphcore_project_kit/scaffold/app_template/backend/app_name/tests/__init__.py-tpl +0 -0
  62. graphcore_project_kit/scaffold/app_template/backend/app_name_agent_frontend/__init__.py-tpl +3 -0
  63. graphcore_project_kit/scaffold/app_template/backend/app_name_agent_frontend/agent_views.py-tpl +12 -0
  64. graphcore_project_kit/scaffold/app_template/backend/pyproject.toml +19 -0
  65. graphcore_project_kit/scaffold/app_template/react_frontend/generated/README.md +14 -0
  66. graphcore_project_kit/scaffold/app_template/react_frontend/index.ts-tpl +25 -0
  67. graphcore_project_kit/scaffold/app_template/react_frontend/package.json +17 -0
  68. graphcore_project_kit/scaffold/app_template/react_frontend/style.css-tpl +4 -0
  69. graphcore_project_kit/scaffold/project_template/.env.example +55 -0
  70. graphcore_project_kit/scaffold/project_template/AGENTS.md +97 -0
  71. graphcore_project_kit/scaffold/project_template/CLAUDE.md +1 -0
  72. graphcore_project_kit/scaffold/project_template/README.md +65 -0
  73. graphcore_project_kit/scaffold/project_template/backend/Dockerfile +27 -0
  74. graphcore_project_kit/scaffold/project_template/backend/manage.py-tpl +20 -0
  75. graphcore_project_kit/scaffold/project_template/backend/project_name/__init__.py-tpl +0 -0
  76. graphcore_project_kit/scaffold/project_template/backend/project_name/asgi.py-tpl +31 -0
  77. graphcore_project_kit/scaffold/project_template/backend/project_name/settings.py-tpl +195 -0
  78. graphcore_project_kit/scaffold/project_template/backend/project_name/urls.py-tpl +14 -0
  79. graphcore_project_kit/scaffold/project_template/backend/requirements.txt +1 -0
  80. graphcore_project_kit/scaffold/project_template/docker-compose.yml +155 -0
  81. graphcore_project_kit/scaffold/project_template/package.json +5 -0
  82. graphcore_project_kit/scaffold/project_template/react_frontend/index.html +12 -0
  83. graphcore_project_kit/scaffold/project_template/react_frontend/package.json +25 -0
  84. graphcore_project_kit/scaffold/project_template/react_frontend/src/App.tsx +37 -0
  85. graphcore_project_kit/scaffold/project_template/react_frontend/src/generated/installedApps.css +2 -0
  86. graphcore_project_kit/scaffold/project_template/react_frontend/src/generated/installedApps.ts +4 -0
  87. graphcore_project_kit/scaffold/project_template/react_frontend/src/index.css +6 -0
  88. graphcore_project_kit/scaffold/project_template/react_frontend/src/main.tsx +10 -0
  89. graphcore_project_kit/scaffold/project_template/react_frontend/src/vite-env.d.ts +1 -0
  90. graphcore_project_kit/scaffold/project_template/react_frontend/tsconfig.json +11 -0
  91. graphcore_project_kit/scaffold/project_template/react_frontend/vite.config.ts +43 -0
  92. graphcore_project_kit/scripts/backup_postgres.sh +126 -0
  93. graphcore_project_kit/scripts/restore_postgres.sh +82 -0
  94. graphcore_project_kit/skills/graphcore-docs/SKILL.md +48 -0
  95. graphcore_user_guides/__init__.py +0 -0
  96. graphcore_user_guides/agent_views.md +247 -0
  97. graphcore_user_guides/app_design/app_tdd_template.md +271 -0
  98. graphcore_user_guides/app_design/how_to_design_gc_apps.md +476 -0
  99. graphcore_user_guides/app_design/stacks_tdd.md +665 -0
  100. graphcore_user_guides/custom_authorization.md +231 -0
  101. graphcore_user_guides/deployment_access.md +360 -0
  102. graphcore_user_guides/entities.md +281 -0
  103. graphcore_user_guides/frontend.md +333 -0
  104. graphcore_user_guides/getting_started.md +357 -0
  105. graphcore_user_guides/identity_infrastructure.md +365 -0
  106. graphcore_user_guides/production.md +111 -0
  107. graphcore_user_guides/service_accounts.md +149 -0
  108. graphcore_user_guides/writing_strategies.md +381 -0
doc_topics.py ADDED
@@ -0,0 +1,75 @@
1
+ """Documentation topics contributed by the graphcore distro.
2
+
3
+ These curated user guides live in the ``graphcore_user_guides`` content
4
+ package. Their public paths are namespaced under ``distro`` by discovery.
5
+ """
6
+
7
+ from graphcore.docs.docs_discovery import Doc
8
+
9
+ TOPICS: dict[str, Doc] = {
10
+ "readme": Doc(
11
+ "graphcore_user_guides",
12
+ "getting_started.md",
13
+ "Setup, creating an app, and CLI live testing",
14
+ ),
15
+ "app-design": Doc(
16
+ "graphcore_user_guides",
17
+ "app_design/how_to_design_gc_apps.md",
18
+ "Design and build an app: the decisions, its TDD, building it, using it over MCP",
19
+ ),
20
+ "app-design/template": Doc(
21
+ "graphcore_user_guides",
22
+ "app_design/app_tdd_template.md",
23
+ "Fill-in technical design (TDD) for a new app",
24
+ ),
25
+ "app-design/example": Doc(
26
+ "graphcore_user_guides",
27
+ "app_design/stacks_tdd.md",
28
+ "Worked example: the Stacks app's technical design",
29
+ ),
30
+ "entities": Doc(
31
+ "graphcore_user_guides",
32
+ "entities.md",
33
+ "Entity types: typed fields and storage, queries, type metadata, references",
34
+ ),
35
+ "agent-views": Doc(
36
+ "graphcore_user_guides",
37
+ "agent_views.md",
38
+ "Agent views over MCP: rendering places, routes, tools and operations, the base views",
39
+ ),
40
+ "frontend": Doc(
41
+ "graphcore_user_guides",
42
+ "frontend.md",
43
+ "The web frontend: views, public pages, base path, layout, running strategies",
44
+ ),
45
+ "writing-strategies": Doc(
46
+ "graphcore_user_guides",
47
+ "writing_strategies.md",
48
+ "Writing strategies: apply, saving entities, retries, refusing requests, testing strategies and agent views",
49
+ ),
50
+ "custom-authorization": Doc(
51
+ "graphcore_user_guides",
52
+ "custom_authorization.md",
53
+ "Configure custom authorization for an app",
54
+ ),
55
+ "deployment-access": Doc(
56
+ "graphcore_user_guides",
57
+ "deployment_access.md",
58
+ "Administrators, groups, deployment roles, and what new users receive",
59
+ ),
60
+ "identity-infrastructure": Doc(
61
+ "graphcore_user_guides",
62
+ "identity_infrastructure.md",
63
+ "Identity domains, linking and token exchange; the local Keycloak, and any OIDC provider in production",
64
+ ),
65
+ "service-accounts": Doc(
66
+ "graphcore_user_guides",
67
+ "service_accounts.md",
68
+ "Service accounts: a process an app ships, signing in with its own client",
69
+ ),
70
+ "production": Doc(
71
+ "graphcore_user_guides",
72
+ "production.md",
73
+ "Running in production: what a project needs, settings, deploy steps",
74
+ ),
75
+ }
@@ -0,0 +1,397 @@
1
+ """Console entry point for the ``graphcore`` command.
2
+
3
+ Command modules (``*_cmd.py``) hold arg parsing and dispatch logic only; this
4
+ module wires them onto one argparse tree. Scaffolding lives in
5
+ ``scaffold_cmd.py``; template assets live in ``graphcore_project_kit``.
6
+ """
7
+
8
+ import argparse
9
+ import sys
10
+ from importlib.metadata import PackageNotFoundError, version
11
+ from pathlib import Path
12
+
13
+ from .scaffold_cmd import startapp, startproject
14
+
15
+ __all__ = ["main", "package_version", "startapp", "startproject"]
16
+
17
+
18
+ def package_version() -> str:
19
+ try:
20
+ return version("graphcore-distro")
21
+ except PackageNotFoundError:
22
+ return "0+unknown"
23
+
24
+
25
+ def cmd_run(args: argparse.Namespace) -> int:
26
+ import graphcore_project
27
+
28
+ port = args.port
29
+ if port is None:
30
+ root = graphcore_project.find_project_root() or Path.cwd()
31
+ port = graphcore_project.dotenv_port(root, "BACKEND_PORT", 8000)
32
+
33
+ return graphcore_project.run(debug=args.debug, host=args.host, port=port, role=args.role)
34
+
35
+
36
+ def cmd_migrate(args: argparse.Namespace) -> int:
37
+ import graphcore_project
38
+
39
+ return graphcore_project.migrate_deployment()
40
+
41
+
42
+ def cmd_db_create(args: argparse.Namespace) -> int:
43
+ import graphcore_project
44
+
45
+ return graphcore_project.create_database()
46
+
47
+
48
+ def cmd_test(args: argparse.Namespace) -> int:
49
+ import subprocess
50
+
51
+ from graphcore_project import require_project_root
52
+
53
+ root = require_project_root(command="graphcore test")
54
+ return subprocess.run(
55
+ [sys.executable, "manage.py", "test", *args.passthrough],
56
+ cwd=root / "backend",
57
+ ).returncode
58
+
59
+
60
+ def cmd_dev_reset(args: argparse.Namespace) -> int:
61
+ import subprocess
62
+
63
+ from graphcore_project import require_project_root
64
+
65
+ root = require_project_root(command="graphcore dev reset")
66
+ return subprocess.run([sys.executable, "manage.py", "dev_reset"], cwd=root / "backend").returncode
67
+
68
+
69
+ def cmd_createadmin(args: argparse.Namespace) -> int:
70
+ import subprocess
71
+
72
+ from graphcore_project import require_project_root
73
+
74
+ from .docker_cmd import createadmin_manage_args
75
+
76
+ root = require_project_root(command="graphcore createadmin")
77
+ return subprocess.run(
78
+ [sys.executable, "manage.py", *createadmin_manage_args(args)], cwd=root / "backend",
79
+ ).returncode
80
+
81
+
82
+ def cmd_policy(args: argparse.Namespace) -> int:
83
+ import subprocess
84
+
85
+ from graphcore_project import require_project_root
86
+
87
+ from .docker_cmd import policy_manage_args
88
+
89
+ root = require_project_root(command="graphcore policy")
90
+ return subprocess.run(
91
+ [sys.executable, "manage.py", *policy_manage_args(args)], cwd=root / "backend",
92
+ ).returncode
93
+
94
+
95
+ def cmd_status(args: argparse.Namespace) -> int:
96
+ import subprocess
97
+
98
+ from graphcore_project import require_project_root
99
+
100
+ root = require_project_root(command="graphcore status")
101
+ return subprocess.run([sys.executable, "manage.py", "graphcore_status"], cwd=root / "backend").returncode
102
+
103
+
104
+ def cmd_docker(args: argparse.Namespace) -> int:
105
+ from . import docker_cmd
106
+
107
+ handlers = {
108
+ "up": docker_cmd.docker_up,
109
+ "down": docker_cmd.docker_down,
110
+ "logs": docker_cmd.docker_logs,
111
+ "test": docker_cmd.docker_test,
112
+ "createadmin": docker_cmd.docker_createadmin,
113
+ "policy": docker_cmd.docker_policy,
114
+ "status": docker_cmd.docker_status,
115
+ "migrate": docker_cmd.docker_migrate,
116
+ }
117
+ return handlers[args.docker_command](args)
118
+
119
+
120
+ def cmd_infra(args: argparse.Namespace) -> int:
121
+ from . import infra_cmd
122
+
123
+ handlers = {
124
+ "up": infra_cmd.infra_up,
125
+ "down": infra_cmd.infra_down,
126
+ }
127
+ return handlers[args.infra_command](args)
128
+
129
+
130
+ def cmd_identity(args: argparse.Namespace) -> int:
131
+ from . import identity_cmd
132
+
133
+ handlers = {
134
+ "apply": identity_cmd.identity_apply,
135
+ "render": identity_cmd.identity_render,
136
+ }
137
+ return handlers[args.identity_command](args)
138
+
139
+
140
+ def cmd_db(args: argparse.Namespace) -> int:
141
+ from . import db_cmd
142
+
143
+ handlers = {
144
+ "create": cmd_db_create,
145
+ "backup": db_cmd.db_backup,
146
+ "restore": db_cmd.db_restore,
147
+ }
148
+ return handlers[args.db_command](args)
149
+
150
+
151
+
152
+ def _add_createadmin_arguments(parser: argparse.ArgumentParser) -> None:
153
+ parser.add_argument("user", help="Username or principal entity id (gc://...)")
154
+ parser.add_argument("--remove", action="store_true", help="Remove the user from the admins")
155
+ parser.add_argument("--force", action="store_true", help="Allow removing the last admin")
156
+
157
+
158
+ LOCAL_FRAMEWORK_HELP = (
159
+ "Use this monorepo checkout's kernel, distro and built-in apps (editable installs, "
160
+ "live mounts, file: links) instead of the published packages"
161
+ )
162
+
163
+
164
+ def main(argv: list[str] | None = None) -> int:
165
+ parser = argparse.ArgumentParser(prog="graphcore")
166
+ parser.add_argument("--version", action="version", version=f"%(prog)s {package_version()}")
167
+ subparsers = parser.add_subparsers(dest="command", required=True)
168
+
169
+ project = subparsers.add_parser("startproject", help="Generate a graphcore deployment")
170
+ project.add_argument("name")
171
+ project.add_argument("directory", nargs="?")
172
+ project.add_argument("--local-framework", action="store_true", help=LOCAL_FRAMEWORK_HELP)
173
+ project.set_defaults(func=startproject)
174
+
175
+ app = subparsers.add_parser("startapp", help="Generate a graphcore app: under apps/ in a project, else in the current directory")
176
+ app.add_argument("name")
177
+ app.add_argument("--local-framework", action="store_true", help=LOCAL_FRAMEWORK_HELP + " (outside a project only)")
178
+ app.set_defaults(func=startapp)
179
+
180
+ run_parser = subparsers.add_parser(
181
+ "run",
182
+ help="Run the deployment on the host (uvicorn + Celery worker + Beat)",
183
+ )
184
+ run_parser.add_argument("--debug", action="store_true", help="Single-process debug mode")
185
+ run_parser.add_argument("--host", default="0.0.0.0")
186
+ run_parser.add_argument(
187
+ "--port",
188
+ type=int,
189
+ default=None,
190
+ help="Defaults to the deployment's .env BACKEND_PORT, then 8000.",
191
+ )
192
+ run_parser.add_argument(
193
+ "--role",
194
+ choices=["web", "worker", "beat", "all"],
195
+ default="all",
196
+ help="Which process(es) to run (default: all, bundled - ignored in --debug mode)",
197
+ )
198
+ run_parser.set_defaults(func=cmd_run)
199
+
200
+ migrate_parser = subparsers.add_parser(
201
+ "migrate",
202
+ help="Apply migrations under a Postgres advisory lock (safe to run from multiple replicas)",
203
+ )
204
+ migrate_parser.set_defaults(func=cmd_migrate)
205
+
206
+ test_parser = subparsers.add_parser(
207
+ "test",
208
+ help="Run python manage.py test on the host (passthrough args allowed)",
209
+ )
210
+ test_parser.add_argument(
211
+ "passthrough",
212
+ nargs="*",
213
+ default=[],
214
+ help="Args forwarded to manage.py test (e.g. graphcore.domain.entity.tests)",
215
+ )
216
+ test_parser.set_defaults(func=cmd_test)
217
+
218
+ dev = subparsers.add_parser("dev", help="Local dev conveniences")
219
+ dev_sub = dev.add_subparsers(dest="dev_command", required=True)
220
+
221
+ dev_reset = dev_sub.add_parser(
222
+ "reset",
223
+ help="Invalidate the entity cache (generation bump) without flushing sessions or other cache entries",
224
+ )
225
+ dev_reset.set_defaults(func=cmd_dev_reset)
226
+
227
+ createadmin = subparsers.add_parser(
228
+ "createadmin", help="Make a user a deployment administrator (or --remove one)",
229
+ )
230
+ _add_createadmin_arguments(createadmin)
231
+ createadmin.set_defaults(func=cmd_createadmin)
232
+
233
+ policy = subparsers.add_parser("policy", help="Print each entity type's effective access policy")
234
+ policy.add_argument("type_id", nargs="?", help="Only this entity_type_id (e.g. graphcore.Grant)")
235
+ policy.set_defaults(func=cmd_policy)
236
+
237
+ status = subparsers.add_parser(
238
+ "status", help="Show Celery workers, their kernel tasks, and what the scheduler holds",
239
+ )
240
+ status.set_defaults(func=cmd_status)
241
+
242
+ docker = subparsers.add_parser("docker", help="Manage the deployment's docker compose stack")
243
+ docker_sub = docker.add_subparsers(dest="docker_command", required=True)
244
+
245
+ up = docker_sub.add_parser("up", help="Start the backend container (uses shared `graphcore infra`)")
246
+ up.add_argument("--build", action="store_true", help="Build images before starting")
247
+ up.add_argument("-d", "--detach", action="store_true", help="Run in the background")
248
+ up.add_argument("--debug", action="store_true", help="Use the debug backend profile")
249
+ up.set_defaults(func=cmd_docker)
250
+
251
+ down = docker_sub.add_parser("down", help="Stop compose services")
252
+ down.add_argument("-v", "--volumes", action="store_true", help="Remove volumes too")
253
+ down.set_defaults(func=cmd_docker)
254
+
255
+ logs = docker_sub.add_parser("logs", help="Tail compose logs")
256
+ logs.add_argument("passthrough", nargs="*", default=["-f"])
257
+ logs.set_defaults(func=cmd_docker)
258
+
259
+ dtest = docker_sub.add_parser(
260
+ "test",
261
+ help="Run manage.py test inside the running backend container",
262
+ )
263
+ dtest.add_argument(
264
+ "passthrough",
265
+ nargs="*",
266
+ default=[],
267
+ help="Args forwarded to manage.py test",
268
+ )
269
+ dtest.set_defaults(func=cmd_docker)
270
+
271
+ dcreateadmin = docker_sub.add_parser(
272
+ "createadmin",
273
+ help="Make a user a deployment administrator inside the running backend container",
274
+ )
275
+ _add_createadmin_arguments(dcreateadmin)
276
+ dcreateadmin.set_defaults(func=cmd_docker)
277
+
278
+ dpolicy = docker_sub.add_parser(
279
+ "policy", help="Print each entity type's effective access policy (in the backend container)",
280
+ )
281
+ dpolicy.add_argument("type_id", nargs="?", help="Only this entity_type_id")
282
+ dpolicy.set_defaults(func=cmd_docker)
283
+
284
+ dstatus = docker_sub.add_parser(
285
+ "status",
286
+ help="Show Celery workers, their kernel tasks, and what the scheduler holds (in the backend container)",
287
+ )
288
+ dstatus.set_defaults(func=cmd_docker)
289
+
290
+ dmigrate = docker_sub.add_parser(
291
+ "migrate",
292
+ help="One-shot `graphcore migrate` via the `migrate` compose profile (multi-replica-safe)",
293
+ )
294
+ dmigrate.set_defaults(func=cmd_docker)
295
+
296
+ infra = subparsers.add_parser(
297
+ "infra",
298
+ help="Shared local Postgres + Redis used by all deployments on this machine",
299
+ )
300
+ infra_sub = infra.add_subparsers(dest="infra_command", required=True)
301
+
302
+ infra_up = infra_sub.add_parser("up", help="Start the shared containers (idempotent)")
303
+ infra_up.set_defaults(func=cmd_infra)
304
+
305
+ infra_down = infra_sub.add_parser("down", help="Stop the shared containers")
306
+ infra_down.add_argument(
307
+ "-v",
308
+ "--volumes",
309
+ action="store_true",
310
+ help="Also delete the shared data volume (ALL deployments' data)",
311
+ )
312
+ infra_down.set_defaults(func=cmd_infra)
313
+
314
+ identity = subparsers.add_parser(
315
+ "identity", help="The deployment's identity domain: the Keycloak realm its users sign in to")
316
+ identity_sub = identity.add_subparsers(dest="identity_command", required=True)
317
+
318
+ identity_apply = identity_sub.add_parser(
319
+ "apply",
320
+ help="Create or update this project's identity domain (Keycloak realm) from its declarations; idempotent",
321
+ )
322
+ identity_apply.set_defaults(func=cmd_identity)
323
+
324
+ identity_render = identity_sub.add_parser(
325
+ "render", help="Print the realm `apply` would create, secrets shown as their .env variables")
326
+ identity_render.add_argument(
327
+ "--with-secrets", action="store_true", help="Print the secret values instead of their variables")
328
+ identity_render.set_defaults(func=cmd_identity)
329
+
330
+ db = subparsers.add_parser("db", help="Postgres backup and restore for a deployment")
331
+ db_sub = db.add_subparsers(dest="db_command", required=True)
332
+
333
+ create = db_sub.add_parser(
334
+ "create",
335
+ help="Create the deployment's database if it doesn't exist yet (no-op otherwise)",
336
+ )
337
+ create.set_defaults(func=cmd_db)
338
+
339
+ backup = db_sub.add_parser(
340
+ "backup",
341
+ help="Chunked compressed pg_dump into <deployment>/backups/",
342
+ )
343
+ backup.add_argument(
344
+ "name",
345
+ nargs="?",
346
+ default=None,
347
+ help="Optional suffix appended to today's date folder name",
348
+ )
349
+ backup.set_defaults(func=cmd_db)
350
+
351
+ restore = db_sub.add_parser(
352
+ "restore",
353
+ help="Restore a backup folder created by graphcore db backup",
354
+ )
355
+ restore.add_argument("backup_path", help="Path to a backups/YYYY-MM-DD[-name] folder")
356
+ restore.add_argument("--host", default=None, help="Override POSTGRES_HOST")
357
+ restore.add_argument("--port", type=int, default=None, help="Override POSTGRES_PORT")
358
+ restore.add_argument("--user", default=None, help="Override POSTGRES_USER")
359
+ restore.add_argument("--database", default=None, help="Override POSTGRES_DB")
360
+ restore.add_argument(
361
+ "--force",
362
+ action="store_true",
363
+ help="Overwrite an existing database without prompting",
364
+ )
365
+ restore.set_defaults(func=cmd_db)
366
+
367
+ api = subparsers.add_parser("api", help="Live-test a running deployment over HTTP")
368
+ from . import api_cmd
369
+
370
+ api_cmd.add_arguments(api)
371
+
372
+ docs = subparsers.add_parser("docs", help="Read framework documentation for this install")
373
+ from . import docs_cmd
374
+
375
+ docs_cmd.add_arguments(docs)
376
+
377
+ frontend = subparsers.add_parser("frontend", help="Prepare and start the project frontend")
378
+ from . import frontend_cmd
379
+
380
+ frontend_cmd.add_arguments(frontend)
381
+
382
+ apps = subparsers.add_parser("apps", help="Inspect discovered graphcore apps")
383
+ from . import apps_cmd
384
+
385
+ apps_cmd.add_arguments(apps)
386
+
387
+ skills = subparsers.add_parser("skills", help="Manage framework-shipped Agent Skills in a deployment")
388
+ from . import skills_cmd
389
+
390
+ skills_cmd.add_arguments(skills)
391
+
392
+ args = parser.parse_args(argv)
393
+ return args.func(args) or 0
394
+
395
+
396
+ if __name__ == "__main__":
397
+ sys.exit(main())