This checklist takes a local pgpkg repository to a production-ready GitHub repository with automated PyPI publishing.
- Create an empty GitHub repo (for example,
pgpkg). - Add the remote and push:
git remote add origin git@github.com:<OWNER>/pgpkg.git
git push -u origin <BRANCH>- Push all long-lived branches you want preserved.
- Enable branch protection on the default branch:
- Require pull request before merging
- Require status checks to pass
- Require branches to be up to date before merging
- Require these checks from CI:
qualityunit (3.11)unit (3.12)unit (3.13)integration (postgres:14-alpine)integration (postgres:15-alpine)integration (postgres:16-alpine)integration (postgres:17-alpine)build-docs
- Enable "Automatically delete head branches" after merge.
- Enable Dependabot alerts and security updates.
- In Settings -> Pages, set Source to
GitHub Actionsso.github/workflows/docs-pages.ymlcan publish the MkDocs site.
You need an account on:
- You must be an Owner or Maintainer for the project on PyPI.
- You must have admin rights on the GitHub repository to configure environments and workflows.
This repository already includes .github/workflows/publish-pypi.yml, which is configured for trusted publishing.
Create these environments in GitHub:
pypi
Optional hardening:
- Add required reviewers for
pypienvironment - Restrict deployment branches/tags
In PyPI project settings, add a trusted publisher with:
- Owner:
<OWNER> - Repository:
pgpkg - Workflow filename:
publish-pypi.yml - Environment:
pypi
With trusted publishing configured correctly:
- No PyPI API token is needed in GitHub secrets.
- No username/password is needed in CI.
- The only required "credential" in CI is GitHub's OIDC identity (
id-token: write, already set in workflow).
You still need:
- GitHub account with repo admin rights
- PyPI account with project owner/maintainer rights
Only use this if trusted publishing cannot be enabled.
- Create a project-scoped API token in PyPI.
- Add these repository secrets:
PYPI_API_TOKEN
- Update publish workflow to pass
password: ${{ secrets.<TOKEN_NAME> }}topypa/gh-action-pypi-publish.
- Run local gate:
uv run pre-commit run --all-files
uv run ty check src tests
uv run pytest -q
uv build --out-dir dist
uv run python -m twine check dist/*
uv run mkdocs build --strict- Create GitHub Release tag
v0.1.0to trigger PyPI publish.
Optional manual path:
- GitHub Actions ->
Publish->Run workflow->expected_version=0.1.0
- Verify install from PyPI:
uv venv /tmp/pgpkg-smoke
uv pip install --python /tmp/pgpkg-smoke/bin/python pgpkg
/tmp/pgpkg-smoke/bin/pgpkg --helpThe Publish workflow's build job also smoke-tests a generated wrapper wheel,
so a successful publish already validates both the base CLI wheel and the
wrapper packaging path before upload.
TestPyPI is intentionally not wired up in this repository right now. If access is restored later, add a separate environment and publish job rather than reusing the PyPI lane implicitly.
Add canonical URLs in pyproject.toml:
[project.urls]
Homepage = "https://github.com/<OWNER>/pgpkg"
Repository = "https://github.com/<OWNER>/pgpkg"
Documentation = "https://<OWNER>.github.io/pgpkg/"
Issues = "https://github.com/<OWNER>/pgpkg/issues"- "invalid-publisher" or "publisher not trusted": trusted publisher fields do not exactly match repo/workflow/environment. For this repo, confirm
bitner/pgpkg, workflowpublish-pypi.yml, and environmentpypiexactly. - Publish job not starting: verify environment name in workflow matches configured environment.
- Artifact missing in publish job: ensure build job used
uv build --out-dir distand uploadeddist/*.