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

2 min read

pyssg.deploy.github_pages

GitHub Pages deploy target (pyssg deploy github-pages).

GitHub Pages is published from a git branch, so this target needs no HTTP client and no pyssg[deploy] extra: it shells out to git and force-pushes the built site to a content branch (gh-pages by default). Authentication reuses whatever git already has -- a stored credential helper, an SSH key, or a GITHUB_TOKEN in the environment (used as an HTTPS bearer header when present) -- so the user does not hand pyssg a secret directly.

The push model is deliberately simple and stateless: every deploy builds a brand-new single-commit repository in a temporary directory and force-pushes it over the content branch. The branch therefore holds exactly the current site with no accumulated history, which is what a generated-output branch wants. The source branch and the project's real history are never touched.

Because pyssg emits root-absolute links, the published site must be served from the domain root: a user/org site (<user>.github.io) or a custom domain via cname. Project sites served from <user>.github.io/<repo>/ need a base URL prefix, which pyssg does not yet support.

Configuration (under Config.deploy["github-pages"]):

  • repo (required) -- "owner/name" slug of the GitHub repository.
  • branch (optional, default "gh-pages") -- the content branch to push.
  • cname (optional) -- custom domain; written as a CNAME file and used as the result URL.
  • commit_message (optional) -- literal commit message for the push.
  • remote (optional) -- full git remote URL, overriding the URL derived from repo. Useful for GitHub Enterprise, a self-hosted mirror, or tests against a local bare repository.

This module registers its singleton target at import time; the CLI imports it lazily via :func:pyssg.deploy.load_builtin_targets.

class GitHubPagesTarget

Push the built site to a GitHub Pages content branch via git.

Stateless: the pipeline owns all persistence, and each :meth:deploy call operates entirely inside a fresh temporary directory it cleans up. The only side effects are subprocess calls to git and the network push.

GitHubPagesTarget.required_env(self) -> list[str]

No required env vars; git supplies its own credentials.

GITHUB_TOKEN is consulted when present (HTTPS bearer auth) but is not required: an SSH remote or a configured credential helper works too.

GitHubPagesTarget.required_config_keys(self) -> list[str]

Only repo is mandatory; everything else has a default.

async GitHubPagesTarget.deploy(self, ctx: DeployContext) -> DeployResult

Force-push ctx.out_dir to the configured content branch.

Builds a single-commit repository in a temporary directory, writes the Pages control files (.nojekyll and, if configured, CNAME), and force-pushes it. Returns the new commit sha as the deployment id and the canonical Pages URL. Raises :class:DeployError on any git failure or missing git binary.