Maintaining the SDK¶
Automation and release policy¶
The Release workflow runs the SDK checks after each push to main. Release
Please then creates or updates a release pull request containing the next
version in pyproject.toml, the SDK's version in uv.lock, the release manifest,
and this site's release notes. Merging that pull request authorizes publication:
Actions creates a GitHub release, builds and validates its distributions, and
uploads them to PyPI using short-lived OIDC credentials. No PyPI API token or
GitHub personal access token is required.
Release Please uses SemVer tags such as v0.1.0-alpha.1; Python packaging
normalizes the equivalent version to 0.1.0a1. The manifest starts at
0.1.0-alpha.0, matching the unpublished 0.1.0a0 package. While alpha is
selected, ordinary features and fixes increment the alpha counter. Breaking
changes can advance the underlying minor version before 1.0. The release PR
shows the resulting version before publication.
Use Conventional Commit messages for squash-merged PRs: feat: ... for a new
capability, fix: ... for a correction, and docs: ... for documentation.
Use feat!: ... or a BREAKING CHANGE: footer for incompatible changes.
Repository-only changes can use ci:, test: or chore:. Release Please derives
version updates and release notes from these messages; ordinary prose commit
titles can be omitted from release notes. Do not hand-edit release versions or
merge a release PR before its checks pass.
The workflow uses GitHub's built-in token. Because PRs it creates do not trigger
pull_request workflows, it explicitly dispatches SDK checks on each generated
release branch. This gives the release PR checks without introducing a separate
long-lived credential. The release workflow runs the same reusable checks before
creating a release, and validates built package metadata against the release tag.
Only the publishing job receives id-token: write, and that job installs no
project code. Distribution files are also attached to the GitHub release after
successful publication.
The lockfile JSONPath uses name.value because the pinned Release Please TOML
updater wraps scalar values with source-position metadata. It selects only the
SDK package's version and preserves the dependency pins. When updating Release
Please, check the generated release PR with uv lock --check before merging.
Stable release remains an owner decision. To move to 0.1.0, change versioning
to default, set prerelease to false, remove prerelease-type, and temporarily
set release-as to 0.1.0 in the package entry in release-please-config.json.
Review and merge the resulting release PR, then remove release-as so subsequent
versions are calculated automatically. Update the alpha classifier and installation
instructions at the same time. Leave the manifest under automation's control.
One-time account setup¶
Complete these steps before merging the first release PR. The repository is currently private; publishing packages and documentation does not require changing its visibility. GitHub Pages support for private repositories depends on the organization's plan, and a Pages site can be public even when its repository is private. Choose the intended documentation visibility in the repository settings.
- In the SDK repository's Settings → Actions → General, allow GitHub Actions to create and approve pull requests. The workflow requests its individual permissions explicitly. This setting permits release PR creation; the workflow does not approve its own PRs.
- Create a GitHub environment named
pypi. Restrict deployment branches tomain: the release workflow runs onmain, even though its build checks out the release tag. If using required reviewers, publication waits for that review; otherwise merging the release PR is the release decision. Run manual publication retries frommainas well. - Sign in to PyPI with a verified email and two-factor authentication. Before the project exists, register a pending Trusted Publisher with:
| Field | Value |
|---|---|
| PyPI project name | porestore |
| GitHub owner | porolytics |
| Repository | porestore-sdk |
| Workflow filename | release.yml |
| Environment name | pypi |
If the PyPI project already exists and is owned by your account, configure the
same publisher under that project's Publishing settings. The package name
was absent from PyPI during preparation; a pending publisher does not reserve
it. The first successful publish creates the project. Confirm availability
before the first release. Keep the workflow filename and environment name
identical to the trusted publisher record.
4. In Settings → Pages, select GitHub Actions as the source. The
Publish documentation workflow publishes the strict Zensical build after
each push to main. If the plan does not support Pages for this private repo,
retain the CI-built documentation artifact and choose a supported host before
enabling deployment. The expected Pages URL is
https://porolytics.github.io/porestore-sdk/.
5. Require the SDK's Python and documentation checks under the repository's
branch rules. Inspect the first successful workflow's actual check names
before choosing required checks. Keep the normal review requirements for
release PRs; the workflow does not merge them automatically.
The account registrations above are external prerequisites. Workflow files alone do not register a PyPI publisher, enable Pages, or prove a successful deployment.
Local verification and documentation¶
make check-dist checks PyPI metadata, version identity, license and typed-package
contents, then installs both the wheel and source distribution in separate clean
environments. It imports every exported object and tool namespace without service
credentials. Keep dist/ free of older builds so only the intended files can be
published. All SDK tests use mocked transports and make no paid submissions.
Zensical and mkdocstrings-python are locked in the docs dependency group.
Before building, scripts/prepare_docs.py derives the notebook guide from the
README and adjusts its relative documentation links. The generated guide is
ignored by Git. Rerun make docs-serve after editing the README. The site retains the
analysis guide, and automatically discovers public source modules with
api-autonav. Private modules and the internal network decoder are excluded.
Public signatures and existing docstrings produce the API reference; explanatory
guides still require editorial maintenance. Improving a public docstring updates
its reference page on the next build. Examples are rendered as code and are not
executed against PoreStore during documentation builds.
CI builds documentation on PRs and uploads a downloadable preview artifact.
Deployment uses a separate github-pages environment and job. Zensical builds
start clean, following its current CI guidance. GitHub Actions dependencies are
pinned to commit SHAs, with monthly Dependabot PRs for updates.
Failed publication and recovery¶
If checks fail, fix the problem before merging the release PR. If publication
fails after GitHub creates the release, first correct the publisher configuration
or environment restriction shown in the Actions logs. For a release that has not
uploaded files to PyPI, run Actions → Release → Run workflow on main and
enter the existing tag, such as v0.1.0-alpha.1. The workflow reruns checks on
that tag, verifies that a published GitHub release exists, rebuilds the package,
and checks its version before uploading.
PyPI versions and filenames are immutable. The publishing action deliberately does not skip existing files. If a prior attempt uploaded some or all files, inspect the published files and their hashes before deciding how to recover; do not overwrite or delete them to retry. A code change needs a new release PR and version. If publication succeeded and only the GitHub asset upload failed, rerun that failed job so PyPI is not invoked again.