# forge

**Declarative TOML-driven build orchestrator \xC2\xB7 Go**

forge is a declarative, TOML-driven build orchestrator with topological dependency ordering and parallel execution. One forge.toml replaces setup.sh — apt packages, source fetch, compile, prebuilt binaries, shell commands, and verification as ordered ops.

- **Status:** v0.1.0
- **License:** Apache License 2.0
- **Repository:** <https://github.com/supanadit/forge>

## What it does

One forge.toml describes your entire build — packages, source fetch, compile, binaries, verification. Topological dependency ordering, parallel execution, automatic caching. Replace setup.sh with a declarative manifest.

## The problem

Container projects conventionally ship a setup.sh. Numbered shell scripts with implicit ordering and no caching. apt-get install scattered across 15 files with no cleanup. Source builds mixed with binary downloads, no dependency graph. Rebuilds re-execute everything because there is no cache key. Package names differ across distros — nobody maps them. Every project reinvents the same fragile shell scaffolding.

## Features

- **Topological ordering** — Components declare dependencies; forge resolves the execution order automatically. Diamond dependencies, fan-in, shared deps — all handled.
- **Parallel execution** — Independent components run concurrently. Control concurrency with --parallel N or let forge auto-detect.
- **Build cache** — Fully automatic. Cache key hashes ops + vars + dependency keys. On a hit, forge verifies outputs still exist before trusting the cache.
- **OS package manager detection** — Detects apt, dnf, yum, or apk automatically. One manifest works on Debian, Alpine, Fedora. Build packages are cleaned up after all components finish.
- **Package name mapping** — Automatically maps common names across distros: build-essential, pkg-config, libfoo-dev/-devel. Unknown names pass through unchanged.
- **12 operation types** — packages, source_install, binary_install, user, mkdir, chown, chmod, copy, touch, generate, verify, raw — everything a build needs.
- **Variable interpolation** — ${VAR} and ${VAR:-default} resolve from [vars], environment, and --var overrides. Precedence: vars < env < overrides.
- **Build strategies** — source_install supports configure, autogen, cmake, meson, make, and detect. Auto-selects from the source tree when strategy = "detect".
- **Conditional packages** — Gate packages behind structured version conditions. Install bison + flex only when POSTGRESQL_VERSION >= 17.
- **Artifact restoration** — On cache hit with missing files, forge restores from an artifact archive. Works with BuildKit cache mounts and CI cache export.

## How it works

forge reads your forge.toml, resolves the dependency graph, and executes components in topological order with maximum parallelism.

Each [[components]] entry is a node in the DAG. The ops list within each component is the build lifecycle — executed in order. Independent components run in parallel; dependent components wait. The build cache hashes each component's ops, vars, and dependency keys — a hit is trusted only if the output files still exist.

## Operations

- **packages** — Install packages via the detected OS package manager (apt, dnf, yum, apk).
- **source_install** — Fetch source (archive/git) and build/install with configurable strategy.
- **binary_install** — Download an archive and copy a prebuilt binary into place.
- **user** — Create a system or user account.
- **mkdir** — Create directories with mode and owner.
- **chown** — Change ownership of a path.
- **chmod** — Change permissions of a path.
- **copy** — Copy a file with optional mode.
- **touch** — Create an empty file.
- **generate** — Generate code (e.g. protoc-c).
- **verify** — Check files/directories exist.
- **raw** — Run an arbitrary shell command (last resort).

