action-platform 0.1.2__tar.gz → 0.3.0__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.
Files changed (86) hide show
  1. {action_platform-0.1.2 → action_platform-0.3.0}/PKG-INFO +150 -9
  2. action_platform-0.3.0/README.md +293 -0
  3. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/__init__.py +2 -2
  4. action_platform-0.3.0/action_platform/api/LAST_VERSION +1 -0
  5. action_platform-0.3.0/action_platform/api/__init__.py +1 -0
  6. action_platform-0.3.0/action_platform/api/credentials.py +87 -0
  7. action_platform-0.3.0/action_platform/api/models.py +177 -0
  8. action_platform-0.3.0/action_platform/api/registry.py +167 -0
  9. action_platform-0.3.0/action_platform/api/server.py +436 -0
  10. action_platform-0.3.0/action_platform/cli/commands/api.py +32 -0
  11. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/branch.py +1 -1
  12. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/cloud.py +2 -2
  13. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/gitflow.py +1 -1
  14. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/init.py +6 -2
  15. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/install.py +6 -2
  16. action_platform-0.3.0/action_platform/cli/commands/login.py +39 -0
  17. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/mcp.py +9 -0
  18. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/pr.py +1 -1
  19. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/release.py +13 -2
  20. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/service.py +2 -2
  21. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/setup.py +6 -0
  22. action_platform-0.3.0/action_platform/core/__init__.py +8 -0
  23. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/core/action_platform.py +21 -7
  24. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/core/config.py +11 -5
  25. action_platform-0.3.0/action_platform/core/flow/__init__.py +1 -0
  26. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/flow}/branching.py +1 -1
  27. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/flow}/git.py +35 -4
  28. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/flow}/gitflow.py +2 -2
  29. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/flow}/pullrequest.py +3 -2
  30. action_platform-0.3.0/action_platform/core/release/__init__.py +1 -0
  31. action_platform-0.3.0/action_platform/core/release/components.py +78 -0
  32. action_platform-0.1.2/action_platform/core/pipeline.py → action_platform-0.3.0/action_platform/core/release/deploy.py +4 -64
  33. action_platform-0.3.0/action_platform/core/release/release.py +135 -0
  34. action_platform-0.3.0/action_platform/core/release/versioning.py +98 -0
  35. action_platform-0.3.0/action_platform/core/scaffold/__init__.py +1 -0
  36. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/scaffold}/generate.py +43 -69
  37. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/scaffold}/install.py +23 -8
  38. action_platform-0.3.0/action_platform/mcp/prompts.py +136 -0
  39. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/server.py +39 -3
  40. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/tools/flow.py +6 -2
  41. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/tools/lifecycle.py +9 -2
  42. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/tools/matrix.py +1 -1
  43. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/tools/project.py +3 -3
  44. action_platform-0.3.0/action_platform/mcp/tools/remote.py +109 -0
  45. action_platform-0.3.0/action_platform/providers/__init__.py +9 -0
  46. action_platform-0.3.0/action_platform/providers/source/__init__.py +48 -0
  47. action_platform-0.3.0/action_platform/providers/source/bitbucket.py +111 -0
  48. action_platform-0.3.0/action_platform/providers/source/generic.py +61 -0
  49. action_platform-0.3.0/action_platform/providers/source/github.py +204 -0
  50. action_platform-0.3.0/action_platform/providers/source/gitlab.py +126 -0
  51. action_platform-0.3.0/action_platform/providers/source/rest.py +58 -0
  52. action_platform-0.3.0/action_platform/remote/__init__.py +1 -0
  53. action_platform-0.3.0/action_platform/remote/client.py +216 -0
  54. action_platform-0.3.0/action_platform/remote/credentials.py +58 -0
  55. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/settings.py +2 -0
  56. {action_platform-0.1.2 → action_platform-0.3.0}/pyproject.toml +12 -5
  57. action_platform-0.1.2/README.md +0 -155
  58. action_platform-0.1.2/action_platform/core/__init__.py +0 -1
  59. action_platform-0.1.2/action_platform/core/versioning.py +0 -43
  60. action_platform-0.1.2/action_platform/providers/__init__.py +0 -5
  61. action_platform-0.1.2/action_platform/providers/source_github.py +0 -122
  62. {action_platform-0.1.2 → action_platform-0.3.0}/LICENSE +0 -0
  63. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/abc/__init__.py +0 -0
  64. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/abc/ci_runner.py +0 -0
  65. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/abc/deploy_target.py +0 -0
  66. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/abc/source_host.py +0 -0
  67. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/__init__.py +0 -0
  68. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/__init__.py +0 -0
  69. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/cli/commands/deploy.py +0 -0
  70. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/core/context.py +0 -0
  71. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/core/exception.py +0 -0
  72. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/core/module.py +0 -0
  73. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/release}/changelog.py +0 -0
  74. {action_platform-0.1.2/action_platform/core → action_platform-0.3.0/action_platform/core/scaffold}/templates.py +0 -0
  75. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/hooks/__init__.py +0 -0
  76. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/hooks/commit-msg +0 -0
  77. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/hooks/gitflow.sh +0 -0
  78. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/hooks/pre-commit +0 -0
  79. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/hooks/pre-push +0 -0
  80. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/logging.py +0 -0
  81. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/main.py +0 -0
  82. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/__init__.py +0 -0
  83. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/__main__.py +0 -0
  84. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/annotations.py +0 -0
  85. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/mcp/tools/__init__.py +0 -0
  86. {action_platform-0.1.2 → action_platform-0.3.0}/action_platform/testing/__init__.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: action-platform
3
- Version: 0.1.2
4
- Summary: From idea to production in one command: scaffold, CI, release and deploy on any stack and cloud, with git-flow and Conventional Commits enforced and an MCP server for AI agents.
3
+ Version: 0.3.0
4
+ Summary: Your platform team, as a CLI.
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
7
7
  http://www.apache.org/licenses/
@@ -222,11 +222,13 @@ Classifier: Programming Language :: Python :: 3.10
222
222
  Classifier: Programming Language :: Python :: 3.11
223
223
  Classifier: Programming Language :: Python :: 3.12
224
224
  Classifier: Programming Language :: Python :: 3.13
225
+ Provides-Extra: api
225
226
  Provides-Extra: github
226
227
  Provides-Extra: gitlab
227
228
  Provides-Extra: mcp
228
229
  Requires-Dist: PyGithub ; extra == "github"
229
230
  Requires-Dist: cookiecutter
231
+ Requires-Dist: fastapi (>=0.115) ; extra == "api"
230
232
  Requires-Dist: jinja2
231
233
  Requires-Dist: mcp (>=2.0) ; extra == "mcp"
232
234
  Requires-Dist: pydantic
@@ -235,6 +237,7 @@ Requires-Dist: python-ulid (>=3.0)
235
237
  Requires-Dist: rich
236
238
  Requires-Dist: typer
237
239
  Requires-Dist: typing-extensions
240
+ Requires-Dist: uvicorn (>=0.30) ; extra == "api"
238
241
  Project-URL: Changelog, https://github.com/actionplatform/action-platform/blob/master/CHANGELOG.md
239
242
  Project-URL: Homepage, https://github.com/actionplatform/action-platform
240
243
  Project-URL: Issues, https://github.com/actionplatform/action-platform/issues
@@ -248,7 +251,7 @@ Description-Content-Type: text/markdown
248
251
  </p>
249
252
 
250
253
  <p align="center">
251
- <strong>From idea to production in one command — on any stack, on any cloud.</strong>
254
+ <strong>Your platform team: a web app, a CLI and an MCP server on one core.</strong>
252
255
  </p>
253
256
 
254
257
  <p align="center">
@@ -260,7 +263,27 @@ Description-Content-Type: text/markdown
260
263
 
261
264
  ---
262
265
 
263
- Every new service costs the same week: scaffold, lint config, CI, versioning, deploy pipeline, IAM. Then the next one drifts from the last. **Action Platform** turns that week into one command and keeps every project on the same rails — without a control plane to host, a UI to learn, or a vendor to trust with your cloud.
266
+ Every new service costs the same week: scaffold, lint config, CI, versioning, deploy pipeline, IAM. Then the next one drifts from the last. **Action Platform** turns that week into one command — or one click — and keeps every app on the same rails, in your git host and your cloud account.
267
+
268
+ Three doors, one core:
269
+
270
+ | | |
271
+ |---|---|
272
+ | **Web app** | Organizations › projects › apps. Create an app from a template, connect GitHub / GitLab / Bitbucket, cut releases, run deploys — from a browser. One command to self-host. |
273
+ | **CLI** | `pipx install action-platform` and the same verbs on your machine: `init`, `branch`, `pr`, `release`, `deploy`, `rollback`, `diagnose`. |
274
+ | **MCP server** | The same operations as tools for Claude Code, Codex, Cursor — locally, or against your hosted platform after `action-platform login`. |
275
+
276
+ ## Self-host in one command
277
+
278
+ ```bash
279
+ curl -fsSL https://raw.githubusercontent.com/actionplatform/action-platform/master/deploy/install.sh | sudo sh
280
+ # with a domain and TLS:
281
+ curl -fsSL https://raw.githubusercontent.com/actionplatform/action-platform/master/deploy/install.sh | sudo sh -s -- platform.example.com you@example.com
282
+ ```
283
+
284
+ Installs Docker if needed, generates the secrets, starts Postgres + API + web (+ Traefik with Let's Encrypt when a domain is given) and prints the URL. Open it: first account, first organization, connect a code host — done. Files live in `/opt/action-platform`; see [`deploy/`](deploy/) for the compose file and the two Dockerfiles.
285
+
286
+ ## Or just the CLI
264
287
 
265
288
  ```bash
266
289
  pipx install action-platform
@@ -277,7 +300,7 @@ Thirty seconds later you have a FastAPI service with tests, lint, CI wired, a SA
277
300
  | **One command, whole lifecycle** | `init` → `release` → `deploy` → `rollback` → `diagnose` → `destroy`. Same verbs for a Python API on Lambda, a Go service in Docker, a React app on Amplify. |
278
301
  | **Templates from production, not tutorials** | Every project template is extracted from a real shipping product. Real layout, real CI, real gotchas already fixed. |
279
302
  | **Cloud is a layer, not a fork** | Projects stay cloud-agnostic. `--cloud aws/lambda` overlays deploy files; swap to `docker` tomorrow with one command. |
280
- | **Your CI, your account, your git** | Runs on GitHub Actions, GitLab CI or Jenkins you already have. Infra lands in **your** AWS account through OIDC — no long-lived keys, no agent, no SaaS in the loop. |
303
+ | **Your CI, your account, your git** | Runs on GitHub Actions, GitLab CI or Jenkins you already have. Repositories on GitHub, GitLab, Bitbucket or any git server, connected with OAuth. Infra lands in **your** AWS account through OIDC — no long-lived keys, no vendor in the loop. |
281
304
  | **Governance that ships with the code** | Git-flow and Conventional Commits enforced by git hooks before a commit exists and by CI on every PR; changelog generated; `AGENTS.md` for humans and AI agents; Trivy scans; least-privilege IAM in `requirements/`. |
282
305
  | **Fix once, everywhere** | CI logic lives in versioned shared repos (`ci-scripts`, `ci-github`, `ci-gitlab`, `ci-jenkins`). Bump `v1`, every project picks it up. |
283
306
 
@@ -321,13 +344,64 @@ action-platform branch feature 42 login # develop (or main) → pull
321
344
  action-platform branch hotfix PROJ-7 # from main/master
322
345
  action-platform gitflow # audit current branch + commits; --install-hooks
323
346
  action-platform pr [--draft] [--dry-run] # PR for the current branch: target from git-flow, body from commits
324
- action-platform release patch # bump, changelog, tag, GitHub release
347
+ action-platform release patch # bump, changelog, tag, GitHub release; off main/master → X.Y.Z-rc.N pre-release
325
348
  action-platform deploy --stage prod
326
349
  action-platform rollback
327
350
  action-platform diagnose
328
351
  action-platform destroy
329
352
  ```
330
353
 
354
+ ## Git-flow, enforced
355
+
356
+ Every project follows the same flow. Git hooks refuse the wrong move before it exists; CI refuses it on the pull request; the CLI and the MCP tools guide the right one.
357
+
358
+ ```mermaid
359
+ gitGraph
360
+ commit id: "chore: bootstrap"
361
+ branch develop
362
+ checkout develop
363
+ commit id: "chore(release): 0.3.2-rc.1" tag: "v0.3.2-rc.1"
364
+ branch feature/42-login
365
+ checkout feature/42-login
366
+ commit id: "feat(login): form"
367
+ commit id: "test(login): cover form"
368
+ checkout develop
369
+ merge feature/42-login id: "PR #1 → develop"
370
+ branch release/0.3.2
371
+ checkout release/0.3.2
372
+ commit id: "chore(release): 0.3.2-rc.2" tag: "v0.3.2-rc.2"
373
+ checkout main
374
+ merge release/0.3.2 id: "PR #2 → main"
375
+ commit id: "chore(release): 0.3.2" tag: "v0.3.2"
376
+ checkout develop
377
+ merge main id: "back-merge"
378
+ checkout main
379
+ branch hotfix/PROJ-7
380
+ checkout hotfix/PROJ-7
381
+ commit id: "fix(auth): expiry"
382
+ checkout main
383
+ merge hotfix/PROJ-7 id: "PR #3 → main"
384
+ commit id: "chore(release): 0.3.3" tag: "v0.3.3"
385
+ checkout develop
386
+ merge main id: "back-merge hotfix"
387
+ ```
388
+
389
+ | Branch | Starts from | Merges into | Release |
390
+ |--------|-------------|-------------|---------|
391
+ | `feature/<code>`, `bugfix/…`, `chore/…`, `docs/…`, `refactor/…`, `test/…`, `ci/…`, `perf/…` | `develop` (or the default branch when there is no `develop`) | `develop` | `X.Y.Z-rc.N` pre-release |
392
+ | `release/<version>` | `develop` | `main` and `develop` | `X.Y.Z-rc.N` until merged |
393
+ | `hotfix/<code>` | `main` | `main` and `develop` | `X.Y.Z-rc.N` until merged |
394
+ | `main` / `master` | — | — | stable `X.Y.Z` → PyPI / npm / … |
395
+
396
+ Rules the hooks and CI apply: branch names are `<kind>/<code>[-slug]`; commits are [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/); no direct commits on `main`, `master` or `develop` except `chore(release):`, `chore(platform):` and the bootstrap commit; a pull request may only target what the table allows.
397
+
398
+ ```bash
399
+ action-platform branch feature 42 login # develop → pull → feature/42-login → push
400
+ action-platform gitflow # audit branch + commits
401
+ action-platform pr # target and body from the rules and the commits
402
+ action-platform release patch # rc off main, stable on main
403
+ ```
404
+
331
405
  Everything a project needs is declared in one file:
332
406
 
333
407
  ```toml
@@ -336,6 +410,7 @@ name = "orders"
336
410
  type = "web"
337
411
  stack = "python"
338
412
  template = "fastapi"
413
+ ci = "github"
339
414
  language = "python"
340
415
 
341
416
  [source_host]
@@ -351,7 +426,7 @@ postgres = "aws-rds"
351
426
 
352
427
  ## Use it from an AI client
353
428
 
354
- The platform ships as an MCP server. Claude Code, Codex, Cursor — anything that speaks MCP — gets `list_matrix`, `init_project`, `cloud_set`, `service_add`, `release`, `deploy`, `diagnose` as tools, plus skills that make the agent preview and ask before pushing or deploying.
429
+ The platform ships as an MCP server. Claude Code, Codex, Cursor — anything that speaks MCP — gets 17 tools (`list_matrix`, `init_project`, `install_platform`, `start_branch`, `gitflow_audit`, `propose_pull_request`, `release`, `deploy`, `diagnose`, …), 6 prompts that put them in the right order (`new_service`, `ship_feature`, `cut_release`, `deploy_project`, `adopt_repository`, `fix_gitflow`) and 12 skills that make the agent preview and ask before anything leaves the machine.
355
430
 
356
431
  ```bash
357
432
  pip install "action-platform[mcp]"
@@ -372,13 +447,80 @@ Any client — add to `.mcp.json`:
372
447
  { "mcpServers": { "action-platform": { "command": "uvx", "args": ["--from", "action-platform[mcp]", "action-platform-mcp"] } } }
373
448
  ```
374
449
 
450
+ ## The web app
451
+
452
+ [`apps/web`](apps/web) — Next.js on top of the Python API. **Organization › Project › App**: an organization is the tenant and owns its code hosts; a project groups the apps that ship together; an app is one git repository the platform clones, audits, releases and deploys.
453
+
454
+ - **Setup wizard** on first run: database (SQLite, PostgreSQL or MySQL), first account, first organization, code hosts.
455
+ - **Connect with GitHub / GitLab / Bitbucket** through OAuth (or paste a token). Tokens are encrypted at rest and refreshed when they expire.
456
+ - **Create project** wizard: type → stack → template → configure → review, with the equivalent `action-platform init` shown. Or add an existing repository by URL.
457
+ - Per app: git-flow audit, commits, branches, tags, release preview → confirm → publish, deploy preflight → confirm → ship.
458
+ - Strictly monochrome UI; every confirmation is an in-app dialog.
459
+
460
+ Local development:
461
+
462
+ ```bash
463
+ pip install "action-platform[api]"
464
+ action-platform api --reload # http://127.0.0.1:7788, OpenAPI at /docs
465
+ cd apps/web && npm install && npm run dev # http://localhost:3000 → /setup
466
+ ```
467
+
468
+ Drive a hosted platform from anywhere:
469
+
470
+ ```bash
471
+ action-platform login https://platform.example.com # browser opens, approve the code
472
+ action-platform mcp --remote # the MCP tools now act on that platform
473
+ ```
474
+
475
+ The TypeScript client is generated from the API's OpenAPI schema (`npm run api:types`): the Python response models in `action_platform/api/models.py` are the contract both sides compile against.
476
+
477
+ ## Releases: three artifacts, three versions
478
+
479
+ One repository, independent versions — declared in `platform.toml`:
480
+
481
+ ```toml
482
+ [components.web]
483
+ path = "apps/web"
484
+
485
+ [components.api]
486
+ path = "action_platform/api"
487
+ ```
488
+
489
+ | Command | Tag | Publishes |
490
+ |---|---|---|
491
+ | `action-platform release minor` | `v0.3.0` | `action-platform` on PyPI (library + CLI) |
492
+ | `action-platform release -c api patch` | `api/v0.1.1` | `actionplatform/action-platform-api` image |
493
+ | `action-platform release -c web minor` | `web/v0.2.0` | `actionplatform/action-platform-web` image |
494
+
495
+ Each component keeps its own `LAST_VERSION` and `CHANGELOG.md` under its path; its changelog lists only the commits that touched it, and the root's excludes them. Off `master` every release is an `-rc.N` pre-release. Images go to Docker Hub and are mirrored to GHCR.
496
+
497
+ ## Layout
498
+
499
+ ```
500
+ action_platform/
501
+ core/
502
+ manifest/ platform.toml: read, edit tables
503
+ scaffold/ templates matrix, generate, install into an existing repo
504
+ flow/ git, git-flow rules, branching, pull requests
505
+ release/ versioning, changelog, release, deploy
506
+ config.py · context.py · exception.py · action_platform.py (facade)
507
+ providers/
508
+ source/ github, gitlab, bitbucket, generic — repositories, releases, PRs
509
+ api/ FastAPI for the web app: apps registry, actions, per-request credentials
510
+ remote/ client + device-flow login for a hosted platform
511
+ mcp/ MCP server: local tools, or remote tools after login
512
+ cli/ Typer commands
513
+ apps/web/ the web app (see its README)
514
+ deploy/ Dockerfiles, docker-compose, install.sh
515
+ ```
516
+
375
517
  ## Extend it
376
518
 
377
519
  Deploy targets are plugins. Implement the `DeployTarget` contract — `preflight`, `create`, `deploy`, `switch_traffic`, `rollback`, `diagnose`, `delete` — publish it under the `action_platform.deploy_target` entry-point group, and `action-platform deploy` finds it by name.
378
520
 
379
521
  ```python
380
522
  from action_platform import ActionPlatform, Config
381
- from action_platform.providers import SourceGithub
523
+ from action_platform.providers.source.github import SourceGithub
382
524
 
383
525
  tool = ActionPlatform(config=Config(source_host=SourceGithub(repo="acme/orders")))
384
526
  tool.release("minor")
@@ -393,7 +535,6 @@ Templates are plain cookiecutters in [actionplatform/templates](https://github.c
393
535
  | [templates](https://github.com/actionplatform/templates) | projects, clouds, services |
394
536
  | [ci-scripts](https://github.com/actionplatform/ci-scripts) | the one implementation of setup / check / release / commit lint |
395
537
  | [ci-github](https://github.com/actionplatform/ci-github) · [ci-gitlab](https://github.com/actionplatform/ci-gitlab) · [ci-jenkins](https://github.com/actionplatform/ci-jenkins) | thin wrappers per CI |
396
- | [strategy](https://github.com/actionplatform/strategy) | why it is built this way |
397
538
 
398
539
  ## License
399
540
 
@@ -0,0 +1,293 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/actionplatform/action-platform/master/docs/assets/cover.png" alt="Action Platform" width="100%">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <strong>Your platform team: a web app, a CLI and an MCP server on one core.</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://pypi.org/project/action-platform/"><img alt="PyPI" src="https://img.shields.io/pypi/v/action-platform?color=2ea44f"></a>
11
+ <a href="https://pypi.org/project/action-platform/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/action-platform"></a>
12
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue"></a>
13
+ <a href="https://github.com/actionplatform/templates"><img alt="Templates" src="https://img.shields.io/badge/templates-13%20projects%20%C2%B7%203%20clouds-6f42c1"></a>
14
+ </p>
15
+
16
+ ---
17
+
18
+ Every new service costs the same week: scaffold, lint config, CI, versioning, deploy pipeline, IAM. Then the next one drifts from the last. **Action Platform** turns that week into one command — or one click — and keeps every app on the same rails, in your git host and your cloud account.
19
+
20
+ Three doors, one core:
21
+
22
+ | | |
23
+ |---|---|
24
+ | **Web app** | Organizations › projects › apps. Create an app from a template, connect GitHub / GitLab / Bitbucket, cut releases, run deploys — from a browser. One command to self-host. |
25
+ | **CLI** | `pipx install action-platform` and the same verbs on your machine: `init`, `branch`, `pr`, `release`, `deploy`, `rollback`, `diagnose`. |
26
+ | **MCP server** | The same operations as tools for Claude Code, Codex, Cursor — locally, or against your hosted platform after `action-platform login`. |
27
+
28
+ ## Self-host in one command
29
+
30
+ ```bash
31
+ curl -fsSL https://raw.githubusercontent.com/actionplatform/action-platform/master/deploy/install.sh | sudo sh
32
+ # with a domain and TLS:
33
+ curl -fsSL https://raw.githubusercontent.com/actionplatform/action-platform/master/deploy/install.sh | sudo sh -s -- platform.example.com you@example.com
34
+ ```
35
+
36
+ Installs Docker if needed, generates the secrets, starts Postgres + API + web (+ Traefik with Let's Encrypt when a domain is given) and prints the URL. Open it: first account, first organization, connect a code host — done. Files live in `/opt/action-platform`; see [`deploy/`](deploy/) for the compose file and the two Dockerfiles.
37
+
38
+ ## Or just the CLI
39
+
40
+ ```bash
41
+ pipx install action-platform
42
+
43
+ action-platform init web python fastapi --name "orders" --cloud aws/lambda
44
+ ```
45
+
46
+ Thirty seconds later you have a FastAPI service with tests, lint, CI wired, a SAM template, a least-privilege IAM policy, and a GitHub repo already pushed (`--no-push` to keep it local).
47
+
48
+ ## Why teams pick it
49
+
50
+ | | |
51
+ |---|---|
52
+ | **One command, whole lifecycle** | `init` → `release` → `deploy` → `rollback` → `diagnose` → `destroy`. Same verbs for a Python API on Lambda, a Go service in Docker, a React app on Amplify. |
53
+ | **Templates from production, not tutorials** | Every project template is extracted from a real shipping product. Real layout, real CI, real gotchas already fixed. |
54
+ | **Cloud is a layer, not a fork** | Projects stay cloud-agnostic. `--cloud aws/lambda` overlays deploy files; swap to `docker` tomorrow with one command. |
55
+ | **Your CI, your account, your git** | Runs on GitHub Actions, GitLab CI or Jenkins you already have. Repositories on GitHub, GitLab, Bitbucket or any git server, connected with OAuth. Infra lands in **your** AWS account through OIDC — no long-lived keys, no vendor in the loop. |
56
+ | **Governance that ships with the code** | Git-flow and Conventional Commits enforced by git hooks before a commit exists and by CI on every PR; changelog generated; `AGENTS.md` for humans and AI agents; Trivy scans; least-privilege IAM in `requirements/`. |
57
+ | **Fix once, everywhere** | CI logic lives in versioned shared repos (`ci-scripts`, `ci-github`, `ci-gitlab`, `ci-jenkins`). Bump `v1`, every project picks it up. |
58
+
59
+ ## What you get
60
+
61
+ ```
62
+ action-platform init --list
63
+ ```
64
+
65
+ | Type | Stacks | Ready with |
66
+ |------|--------|-----------|
67
+ | `web` | python (FastAPI, FastMCP), go (Gin), node (React) | `/ping`, versioned API, tests, lint, CI |
68
+ | `library` | python, go, php, node, java, rust | packaging, version test, publish workflow |
69
+ | `docs` | mkdocs | Material theme, strict build in CI |
70
+ | `plugin` | chrome | Manifest V3, popup, background, tests, store zip |
71
+ | `empty` | — | `platform.toml` + code quality only |
72
+
73
+ | Cloud | Adds |
74
+ |-------|------|
75
+ | `aws/lambda` | SAM template, HTTP API, custom domain, deploy workflow, IAM policy |
76
+ | `aws/amplify` | `amplify.yml`, security headers, start-job workflow, IAM policy |
77
+ | `docker` | Dockerfile per language, compose |
78
+
79
+ | Service | Providers |
80
+ |---------|-----------|
81
+ | `postgres` | docker (local), aws-rds (Terraform/OpenTofu + SSM) |
82
+
83
+ ## Commands
84
+
85
+ ```bash
86
+ action-platform init # interactive: type → stack → template → name → ci
87
+ action-platform init web go gin --ci gitlab # direct
88
+ action-platform init web python --cloud docker # project + deploy overlay
89
+ action-platform init ... --no-push # skip creating the remote repo
90
+ action-platform install [--dry-run] # existing repo: platform.toml, hooks, code quality, CI — never overwrites
91
+
92
+ action-platform cloud set aws/lambda # add or switch the deploy target
93
+ action-platform service add postgres --provider aws-rds
94
+
95
+ action-platform branch feature 42 login # develop (or main) → pull → feature/42-login → push
96
+ action-platform branch hotfix PROJ-7 # from main/master
97
+ action-platform gitflow # audit current branch + commits; --install-hooks
98
+ action-platform pr [--draft] [--dry-run] # PR for the current branch: target from git-flow, body from commits
99
+ action-platform release patch # bump, changelog, tag, GitHub release; off main/master → X.Y.Z-rc.N pre-release
100
+ action-platform deploy --stage prod
101
+ action-platform rollback
102
+ action-platform diagnose
103
+ action-platform destroy
104
+ ```
105
+
106
+ ## Git-flow, enforced
107
+
108
+ Every project follows the same flow. Git hooks refuse the wrong move before it exists; CI refuses it on the pull request; the CLI and the MCP tools guide the right one.
109
+
110
+ ```mermaid
111
+ gitGraph
112
+ commit id: "chore: bootstrap"
113
+ branch develop
114
+ checkout develop
115
+ commit id: "chore(release): 0.3.2-rc.1" tag: "v0.3.2-rc.1"
116
+ branch feature/42-login
117
+ checkout feature/42-login
118
+ commit id: "feat(login): form"
119
+ commit id: "test(login): cover form"
120
+ checkout develop
121
+ merge feature/42-login id: "PR #1 → develop"
122
+ branch release/0.3.2
123
+ checkout release/0.3.2
124
+ commit id: "chore(release): 0.3.2-rc.2" tag: "v0.3.2-rc.2"
125
+ checkout main
126
+ merge release/0.3.2 id: "PR #2 → main"
127
+ commit id: "chore(release): 0.3.2" tag: "v0.3.2"
128
+ checkout develop
129
+ merge main id: "back-merge"
130
+ checkout main
131
+ branch hotfix/PROJ-7
132
+ checkout hotfix/PROJ-7
133
+ commit id: "fix(auth): expiry"
134
+ checkout main
135
+ merge hotfix/PROJ-7 id: "PR #3 → main"
136
+ commit id: "chore(release): 0.3.3" tag: "v0.3.3"
137
+ checkout develop
138
+ merge main id: "back-merge hotfix"
139
+ ```
140
+
141
+ | Branch | Starts from | Merges into | Release |
142
+ |--------|-------------|-------------|---------|
143
+ | `feature/<code>`, `bugfix/…`, `chore/…`, `docs/…`, `refactor/…`, `test/…`, `ci/…`, `perf/…` | `develop` (or the default branch when there is no `develop`) | `develop` | `X.Y.Z-rc.N` pre-release |
144
+ | `release/<version>` | `develop` | `main` and `develop` | `X.Y.Z-rc.N` until merged |
145
+ | `hotfix/<code>` | `main` | `main` and `develop` | `X.Y.Z-rc.N` until merged |
146
+ | `main` / `master` | — | — | stable `X.Y.Z` → PyPI / npm / … |
147
+
148
+ Rules the hooks and CI apply: branch names are `<kind>/<code>[-slug]`; commits are [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/); no direct commits on `main`, `master` or `develop` except `chore(release):`, `chore(platform):` and the bootstrap commit; a pull request may only target what the table allows.
149
+
150
+ ```bash
151
+ action-platform branch feature 42 login # develop → pull → feature/42-login → push
152
+ action-platform gitflow # audit branch + commits
153
+ action-platform pr # target and body from the rules and the commits
154
+ action-platform release patch # rc off main, stable on main
155
+ ```
156
+
157
+ Everything a project needs is declared in one file:
158
+
159
+ ```toml
160
+ [project]
161
+ name = "orders"
162
+ type = "web"
163
+ stack = "python"
164
+ template = "fastapi"
165
+ ci = "github"
166
+ language = "python"
167
+
168
+ [source_host]
169
+ kind = "github"
170
+ repo = "acme/orders"
171
+
172
+ [deploy]
173
+ target = "aws/lambda"
174
+
175
+ [services]
176
+ postgres = "aws-rds"
177
+ ```
178
+
179
+ ## Use it from an AI client
180
+
181
+ The platform ships as an MCP server. Claude Code, Codex, Cursor — anything that speaks MCP — gets 17 tools (`list_matrix`, `init_project`, `install_platform`, `start_branch`, `gitflow_audit`, `propose_pull_request`, `release`, `deploy`, `diagnose`, …), 6 prompts that put them in the right order (`new_service`, `ship_feature`, `cut_release`, `deploy_project`, `adopt_repository`, `fix_gitflow`) and 12 skills that make the agent preview and ask before anything leaves the machine.
182
+
183
+ ```bash
184
+ pip install "action-platform[mcp]"
185
+ action-platform mcp # stdio
186
+ action-platform mcp --http # http://127.0.0.1:8765/mcp
187
+ ```
188
+
189
+ Claude Code:
190
+
191
+ ```bash
192
+ /plugin marketplace add actionplatform/action-platform
193
+ /plugin install action-platform@action-platform
194
+ ```
195
+
196
+ Any client — add to `.mcp.json`:
197
+
198
+ ```json
199
+ { "mcpServers": { "action-platform": { "command": "uvx", "args": ["--from", "action-platform[mcp]", "action-platform-mcp"] } } }
200
+ ```
201
+
202
+ ## The web app
203
+
204
+ [`apps/web`](apps/web) — Next.js on top of the Python API. **Organization › Project › App**: an organization is the tenant and owns its code hosts; a project groups the apps that ship together; an app is one git repository the platform clones, audits, releases and deploys.
205
+
206
+ - **Setup wizard** on first run: database (SQLite, PostgreSQL or MySQL), first account, first organization, code hosts.
207
+ - **Connect with GitHub / GitLab / Bitbucket** through OAuth (or paste a token). Tokens are encrypted at rest and refreshed when they expire.
208
+ - **Create project** wizard: type → stack → template → configure → review, with the equivalent `action-platform init` shown. Or add an existing repository by URL.
209
+ - Per app: git-flow audit, commits, branches, tags, release preview → confirm → publish, deploy preflight → confirm → ship.
210
+ - Strictly monochrome UI; every confirmation is an in-app dialog.
211
+
212
+ Local development:
213
+
214
+ ```bash
215
+ pip install "action-platform[api]"
216
+ action-platform api --reload # http://127.0.0.1:7788, OpenAPI at /docs
217
+ cd apps/web && npm install && npm run dev # http://localhost:3000 → /setup
218
+ ```
219
+
220
+ Drive a hosted platform from anywhere:
221
+
222
+ ```bash
223
+ action-platform login https://platform.example.com # browser opens, approve the code
224
+ action-platform mcp --remote # the MCP tools now act on that platform
225
+ ```
226
+
227
+ The TypeScript client is generated from the API's OpenAPI schema (`npm run api:types`): the Python response models in `action_platform/api/models.py` are the contract both sides compile against.
228
+
229
+ ## Releases: three artifacts, three versions
230
+
231
+ One repository, independent versions — declared in `platform.toml`:
232
+
233
+ ```toml
234
+ [components.web]
235
+ path = "apps/web"
236
+
237
+ [components.api]
238
+ path = "action_platform/api"
239
+ ```
240
+
241
+ | Command | Tag | Publishes |
242
+ |---|---|---|
243
+ | `action-platform release minor` | `v0.3.0` | `action-platform` on PyPI (library + CLI) |
244
+ | `action-platform release -c api patch` | `api/v0.1.1` | `actionplatform/action-platform-api` image |
245
+ | `action-platform release -c web minor` | `web/v0.2.0` | `actionplatform/action-platform-web` image |
246
+
247
+ Each component keeps its own `LAST_VERSION` and `CHANGELOG.md` under its path; its changelog lists only the commits that touched it, and the root's excludes them. Off `master` every release is an `-rc.N` pre-release. Images go to Docker Hub and are mirrored to GHCR.
248
+
249
+ ## Layout
250
+
251
+ ```
252
+ action_platform/
253
+ core/
254
+ manifest/ platform.toml: read, edit tables
255
+ scaffold/ templates matrix, generate, install into an existing repo
256
+ flow/ git, git-flow rules, branching, pull requests
257
+ release/ versioning, changelog, release, deploy
258
+ config.py · context.py · exception.py · action_platform.py (facade)
259
+ providers/
260
+ source/ github, gitlab, bitbucket, generic — repositories, releases, PRs
261
+ api/ FastAPI for the web app: apps registry, actions, per-request credentials
262
+ remote/ client + device-flow login for a hosted platform
263
+ mcp/ MCP server: local tools, or remote tools after login
264
+ cli/ Typer commands
265
+ apps/web/ the web app (see its README)
266
+ deploy/ Dockerfiles, docker-compose, install.sh
267
+ ```
268
+
269
+ ## Extend it
270
+
271
+ Deploy targets are plugins. Implement the `DeployTarget` contract — `preflight`, `create`, `deploy`, `switch_traffic`, `rollback`, `diagnose`, `delete` — publish it under the `action_platform.deploy_target` entry-point group, and `action-platform deploy` finds it by name.
272
+
273
+ ```python
274
+ from action_platform import ActionPlatform, Config
275
+ from action_platform.providers.source.github import SourceGithub
276
+
277
+ tool = ActionPlatform(config=Config(source_host=SourceGithub(repo="acme/orders")))
278
+ tool.release("minor")
279
+ ```
280
+
281
+ Templates are plain cookiecutters in [actionplatform/templates](https://github.com/actionplatform/templates). Add a stack or a cloud with a pull request — the CLI reads `index.toml`, nothing to redeploy. Point `ACTION_PLATFORM_TEMPLATES` at a local checkout while you work on them.
282
+
283
+ ## Ecosystem
284
+
285
+ | Repo | Role |
286
+ |------|------|
287
+ | [templates](https://github.com/actionplatform/templates) | projects, clouds, services |
288
+ | [ci-scripts](https://github.com/actionplatform/ci-scripts) | the one implementation of setup / check / release / commit lint |
289
+ | [ci-github](https://github.com/actionplatform/ci-github) · [ci-gitlab](https://github.com/actionplatform/ci-gitlab) · [ci-jenkins](https://github.com/actionplatform/ci-jenkins) | thin wrappers per CI |
290
+
291
+ ## License
292
+
293
+ Apache 2.0.
@@ -1,7 +1,7 @@
1
1
  """Action Platform __init__ module."""
2
2
 
3
- __version__ = "0.1.0"
4
- __description__ = "🛠️ Action Platform padroniza init, release e deploy."
3
+ __version__ = "0.3.0"
4
+ __description__ = "Your platform team, as a CLI."
5
5
 
6
6
  from .core.config import Config
7
7
  from .core.context import Context
@@ -0,0 +1 @@
1
+ """Local web UI: a JSON API over the core modules plus the bundled SPA."""
@@ -0,0 +1,87 @@
1
+ """Source-host credentials handed to the API per request by the web app.
2
+
3
+ Nothing is stored here: the web app keeps them (encrypted, per
4
+ organization) and sends them with the calls that need them — push,
5
+ release, pull request. While such a call runs, git authenticates with the
6
+ same token through a credential helper injected via the environment.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ from contextlib import contextmanager
13
+ from typing import Iterator, Optional
14
+
15
+ from pydantic import BaseModel
16
+
17
+ from action_platform.core.config import Config
18
+ from action_platform.providers.source import build_source_host
19
+
20
+ GIT_USERNAMES = {
21
+ "github": "x-access-token",
22
+ "gitlab": "oauth2",
23
+ "bitbucket": "x-token-auth",
24
+ }
25
+
26
+
27
+ class SourceCredentials(BaseModel):
28
+ kind: str
29
+ token: str
30
+ username: Optional[str] = None
31
+ base_url: Optional[str] = None
32
+ owner: Optional[str] = None
33
+
34
+
35
+ def apply(config: Config, creds: Optional[SourceCredentials]) -> Config:
36
+ """Rebuild config.source_host with the request's token instead of the environment's."""
37
+ if creds is None or config.source_host is None:
38
+ return config
39
+
40
+ config.source_host = build_source_host(
41
+ creds.kind,
42
+ config.source_host.repo,
43
+ base_url=creds.base_url,
44
+ token=creds.token,
45
+ username=creds.username,
46
+ )
47
+
48
+ return config
49
+
50
+
51
+ @contextmanager
52
+ def git_auth(creds: Optional[SourceCredentials]) -> Iterator[None]:
53
+ """Make every git subprocess in this block authenticate with `creds`.
54
+
55
+ Uses GIT_CONFIG_{COUNT,KEY,VALUE} (git ≥ 2.31) to replace the credential
56
+ helpers with one that answers from two environment variables, so the
57
+ token never lands in .git/config or on a command line — and the host's
58
+ own helpers (keychain, gh) never answer for the wrong account.
59
+ """
60
+ if creds is None:
61
+ yield
62
+ return
63
+
64
+ username = creds.username or GIT_USERNAMES.get(creds.kind, "git")
65
+ helper = '!f() { printf \'username=%s\\npassword=%s\\n\' "$AP_GIT_USER" "$AP_GIT_TOKEN"; }; f'
66
+ keys = {
67
+ "GIT_TERMINAL_PROMPT": "0",
68
+ "AP_GIT_USER": username,
69
+ "AP_GIT_TOKEN": creds.token,
70
+ "GIT_CONFIG_COUNT": "2",
71
+ # an empty value clears the helpers configured so far
72
+ "GIT_CONFIG_KEY_0": "credential.helper",
73
+ "GIT_CONFIG_VALUE_0": "",
74
+ "GIT_CONFIG_KEY_1": "credential.helper",
75
+ "GIT_CONFIG_VALUE_1": helper,
76
+ }
77
+ saved = {k: os.environ.get(k) for k in keys}
78
+ os.environ.update(keys)
79
+
80
+ try:
81
+ yield
82
+ finally:
83
+ for k, v in saved.items():
84
+ if v is None:
85
+ os.environ.pop(k, None)
86
+ else:
87
+ os.environ[k] = v