Metadata-Version: 2.4
Name: pyplines-builder
Version: 2026.9.3a1
Summary: Build and sign Pyplines Actions and Distributions
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: pyplines-cli-common>=0.0.dev0
Requires-Dist: typer<1,>=0.24
Requires-Dist: docker<8,>=7.1
Requires-Dist: cryptography>=44
Requires-Dist: packaging>=25
Requires-Dist: PyYAML>=6
Requires-Dist: jsonschema>=4.23
Requires-Dist: referencing>=0.36

# Pyplines Builder

`pyplines-builder` is the Python/Typer authoring tool. `pyplines` remains the
operational CLI: it installs and operates the resulting Distribution. Neither
tool depends on the other. The obsolete Go/Buildah Action Builder is not used.

Install with `pip install pyplines-builder`. Development: `uv sync --project builder`.
Docker must provide Linux containers. The builder uses the Docker API, never a
Docker/Buildah shell command. Source inspection runs in the target image using
the SDK, not in the host interpreter.

## Commands

```text
pyplines-builder version
pyplines-builder check pyplines-build.yaml
pyplines-builder keygen ./signing --source https://example.com --publisher example
pyplines-builder build pyplines-build.yaml --registry registry.example.com/example \
  --signing-key ./signing/publisher.pem --output ./hello-world-1.0.0.tar.gz
pyplines-builder inspect ./hello-world-1.0.0.tar.gz
pyplines-builder verify ./hello-world-1.0.0.tar.gz --trust-file ./signing/trust.json
pyplines-builder action build ./action --platform linux/arm64
pyplines-builder action inspect sha256:IMAGE_ID
pyplines-builder action run sha256:IMAGE_ID --input-file ./input.yaml
```

Every command supports `--json`. Data goes to stdout, failures to stderr;
failures have nonzero exit codes. No prompts, animations, or credential values
in diagnostics. Local image IDs are reported by `action build`. `action run`
reports runtime logs and the terminal InvocationResult; it does not replace
testing against the Server. `--allow-network` explicitly enables test egress.

## Build document

See [Hello World](../example/v1alpha1/distributions/hello-world). The tooling-only
`pyplines.dev/build/v1alpha1` document references workspace-neutral, standard
Procedure resources and Action sources (or immutable prebuilt image references).
IDs in Procedure references match IDs in the build document. Exactly one root
Procedure is required; every included resource must be reachable from it.
There is no additional Action Package format and no new platform resource.

`check` performs offline structural checks; it does not import Action source or
claim to validate runtime schemas. `build` validates the complete included
resource graph. Server installation remains authoritative for semantic planning,
authorization, trust and runtime compatibility.

Each Action's `pyproject.toml` supplies static `project.name`, `version`,
`requires-python`, and the `pyplines.action` handler entry point. Include source
files explicitly with `[tool.pyplines.builder] include = ["hello_world.py"]`
(default: `src`). Include required README/license/package data there too. No
symlinks, hidden directories, environments or private-key files are copied.
Review this allowlist: an ordinary source file can still contain a hardcoded
secret. Building executes author-controlled packaging code and must only be
done for trusted source on a suitable Docker engine.

Python 3.11–3.14 is supported; the newest compatible minor is selected, or use
`--python`. `--platform auto` uses the Docker engine's architecture. Cross-platform
builds require engine-provided emulation. A build targets one architecture;
produce a separately signed Distribution for each platform. Multi-platform OCI
index assembly is not provided. `--base-image` permits an explicitly pinned Python
base. Otherwise the selected Python slim tag is resolved to a digest before
building. Base, source, SDK and recipe attribution is embedded at
`/opt/pyplines/action/build.json` and returned in the build report. Docker provides
layer caching. Unlocked third-party dependencies can change between builds;
pin dependencies for reproducibility. Distribution bytes are deterministic for
the same resource documents and signing key; source-to-image reproducibility is
not claimed for unpinned dependencies.

Released builders pin the matching published `pyplines` SDK. A development builder
requires an explicit `--sdk-wheel`; it never silently includes the repository.
Keep a private signing key outside Action sources. Keys are Ed25519 PKCS8 PEM,
mode 0600 on POSIX. Existing keys and output archives are never overwritten.
Existing registry version tags are reused only for identical images. Enable
registry-side immutable tags as well to protect against concurrent publishers.
The separate `trust.json` is public and can be supplied to Server trust
configuration; the builder does not install trust or weaken verification.

Private registries use `--registry-credentials /path/to/docker-auth.json`, a
portable Docker `auths` file. Credential helpers/keychains are not required or
invoked. Never put credentials in the build document or image reference.
The default is anonymous registry access. Docker daemon insecure-registry
configuration is needed for a local HTTP registry; the builder does not alter it.

Local runtime tests use the same entrypoint, Unix socket transport, non-root UID,
read-only root, capability restrictions and scratch mounts as the appliance.
Test limits are 1 CPU, 256 MiB, 128 PIDs, 16 MiB scratch, 64 KiB test input/secrets,
4 MiB collected logs and a configurable 1–3600 second deadline. Only the test's
own containers/volume are removed. Build images/cache remain for reuse.

## Development

```sh
python3 scripts/sync_builder_contracts.py --check
uv run --project builder pytest -q builder/tests
uv run --project builder black --check builder/pyplines_builder/app.py
uv build --project builder
```

The generated readers and schema snapshot come from the same sources as the
operational CLI. Edit those sources and regenerate, not the bundled copies.
# Shared CLI behavior

The Builder follows the same standard as `pyplines`: readable output by default,
or JSON with `AUTOMATION_MODE=enabled` / `--json`. Automation never prompts.
Help requires no Docker connection. Use `version` or `--version` for the installed
package version. Common behavior is provided by `pyplines-cli-common`.
