Skip to main content

cal-publish-python

CLI tool to publish Python packages and documentation with external configuration.

Overview

cal-publish-python is designed to keep sensitive configuration (tokens, registry URLs, SSH keys) outside of build jobs. The project being published defines the "what" (name, version), while a named profile in the publishing configuration defines the "where" (registry, documentation platform).

Installation

pip install cal-publish-python

Or with uv:

uv pip install cal-publish-python

Usage

# Publish everything in output/ (wheel + docs zip)
cal-publish-python --set-latest output/

# Publish only the PyPI package
cal-publish-python --pypi-only output/

# Publish only the documentation
cal-publish-python --docs-only --set-latest output/

# Specify a profile explicitly
cal-publish-python --profile internal --set-latest output/

# Specify individual files
cal-publish-python output/my-package-1.0.0-py3-none-any.whl output/my-package-1.0.0-docs.zip

CLI Arguments

Argument Short Description
ARTIFACT Directory or file(s) to publish (.whl and/or docs .zip)
--config -c Path to JSON configuration file
--profile Profile to use from the configuration file
--pypi-only Only publish to PyPI (skip documentation)
--docs-only Only publish documentation (skip PyPI)
--set-latest -l Also set this version as 'latest' (GitLab Pages mode only)
--force -f Overwrite existing documentation version if it exists
--verbose -v Verbose output

Configuration

Profiles

Configuration uses named profiles. Each profile contains the full set of publishing settings (PyPI credentials, documentation targets, etc.). This allows the same config file to serve both public and internal publishing.

Create a JSON config file at ~/.config/cal-publish-python/config.json:

{
    "profiles": {
        "public": {
            "pypi": {
                "token": "pypi-xxxxxxxxxxxx",
                "username": "__token__",
                "repository_url": "https://upload.pypi.org/legacy/"
            },
            "docs": {
                "mode": "gitlab-pages",
                "gitlab_pages": {
                    "token": "glpat-xxxxxxxxxxxx",
                    "url": "https://gitlab.com",
                    "group": "mygroup/public/docs"
                }
            }
        },
        "internal": {
            "pypi": {
                "token": "nexus-xxxxxxxxxxxx",
                "username": "deploy-user",
                "repository_url": "https://nexus.internal/repository/pypi/"
            },
            "docs": {
                "mode": "ssh",
                "ssh": {
                    "host": "docs.internal",
                    "base_path": "/var/www/docs"
                }
            }
        }
    }
}

Profile Selection

A profile is required when a config file is present. The profile is resolved in this order:

  1. --profile NAME CLI argument
  2. CAL_PUBLISH_PROFILE environment variable
  3. [tool.cal-publish-python] in pyproject.toml:
[tool.cal-publish-python]
profile = "public"

This means each project can declare which profile it uses, and make publish just works without any extra arguments.

Config File Location

The config file is resolved in this order:

  1. --config FILE CLI argument
  2. CAL_PUBLISH_CONFIG environment variable
  3. ~/.config/cal-publish-python/config.json (default)

If no config file exists at the default path, the tool runs in environment-variable-only mode (useful for CI).

Environment Variables

All configuration values can be overridden by environment variables, regardless of what the config file/profile contains:

Variable Description
CAL_PUBLISH_CONFIG Path to JSON config file
CAL_PUBLISH_PROFILE Profile name to use from config file
CAL_PUBLISH_PYPI_TOKEN PyPI API token or password
CAL_PUBLISH_PYPI_USERNAME PyPI username (default: __token__)
CAL_PUBLISH_PYPI_REPOSITORY_URL PyPI repository URL
CAL_PUBLISH_DOCS_MODE Documentation mode (gitlab-pages, ssh, or cal-docs-server)
CAL_PUBLISH_GITLAB_TOKEN GitLab personal access token
CAL_PUBLISH_GITLAB_URL GitLab instance URL
CAL_PUBLISH_GITLAB_GROUP GitLab group for docs
CAL_PUBLISH_SSH_HOST SSH host
CAL_PUBLISH_SSH_BASE_PATH Base path on remote server
CAL_PUBLISH_SSH_KEY Path to SSH private key
CAL_PUBLISH_SSH_USER SSH user
CAL_PUBLISH_SSH_PORT SSH port
CAL_PUBLISH_DOCS_SERVER_URL cal-docs-server URL
CAL_PUBLISH_DOCS_SERVER_TOKEN API token for cal-docs-server

Integration with Makefile

Add a publish target to your project's Makefile:

.PHONY: publish
publish: check-dependencies
	uv run cal-publish-python --set-latest output/

And declare the profile in pyproject.toml:

[tool.cal-publish-python]
profile = "public"

Documentation Zip Filename

The docs zip filename is used to determine the project name and version:

project-name-VERSION-docs.zip

Examples: myproject-1.0.0-docs.zip, my-lib-2.3.4.post5+gabcdef-docs.zip

Development

# Clone the repository
git clone <repo-url>
cd cal-publish-python

# Set up development environment
make dev

# Run checks
make check

# Build
make build

Licence

MIT License - Copyright (c) 2026 Cyber Assessment Labs

Metadata

Release files for cal-publish-python 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for cal-publish-python 1.1.1
File Interpreter ABI Platform
cal_publish_python-1.1.1-py3-none-any.whl Python 3 none any Details

Release files / cal_publish_python-1.1.1-py3-none-any.whl

Download URL cal_publish_python-1.1.1-py3-none-any.whl
Size 31.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e98076c067948d45db90dee31a6d27266ac31c01f2afa89fb50dd9dafb5d34c
BLAKE2b-256 checksum
How to use checksums
77b0b93de5beae576e96d206d147f0dff972365f4980a6bddd35da1e10d49f75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.2

Release history Release notifications | RSS feed

This release

1.1.1 This release

1 release file

1.1.0

1 release file

1.0.0

1 release file

0.7.2

1 release file

0.7.1

1 release file

0.7.0

1 release file

0.6.0

1 release file

0.5.3

1 release file

0.5.2

1 release file

0.5.0

1 release file

0.4.1

1 release file

0.4.0

1 release file

0.3.1

1 release file

0.3.0

1 release file

0.2.3

1 release file

0.2.2

1 release file

0.2.0

1 release file

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page