How to Set Up Publishing to PyPI

This guide covers configuring your generated project to publish packages to PyPI, TestPyPI, GitHub Packages, and GitHub Releases.

Enable publishing during generation

When running copier copy, answer yes to the publishing questions:

🎤 Publish to TestPyPI?
   Yes
🎤 Publish to PyPI?
   Yes
🎤 Publish to GitHub Packages?
   Yes
🎤 Attach artifacts to GitHub release?
   Yes

If you already generated your project, you can re-run copier to enable publishing — see below.

Configure PyPI trusted publishing

The generated publish workflow uses trusted publishing (OpenID Connect) — no API tokens needed.

For PyPI

  1. Go to pypi.org and create an account

  2. Navigate to PublishingAdd a new pending publisher

  3. Fill in:

    • PyPI project name: your package name (e.g., my-awesome-project)

    • Owner: your GitHub username or organization

    • Repository name: your GitHub repository name

    • Workflow name: publish.yml

    • Environment name: publish_pypi

  4. Click Add

For TestPyPI

  1. Go to test.pypi.org and create an account

  2. Navigate to PublishingAdd a new pending publisher

  3. Fill in the same details but with:

    • Environment name: publish_testpypi

  4. Click Add

Configure GitHub environments

The publish workflow uses GitHub environments for deployment protection:

  1. Go to your repository SettingsEnvironments

  2. Create these environments as needed:

    • publish_testpypi — for TestPyPI publishing (triggered on push to main)

    • publish_pypi — for PyPI publishing (triggered on release)

    • publish_github_packages — for GitHub Packages (triggered on release)

    • attach_to_github_release — for release artifacts (triggered on release)

  3. Optionally add required reviewers for production environments

Trigger a publish

TestPyPI (on every push to main)

TestPyPI publishing triggers automatically when you push to the main branch. Merge a PR or push directly:

git push origin main

PyPI and GitHub Releases (on release)

  1. Create a GitHub release using the release drafter:

    • Go to ReleasesDraft a new release

    • The release drafter pre-populates notes from merged PRs

    • Choose a semantic version tag (e.g., v1.0.0)

    • Click Publish release

  2. The publish workflow triggers automatically

Re-run copier to enable publishing

If you generated your project without publishing enabled, re-run copier to add it:

copier update /path/to/your-project

Answer yes to the publishing questions you want to enable. Copier merges the new workflow configuration into your existing project.

Verify the workflow

Check the Actions tab in your GitHub repository to monitor workflow runs. Each publishing destination runs as a separate job with its own environment protection.

The build job always runs regardless of publishing configuration — it builds the package and uploads artifacts to GitHub Actions for manual inspection.