English
Sources of truth (code)
- Placement and enqueue: prego-control-plane
tenants.ts(free-tenant API), webhooks-stripe.ts (paid checkout). - Message shape: buildProvisionQueueMessage, type ProvisionQueueMessage.
- Workflow: Prego
.github/workflows/provision-tenant.yml.
D1 provision_jobs ↔ placement
| Column | Values | Meaning |
|---|---|---|
infra_mode | create_new_server | use_existing | Mirrors placement.create_new_server. |
dedicated | 1 or NULL | 1 when placement.dedicated is true (dedicated stack: three-server model per product docs). |
region | sg | us | eu | From decidePlacement. |
trace_id | trace_* | Funnel and POST /internal/trace-events correlation. |
ProvisionQueueMessage (queue or workflow_dispatch body inputs)
| Field | Type in TS | Source |
|---|---|---|
job_id | string | provision_jobs.job_id |
tenant_id | string | Tenant canonical id |
region | string | placement.region |
create_new_server | string | String(placement.create_new_server) → "true" or "false" |
target_server_id | string | placement.target_server_id ?? '' |
subdomain_slug | string | Request / checkout metadata |
canonical_hostname | string | Derived tenant hostname |
dedicated | string (optional) | placement.dedicated ? 'true' : 'false' |
trace_id | string (optional) | Same as job |
Note: GitHub’s workflow_dispatch API expects inputs to match workflow input types. If your dispatcher sends JSON strings for booleans, ensure the workflow still evaluates correctly (boolean create_new_server, string dedicated compared with "true" in YAML).
GitHub Actions provision-tenant.yml inputs (subset)
| Workflow input | Typical source | Pulumi / resolve behavior |
|---|---|---|
job_id | job_id | Trace and callbacks |
tenant_id | tenant_id | DNS, dedicated stack name |
region | region | Shared stack name when not dedicated |
target_server_id | target_server_id | If set: GET /internal/nodes/:node_id for host |
create_new_server | create_new_server | If true and no target: run pulumi up in cloned prego-pulumi |
subdomain_slug, canonical_hostname | Same | Cloudflare tenant DNS job |
dedicated | dedicated | If string true: Pulumi stack dedicated-{sanitized_tenant_id}; else stack {region} |
trace_id | trace_id | POST /internal/trace-events |
Pulumi stack selection (from workflow)
- Dedicated:
stack = dedicated-${safe_id}wheresafe_idis derived fromtenant_id(alphanumeric/hyphen, truncated). - Shared:
stack = region(e.g.sg). - Secrets: workflow uses
HCLOUD_TOKEN_SGandPULUMI_ACCESS_TOKENin thePulumi upstep (adjust per org if you add per-region tokens).
Post-Pulumi: node registration
When create_new_server is true and Pulumi succeeds, the workflow posts POST /internal/nodes with a generated node_id (see workflow Register new node step). Align naming with Hetzner node ID mapping so metrics agents use the same node_id.
Internal placement compute (read-only)
To preview the same PlacementResult as production without enqueueing a job or calling Zuplo, use POST /internal/placement/compute on the Control Plane Worker (Bearer). See Internal placement API.
Related
- Internal placement API (no Zuplo)
- Definition of done — monitoring & provisioning
- Tenant provisioning flow (planning)
한국어
요약
- Control Plane의
decidePlacement결과가provision_jobs와 ProvisionQueueMessage로 옮겨지고, GitHub Actionsprovision-tenant워크플로 입력으로 전달됩니다. - 신규 서버가 필요하면 워크플로에서 prego-pulumi 저장소를 클론한 뒤
pulumi up을 실행하며, dedicated 여부에 따라 스택 이름이 갈립니다 (dedicated-*vs 리전명). - 생성 후
POST /internal/nodes로 노드가 등록되므로, 메트릭 푸시에 쓰는node_id와 운영 매핑표를 일치시켜야 합니다.
관련 문서: 내부 Placement API, 완료 정의(DoD), 테넌트 프로비저닝 플로