Skip to content

feat: Support multi-package PyPI publishing #1175

Description

@myakove

Problem

The current PyPI publishing support assumes one Python package per repo — it always builds at the worktree root. Repos like myk-org/pi-config have 2 Python packages in different directories:

  • Root: myk-pi-tools (hatchling, pyproject.toml)
  • packages/pi-sidecar/: pi-sidecar-client (setuptools, packages/pi-sidecar/pyproject.toml)

Currently there's no way to specify subdirectories or build/publish multiple packages.

Current Behavior

  • Config schema: pypi: {token: "..."} — flat, no package paths
  • push_handler.pyupload_to_pypi(): on tag push, checks out tag into worktree, runs uv build --sdist at worktree root, then twine upload — only finds the root package
  • runner_handler.pyrun_install_python_module(): PR check runs uvx pip wheel at worktree root — one package only
  • check_run_handler.py: registers one status check (PYTHON_MODULE_INSTALL_STR)
  • github_api.py: self.pypi: dict[str, str] — flat dict with just token

Proposed Solution

1. Schema change (webhook_server/config/schema.yaml)

Add optional packages list to pypi:

pypi:
  token: <PYPI TOKEN>
  packages:           # optional — defaults to ["."] (repo root)
    - "."
    - "packages/pi-sidecar"

Backward compatible — if packages is absent, behaves like today (root only).

2. Config loading (webhook_server/libs/github_api.py)

Add pypi_packages property that resolves to ["."] when packages key is absent.

3. Push handler (webhook_server/libs/handlers/push_handler.py)

Loop upload_to_pypi() over each package directory:

  • Build each package in its own subdirectory
  • Upload each package separately
  • Create issue on failure per package

4. Runner handler (webhook_server/libs/handlers/runner_handler.py)

Loop run_install_python_module() over each package dir. Option to register separate check runs per package (e.g., Python module install [myk-pi-tools]) or keep one combined check.

5. Check run handler (webhook_server/libs/handlers/check_run_handler.py)

If separate checks per package: register PYTHON_MODULE_INSTALL_STR per package name. If combined: no change needed.

Files to change

File Change
webhook_server/config/schema.yaml Add packages array to pypi
examples/config.yaml Add example with packages
webhook_server/libs/github_api.py Parse pypi.packages, add pypi_packages property
webhook_server/libs/handlers/push_handler.py Loop upload_to_pypi over each package dir
webhook_server/libs/handlers/runner_handler.py Loop run_install_python_module over each package dir
Tests Cover multi-package config + build/upload loop

Backward Compatibility

Zero breaking changes — pypi: {token: "..."} without packages defaults to root-only, exactly as today.

Done

  • Schema updated with packages array under pypi
  • github_api.py parses pypi.packages with ["."] default
  • push_handler.py loops upload_to_pypi over each package dir
  • runner_handler.py loops run_install_python_module over each package dir
  • examples/config.yaml updated with multi-package example
  • Tests cover multi-package config, build, and upload

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions