Secure PyPI Publishing Workflow

VerifiedSafe

Complete interactive workflow for publishing Python packages to PyPI using GitHub Actions with Trusted Publishers. Includes versioning, validation, and automatic workflow generation.

Sby Skills Guide Bot
DevOpsIntermediate
107/25/2026
Claude Code
#pypi#python-package#github-actions#oidc#secure-publishing

Recommended for

Our review

Automates a secure GitHub Actions workflow to publish Python packages to PyPI using OIDC (Trusted Publishers), with interactive PEP 440 versioning and project validation.

Strengths

  • Validates project structure before attempting to publish
  • Offers interactive PEP 440‑compliant version bumping (alpha, beta, RC, stable)
  • Uses OIDC-based Trusted Publishers for enhanced security
  • Automatically generates the required GitHub Actions workflow file

Limitations

  • Requires a Git repository and targets only GitHub Actions for CI/CD
  • Only supports Python packages using pyproject.toml, setup.py, or setup.cfg
  • Interactive versioning may be too rigid for custom version schemes
When to use it

When you need a secure, automated PyPI publishing pipeline with version bumping and project structure checks.

When not to use it

If you use a different CI system (e.g., Jenkins, GitLab CI) or prefer fully manual version control without an interactive assistant.

Security analysis

Safe
Quality score92/100

The skill performs standard package publishing tasks using secure OIDC method. It uses git commands and Python invocations for validation and configuration, but no destructive or exfiltrating actions are instructed. The generated workflow pushes packages to PyPI via trusted publisher, which is safe.

No concerns found

Examples

Set up secure PyPI publishing
I want to publish my Python package to PyPI securely with automatic version bumping. Please use GitHub Actions and OIDC.
Create release workflow for PyPI
Help me create a GitHub Actions workflow that publishes to PyPI using Trusted Publishers, with interactive version selection (alpha, beta, RC, stable).
Publish new version with version bump
I need to publish a new release of my Python package. Guide me through version bumping and set up the PyPI publish workflow.

name: secure-pypi-publish description: Complete workflow for publishing Python packages to PyPI securely using GitHub Actions and Trusted Publishers (OIDC). Includes interactive PEP 440 versioning, structure validation, and automatic workflow generation. allowed-tools: Bash(git:), Bash(python:), Read, Write, Edit, Question

Secure PyPI Publishing Workflow

You are a Python package publishing specialist. When the user activates this skill, execute the following sequential and interactive workflow:

Phase 1: Project Validation

1.1 Verify Git Environment

  • Execute git rev-parse --is-inside-work-tree to confirm you're in a Git repository
  • If not a Git repo, inform the user and halt the process

1.2 Detect Project Type

Search in order of preference:

  1. pyproject.toml (recommended)
  2. setup.py
  3. setup.cfg

Read the first file found and extract:

  • Package name: Search in [project.name], setup(name=...), or [metadata] name
  • Current version: Search in [project.version], [tool.poetry.version], setup(version=...), or [metadata] version

1.3 Get Repository Information

  • Execute git remote get-url origin to get the repo URL
  • Parse the URL to extract: owner/organization and repository name
  • Validate that remote is configured correctly

1.4 Validate Minimum Structure

Verify that at least one exists:

  • Source code directory (package name)
  • __init__.py file or Python modules

If validation fails, ask the user if they want to continue anyway.

Phase 2: Interactive Versioning (PEP 440)

2.1 Display Current Version

Present to the user:

Current version detected: X.Y.Z
Package name: your-package
Repository: owner/repo

2.2 Select Release Type

Use the question tool to ask:

Main question:

What kind of release is this?

Options:

  1. Stable (e.g., 1.0.0) - Final release, production-ready
  2. Alpha (e.g., 1.0.0a1) - New features in development, unstable API
  3. Beta (e.g., 1.0.0b1) - Feature complete, testing for bugs
  4. Release Candidate (e.g., 1.0.0rc1) - Potential final version, final testing

2.3 For Pre-releases (Options 2-4)

If the user selects Alpha, Beta, or RC:

Ask for iteration number:

Enter the pre-release iteration number (default: 1):
  • Validate it's a positive integer
  • If empty, use 1

2.4 Calculate New Version

Apply PEP 440 rules:

For Stable:

  • If current version is 1.2.3 and user wants minor bump → 1.3.0
  • Ask which part to increment: major, minor, or patch

For Pre-releases:

  • If current version is 1.2.3 and user chooses Beta iteration 1 → 1.2.3b1
  • If pre-release already exists (e.g., 1.2.3b1) and chooses Beta iteration 2 → 1.2.3b2

PEP 440 Format:

  • Alpha: X.Y.ZaN (e.g., 1.0.0a1, 2.3.4a2)
  • Beta: X.Y.ZbN (e.g., 1.0.0b1, 2.3.4b2)
  • Release Candidate: X.Y.ZrcN (e.g., 1.0.0rc1, 2.3.4rc3)

2.5 Confirm Version

Display:

New version will be: X.Y.Z[suffix]

Version breakdown:
- Base version: X.Y.Z
- Release type: [Stable|Alpha|Beta|Release Candidate]
- Pre-release iteration: N (if applicable)

Confirm this version? [y/N]

If not confirmed, return to step 2.2.

2.6 Update Configuration File

Modify the file detected in Phase 1:

pyproject.toml:

[project]
name = "your-package"
version = "X.Y.Zsuffix"

or if using Poetry:

[tool.poetry]
name = "your-package"
version = "X.Y.Zsuffix"

setup.py:

setup(
    name="your-package",
    version="X.Y.Zsuffix",
    ...
)

setup.cfg:

[metadata]
name = your-package
version = X.Y.Zsuffix

Use the Edit tool to make the precise change.

Phase 3: GitHub Actions Setup

3.1 Create Directory Structure

mkdir -p .github/workflows

3.2 Generate Workflow File

Create .github/workflows/pypi-publish.yml using the template from templates/pypi-publish.yml:

  • Replace {{PACKAGE_NAME}} with the package name
  • Workflow must use Trusted Publishers (OIDC) - DO NOT use API tokens
  • Configure GitHub Environment: pypi
  • Trigger: push tags with pattern v*

3.3 Create/Update .gitignore (if necessary)

Verify if .gitignore exists and ensure it includes:

# Python
__pycache__/
*.py[cod]
*$py.class
dist/
build/
*.egg-info/

# Virtual environments
venv/
env/
.venv/

Phase 4: Final Instructions

Generate and display the following formatted output:

====================================================================
🎉 Your secure publishing flow (secure-pypi-publish) is ready!
====================================================================

To finish publishing version [X.Y.Zsuffix] of [package-name], 
follow exactly these steps:

1️⃣ CONFIGURE TRUSTED PUBLISHER ON PYPI:
   Go to: https://pypi.org/manage/account/publishing/
   
   Click "Add a new pending publisher" and fill in:
   - PyPI Project Name: [package-name]
   - Owner: [owner]
   - Repository name: [repo-name]
   - Workflow name: pypi-publish.yml
   - Environment name: pypi
   
   Note: If the package already exists on PyPI, go to:
   https://pypi.org/manage/project/[package-name]/publishing/

2️⃣ CREATE THE GITHUB ENVIRONMENT:
   Go to: https://github.com/[owner]/[repo-name]/settings/environments/new
   
   Create an environment named: pypi
   
   (Optional) Add protection rules:
   - Required reviewers for deployments
   - Wait timer before deployments
   - Deployment branches: main (or your default branch)

3️⃣ SAVE CHANGES IN GIT:
   Run in your terminal:
   
   git add .github/workflows/pypi-publish.yml [config-file]
   git commit -m "chore: setup secure PyPI publishing for vX.Y.Zsuffix"
   git push origin [default-branch]

4️⃣ CREATE THE TAG AND TRIGGER THE PIPELINE:
   To trigger the publishing process, create a version tag and push it:
   
   git tag -a vX.Y.Zsuffix -m "Release vX.Y.Zsuffix"
   git push origin vX.Y.Zsuffix

👀 Track your publishing status at:
   https://github.com/[owner]/[repo-name]/actions

📚 Documentation:
   - PEP 440 Versioning: https://peps.python.org/pep-0440/
   - Trusted Publishers: https://docs.pypi.org/trusted-publishers/
   - GitHub Actions Environments: https://docs.github.com/en/actions/deployment/targeting-different-environments

💡 Tips:
   - Test on TestPyPI first: Replace pypi.org with test.pypi.org in step 1
   - Monitor the Actions run to catch any build errors
   - Verify the package appears on PyPI after successful publish
====================================================================

Technical Notes

Parsing pyproject.toml

  • Use simple regular expressions or manual parsing (avoid dependencies)
  • Search for [project] or [tool.poetry] section
  • Keep the rest of the file intact

Error Handling

  • If configuration file cannot be parsed, show error and halt
  • If current version doesn't comply with PEP 440, warn the user
  • If remote is not configured, suggest git remote add origin <url>

Optional Validations

  • Check if package name already exists on PyPI (warning, not error)
  • Check if there are uncommitted changes (ask if they want to continue)

Compatibility

  • Support Python 3.8+
  • Don't require external tools (only git and standard python)
  • Work on Linux, macOS, and Windows

References

Related skills