pyssg is pre-1.0 and under active development - APIs, config, and themes may change.
pyssg.deploy.pipeline

1 min read

pyssg.deploy.pipeline

Provider-agnostic orchestrator for pyssg deploy <target>.

This is the only public entry point a CLI command (or programmatic caller) needs to invoke a deploy. It strings together the steps that every target shares so each target stays focused on the one thing it cannot delegate -- the actual upload to its provider.

Pipeline, in order:

  1. Load the site config and pull the [deploy.<target>] section.
  2. Look up the target in the registry; fail clearly if it is unknown.
  3. Validate environment variables and required config keys.
  4. Build the site (unless skip_build and out_dir already exists).
  5. Sanity-check the output (unless skip_check): at least one file present.
  6. Hash the output tree and compare against the previous deploy record; short-circuit with a friendly "no changes" message unless force.
  7. If dry_run, report what would be uploaded and stop.
  8. Run target.deploy(ctx) (async); the pipeline blocks on it.
  9. Persist the new record and print the friendly summary.

The function is sync; only target.deploy is async, since real targets will want concurrent uploads via httpx. The pipeline owns clock access (datetime.now) so the rest of the deploy subsystem stays pure.

run_deploy(site_dir: Path, target_name: str, *, dry_run: bool = False, force: bool = False, skip_build: bool = False, skip_check: bool = False, targets: dict[str, DeployTarget] | None = None, console: Console | None = None) -> DeployResult

Run the deploy pipeline for target_name against site_dir.

targets overrides the global registry (used by tests for isolation); console overrides stdout/stderr (also used by tests). Raises :class:DeployError on any user-actionable failure; the CLI wrapper turns that into error: ... on stderr and a non-zero exit code.