Skip to content

Python API

Call Stacksmith from Python when an application needs orchestration without shelling out to the CLI.

Stacksmith exposes a stable Python API for applications, automation, and CI systems that need the same behavior as the CLI without launching a subprocess. Import supported names directly from stacksmith; submodules and names that begin with an underscore are implementation details.

Function Purpose
validate_stack Validate a stack and its resolved inputs, returning a structured report.
generate_stack Generate the OpenTofu and Terragrunt files for a stack.
lock_stack Create or verify a deterministic Stacksmith lockfile.
run_stack_action Generate one stack and run a Terragrunt action.
run_all_stacks Discover or select stacks and run an action in dependency order.
prepare_ci_execution Build a provider-neutral CI execution manifest.
redact_plan Create an archive-safe copy of a parsed OpenTofu plan.
redact_plan_file Redact an OpenTofu plan JSON file into an archive-safe artifact.

The workflow functions accept the same layered stack, managed-config, variable, targeting, cache, and validation options used by the corresponding CLI commands. Execution functions return process-style exit codes, while generation returns the generated directory.

Direct generate_stack and run_stack_action calls warn unless locked=True or offline=True enables lockfile enforcement. Set STACKSMITH_WARN_ON_UNLOCKED=0 when an embedding application intentionally manages reproducibility another way.

import sys
from pathlib import Path

from stacksmith import run_stack_action

exit_code = run_stack_action(
    "plan",
    "stack.yaml",
    config=["stacksmith-config.yaml"],
    save_redacted_plan_json=Path("artifacts/plan.json"),
)
sys.exit(exit_code)

The top-level package also exports Stacksmith's exception types, merge-policy models, StacksmithTestRunner, and the GitOps change helpers described below.

Source authoring

author_stack accepts original YAML/JSON text and ordered StackEdit objects, then returns a SourceChange containing proposed source, a unified diff, and a change indicator. It has no filesystem or Git effects. Semantic no-ops retain the exact original source. set replaces a value, merge shallow-merges a mapping, and remove deletes a mapping key. Missing intermediate mappings are created for set and merge; traversal through a scalar fails.

from stacksmith import StackEdit, author_stack

proposal = author_stack(
    source,
    [
        StackEdit(
            action="merge",
            path=("components", "app", "properties"),
            value={"image": "example:v2"},
        )
    ],
    path="stacks/app.yaml",
)
print(proposal.diff)

GitOps change helpers

Stacksmith offers small, importable helpers for automated GitOps changes. Document helpers live in stacksmith.authoring, local Git publication lives in stacksmith.repository, and stacksmith.gitops provides convenience compositions. Document helpers validate proposed authored source before writing it; commit_and_push commits only the paths supplied by the caller. CI environment selection lives in stacksmith.ci.selection.

What they do is easily implemented with your own git commands, but these helpers are simply convenient for Python-based automation scripts.

from stacksmith import repository_status, request_operation_rerun

result = request_operation_rerun(
    repo_path=".",
    stack_path="stacks/app.yaml",
    operation="deploy_app",
    expected_head=repository_status(".").head,
    push=False,
)
print(result.rerun_token)

Use update_operation_rerun_token, set_operation_inputs, and update_component_properties when mutation and Git publication should be controlled separately. YAML edits retain surviving comments and scalar styles. Comments on removed keys are removed with those keys. Whole-file Jinja, YAML anchors, aliases, and custom tags are read-only. Document validation checks the stack schema without rendering templates, loading managed configuration, or running platform hooks; use separate inspection and validation workflows for those checks.

The Jenkins and GitHub Actions GitOps entrypoints also support native operation batches. Use COMMAND=plan-operation for a dry run or COMMAND=apply-operation for an approved execution in Jenkins; use the corresponding reusable workflow command value in GitHub Actions. Provide comma-delimited names through OPERATION_NAMES or operation_names, or leave the value empty to select all operations. Set STACKSMITH_FORCE_RERUN=1 in Jenkins folder properties or GitHub repository variables for a definite dispatch. Native operations use the same environment discovery, runfile layering, credentials, branch protections, and deployment approvals as infrastructure applies.

In this pattern, the shared runfile references the platform and service stack layers first, then environment-specific vars and overlays are layered on top.

merge_mode: deep
configs:
  - source: local
    data:
      path: examples/gitops-repo/common/stacksmith.yaml
vars:
  - source: local
    data:
      path: examples/gitops-repo/vars/vars.dev.yaml

For production use, add GitHub Environment protections and secrets per environment. The reusable workflow completes the unprotected plan phase first, then maps each apply phase to the matching GitHub Environment so approvals and scoped credentials gate deployment after the plan is available.

The opinionated workflow resolves STACKSMITH_ENV_FILE from repository variables and falls back to /dev/null so CI runs are deterministic and do not implicitly load repository .env values.

The GitOps workflows save the infrastructure preview to reviewed.tfplan and apply that exact binary after approval, including for destroy previews. Execution restores the generated configuration and provider lockfile from planning instead of regenerating them against the latest branch tip. The plan is bound to the CI manifest, environment, source revision, and run identity; missing, modified, mismatched, or expired plans fail without replanning. OpenTofu rejects stale state, so rerun the complete lifecycle when a saved plan cannot be applied.

GitHub Actions transfers the binary and its configuration context in an encrypted artifact and requires the repository or organization secret STACKSMITH_PLAN_ENCRYPTION_KEY. Jenkins retains them in its protected workspace. See reviewed-plan handling for setup, retention, and review receipts. Native operations continue to plan their isolated state using current outputs, including after-apply operations.

Local publication contracts

commit_and_push and request_operation_rerun require expected_head, the full SHA against which the caller reviewed the change. Relative publication paths resolve from the repository root. Paths must identify explicit files; tracked deletions are supported. Wildcards are treated literally. A local branch must be checked out. destination_branch names only the remote destination and does not create or check out a local branch. Pushing defaults to false.

Local publication builds a commit from selected worktree files using a private index and updates the local branch only if its head still matches expected_head. Unrelated staged changes remain staged. These automation commits use git commit-tree and git update-ref; commit hooks and automatic signing are not invoked. Use the normal Git workflow when those are required. Serialize worktree edits and branch switches during publication.

A successful local commit is retained when pushing fails. Inspect CommitPushResult.pushed and push_error, then use retry_push(result, repo_path) to publish the exact recorded commit, even if local HEAD has since advanced. Pushes never force-update remote branches. branch records the local source branch and destination_branch records the remote destination. If updating selected entries in the real index fails after the commit, index_error records that failure; after resolving the index lock or other problem, synchronize the selected files with git reset <commit_sha> -- <selected-files>. Neither publication failure creates a second commit.

Operation rerun requests check repository prerequisites before editing the document. If local commit creation subsequently fails, the validated document edit remains available for review and another publication attempt.