Skip to main content

Package publishing (a2c-core, a2c-cli, a2c-tui)

Three lockstep Python distributions are built and published from this repository (ai-workflows/a2c-workflow).

PyPI distributionImport packageConsole script
a2c-corea2c_core
a2c-clia2c_clia2c
a2c-tuia2c_tuia2c-tui

All three share one product version (a2c_core.__version__, root VERSION, git tag vX.Y.Z).

Release runbook: release-pipeline.md

Normative policy: ADR-0010 (specializes ADR-0009)

Package layout

  • Build: PEP 517 setuptools via packages/*/pyproject.toml
  • Source: shared src/a2c_core/, src/a2c_cli/, src/a2c_tui/
  • Version: src/a2c_core/__init__.py (__version__) — synced by scripts/bump_release.py
  • Dependencies: a2c-cli and a2c-tui pin a2c-core==X.Y.Z in their pyproject.toml

Local development install

pip install -e "./packages/a2c-core" -e "./packages/a2c-cli" -e "./packages/a2c-tui" -e ".[dev]"

Or run ./scripts/setup-dev.sh (Windows: .\scripts\setup-dev.ps1).

Local build and smoke

python scripts/build_packages.py
python -m twine check dist/*
python scripts/smoke_install_packages.py --dist dist --expected-version 0.1.1 --venv .smoke-venv
a2c validate --help

Artifacts: six files in dist/ (wheel + sdist for each distribution).

CI pipeline (GitLab)

StageJobWhen
lintpre-commit, workflow-docs:contractfeature branch / develop / release/* / MR
testtest:pytestfeature branch / develop / release/* / MR
buildbuild:packageDevelopment CI (build only; no registry publish)
buildbuild:a2c-cli-binaryDevelopment CI (linux x64 artifact: dist/binary/a2c)
buildbuild:a2c-cli-binary-linux-arm64Development CI (linux arm64 artifact: dist/binary/a2c)
buildbuild:a2c-tui-binaryDevelopment CI (linux x64 artifact: dist/binary/a2c-tui)
buildbuild:a2c-tui-binary-linux-arm64Development CI (linux arm64 artifact: dist/binary/a2c-tui)
buildpackage:buildtags v*.*.* (final X.Y.Z artifacts)
releaserelease:verifytags
releasepackage:smoketags (local wheel smoke at X.Y.Z)
publishpublish:gitlabtags (automatic, X.Y.Z)
publishpublish:testpypitags (automatic; queries TestPyPI, publishes unused X.Y.ZrcU)
publishpackage:smoke-testpypitags (smoke X.Y.ZrcU from TestPyPI)
publishpublish:pypitags (automatic after TestPyPI smoke; uploads X.Y.Z)
publishpackage:smoke-pypitags (smoke X.Y.Z from PyPI)

Development CI never publishes to TestPyPI or PyPI.

Automated tag publishing flow (ADR-0010)

  1. package:build builds final-release wheels at X.Y.Z.
  2. publish:testpypi queries TestPyPI, selects the first unused X.Y.ZrcU (starting at rc1), rebuilds wheels at that version, and uploads.
  3. package:smoke-testpypi installs the published X.Y.ZrcU from TestPyPI.
  4. publish:pypi asserts X.Y.Z is absent on PyPI, then uploads the package:build artifacts.
  5. package:smoke-pypi installs X.Y.Z from PyPI.

A tagged commit is released only after publish:pypi and package:smoke-pypi both succeed.

Scripts:

  • scripts/registry_publish.py — registry queries and version guards
  • scripts/build_packages.py --publish-version — temporary rc builds for TestPyPI

GitLab PyPI registry

https://gitlab.com/api/v4/projects/<PROJECT_ID>/packages/pypi
VariablePurpose
CI_JOB_TOKENBuilt-in; upload to GitLab package registry

TestPyPI

VariablePurpose
TWINE_PASSWORD_TESTPYPITestPyPI API token (masked, protected)

PyPI (production)

VariablePurpose
TWINE_PASSWORD_PYPIPyPI API token (masked, protected)

Register three projects on PyPI / TestPyPI: a2c-core, a2c-cli, a2c-tui.

Release flow (summary)

  1. Curate CHANGELOG.md [Unreleased] during development.
  2. Create release/X.Y.Z from master and run python scripts/bump_release.py.
  3. Green Development CI on release/X.Y.Z.
  4. Push tag vX.Y.ZRelease CI runs the automated publish chain above.
  5. Fast-forward master only after Release CI is released (PyPI smoke green).

Details: release-pipeline.md.