Component Schema

Component configuration defines buildable and deployable units stored in components/<id>.json.

Schema

json
{
  "id": "string",
  "name": "string",
  "local_path": "string",
  "remote_path": "string",
  "build_artifact": "string",
  "deploy_together": ["component-id"],
  "artifact_inputs": [
    {
      "component": "string",
      "artifact": "string",
      "target": "string",
      "sha256": "string"
    }
  ],
  "extract_command": "string",
  "version_targets": [
    {
      "file": "string",
      "pattern": "string",
      "artifact_path": "string"
    }
  ],
  "changelog_target": "string",
  "hooks": {
    "pre:version:bump": ["shell command"],
    "post:version:bump": ["shell command"],
    "post:release": ["shell command"],
    "post:deploy": ["shell command"]
  },
  "scripts": {
    "lint": ["shell command"],
    "test": ["shell command"],
    "build": ["shell command"],
    "bench": ["shell command"],
    "trace": ["shell command"]
  },
  "extensions": {},
  "release": {}
}

Fields

Required Fields

  • id (string): Unique component identifier, derived from local_path directory name (lowercased)
  • local_path (string): Absolute path to local source / git checkout directory, ~ is expanded
  • remote_path (string): Remote path relative to project base_path (the deploy target)
  • build_artifact (string): Build artifact path relative to local_path, must include filename

Important: local_path must point to a git repository / source checkout, not the production deploy target. The deploy target is derived from project.base_path + component.remote_path. If local_path points to the deployed directory, builds will run inside production and uncommitted-changes checks will fail (the directory isn’t a git repo). This is a common misconfiguration after server migrations.

Optional Fields

  • name (string): Human-readable component name, defaults to id
  • extract_command (string): Command to execute after artifact upload, runs inside target directory
    • Supports template variables: {artifact}, {targetDir}
  • version_targets (array): List of version detection patterns
    • file (string): Path to file containing version (relative to local_path). This is the source path that the version bump writes to.
    • pattern (string): Regex pattern to extract version (first capture group)
  • changelog_target (string): Path to changelog file (relative to local_path)
  • extensions (object): Extension-specific settings
    • Keys are extension IDs (e.g., "wordpress", "rust")
    • Values are flat extension setting objects; version is reserved for extension version constraints
  • scripts (object): Component-owned shell commands for extension-shaped capabilities
    • Supported keys: lint, test, build, bench, trace
    • Each value is an array of shell commands run sequentially in local_path
    • Resolution order is scripts.<capability> first, then linked extension support, then not-applicable
    • Scripts receive the same runner env paths (HOMEBOY_COMPONENT_ID, HOMEBOY_COMPONENT_PATH, HOMEBOY_RUN_DIR and sidecar file vars when relevant) as extension runners, with HOMEBOY_EXTENSION_ID=component-script
    • Use scripts.build, not build_command; build_command is still only a diagnostic output field.
  • artifact_inputs (array): Producer artifacts to resolve and compose into this component’s build artifact after this component builds
    • component (string): Producer component ID to build before composition
    • artifact (string): Producer artifact path or glob, resolved relative to the producer local_path
    • target (string): Relative path where the producer artifact is placed inside the consumer artifact
    • sha256 (string, optional): Expected producer artifact SHA-256; comparison is case-insensitive
    • The resolved input metadata is generic (component, resolved artifact, target, sha256). The current writer implementation supports ZIP consumer artifacts and writes each input at target inside the ZIP.
  • deploy_together (array): Component IDs that must be deployed in the same operation as this component
    • Use this when separately tracked components form one runtime contract, such as a WordPress plugin and theme that must stay in sync.
    • Deploy planning fails closed when a selection includes only part of a declared group. Select all coupled components explicitly or use --all for the project.
  • release (object): Component-scoped release configuration
    • enabled (boolean): Whether release pipeline is enabled
    • steps (array): Release step definitions
    • settings (object): Release pipeline settings

Runtime Requirements

Important: local_path must point to a git repository / source checkout, not the production deploy target. The deploy target is derived from project.base_path + component.remote_path. If local_path points to the deployed directory, builds will run inside production and uncommitted-changes checks will fail (the directory isn’t a git repo). This is a common misconfiguration after server migrations.

json
{
  "command": "component.env",
  "id": "example",
  "extension": "example-extension",
  "runtimes": {
    "php": { "version": "8.2", "source": "component" },
    "node": { "version": "22", "source": "extension:example-extension" }
  }
}

Important: local_path must point to a git repository / source checkout, not the production deploy target. The deploy target is derived from project.base_path + component.remote_path. If local_path points to the deployed directory, builds will run inside production and uncommitted-changes checks will fail (the directory isn’t a git repo). This is a common misconfiguration after server migrations.

Hook Fields

  • Supports template variables: {artifact}, {targetDir}

local_path vs remote_path

local_path (source)                          remote_path (deploy target)
┌──────────────────────────┐                ┌──────────────────────────────────────────┐
│ ~/repos/extrachill-api/  │  ── build ──▶  │ /var/www/site/wp-content/plugins/        │
│ (git checkout, builds    │    deploy      │ extrachill-api/                          │
│  run here)               │                │ (project.base_path + remote_path)        │
└──────────────────────────┘                └──────────────────────────────────────────┘
  • file (string): Path to file containing version (relative to local_path). This is the source path that the version bump writes to.
  • pattern (string): Regex pattern to extract version (first capture group)

homeboy component env reports runtime requirements in a generic runtimes map:

Example

json
{
  "id": "extrachill-api",
  "name": "Extra Chill API",
  "local_path": "/Users/dev/extrachill-api",
  "remote_path": "wp-content/plugins/extrachill-api",
  "build_artifact": "build/extrachill-api.zip",
  "extract_command": "unzip -o {{artifact}} && rm {{artifact}}",
  "version_targets": [
    {
      "file": "composer.json",
      "pattern": ""version":\s*"([^"]+)""
    }
  ],
  "changelog_target": "CHANGELOG.md",
  "hooks": {
    "pre:version:bump": [
      "./scripts/verify-generated-sources"
    ],
    "post:version:bump": [
      "./scripts/refresh-versioned-artifacts"
    ],
    "post:release": [
      "echo 'Release complete!'"
    ]
  },
  "extensions": {
    "wordpress": {
      "php_version": "8.1"
    }
  },
  "release": {
    "enabled": true,
    "steps": [
      {
        "id": "preflight.test",
        "type": "preflight.test",
        "label": "Run Tests"
      }
    ]
  }
}

Version Target Format

Runtime IDs are extension-owned strings. source is component for component config or detector output and extension:<id> for extension-provided defaults. Component extension settings and detector output must use the canonical runtimes map with object values containing version.

Setting local_path to the same directory as the deploy target is a misconfiguration — builds would run in production and homeboy deploy would fail uncommitted-changes checks.

  • Keys are extension IDs (e.g., "wordpress", "rust")
  • Values are flat extension setting objects; version is reserved for extension version constraints

Extract Command Context

Version targets use regex to extract semantic versions from files. The pattern must include a capture group for the version string.

  • Supported keys: lint, test, build, bench, trace
  • Each value is an array of shell commands run sequentially in local_path
  • Resolution order is scripts.<capability> first, then linked extension support, then not-applicable
  • Scripts receive the same runner env paths (HOMEBOY_COMPONENT_ID, HOMEBOY_COMPONENT_PATH, HOMEBOY_RUN_DIR and sidecar file vars when relevant) as extension runners, with HOMEBOY_EXTENSION_ID=component-script
  • Use scripts.build, not build_command; build_command is still only a diagnostic output field.

Common patterns:

  • component (string): Producer component ID to build before composition
  • artifact (string): Producer artifact path or glob, resolved relative to the producer local_path
  • target (string): Relative path where the producer artifact is placed inside the consumer artifact
  • sha256 (string, optional): Expected producer artifact SHA-256; comparison is case-insensitive
  • The resolved input metadata is generic (component, resolved artifact, target, sha256). The current writer implementation supports ZIP consumer artifacts and writes each input at target inside the ZIP.

Storage Location

The extract_command runs inside the target directory after artifact upload. The working directory is:

  • Use this when separately tracked components form one runtime contract, such as a WordPress plugin and theme that must stay in sync.
  • Deploy planning fails closed when a selection includes only part of a declared group. Select all coupled components explicitly or use --all for the project.
  • enabled (boolean): Whether release pipeline is enabled
  • steps (array): Release step definitions
  • settings (object): Release pipeline settings