Custom-scaffold engine for data-product-forge — install, plug in any scaffold bundle (Python plugin or YAML/Jinja), generate a complete project from your contract
Project description
data-product-forge-custom-scaffold
The custom-scaffold engine for data-product-forge. Install it alongside the CLI, plug in any scaffold bundle, and generate a complete project from your contract.
pip install data-product-forge data-product-forge-custom-scaffold
This pulls data-product-forge-sdk transitively (import path: fluid_sdk). Requires Python >=3.10.
Then in any fluid contract:
extensions:
customScaffold:
libraries:
- id: ci
source: { kind: git, url: "https://github.com/example/my-bundle", ref: "v1.0" }
patterns:
- use: ci:basic
fluid custom-scaffold
# ✓ 3 files written, 0 failed
# README.md
# .gitlab-ci.yml
# docs/runbook.md
Deterministic, idempotent, atomic.
What this engine does
This is the runtime for data-product-forge's custom-scaffold feature:
- Discovers itself with the CLI via Python entry-points (just
pip install). - Resolves bundles from
path(local),git(clone into cache), orentrypoint(installed Python plugin). - Validates the
extensions.customScaffoldblock in your contract. - Renders each pattern through Jinja2.
- Writes the generated files atomically with path-traversal protection.
- Copies the bundle's
static/directory verbatim alongside rendered templates (for binary fixtures, sample data, pre-rendered files).
What's in the contract
extensions:
customScaffold:
libraries:
- id: ci # local alias
source:
kind: git # path | git
url: "https://github.com/example/ci-bundle"
ref: "v1.0"
subdir: "scaffold" # optional
auth: { secret_ref: GITHUB_TOKEN } # optional
patterns:
- use: ci:gitlab-ci # <library-id>:<pattern-name>
variables:
parentCiTemplateRef: "my-org/ci-templates@main"
Source kinds
| Kind | What it does | When to use |
|---|---|---|
path |
Reads a local directory. Relative paths anchor to the contract's directory. | Bundle development; private monorepos that vendor bundles. |
git |
git clone into the cache. |
Shared bundles distributed via a git repo. |
entrypoint |
Loads a Python CustomScaffold subclass registered via fluid_build.custom_scaffolds entry-point. |
Bundles that need full programmatic control (external API calls, complex conditionals). |
Auth via auth.secret_ref (env-var name, never persisted).
Note: explicit npm and pypi source kinds (auto-fetch from registry) are not in v0. For pip-installable Python plugins, use
kind: entrypointafterpip install-ing the plugin package. Git covers most YAML/Jinja distribution today. File an issue if you need direct-from-registry npm/pypi fetch.
Bundle authoring
Two paths — pick whichever fits:
A. YAML + Jinja bundle (no Python)
Drop a directory like this:
my-bundle/
├── fluid-scaffold.yaml ← manifest
├── templates/
│ ├── README.md.j2 ← Jinja templates
│ └── .gitlab-ci.yml.j2
└── static/ ← optional — copied verbatim
└── docs/
└── runbook.md
The engine's built-in TemplatedCustomScaffold reads the manifest, renders the templates, and copies static/ verbatim.
→ See docs/walkthrough/build-a-yaml-bundle.md for the step-by-step.
B. Python plugin bundle
Subclass fluid_sdk.CustomScaffold directly. Full programmatic control.
→ See the SDK walkthrough.
CLI surface
fluid custom-scaffold [OPTIONS]
-c, --contract PATH Path to contract.fluid.yaml (default: ./contract.fluid.yaml)
-o, --output PATH Output root (default: cwd)
--dry-run Plan only — print the file list, write nothing.
--pattern USE Restrict to specific patterns (repeatable)
--lib ID Restrict to specific library ids (repeatable)
--pin Reproducible re-run: resolve git sources to the commit
recorded in fluid-scaffold.lock (not the floating ref).
--update Update an existing output to the evolved template —
3-way merge that preserves your edits (see below).
--target REF With --update: the git ref/commit to update to.
--json Emit JSON instead of human output
Exit codes:
| Code | Meaning |
|---|---|
0 |
success |
1 |
bad CLI args / contract not found |
2 |
engine error (resolution, plan, or apply failed) |
3 |
at least one apply() action failed |
4 |
--update completed with merge conflicts (markers written; resolve them) |
Reproducibility & updates
Every successful generation writes a fluid-scaffold.lock at the output
root (commit it alongside the generated files). It records, per resolved
library, the exact commit it resolved to, plus the patterns and variables used —
the same model as copier's .copier-answers.yml.
# Generate — writes the output + fluid-scaffold.lock
fluid custom-scaffold -c contract.fluid.yaml -o ./my-project
# Reproducible re-run — resolve git sources to the LOCKED commit, not the
# moving ref. (npm-ci / poetry --frozen semantics; non-git sources can't be
# reproducibly pinned and the engine says so.)
fluid custom-scaffold -c contract.fluid.yaml -o ./my-project --pin
# Update — the template evolved? Re-render at the new ref and 3-way-merge it
# onto your working tree, preserving your edits. Non-overlapping changes merge
# cleanly; overlaps get Git-style conflict markers (exit 4).
fluid custom-scaffold -c contract.fluid.yaml -o ./my-project --update
--update renders the template at the locked commit (the baseline you
started from) and at the new ref, then merges with git merge-file
(base = old render, ours = your file, theirs = new render). On success the lock
advances. Full walkthrough: docs/walkthrough/reproducible-updates.md.
Documentation
| Doc | What's inside |
|---|---|
docs/getting-started/ |
5-min: install, run against a fixture bundle, see the output |
docs/walkthrough/build-a-yaml-bundle.md |
15-min: author your own YAML/Jinja bundle from scratch |
docs/walkthrough/from-git-bundle.md |
5-min: consume a public bundle straight from a git repo |
docs/walkthrough/reproducible-updates.md |
The lockfile, --pin, and --update (3-way merge) — reproducibility & updates |
docs/reference/manifest-format.md |
Full fluid-scaffold.yaml reference |
License
Apache-2.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file data_product_forge_custom_scaffold-0.4.1.tar.gz.
File metadata
- Download URL: data_product_forge_custom_scaffold-0.4.1.tar.gz
- Upload date:
- Size: 43.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
833c414ffe910cb0fe5e2fbf4d2b84ce7fd8f9b018c9ef3a563c691d0cb28283
|
|
| MD5 |
681553edc6e4d451fe1327ae55745b98
|
|
| BLAKE2b-256 |
c59aa499c95fab1a3895d549940c377964757afb7d94a67dc4de6142a994e4aa
|
Provenance
The following attestation bundles were made for data_product_forge_custom_scaffold-0.4.1.tar.gz:
Publisher:
release.yml on Agenticstiger/data-product-forge-custom-scaffold
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
data_product_forge_custom_scaffold-0.4.1.tar.gz -
Subject digest:
833c414ffe910cb0fe5e2fbf4d2b84ce7fd8f9b018c9ef3a563c691d0cb28283 - Sigstore transparency entry: 1984240109
- Sigstore integration time:
-
Permalink:
Agenticstiger/data-product-forge-custom-scaffold@0ff912e74d6a528a59e73d4603d9beba2779af1d -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/Agenticstiger
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0ff912e74d6a528a59e73d4603d9beba2779af1d -
Trigger Event:
push
-
Statement type:
File details
Details for the file data_product_forge_custom_scaffold-0.4.1-py3-none-any.whl.
File metadata
- Download URL: data_product_forge_custom_scaffold-0.4.1-py3-none-any.whl
- Upload date:
- Size: 50.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dfe2c2a963501882c23210f9763fff0f444205ef5b1401d7b4af6ddbce78327c
|
|
| MD5 |
98d944d0160510534e38d3f93ed4a125
|
|
| BLAKE2b-256 |
3c5b040c3ff1e61b77cb4474af822b1c3da142e818549e9ac44fa16083729145
|
Provenance
The following attestation bundles were made for data_product_forge_custom_scaffold-0.4.1-py3-none-any.whl:
Publisher:
release.yml on Agenticstiger/data-product-forge-custom-scaffold
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
data_product_forge_custom_scaffold-0.4.1-py3-none-any.whl -
Subject digest:
dfe2c2a963501882c23210f9763fff0f444205ef5b1401d7b4af6ddbce78327c - Sigstore transparency entry: 1984240212
- Sigstore integration time:
-
Permalink:
Agenticstiger/data-product-forge-custom-scaffold@0ff912e74d6a528a59e73d4603d9beba2779af1d -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/Agenticstiger
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0ff912e74d6a528a59e73d4603d9beba2779af1d -
Trigger Event:
push
-
Statement type: