Skip to main content

artifact-deploy

One-click deploy a user's pre-built app/artifact into their OWN AWS account and get a global public HTTPS link (Vercel-like), with a default TTL and promote-to-persistent. Use when the user says "deploy this", "ship this demo", "give me a public link", "share this externally", or "deploy to AWS".

소스 정보

저장소
kirodotdev/KiroCrew
최근 소스 활동
2026년 10월 7일 21:25
감지된 SKILL.md 언어
영어
스타
4,452
포크
820

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
21 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
artifact-deploy
description
One-click deploy a user's pre-built app/artifact into their OWN AWS account and get a global public HTTPS link (Vercel-like), with a default TTL and promote-to-persistent. Use when the user says "deploy this", "ship this demo", "give me a public link", "share this externally", or "deploy to AWS".
triggers
deploy, ship, publish demo, public link, deploy to aws, share externally, one-click deploy, vercel
# Kiro Crew One-Click Deploy (MVP) > **Shipped by Kiro Crew core** (`src/kiro_crew/deploy/`), not by an installable > app. Gateway startup copies this skill into `~/.kiro/crew/skills/artifact-deploy/`. > The `/deploy` console owns AWS profile setup, verification, pending confirmations, > and the fleet/cost view; this skill prepares and previews deployments. ## AWS config -- resolve the profile from the core registry, don't ask The Artifact Deploy core module owns the AWS configuration as a **multi-profile registry** at `~/.kiro/crew/deploy/profiles.json` (`{"profiles": [{"name", "region", ...}], "default": "<name>"}`). Resolve the deploy profile in this order, **before asking the user anything**: 1. **User picked one**: if the deploy request names a profile (the artifact card's dropdown injects `Use the AWS profile "<name>".`), use that entry's `name`/`region` from the registry. If the name is not in the registry, stop and send the user to the `/deploy` console to register it -- never deploy with an unregistered profile name. 2. **Registry default**: otherwise use the entry named by `default`. 3. **Legacy fallback**: if the core registry doesn't exist, read the old `~/.kiro/crew/apps/deploy-web/data/profiles.json`, then its sibling `config.json` (`{"profile", "region"}`). 4. **Unconfigured** (no registry, no legacy profile): do NOT walk the user through manual profile setup in chat -- link them to the `/deploy` console (Artifacts -> Artifact Deploy), which has the Profiles control plane (register / create + Verify access + IAM policy generator). Resume once a profile exists. After a successful deploy, back-fill `webapp_metadata.deploy_target.profile` with the profile NAME actually used, so the fleet table and the artifact's control card show which identity owns the deployment. This replaces the old "pick the AWS profile" step: profiles are managed once in the console, then every deploy (static publish or fullstack webapp) reuses them. Reachability is confirmed by the human with **Verify access** on `/deploy` (`POST /api/deploy/verify`, an STS read). That route refuses MCP/internal callers, so an agent cannot call it; the `deploy_artifact` preview reports the resolved profile and region instead. Deploy a **pre-built** static site (and later, an app with a backend) into the **user's own AWS account**, served globally over HTTPS via CloudFront. ## Where this fits — app artifacts come first An **app-style artifact** (`kind="webapp"`) is generated **first**, as the primary object: every generated app is saved as an artifact up front (initially *not deployed*). **Deploy is an optional downstream action on that existing artifact**, offered two ways — a **skill** (in-conversation) and a **Deploy button** on the artifact card. This skill *is* that deploy action; it does NOT create the artifact. Deploying **fills in** the artifact's `webapp_metadata` (deploy target, architecture, cost, TTL, teardown) and flips the card from its not-deployed state (Deploy button) to the deployed control card. **Producer — register at generation time.** When you generate a deployable app, create the artifact immediately (before any deploy) via `artifact_save(name, content=<one-line human summary>, kind="webapp", webapp_metadata=…)`. For a not-yet-deployed app: fill `architecture` (intended tiers) + `cost` (projected from the model), set `lifecycle.status="draft"`, and leave `deploy_target.public_url` empty — the card then shows the Deploy button. Filling `cost.estimates` is REQUIRED (empty estimates render a blank cost area on the card; `artifact_save` warns when you skip it). For the unit prices, GET `/api/deploy/pricing?profile=<name>` on the gateway — it returns live AWS Pricing API rates for the profile's region (`source: "live"`) or the fallback table when the API is unreachable; multiply into per-bucket what-if totals (e.g. 1,000 / 100,000 / 1,000,000 views). (The MCP `artifact_save` tool accepts `kind="webapp"` + `webapp_metadata`.) Deploy — via this skill or the card's Deploy button — fills in the rest. ## Model — two static deployment paths - **Operator-script app path — cheap AND instant:** one shared base stack per account (`kirocrew-deploy-base`): a private S3 bucket + a global CloudFront distribution. Created once (~5-15 min for the first CloudFront propagation — the only slow step on this path). Each deploy is just an S3 upload under a `/<slug>/` prefix + a CloudFront invalidation → **seconds**. No per-deploy stack, no per-deploy cold-create. Backend scripts attach `/<slug>/api/*` to that same distribution. - **Artifact publish / MCP preview path:** `POST /api/deploy/deploy` uses the core Python engine and creates per-site `kirocrew-web-*` S3 + CloudFront + OAC infrastructure. It does not wrap `scripts/deploy.sh` and must not be mixed with `deploy-backend.sh`, which targets the shared stack. - Cost lives in the **user's** account and is scale-to-zero (S3 storage + CloudFront requests). Idle ≈ $0. AWS earns the consumption; Kiro Crew pays nothing. ## Invocation — how this skill is summoned (and where isolation comes from) Every deploy runs in its **own isolated, agent-debuggable context** — deploys are long (CloudFront cold-create), fail in ways that need iterative fixing (IAM, boto3 `Decimal`, framework quirks), and are context-heavy. There are two entry points; the isolation source differs: - **The "Deploy" button (Feature Preview).** On a webapp card the button runs the dashboard's own two-call deploy (preview, public-link acknowledgment, confirm) on the artifact's built `app_dir/public/` root — no agent involved. Only when the backend reports `webapp_root_unavailable` (no built static root) does the card offer a labelled fallback that **opens a fresh session pre-loaded with this skill** and a seed prompt. That new session **IS** the isolated context — run the whole adapt→deploy→debug flow **inline** in it. **Do NOT spawn a subagent here** (you are already in a dedicated session; debug errors directly in-session). - **In-conversation ("deploy my app" mid-session).** The user asks inside an existing, busy session. Here you **MUST run the deploy via a `spawn_run` subagent** — the subagent is the isolation boundary, so the long/noisy deploy and its debugging don't pollute or blow the current session's context. Rule of thumb: **one isolated context per deploy — a fresh session (button) OR a subagent (in-conversation). Never run a deploy inline in a busy existing session.** > The button is a *launcher*, not an executor: it does not run the deploy itself > (a button can't debug a failed CloudFormation/IAM step) — it summons a > skill-loaded session where the agent can. That is why deploy is a skill, not a > button-triggered script. ## The deploy contract (target shape) The deploy scripts consume ONE fixed layout. The skill's real job is to get the user's app **into** this shape (see Adapter playbook), then ship it: ``` <app>/public/ static SPA — index.html at root → S3 + CloudFront <app>/api/ an HTTP backend → API Gateway → Lambda at /<slug>/api/* (index.py handler, OR any HTTP server wrapped in a Lambda shim — see playbook; pick language via --runtime) state DynamoDB single table (--table), read via os.environ["TABLE_NAME"] ``` Static-only apps need just `public/`. No auth in MVP (content is public). ## Adapter playbook — wrap, don't rewrite A user's app almost never arrives in the contract shape. Conform it — but **prefer wrapping the app's existing HTTP server in a Lambda adapter over hand-rewriting its routes** (hand-rewriting is usually a language port + a data-model rewrite = fragile). Wrapping keeps the user's code and adds a thin shim: - **ASGI (FastAPI / Django / Starlette)** → **Mangum** adapter, `--runtime python*`. - **Express / Node / Next.js standalone** → **serverless-http** or **AWS Lambda Web Adapter**, `--runtime nodejs*`. - **Static SPA** → point the build output at `public/`. - Don't force Python — `deploy-backend.sh --runtime` already supports the app's own language. This broadens "our format" from *one Python handler* to **static assets + any HTTP server + DynamoDB**, so the adapter mostly *places dirs + adds a shim*, not *rewrites business logic*. ### Tiers — what adapts, and where to fail loud - **Tier 1 — mechanical (reliable):** static SPA + a simple JSON API. Place dirs, align the handler entry, done. - **Tier 2 — wrap (agent-doable, must test):** a framework backend in a supported runtime + stateless or KV-mappable state → wrap in a shim + DynamoDB. Deploy, then exercise the real endpoints (incl. the base64 body path) before handoff. - **Tier 3 — needs redesign (fail loud, don't fake it):** SSR needing a live server beyond a single Lambda, websockets, background workers/cron, or a **relational schema with joins/transactions**. **Detect these and tell the user they're unsupported / need a redesign — never silently ship a broken deploy.** ### Database strategy (a real boundary, not laziness) - Stateless or KV-mappable → **DynamoDB** (`--table`, `TABLE_NAME`). - **SQL / relational → out of tier.** The "$0-idle, cents-per-demo" cost story depends on scale-to-zero DynamoDB. SQL means RDS/Aurora → floor cost + VPC + not scale-to-zero, which breaks the cheap/ephemeral promise. So map state to DynamoDB, or tell the user this app doesn't fit the cheap-ephemeral tier (offer a redesign). Do **not** silently mangle a relational schema into KV. ## Prerequisites - **POSIX platform (Linux / macOS)** — deploy scripts require `bash`. Windows is not supported; use WSL (Windows Subsystem for Linux) to run the Kiro Crew gateway if your host OS is Windows. The backend returns HTTP 400 with a clear message on unsupported platforms. - AWS access configured **once in the Artifact Deploy console** (profiles registered in `~/.kiro/crew/deploy/profiles.json`, verified at `/deploy`). Prefer a **least-privilege deploy profile**, not admin (see Security). - **Finite TTL needs auto-cleanup in the account.** A confirmed deploy with `ttl_hours > 0` (the default is 72) is refused with `reaper_required` unless the `kirocrew-deploy-base` and `kirocrew-deploy-reaper` stacks exist; the preview does not check this. The operator installs them with `scripts/install-reaper.sh` (which needs the base stack and the `kirocrew-deploy-app-boundary` policy from `/deploy`). Otherwise preview with `ttl_hours=0` (persistent) and say so. - The app is conformed to the **deploy contract** (above) — producing that layout is the skill's job (Greenfield: generate in-contract; Brownfield: run the Adapter playbook). The deploy *scripts* consume a built `public/` (+ optional `api/`); they don't build or adapt for you, so the agent produces that layout first. Static apps need an `index.html` at the static root. ## Commands (operator-terminal reference) These are run from this skill's directory by **human operators in a terminal**, not by agents. They implement the separate shared-stack app path; the core `POST /api/deploy/deploy` endpoint does not wrap them. The shell scripts accept `--profile` and `--region` (default `us-west-2`). `attach_backend.py` / `detach_backend.py` refuse to run unless `kiro_crew` is importable, and `deploy-backend.sh`, `teardown.sh` and `reaper.sh` call them with the first `python3` on `PATH`, so run these scripts with the Kiro Crew environment's Python first on `PATH`. - **Deploy (static)**: `scripts/deploy.sh <app_dir> [--slug NAME] [--ttl HOURS] [--profile P] [--region R]` - **Deploy (fullstack)**: `scripts/deploy-app.sh <app_dir> --slug NAME [--table] [--runtime R] [--handler H] [--wait] [--profile P] [--region R]` - **Deploy (backend only)**: `scripts/deploy-backend.sh <handler_dir> --slug NAME [--table] [--runtime R] [--handler H] [--wait] [--profile P] [--region R]` - **Install reaper**: `scripts/install-reaper.sh [--rate 'rate(1 hour)'] [--alarm-email EMAIL] [--profile P] [--region R]` - **Teardown**: `scripts/teardown.sh <slug> [--profile P] [--region R]` - **Lifecycle**: `scripts/list.sh`, `scripts/cost.sh [slug]`, `scripts/persist.sh <slug>`, `scripts/detach_backend.py --region R --dist-id ID --slug NAME [--profile P]` ## Backend handler contract Copy `templates/handler-example.py` as your app's `api/index.py` starting point. Behind an API Gateway HTTP API (payload v2): - Route on the path after `/api/`: `event["rawPath"].split("/api/",1)[1]`. - **Decode the body via `isBase64Encoded`** — API Gateway base64-encodes the request body when Content-Type isn't a known text type (or is absent, e.g. `curl -d` without `-H application/json`). Calling `json.loads(event["body"])` directly will 500 for those callers. `base64.b64decode` first when `event.get("isBase64Encoded")`. (Browsers sending `application/json` are unaffected — a browser-only test won't catch this.) - Return `{"statusCode", "headers", "body": json.dumps(...)}`. - Stateful apps: table name in `os.environ["TABLE_NAME"]` (deploy with `--table`). ## Agent workflow — preview through the audited MCP tool First honor **Invocation** (above): summoned mid-session → run the steps below inside a `spawn_run` subagent; launched in a fresh Deploy-button session → run them inline. When the user asks to deploy / ship / share a demo: 0. **Conform the app to the contract** (Adapter playbook) — greenfield: generate in-contract; brownfield: wrap the existing server in a Lambda shim. Fail loud on Tier-3 apps rather than shipping something broken. 1. Confirm the resulting app dir has `public/` (an `index.html` at its static root) and, if there's a backend, `api/`. 2. Resolve the AWS profile from the **core registry** (see "AWS config" above): user-picked > registry default > legacy config; if unconfigured, send the user to the Artifact Deploy page (`/deploy`) for the one-time setup. Then **confirm which account** (ask the user to check the account that **Verify access** on `/deploy` shows; the preview reports profile/region) -- this provisions REAL resources that cost money. Never guess a prod account; if unsure, ask. 3. **Scan the app for internal tokens** first (see Security) — this content is going to the public internet. Credential findings are a hard stop. 4. Choose one coherent deployment path: - **Static artifact or static-only app:** call the MCP `deploy_artifact` tool once. Use `artifact_slug` for `widget`, `html`, or `markdown`, and for a `webapp` artifact whose `webapp_metadata.app_dir` holds the built `public/` root (the server resolves `app_dir/public` and writes the deployment back into the artifact on confirm). Use `local_dir` only for a directory that is not an artifact's `app_dir`. - **App with `api/`:** prepare the complete layout, then give the human operator the exact `scripts/deploy-app.sh <app_dir> --slug <slug> ...` command. That script deploys the static and backend pieces behind the same shared distribution. Do not preview only `public/` and then claim that `deploy-backend.sh` will attach to that per-site distribution. 5. `deploy_artifact` is **preview-only**. It never accepts `confirm` or `override_scan`; it stores a pending entry and returns instructions for the human to confirm on the Artifact Deploy page. Relay that the link is public with no authentication. A human may override only non-credential findings in the dashboard; credential findings cannot be overridden. The API path behind the tool provides: schema validation, fail-closed scan gate, confirm gate, SEL audit trail, and `_deny_restricted` session guard. **Do NOT bypass it by calling deploy scripts directly.** 6. Stop after the preview: tell the user to confirm under **Pending confirmations** on `/deploy`. This session is not notified when they do, so never report a public URL you have not seen. For an `artifact_slug` deploy
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기