fabrica

command module
v0.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 2 Imported by: 0

README

Fabrica

CI npm golangci-lint Go

Game studio infrastructure as code for AWS — one binary and one YAML file to provision Perforce (or Lore), Unreal Horde, Distributed DDC, CI, GameLift deploy, and cloud workstations.

Fabrica is the sister tool to Ludus: Ludus orchestrates builds; Fabrica gives them somewhere to run. Single Go binary, no Terraform/Pulumi, no external CLIs — AWS Cloud Control API under the hood, cost estimates before you write, DynamoDB-locked state so two engineers don't clobber each other.

Why Fabrica

Game studios aren't web apps. You need version control for terabyte asset histories, a build farm for distributed cooks, a DDC that keeps iteration fast, and a reliable way to stand all of it up without stitching Terraform modules, bash scripts, and console clicks. Fabrica owns the full lifecycle — provision, status, tear down — with typed-phrase confirmations and recoverable partial state.

Current Status

Current stable: v0.3.2. Phase 0, Phase 1, Lore (v0.2), and DDC (V1 + multi-region edge nodes) are complete: Perforce, Horde, Lore, Distributed DDC (home + edge regions), Workstation, CI, Deploy, Cost, drift detection with auto-remediation (--fix), MCP server, IaC export, full-stack destroy --all, offline cost visibility, and a CLI E2E suite. Install via npm install -g fabrica-cli or GitHub Releases. See ROADMAP.md for status and what's next.

Operational diagnostics are available on stderr via --verbose or FABRICA_LOG_LEVEL=debug — normal stdout output (including --json) is not affected.

Module Commands Status
setup / doctor / status / drift / config show Foundation Complete
perforce create, status, destroy, backup, restore Complete
horde create, status, submit, destroy, ami build Complete
lore create, status, destroy Complete
ddc setup, status, destroy, region add Complete (V1, home + edge regions)
workstation create, list, stop, start, terminate Complete
ci setup, trigger, status, logs, destroy Complete
deploy setup, promote, rollback, status, destroy Complete
cost report, forecast, alerts Complete
export --format cloudformation|terraform Complete (V2)
destroy --all full-stack teardown Complete

Requirements

  • Go 1.25.12+
  • AWS credentials with permissions to create EC2 instances, security groups, S3 buckets, and DynamoDB tables
  • IAM permission for sts:GetCallerIdentity

Install

Fabrica ships as a single Go binary. Two ways to get it:

# Via npm (downloads the matching prebuilt binary for your platform):
npm install -g fabrica-cli
# …or run without installing:
npx fabrica-cli --help

# Or via the Go toolchain:
go install github.com/jpvelasco/fabrica@latest

Prebuilt binaries for linux/macOS/windows (amd64) and linux/macOS (arm64) are attached to each GitHub Release.

Building

git clone https://github.com/jpvelasco/fabrica.git
cd fabrica
go build -o fabrica .

Getting Started

Recommended first path: foundation → DDC → Horde → deploy (plus VCS when you need a depot). Every create/setup command is idempotent, shows a plan + cost estimate, and prompts before writing AWS (--yes skips; --dry-run previews).

1. Foundation (once per account)
go build -o fabrica .
cp fabrica.example.yaml fabrica.yaml   # set aws.region (accountId is optional)

fabrica setup --dry-run                # plan + ~$0.15/mo state backend estimate
fabrica setup                          # S3 state bucket + DynamoDB lock table
fabrica doctor                         # credentials, region, bucket, lock table
fabrica status                         # aggregate health (empty modules is fine)
2. Source of truth (pick one or both)
# Perforce Helix Core (terabyte asset history)
fabrica perforce create
fabrica perforce status                # TCP probe on 1666 → provisioning → ready

# Or Epic Lore (parallel alternative — see docs/lore-ami.md)
fabrica lore create && fabrica lore status -w
3. Distributed DDC (keep cooks fast)
# AMI-first Unreal Cloud DDC (Jupiter) — see docs/ddc-ami.md
fabrica ddc setup                      # default backend: zen
fabrica ddc status --probe             # GET /health/ready
4. Horde build farm + CI
# Horde coordinator — job-capable Docker compose AMI (see docs/horde-ami.md)
fabrica horde create
fabrica horde status
fabrica ci setup
fabrica ci trigger examples/BuildGraph.sample.xml --wait
# low-level direct submit also works:
fabrica horde submit examples/BuildGraph.sample.xml
5. Deploy to GameLift (blue/green)

Set deploy.buildBucket in fabrica.yaml. CI/Horde packages land at s3://<deploy.buildBucket>/builds/<version>/server.zip.

fabrica deploy setup
fabrica deploy promote v1.0.0          # new fleet → wait ACTIVE → alias flip
fabrica deploy status
fabrica deploy rollback                # instant flip to previous fleet if needed
Optional: workstations & cost
fabrica workstation create --template programmer
fabrica cost report
fabrica status --probe                 # aggregate view (VPN/in-VPC for private IPs)
fabrica destroy --all                  # full-stack teardown when you're done
End-to-end pipeline (compressed)
fabrica setup --yes
fabrica ddc setup                      # optional but recommended for UE teams
fabrica horde create && fabrica ci setup
fabrica ci trigger examples/BuildGraph.sample.xml --wait
fabrica deploy setup && fabrica deploy promote v1.0.0
fabrica deploy status

Commands

Foundation
fabrica doctor

Checks your environment: Go version, AWS credentials, region, S3 state bucket, DynamoDB lock table.

fabrica setup

Creates the state backend for this account: the S3 bucket (versioning, encryption, and public-access block) and the DynamoDB lock table. Idempotent — re-running reconciles configuration and leaves existing resources in place.

  • fabrica setup --dry-run — preview resource names and estimated monthly cost (~$0.15), no changes.
  • fabrica setup — create the backend after a y/N confirmation.
  • fabrica setup --yes — skip the prompt (CI / automation).
fabrica status

Read-only aggregate overview of every provisioned module plus the state backend: a one-line health summary, per-module status with [OK]/[WARN] indicators and resource counts, and context-aware next steps. --json for scripts; --probe adds TCP readiness checks (requires VPN / in-VPC reachability). Use --verbose or FABRICA_LOG_LEVEL=debug to enable operational diagnostics on stderr (normal stdout output is unaffected).

fabrica drift

Drift detection: compares recorded state (.fabrica/state.json) against live AWS resources and reports whether each resource is in sync, missing, extra (live but not in state), or has attribute mismatches. Checks the state backend (S3 bucket, DynamoDB table), EC2 instances (existence, state, instance type, AMI), security groups, IAM roles, and CodeBuild projects. Extra detection uses ResourceClient.List to enumerate live resources and diff against recorded state — CodeBuild projects are excluded since they have no List API. --json for machine-readable output.

By default fabrica drift is read-only. Add --fix to enable auto-remediation: missing managed resources (EC2 instances, security groups) are recreated from recorded state. --fix --dry-run shows the remediation plan without applying changes. Mismatch and Extra resources are report-only and skipped during remediation.

fabrica config show

Displays the current configuration as clean YAML, including resolved resource names.

fabrica mcp

Runs the Fabrica MCP (Model Context Protocol) server over stdio transport. Exposes 6 read-only tools for querying Fabrica state: fabrica_version, fabrica_doctor, fabrica_status, fabrica_drift, fabrica_cost_report, and fabrica_config_show. Reuses the same business logic as the CLI — no duplicated AWS paths. Connect an MCP client (Claude, editors, agents) by running this command as a subprocess.

Perforce
fabrica perforce create

Provisions a Perforce Helix Core server: creates an EC2 security group (port 1666) and launches an EC2 instance. Generates credentials to .fabrica/perforce-credentials.yaml (mode 0600). Writes state incrementally so partial failures are recoverable.

fabrica perforce status

Reads live state from AWS and TCP-probes port 1666. Transitions the module state from provisioningready once the server is reachable. Supports --json output.

fabrica perforce destroy

Terminates the EC2 instance, IAM instance profile/role, and security group in reverse order. Idempotent — already-terminated instances are skipped. The data volume is retained (DeleteOnTermination=false) so local backups survive as an orphan EBS volume; S3 exports are never deleted by destroy.

fabrica perforce backup

Creates a consistent Helix Core backup on the instance EBS volume (under /hxdepots/fabrica-backups by default) via SSM Run Command. Optional S3 export when perforce.backup.s3Export is set. Checkpoint briefly quiesces the server — prefer a quiet window. Requires a ready module and an SSM-managed instance profile (attached at perforce create).

--name           Optional short name appended to the backup id
--description    Stored in backup metadata
--no-s3          Skip S3 export even if configured
fabrica perforce backup list

Lists backups on the server (reads metadata.json over SSM). Supports --json.

fabrica perforce backup delete

Deletes a backup by id from the EBS volume (and S3 when metadata has s3Uri).

fabrica perforce restore

Restores Helix Core from a backup id: stops helix-p4d, restores checkpoint/journal artifacts, restarts. Requires --force when the server is ready (serving clients). Confirmation phrase: restore perforce <account-id>.

Horde

AMI requirement: fabrica horde create is AMI-first. Your AMI must be a Docker-compose-based stack (Ubuntu 22.04 + Docker CE) with MongoDB, Redis, and a job-capable Horde server under /etc/horde/GET /api/v1/jobs must not return 404. Fabrica's cloud-init only runs docker compose up -d and probes port 5000. See docs/horde-ami.md for build instructions and bake-time verification.

fabrica horde create

Provisions an Unreal Horde build coordinator on an m7i.2xlarge instance using your pre-baked AMI. Security group allows ports 5000 (HTTP) and 5002 (gRPC) inbound from the configured horde.allowedCidr (default 10.0.0.0/8). Important: the default 10.0.0.0/8 does not cover AWS default VPCs (172.31.0.0/16). If your CodeBuild project, workstations, or operators live in a different CIDR, set horde.allowedCidr to your VPC CIDR (e.g. 172.31.0.0/16) in fabrica.yaml before creating — or horde create will resolve the VPC CIDR automatically and use it as the default. Do not use 0.0.0.0/0 on ports 5000/5002. Generates MongoDB credentials to .fabrica/horde-credentials.yaml (mode 0600).

fabrica horde status

Reads live state and TCP-probes port 5000. Reports the Horde web UI URL and gRPC endpoint. --json emits hordeUrl and hordeGrpc fields.

fabrica horde submit

Parses a BuildGraph XML file and POSTs the job to the Horde REST API via the coordinator's private IP. The target is resolved from the XML (first <Agent>'s first <Node> name). Use examples/BuildGraph.sample.xml as a starting point. Options:

--wait         Poll until the job completes

Requires VPN or same-VPC access; no public IP is assigned in V1.

fabrica horde destroy

Permanently deletes the Horde coordinator and its AWS resources in reverse-creation order (EC2 instance, then security group). State is updated after each deletion, so a partial failure leaves a recoverable record and re-running skips resources already gone. Typed-phrase confirmation; --yes to skip, --dry-run to preview.

fabrica horde ami build

Generates the files needed to build a Horde AMI. Produces an EC2 Image Builder component (component.yaml) and recipe (image-builder-recipe.json) by default, an optional Packer HCL template (--include-packer), and a build-guide.md with end-to-end instructions. No AWS calls are made — all output is written to a local directory.

Two install methods are supported:

--install docker   (default) Epic's official docker compose stack
--install native   .NET 8 + MongoDB 7 + Redis installed directly from apt

Key flags: --horde-version, --base-image, --region, --output-dir, --include-packer, --dry-run.

fabrica horde agents create

Provisions a pool of Horde build agents on AWS. Creates an Auto Scaling Group with a Launch Template that launches agent instances in private subnets. The agents enroll against the existing Horde coordinator using its private IP address.

AMI requirement: horde.agents.amiId must be a dedicated agent AMI — not the coordinator AMI (horde.amiId). The agent AMI should contain only the Horde agent binary (or container), SSM agent, and Ubuntu 22.04. It must NOT include MongoDB, Redis, or the full Horde server stack. Fabrica fails agents create with a clear error if horde.agents.amiId is not set — it does not silently fall back to the coordinator AMI. See docs/horde-agent-ami.md for the build guide.

Creates five resources: agent security group (no inbound from internet), IAM role (SSM only), instance profile, launch template, and auto scaling group. CLI flags --instance-type, --min-size, --desired-capacity, and --max-size override config defaults. --dry-run shows the plan and cost estimate.

Queue-based autoscaling — add --scaling-enabled to provision two CloudWatch alarms and two SimpleScaling policies (one for scale-out, one for scale-in) that adjust the ASG based on a custom queue-depth metric. Configure thresholds with --scale-out-threshold, --scale-in-threshold, and --scale-in-cooldown. Min/max capacity act as hard bounds. See docs/horde-scaling.md for details.

fabrica horde agents status

Shows agent pool status: ASG capacity (min/desired/max), launch template, instance type, agent AMI, and coordinator endpoint. --json for machine-readable output.

fabrica horde agents destroy

Permanently deletes the agent pool and its AWS resources (ASG, launch template, IAM role/profile, security group) in reverse-creation order. The Horde coordinator is not affected. Typed-phrase confirmation; --yes to skip, --dry-run to preview.

Lore

AMI requirement: fabrica lore create is AMI-first. Your AMI must already contain the loreserver binary (and optional systemd unit). Fabrica only mounts the EBS store, writes local store config, and starts the service. See docs/lore-ami.md. Lore is a parallel VCS option alongside Perforce — both modules can coexist.

fabrica lore create

Provisions an Epic Lore (loreserver) server: security group opens TCP 41337 (gRPC), UDP 41337 (QUIC), and TCP 41339 (HTTP health); EC2 instance uses your pre-baked AMI with a gp3 data volume for local store. Connection notes go to .fabrica/lore-credentials.yaml (mode 0600). V1 uses local/EBS storage, self-signed TLS, and no JWT.

fabrica lore status

Reads live state and probes GET /health_check on port 41339. Transitions provisioningready when healthy. --json emits loreUrl and loreGrpc. Supports --wait / -w.

fabrica lore destroy

Terminates the EC2 instance and deletes the security group in reverse order. Idempotent. Typed-phrase confirmation; --yes to skip, --dry-run to preview.

fabrica lore ami build

Generates the files needed to build a Lore AMI. Produces an EC2 Image Builder component (component.yaml) and recipe (image-builder-recipe.json) by default, an optional Packer HCL template (--include-packer), and a build-guide.md with end-to-end instructions. No AWS calls are made — all output is written to a local directory.

Key flags: --lore-version, --base-image, --region, --output-dir, --include-packer, --dry-run.

DDC

AMI requirement: fabrica ddc setup is AMI-first. Your AMI must already contain Unreal Cloud DDC (Jupiter). Fabrica mounts the hot EBS volume, writes hybrid-storage config, and starts the service. See docs/ddc-ami.md.

Current scope: one home-region EC2 (co-located coordinator + edge roles) plus additional edge regions via ddc region add. Default backend is zen. Scylla is an optional single-node bootstrap path only (not production HA).

fabrica ddc setup

Provisions IAM role + instance profile, S3 blob bucket, security group, optional Scylla bootstrap EC2, and the DDC EC2 instance. Writes .fabrica/ddc-endpoints.yaml. Cost estimate and dry-run supported. Idempotent if already provisioned.

--backend    zen (default) or scylla (1-node bootstrap only — not HA)
fabrica ddc region add REGION

Provisions one additional DDC edge node in REGION (e.g. eu-west-1): a security group (public + internal API ports) and an AMI-first EC2 instance that reuses the home stack's IAM profile and shares the home blob bucket. The AMI must exist in REGION — copy the home AMI first (aws ec2 copy-image --source-region <home> --region REGION --name ddc-edge). Idempotent — re-running with an already-provisioned region exits cleanly. Cost estimate and dry-run supported.

--ami-id           AMI for this region (default: ddc.amiId; must exist in REGION)
--instance-type    EC2 instance type (default: ddc.instanceType or m7i.xlarge)
--volume-size      Hot volume size in GiB (default: ddc.volumeSize or 500)
--vpc-id           VPC in REGION (default: the region's default VPC)
--subnet-id        Subnet in REGION (default: the region's default subnet)
fabrica ddc status

Reads live state and probes GET /health/ready on the public API port. Transitions provisioningready when healthy. Supports --wait / -w and --json. Edge regions are probed live via region-scoped Cloud Control queries and optional health probes; each edge reports ready, unreachable, stopped, terminated, or missing. With --json, edge regions are listed in the edges array with live instance state, probe status, and private IP when available.

fabrica ddc destroy

Deletes edge nodes first (each in its region), then home resources (instances → bucket → IAM → SG). Non-empty S3 buckets are not force-deleted. Typed-phrase confirmation; --yes to skip, --dry-run to preview.

Workstation

AMI requirement: fabrica workstation create is AMI-first. Your AMI must already have NICE DCV installed. Fabrica only configures and starts the DCV session via cloud-init. Port 8443 (NICE DCV HTTPS) is opened inbound; restrict workstation.allowedCidr in fabrica.yaml for production.

fabrica workstation create

Provisions a NICE DCV cloud workstation: creates an EC2 security group (port 8443) and launches an EC2 instance. Generates a DCV session password to .fabrica/workstation-credentials.yaml (mode 0600).

Key flags:

--instance-type    EC2 instance type (default: g4dn.xlarge)
--volume-size      EBS root volume size in GiB (default: 100)
--template         Preset: "artist" (g6.xlarge, 200 GiB) or "programmer" (c7i.xlarge, 100 GiB)
--mount-perforce   Install Perforce CLI and write ~/.p4config from local Fabrica state

When --mount-perforce is set, create reads the Perforce server's private IP from local state (requires fabrica perforce create to have run first) and writes ~/.p4config on the workstation with P4PORT set. The developer still runs p4 sync manually.

fabrica workstation list

Displays provisioned workstation status and resource IDs. Supports --json.

fabrica workstation stop

Stops the EC2 instance to pause compute billing. Data and configuration are preserved. Supports --dry-run, --yes, --json.

fabrica workstation start

Starts a previously stopped workstation. Supports --dry-run, --yes, --json.

fabrica workstation terminate

Permanently terminates the workstation EC2 instance and security group. Deletes resources in reverse-creation order. Idempotent — already-terminated instances are skipped. Supports --dry-run, --yes, --json.

CI

Orchestration over Horde: fabrica ci provisions a CodeBuild project that orchestrates Horde BuildGraph jobs. CodeBuild is the conductor; Horde stays the executor. The IAM service role is created via Cloud Control; the CodeBuild project via the AWS SDK (Cloud Control does not support CodeBuild project creation).

fabrica ci setup

Provisions the CI infrastructure for this account: an IAM service role, a security group, and a CodeBuild project. Idempotent — existing resources are detected and left in place. Shows a plan + monthly cost estimate, then prompts before creating (use --yes to skip, --dry-run to preview).

By default the CodeBuild project is placed inside the account's default VPC (or the VPC/subnet from ci.vpcId/ci.subnetId in fabrica.yaml) so builds can reach a private-IP Horde coordinator. The CodeBuild ENI gets an IP from the VPC's subnet CIDR — ensure horde.allowedCidr includes that CIDR, or builds will be blocked by the Horde security group (common if your VPC is 172.31.0.0/16 but allowedCidr is still the default 10.0.0.0/8). The project's security group is created by Fabrica. If no VPC can be resolved, setup still succeeds but the project runs VPC-less and cannot reach private endpoints.

fabrica ci trigger <buildgraph.xml>

Starts a build run. Parses the BuildGraph XML for the job name and target (first <Agent>'s first <Node> name), resolves the Horde coordinator's address from local state, and starts the CodeBuild project with those values as environment overrides; the build submits the job to Horde. Requires fabrica ci setup and a provisioned, reachable Horde coordinator. Use --wait to poll until the build reaches a terminal state.

If the BuildGraph has no <Agent>/<Node> elements, the command fails fast with an actionable error pointing to examples/BuildGraph.sample.xml.

fabrica ci status

Shows the CI infrastructure (CodeBuild project + IAM role) from local state, with [OK]/[WARN] indicators and a one-line summary. Pass --build <id> to also query live build status; --json for machine-readable output. Read-only.

fabrica ci logs <build-id>

Fetches the CloudWatch log output for a specific build.

fabrica ci destroy

Tears down the CI infrastructure: deletes the CodeBuild project (via the AWS SDK), then the IAM service role (via Cloud Control). A missing project is not an error. Typed-phrase confirmation before any deletion; --yes to skip, --dry-run to preview.

Example pipeline:

# One-time: provision the CI infrastructure
fabrica ci setup

# Trigger a build for a BuildGraph script and watch it run
fabrica ci trigger examples/BuildGraph.sample.xml --wait

# Or fire-and-forget, then check status / logs by build ID
fabrica ci trigger examples/BuildGraph.sample.xml
fabrica ci status --build <build-id>
fabrica ci logs <build-id>
Deploy

Orchestration over GameLift: fabrica deploy rolls CI/Horde-produced server builds out to GameLift managed-EC2 fleets using alias-flip blue/green. Fabrica owns the build-to-deploy path; live runtime fleet operations (scaling, matchmaking, sessions) are outside Fabrica scope. GameLift Build/Fleet/Alias resources are created via Cloud Control; the 20–40 min fleet activation is tracked through an SDK auxiliary interface so you see live phase progress and real failure events.

fabrica deploy setup

Provisions the deploy infrastructure: an IAM role GameLift assumes to read builds from S3, and a GameLift alias used for blue/green promotion. Idempotent — existing resources are detected and left in place. Shows a plan + monthly cost estimate, then prompts before creating (--yes to skip, --dry-run to preview). Requires deploy.buildBucket in fabrica.yaml.

fabrica deploy promote <build-version>

Registers a packaged server build from S3 as a GameLift build, creates a new fleet for it, waits until the fleet is ACTIVE (printing phase transitions), then flips the alias to the new fleet. The previously-active fleet is retained for rollback. By default the build is read from s3://<deploy.buildBucket>/builds/<version>/server.zip (override with --s3-bucket/--s3-key). Use --no-wait to start fleet creation without blocking (skips the alias flip). On fleet ERROR or timeout the alias is left untouched and the failure events are shown.

fabrica deploy rollback

Flips the alias back to the most-recent retained ("superseded") fleet — an instant blue/green rollback with no re-provisioning. Verifies the target fleet is still ACTIVE first, shows current → target, and prompts before flipping (--yes to skip).

fabrica deploy status

Read-only overview: the alias, the active fleet, and any retained rollback candidates, each with live GameLift fleet status ([OK]/[....]/[FAIL] indicators) and a one-line summary. --json for machine-readable output.

fabrica deploy destroy

Tears down deploy resources. By default deletes the fleets and builds but preserves the alias and IAM role (game backends reference the alias, which is meant to outlive individual deployments). Pass --all to remove the alias and role too. Typed-phrase confirmation; --dry-run to preview.

Example pipeline:

# One-time: provision the deploy infrastructure (IAM role + alias)
fabrica deploy setup

# Roll a build out to a new fleet (blue/green: waits for ACTIVE, flips alias)
fabrica deploy promote v1.2.3

# Check what's live and what you could roll back to
fabrica deploy status

# A bad build? Flip back to the previous fleet instantly
fabrica deploy rollback

# Tear down fleets/builds (keeps the alias + role for the next promote)
fabrica deploy destroy
Cost

Offline cost visibility: fabrica cost estimates monthly cost for the modules present in local state, preferring the deployed shape recorded in state (instance type, volume/fleet size) and falling back to your current fabrica.yaml for anything not recorded. Fully offline — no AWS Cost Explorer calls, no billing API. Run <module> status to reconcile if state and reality have drifted.

fabrica cost report

Shows the estimated monthly cost broken down by provisioned module and resource, with a grand total and confidence level. Reads the deployed shape from local state where recorded, falling back to fabrica.yaml for cost inputs not yet in state. --json for machine-readable output.

fabrica cost forecast

Projects the current monthly estimate over a time horizon: daily burn rate, total over the horizon, and annualized cost. --days <n> sets the horizon (default 30). --json for machine-readable output.

fabrica cost alerts

Manages local budget thresholds (written to fabrica.yaml — no AWS Budgets resources are created) and checks the current estimate against them:

  • fabrica cost alerts list — show configured thresholds.
  • fabrica cost alerts set <scope> <monthly> [--warn-pct N] — upsert a threshold (scope is total or a module name; --warn-pct defaults to 80). Honors --dry-run.
  • fabrica cost alerts check — evaluate the current estimate against thresholds and report OK/WARN/OVER. Informational (exit code stays 0). --json for machine-readable output.
Other
fabrica destroy --all

Full-stack teardown: destroys every provisioned module in reverse dependency order (deploy → ci → workstation → ddc → horde → lore → perforce), then the state backend — but only if every module succeeded (a module failure preserves the backend so orphaned resources stay tracked for retry). One aggregate typed-phrase confirmation; --yes to skip, --dry-run to preview the full plan. Plain fabrica destroy (no --all) just prints usage.

fabrica version

Prints version, commit hash, Go toolchain version, and platform.

fabrica export

Generates infrastructure-as-code templates from Fabrica's recorded local state and configuration. Reads .fabrica/state.json and fabrica.yaml, then produces CloudFormation YAML or Terraform HCL for the resources Fabrica manages. No live AWS calls — all data comes from local state.

V2 covers all modules: state backend (S3 bucket, DynamoDB table), Horde, Perforce, Lore, DDC (home + edge regions), Workstation, CI, and Deploy.

# Export as CloudFormation YAML to stdout:
fabrica export --format cloudformation

# Export as Terraform HCL to a file:
fabrica export --format terraform --output infrastructure.tf

# Preview what would be exported (dry-run):
fabrica export --format cloudformation --dry-run

Key flags:

--format   Export format: cloudformation or terraform (required)
--output   Output file path (default: stdout)

UserData and credential-like fields are automatically redacted in the output.

Configuration

# fabrica.yaml
aws:
  account_id: "123456789012"   # auto-detected on first setup
  region: us-west-2

perforce:
  instance_type: c5.2xlarge
  ami_id: ami-xxxxxxxxxxxxxxxxx
  volume_size_gb: 500

horde:
  instance_type: m7i.2xlarge
  ami_id: ami-xxxxxxxxxxxxxxxxx   # job-capable Docker compose AMI (MongoDB, Redis, Horde with jobs API)
  agents:
    amiId: ami-yyyyyyyyyyyyyyyyy  # dedicated agent AMI (see docs/horde-agent-ami.md)
    instanceType: m7i.xlarge
    minSize: 2
    desiredCapacity: 3
    maxSize: 10
    scaling:                      # optional — queue-based autoscaling
      enabled: false
      scaleOutThreshold: 5.0
      scaleInThreshold: 1.0
      scaleInCooldown: 300

lore:
  amiId: ami-xxxxxxxxxxxxxxxxx    # must contain loreserver (see docs/lore-ami.md)
  instanceType: m5.xlarge
  volumeSize: 500
  allowedCidr: 10.0.0.0/8

ddc:
  amiId: ami-xxxxxxxxxxxxxxxxx    # Unreal Cloud DDC / Jupiter (see docs/ddc-ami.md)
  instanceType: m6i.xlarge
  volumeSize: 500
  backend: zen                    # or scylla (1-node bootstrap only — not HA)

ci:
  vpcId: vpc-0a1b2c3d4e5f67890   # optional — CodeBuild VPC for reaching a private-IP Horde
  subnetId: subnet-0123456789abcdef0   # optional — defaults to the account default VPC when unset

deploy:
  buildBucket: my-studio-builds   # S3 bucket where packaged server builds land

Architecture

cmd/* → internal/{config, state, cost, tags, prompt, cloud}
                                                    ↓
                                        internal/cloud/aws

internal/* packages are SDK-free pure plan layers. The cmd/<module> layer calls them, then executes via the AWS provider. See AGENTS.md for the full architecture and contribution guide.

Contributing / Development

See CONTRIBUTING.md for the full workflow. Quick loop:

go test ./...                          # Windows
go test -race -coverprofile=coverage.out -covermode=atomic ./...  # Linux/macOS
golangci-lint run ./...
git config core.hooksPath .githooks    # once per clone

Pull requests go to main. Please follow the Code of Conduct. Report vulnerabilities via SECURITY.md.

License

MIT — see LICENSE.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
ci
Package ci wires the "ci" parent command and its subcommands (setup, trigger, status, logs): a CodeBuild-based orchestration layer over Horde.
Package ci wires the "ci" parent command and its subcommands (setup, trigger, status, logs): a CodeBuild-based orchestration layer over Horde.
ci/destroy
Package destroy implements "fabrica ci destroy": tear down the CI infrastructure — the CodeBuild project (via the CodeBuildRunner SDK, since AWS::CodeBuild::Project has no Cloud Control CREATE/DELETE) and the IAM role (via Cloud Control).
Package destroy implements "fabrica ci destroy": tear down the CI infrastructure — the CodeBuild project (via the CodeBuildRunner SDK, since AWS::CodeBuild::Project has no Cloud Control CREATE/DELETE) and the IAM role (via Cloud Control).
ci/logs
Package logs implements "fabrica ci logs <build-id>": fetch CloudWatch logs for a specific CodeBuild build.
Package logs implements "fabrica ci logs <build-id>": fetch CloudWatch logs for a specific CodeBuild build.
ci/setup
Package setup implements "fabrica ci setup": provision the CI infrastructure (IAM role + CodeBuild project) that orchestrates Horde BuildGraph jobs.
Package setup implements "fabrica ci setup": provision the CI infrastructure (IAM role + CodeBuild project) that orchestrates Horde BuildGraph jobs.
ci/status
Package status implements "fabrica ci status": show the CI infrastructure and the status of the most recent build.
Package status implements "fabrica ci status": show the CI infrastructure and the status of the most recent build.
ci/trigger
Package trigger implements "fabrica ci trigger <buildgraph>": start a CI build run that submits a BuildGraph job to the Horde coordinator.
Package trigger implements "fabrica ci trigger <buildgraph>": start a CI build run that submits a BuildGraph job to the Horde coordinator.
cost
Package cost wires the "cost" parent command and its subcommands (report, forecast, alerts): offline, config-derived cost visibility and local budget guardrails.
Package cost wires the "cost" parent command and its subcommands (report, forecast, alerts): offline, config-derived cost visibility and local budget guardrails.
cost/alerts
Package alerts implements "fabrica cost alerts": manage and evaluate local budget thresholds.
Package alerts implements "fabrica cost alerts": manage and evaluate local budget thresholds.
cost/forecast
Package forecast implements "fabrica cost forecast": project the current monthly cost estimate over a time horizon (daily burn, horizon cost, annualized).
Package forecast implements "fabrica cost forecast": project the current monthly cost estimate over a time horizon (daily burn, horizon cost, annualized).
cost/report
Package report implements "fabrica cost report": an offline monthly cost estimate broken down by provisioned module.
Package report implements "fabrica cost report": an offline monthly cost estimate broken down by provisioned module.
ddc
ddc/region
Package region implements `fabrica ddc region add`: provisioning an additional DDC edge node in a peer region, reusing the home stack's global IAM profile and shared blob bucket.
Package region implements `fabrica ddc region add`: provisioning an additional DDC edge node in a peer region, reusing the home stack's global IAM profile and shared blob bucket.
deploy
Package deploy wires the "deploy" parent command and its subcommands (setup, promote, rollback, status, destroy): GameLift deployment orchestration over CI/Horde-produced builds.
Package deploy wires the "deploy" parent command and its subcommands (setup, promote, rollback, status, destroy): GameLift deployment orchestration over CI/Horde-produced builds.
deploy/destroy
Package destroy implements "fabrica deploy destroy": tear down deploy resources.
Package destroy implements "fabrica deploy destroy": tear down deploy resources.
deploy/promote
Package promote implements "fabrica deploy promote <build-version>": register a server build from S3, create a new GameLift fleet for it, wait for the fleet to reach ACTIVE, then flip the alias to it (blue/green).
Package promote implements "fabrica deploy promote <build-version>": register a server build from S3, create a new GameLift fleet for it, wait for the fleet to reach ACTIVE, then flip the alias to it (blue/green).
deploy/rollback
Package rollback implements "fabrica deploy rollback": flip the GameLift alias back to the most-recent superseded (retained) fleet.
Package rollback implements "fabrica deploy rollback": flip the GameLift alias back to the most-recent superseded (retained) fleet.
deploy/setup
Package setup implements "fabrica deploy setup": provision the deploy infrastructure (IAM role GameLift uses to read builds from S3 + a GameLift alias) that later promotes flip between fleets.
Package setup implements "fabrica deploy setup": provision the deploy infrastructure (IAM role GameLift uses to read builds from S3 + a GameLift alias) that later promotes flip between fleets.
deploy/status
Package status implements "fabrica deploy status": a read-only overview of the deploy module — the alias, the active fleet, and any retained rollback candidates, with live GameLift fleet status.
Package status implements "fabrica deploy status": a read-only overview of the deploy module — the alias, the active fleet, and any retained rollback candidates, with live GameLift fleet status.
drift
Package driftcmd implements `fabrica drift`: drift detection and optional auto-remediation.
Package driftcmd implements `fabrica drift`: drift detection and optional auto-remediation.
export
Package export implements "fabrica export": generate infrastructure-as-code templates from Fabrica's recorded state and configuration.
Package export implements "fabrica export": generate infrastructure-as-code templates from Fabrica's recorded state and configuration.
horde/agents
Package agents provides the "horde agents" subcommand group for managing Horde build agent pools (Auto Scaling Group + Launch Template).
Package agents provides the "horde agents" subcommand group for managing Horde build agent pools (Auto Scaling Group + Launch Template).
horde/agents/destroy
Package destroy provides the "horde agents destroy" subcommand.
Package destroy provides the "horde agents destroy" subcommand.
horde/agents/status
Package status provides the "horde agents status" subcommand.
Package status provides the "horde agents status" subcommand.
internal/costsource
Package costsource is the shared engine that turns provisioned state plus the current config into an estimated cost breakdown.
Package costsource is the shared engine that turns provisioned state plus the current config into an estimated cost breakdown.
internal/destroyall
Package destroyall orchestrates a full-stack teardown for `fabrica destroy --all`: it runs a caller-supplied, ordered set of per-module teardown closures, then deletes the state backend — but only if every module succeeded.
Package destroyall orchestrates a full-stack teardown for `fabrica destroy --all`: it runs a caller-supplied, ordered set of per-module teardown closures, then deletes the state backend — but only if every module succeeded.
internal/doctorchecks
Package doctorchecks provides shared diagnostic checks used by both the CLI doctor command and the MCP doctor tool.
Package doctorchecks provides shared diagnostic checks used by both the CLI doctor command and the MCP doctor tool.
internal/modstatus
Package modstatus is the shared engine behind the EC2 module status commands.
Package modstatus is the shared engine behind the EC2 module status commands.
internal/provision
Package provision owns the shared orchestration used by module create commands.
Package provision owns the shared orchestration used by module create commands.
internal/statusreport
Package statusreport provides the shared status report builder used by both the CLI status command and the MCP fabrica_status tool.
Package statusreport provides the shared status report builder used by both the CLI status command and the MCP fabrica_status tool.
internal/teardown
Package teardown is the shared engine behind the module destroy/terminate commands (perforce destroy, horde destroy, workstation terminate).
Package teardown is the shared engine behind the module destroy/terminate commands (perforce destroy, horde destroy, workstation terminate).
internal/testutil
Package testutil provides shared helpers for cobra black-box tests.
Package testutil provides shared helpers for cobra black-box tests.
mcp
Package mcp implements `fabrica mcp`: an MCP (Model Context Protocol) server that exposes read-only Fabrica tools over stdio transport.
Package mcp implements `fabrica mcp`: an MCP (Model Context Protocol) server that exposes read-only Fabrica tools over stdio transport.
perforce/backup
Package backup implements fabrica perforce backup (create), backup list, and backup delete.
Package backup implements fabrica perforce backup (create), backup list, and backup delete.
perforce/internal/provisioning
Package provisioning resolves the state-backed resources required by Perforce operational commands.
Package provisioning resolves the state-backed resources required by Perforce operational commands.
perforce/internal/remoteexec
Package remoteexec owns the shared Perforce SSM script lifecycle.
Package remoteexec owns the shared Perforce SSM script lifecycle.
perforce/restore
Package restore implements fabrica perforce restore.
Package restore implements fabrica perforce restore.
status
Package status implements `fabrica status`: a read-only aggregate overview of all provisioned modules plus state-backend health.
Package status implements `fabrica status`: a read-only aggregate overview of all provisioned modules plus state-backend health.
workstation/action
Package action owns the shared workstation start and stop command pattern.
Package action owns the shared workstation start and stop command pattern.
internal
assert
Package assert provides shared test assertion helpers.
Package assert provides shared test assertion helpers.
ci
Package ci is the pure plan layer for the Fabrica CI module.
Package ci is the pure plan layer for the Fabrica CI module.
cloud
Package cloud defines provider-agnostic interfaces and shared constants used across plan layers and cost estimators.
Package cloud defines provider-agnostic interfaces and shared constants used across plan layers and cost estimators.
cost
Package cost provides a provider-agnostic cost estimation framework.
Package cost provides a provider-agnostic cost estimation framework.
credentials
Package credentials provides shared helpers for generating and storing per-module credential files under .fabrica/.
Package credentials provides shared helpers for generating and storing per-module credential files under .fabrica/.
ddc
deploy
Package deploy is the pure plan layer for the Fabrica deploy module.
Package deploy is the pure plan layer for the Fabrica deploy module.
drift
Package drift provides drift detection and optional auto-remediation for Fabrica-managed resources.
Package drift provides drift detection and optional auto-remediation for Fabrica-managed resources.
ec2cost
Package ec2cost provides shared cost-resource builders for EC2-based modules.
Package ec2cost provides shared cost-resource builders for EC2-based modules.
ec2plan
Package ec2plan provides shared base struct and constructor for EC2-based module plans, plus assertion helpers for plan-layer tests.
Package ec2plan provides shared base struct and constructor for EC2-based module plans, plus assertion helpers for plan-layer tests.
ec2state
Package ec2state provides a shared Cloud Control desired-state builder for EC2 instances.
Package ec2state provides a shared Cloud Control desired-state builder for EC2 instances.
export
Package export provides infrastructure-as-code generation from Fabrica's recorded state and configuration.
Package export provides infrastructure-as-code generation from Fabrica's recorded state and configuration.
horde
Package horde provides the plan layer for the Horde build coordinator and its managed agent pool (Auto Scaling Group).
Package horde provides the plan layer for the Horde build coordinator and its managed agent pool (Auto Scaling Group).
iamrole
Package iamrole provides shared helpers for building IAM role desired-state documents used by multiple modules (perforce, ddc, ci, deploy) when creating IAM roles via Cloud Control.
Package iamrole provides shared helpers for building IAM role desired-state documents used by multiple modules (perforce, ddc, ci, deploy) when creating IAM roles via Cloud Control.
oplog
Package oplog provides operational logging for Fabrica using the Go stdlib log/slog package.
Package oplog provides operational logging for Fabrica using the Go stdlib log/slog package.
prompt
Package prompt provides a simple tty-aware confirmation prompt.
Package prompt provides a simple tty-aware confirmation prompt.
stateutil
Package stateutil provides shared helpers for querying module state.
Package stateutil provides shared helpers for querying module state.
topology
Package topology provides provider-agnostic coordinator/edge graph types.
Package topology provides provider-agnostic coordinator/edge graph types.
userdata
Package userdata provides shared helpers for rendering cloud-init templates.
Package userdata provides shared helpers for rendering cloud-init templates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL