Agent skill

python3-publish-release-pipeline

Set up CI/CD pipeline for Python package publishing to PyPI. Use when preparing to publish a package, when setting up automated releases, or when configuring GitHub Actions or GitLab CI for Python projects.

Stars 33
Forks 4

Install this agent skill to your Project

npx add-skill https://github.com/Jamie-BitFlight/claude_skills/tree/main/plugins/python3-development/skills/python3-publish-release-pipeline

SKILL.md

<pipeline_target>$ARGUMENTS</pipeline_target>

Python Release Pipeline Configuration

The model configures CI/CD pipelines for automated Python package publishing.

Arguments

<pipeline_target/>

If no argument provided, detect from repository (look for .github/ or .gitlab-ci.yml).

Instructions

Consult ../python3-development/references/python3-standards.md when applying shared architecture, typing, testing, or CLI rules; full standards, graphs, and amendment process are documented there.

  1. Detect CI platform (GitHub Actions or GitLab CI)
  2. Create workflow files for testing, linting, and publishing
  3. Configure secrets documentation for PyPI tokens
  4. Set up version management with git tags
  5. Document release process

GitHub Actions Pipeline

Directory Structure

text
.github/
├── workflows/
│   ├── ci.yml           # Run on every push/PR
│   ├── release.yml      # Run on version tags
│   └── docs.yml         # Optional: documentation
└── dependabot.yml       # Optional: dependency updates

CI Workflow (ci.yml)

yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v4
        with:
          enable-cache: true

      - name: Set up Python
        run: uv python install 3.11

      - name: Install dependencies
        run: uv sync --all-extras

      - name: Run ruff
        run: |
          uv run ruff check src/ tests/
          uv run ruff format --check src/ tests/

      - name: Run type check (ty default; swap to mypy if hooks/CI run mypy — not merely [tool.mypy])
        run: uv run ty check src/ tests/

  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v4
        with:
          enable-cache: true

      - name: Set up Python ${{ matrix.python-version }}
        run: uv python install ${{ matrix.python-version }}

      - name: Install dependencies
        run: uv sync --all-extras

      - name: Run tests
        run: uv run pytest tests/ -v --cov=src --cov-report=xml

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          files: coverage.xml
          fail_ci_if_error: false

Release Workflow (release.yml)

yaml
name: Release

on:
  push:
    tags:
      - "v*.*.*"

permissions:
  contents: write
  id-token: write  # Required for trusted publishing

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v4

      - name: Set up Python
        run: uv python install 3.11

      - name: Build package
        run: uv build

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

  # Option 1: Trusted Publishing (Recommended)
  publish-pypi:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: pypi
      url: https://pypi.org/p/your-package
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        # No token needed with trusted publishing!

  # Option 2: Token-based Publishing (Alternative)
  # publish-pypi:
  #   needs: build
  #   runs-on: ubuntu-latest
  #   steps:
  #     - name: Download artifacts
  #       uses: actions/download-artifact@v4
  #       with:
  #         name: dist
  #         path: dist/
  #
  #     - name: Publish to PyPI
  #       uses: pypa/gh-action-pypi-publish@release/v1
  #       with:
  #         password: ${{ secrets.PYPI_API_TOKEN }}

  github-release:
    needs: [build, publish-pypi]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: dist/*
          generate_release_notes: true

GitLab CI Pipeline

.gitlab-ci.yml

yaml
stages:
  - lint
  - test
  - build
  - publish

variables:
  UV_CACHE_DIR: "$CI_PROJECT_DIR/.uv-cache"
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"

default:
  image: python:3.11-slim
  before_script:
    - pip install uv
    - uv sync --all-extras
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .uv-cache/
      - .pip-cache/
      - .venv/

lint:
  stage: lint
  script:
    - uv run ruff check src/ tests/
    - uv run ruff format --check src/ tests/
    - uv run ty check src/ tests/

test:
  stage: test
  parallel:
    matrix:
      - PYTHON_VERSION: ["3.11", "3.12", "3.13"]
  image: python:${PYTHON_VERSION}-slim
  script:
    - uv run pytest tests/ -v --cov=src --cov-report=xml --junitxml=report.xml
  coverage: '/TOTAL.*\s+(\d+%)/'
  artifacts:
    reports:
      junit: report.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml

build:
  stage: build
  script:
    - uv build
  artifacts:
    paths:
      - dist/
    expire_in: 1 week

# Publish to PyPI on tags
publish:pypi:
  stage: publish
  rules:
    - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
  script:
    - uv publish --token $PYPI_TOKEN
  environment:
    name: pypi
    url: https://pypi.org/project/your-package

# Publish to GitLab Package Registry on tags
publish:gitlab:
  stage: publish
  rules:
    - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
  script:
    - |
      TWINE_PASSWORD=${CI_JOB_TOKEN} \
      TWINE_USERNAME=gitlab-ci-token \
      uv publish --publish-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi
  environment:
    name: gitlab-registry

Trusted Publishing Setup (PyPI)

Why Trusted Publishing?

  • No API tokens to manage
  • No secrets to rotate
  • Cannot be leaked
  • Scoped to specific workflows

Setup Steps

  1. Go to PyPI → Your Project → Publishing

  2. Add GitHub Publisher:

    • Owner: your-username
    • Repository: your-repo
    • Workflow name: release.yml
    • Environment: pypi (optional but recommended)
  3. Create GitHub Environment:

    • Settings → Environments → New environment: pypi
    • Add protection rules (optional):
      • Required reviewers
      • Restrict to tags only

Alternative: API Token

If trusted publishing isn't available:

  1. Create PyPI Token:

    • PyPI → Account Settings → API tokens
    • Create token scoped to your project
  2. Add to Repository Secrets:

    • GitHub: Settings → Secrets → PYPI_API_TOKEN
    • GitLab: Settings → CI/CD → Variables → PYPI_TOKEN

Version Management

Manual Version (pyproject.toml)

Update version in pyproject.toml before tagging:

toml
[project]
version = "1.2.3"

Dynamic Version from Git Tags

Using hatch-vcs:

toml
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

[project]
dynamic = ["version"]

[tool.hatch.version]
source = "vcs"

[tool.hatch.build.hooks.vcs]
version-file = "src/my_package/_version.py"

Release Workflow

bash
# 1. Update CHANGELOG.md

# 2. Commit changes
git add -A
git commit -m "Prepare release v1.2.3"

# 3. Create annotated tag
git tag -a v1.2.3 -m "Release v1.2.3"

# 4. Push with tags
git push origin main --tags

TestPyPI for Testing

GitHub Actions TestPyPI Job

yaml
publish-testpypi:
  needs: build
  runs-on: ubuntu-latest
  environment:
    name: testpypi
    url: https://test.pypi.org/p/your-package
  steps:
    - uses: actions/download-artifact@v4
      with:
        name: dist
        path: dist/

    - uses: pypa/gh-action-pypi-publish@release/v1
      with:
        repository-url: https://test.pypi.org/legacy/

Manual TestPyPI Upload

bash
# Build
uv build

# Upload to TestPyPI
uv publish --publish-url https://test.pypi.org/legacy/ --token $TESTPYPI_TOKEN

# Test install
uv pip install --index-url https://test.pypi.org/simple/ your-package

Required Configuration Files

Minimum Files for Publishing

text
your-package/
├── pyproject.toml          # Package metadata and build config
├── README.md               # Required by PyPI
├── LICENSE                 # Required for distribution
├── src/
│   └── your_package/
│       ├── __init__.py
│       └── py.typed        # PEP 561 marker
└── .github/
    └── workflows/
        ├── ci.yml
        └── release.yml

pyproject.toml Checklist

text
- [ ] [build-system] with requires and build-backend
- [ ] [project] with name, version, description
- [ ] readme = "README.md"
- [ ] license specified
- [ ] requires-python = ">=3.11"
- [ ] authors with name and email
- [ ] classifiers (Development Status, License, Python versions)
- [ ] dependencies list
- [ ] [project.urls] with Documentation, Issues, Source
- [ ] [project.scripts] if CLI tool

Security Best Practices

  1. Use Trusted Publishing over API tokens
  2. Scope tokens to specific projects (not account-wide)
  3. Use environments with protection rules
  4. Pin action versions with full SHA or version tags
  5. Review workflow changes carefully
  6. Enable branch protection on main

Troubleshooting

Build Fails

bash
# Check package metadata
uv run python -m build --no-isolation
uvx twine check dist/*

Upload Fails

bash
# Verify token
echo $PYPI_TOKEN | head -c 10

# Check package name availability
curl https://pypi.org/pypi/your-package/json

Version Already Exists

PyPI doesn't allow re-uploading the same version. Increment version and create new tag.


References

Expand your agent's capabilities with these related and highly-rated skills.

Jamie-BitFlight/claude_skills

ccc

This skill should be used when code search is needed (whether explicitly requested or as part of completing a task), when indexing the codebase after changes, or when the user asks about ccc, cocoindex-code, or the codebase index. Trigger phrases include 'search the codebase', 'find code related to', 'update the index', 'ccc', 'cocoindex-code'.

33 4
Explore
Jamie-BitFlight/claude_skills

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction.

33 4
Explore
Jamie-BitFlight/claude_skills

delegate

Quick delegation template for sub-agent prompts. Use when assigning work to a sub-agent, before invoking the Agent tool, or when preparing prompts for specialized agents. Provides the WHERE-WHAT-WHY framework. For comprehensive delegation guidance, activate the agent-orchestration how-to-delegate skill.

33 4
Explore
Jamie-BitFlight/claude_skills

swarm-spawning

Spawn agents and teammates in Claude Code swarms. Use when choosing between subagents vs teammates, selecting agent types (Explore, Plan, general-purpose, plugin agents), configuring spawn backends (in-process, tmux, iterm2), or setting environment variables for spawned agents.

33 4
Explore
Jamie-BitFlight/claude_skills

knowledge-explorer

Manage the research/ knowledge base (KB) of tool and library research entries. Use when browsing KB topics, adding new research entries, updating existing entries with dated revisions, fetching GitHub repo metadata into a draft KB entry, or migrating old-format entries to skill-spec frontmatter. Triggers on tasks like "what do we have on X", "add this to the KB", "update the KB entry for Y", "fetch github info for owner/repo", or "migrate old entries".

33 4
Explore
Jamie-BitFlight/claude_skills

design-anti-patterns

Enforce anti-AI UI design rules based on the Uncodixfy methodology. Use when generating HTML, CSS, React, Vue, Svelte, or any frontend UI code. Prevents "Codex UI" — the generic AI aesthetic of soft gradients, floating panels, oversized rounded corners, glassmorphism, hero sections in dashboards, and decorative copy. Applies constraints from Linear/Raycast/Stripe/GitHub design philosophy: functional, honest, human-designed interfaces. Triggers on: UI generation, dashboard building, frontend component creation, CSS styling, landing page design, or any task producing visual interface code.

33 4
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results