IMPORTANT: Developer documentation for the current development branch. This content is unreleased, may change without notice, and must not be treated as Buildish release documentation.

Bootstrap Process

How the action initializes configuration, the cache model, and the build tool adapter (Gradle or Maven) before handing off to the build.

The bootstrap process runs at the start of every phase (prepare and finalize). It resolves configuration, builds the cache model, and runs the build tool adapter’s bootstrap step — all before any cache-specific logic runs. The adapter step is tool-specific: for Gradle it provisions wrapper JARs; for Maven it is a no-op in v1.

Entrypoints

The two CI-facing entrypoints call into the shared phase logic:

Phase CI entrypoint Phase entry function
prepare src/phases/prepare/cli.ts runPrepareExecution()
finalize src/phases/finalize/cli.ts runFinalizeExecution()

Both entry functions call bootstrapPhase() from src/phases/bootstrap.ts as their first step.

Prepare phase

flowchart TD
    A[runPrepareExecution] --> B[bootstrapPhase]
    B --> C[Read & validate config]
    C --> D[Build CacheModel]
    D --> E[adapter.provision\ne.g. provisionWrapperJars for Gradle]
    E --> F[executePrepareAction]
    F --> G[restoreBaseCache]
    G --> H[download + apply delta artifacts\nif distributed-aggregator]
    H --> I[capture pre-build manifest]
    I --> J[persist validated lifecycle record]
    J --> Z[hand off to build steps]

bootstrapPhase() (src/phases/bootstrap.ts):

  1. Reads action inputs (via HostInputSource).
  2. Optionally loads and merges a config file.
  3. Validates and normalizes the merged config with Zod.
  4. Detects the Java major version by running java -version.
  5. Constructs the CacheModel (src/cache/model.ts): partition definitions, cache keys, path calculations.
  6. Calls the build tool adapter’s provision() method. For Gradle this runs provisionWrapperJars() (src/build-tool/gradle/wrapper/download.ts) to download, verify, and install any missing gradle-wrapper.jar files. For Maven this is a no-op in v1.

executePrepareAction() (src/phases/prepare/flow.ts):

  1. Calls restoreBaseCache() which classifies the outcome as a miss, current-lineage hit, or default-branch fallback hit.
  2. If cleanup is enabled and restore-cleanup mode is prune-managed, deletes managed files and re-restores.
  3. For writable distributed-aggregator jobs with configured dependent-jobs, downloads and applies applicable delta artifact packages. Read-only aggregators return skipped-read-only without requiring an artifact backend.
  4. Captures the pre-build file snapshot (captureCacheManifest()).
  5. Persists one validated lifecycle record containing cache identity, restore outcome, generation seed, manifest digest, execution identity, and dependent-delta evidence.

Finalize phase

flowchart TD
    A[runFinalizeExecution] --> B[bootstrapPhase]
    B --> C[Read & validate config]
    C --> D[Build CacheModel]
    D --> E[adapter.provision\ne.g. provisionWrapperJars for Gradle]
    E --> F[executeFinalizeAction]
    F --> G{validated lifecycle record?}
    G -- No --> Z1[fail closed]
    G -- Yes --> H[optional timestamp GC]
    H --> I[capture post-build manifest]
    I --> J[computeCacheDelta]
    J --> K[stageDeltaArtifact +\nuploadDeltaArtifact\nif distributed-worker]
    J --> L[saveBaseCache\nif eligible]
    K --> Z2[done]
    L --> Z2

executeFinalizeAction() (src/phases/finalize/flow.ts):

  1. Loads and validates the complete prepare-phase lifecycle record and its pre-build manifest.
  2. Runs timestamp cache garbage collection for standalone and distributed-aggregator jobs when cleanup is enabled and cache-gc-mode is timestamp.
  3. Captures the post-build file snapshot.
  4. Calls computeCacheDelta() (src/cache/manifest-format.ts, re-exported by src/cache/manifest.ts) to diff pre- and post-build manifests.
  5. For a writable distributed-worker: stages the delta artifact locally, then uploads it. Read-only workers upload nothing.
  6. Calls saveBaseCache() (skipped for distributed-worker; see Base Cache Design).
  7. For distributed-aggregator: cleans up consumed worker delta artifacts.

src/phases/finalize/flow.ts owns lifecycle orchestration and side effects. src/phases/finalize/reporting.ts owns the final status model, manifest-derived statistics, and human-readable log and job-summary rendering. flow.ts re-exports the reporting contract so existing consumers retain a stable facade.

Configuration loading

The full priority order for action configuration:

Action input overrides
        ↓
Config-file values (workspace-relative .yml / .json / .yaml)
        ↓
Built-in defaults

src/config/inputs.ts reads the canonical public contract, validates and overlays the optional config file, and preserves direct-input precedence. src/config/normalize.ts validates shared values before the tool-specific normalizer (src/build-tool/gradle/config.ts or src/build-tool/maven/config.ts) handles only its additional fields. If any value is invalid, the action fails at bootstrap before touching the cache or wrappers.

Cache model

The CacheModel (src/cache/model.ts) is constructed once during bootstrap and passed through the whole phase. It encapsulates:

  • The resolved build tool cache root path (e.g. GRADLE_USER_HOME for Gradle, ~/.m2 for Maven).
  • The active partition list with their computed include/exclude globs.
  • The action-owned compatibility family key.
  • The collision-resistant current ref token and lineage prefix.
  • The ordered default-branch fallback lineage, when applicable.
  • The planned immutable generation identifier.
  • The computed partitionFingerprint.

The CacheModel is intentionally immutable after construction so that both phases see exactly the same partition layout and key values.