Skip to content

chore(release): conclave-cli distribution + OIDC publish workflow + dep audit#42

Closed
ernestprovo23 wants to merge 2 commits into
mainfrom
chore/v1-distribution-release-eng
Closed

chore(release): conclave-cli distribution + OIDC publish workflow + dep audit#42
ernestprovo23 wants to merge 2 commits into
mainfrom
chore/v1-distribution-release-eng

Conversation

@ernestprovo23

@ernestprovo23 ernestprovo23 commented Jun 14, 2026

Copy link
Copy Markdown
Member

PR-A of the conclave v1.0 release: distribution + release-engineering.
Implements readiness-review must-dos #1 (distribution + publish workflow), #2
scaffolding (release runbook; the version bump + CHANGELOG land in the release
commit, not here), and #6 (pip-audit in CI).

What changed

1. Distribution rename → conclave-cli

The PyPI name conclave is taken by an unrelated project (a blockchain client).

  • pyproject.toml [project].nameconclave-cli. Command (conclave),
    import package (conclave), and repo all unchanged.
    Added [project.urls].
    Version left at 0.3.0 — the 1.0.0 bump is the release commit (see RELEASING.md).
  • README install → pip install conclave-cli, with a short note documenting the
    install-name vs command/import split, and that the PyPI conclave package is an
    unrelated project. Editable source install kept for development.
  • Verified: python -m build now emits conclave_cli-0.3.0{.tar.gz,-py3-none-any.whl}.

2. OIDC publish workflow — .github/workflows/release.yml

  • Trigger on: release: published (a pushed tag alone does nothing).
  • Jobs: build (python -m build sdist+wheel → artifact) → pypi-publish
    (pypa/gh-action-pypi-publish, OIDC Trusted Publishing, no stored token, PEP 740
    attestations
    ) → sign (sigstore/gh-action-sigstore-python keyless; signs
    sdist+wheel, attaches .sigstore bundles to the Release; self-verifies).
  • Every uses: SHA-pinned with a # vX.Y.Z comment.
  • Top-of-file comment: inert until a Release is published AND the conclave-cli
    Trusted Publisher is configured.
Action Pin (commit SHA) Tag
actions/checkout 11bd71901bbe5b1630ceea73d27597364c9af683 v4.2.2
actions/setup-python a26af69be951a213d495a4c3e4e4022e16d87065 v5.6.0
actions/upload-artifact ea165f8d65b6e75b540449e92b4886f43607fa02 v4.6.2
actions/download-artifact d3f86a106a0bac45b974a628896c90dbdf5c8093 v4.3.0
pypa/gh-action-pypi-publish cef221092ed1bacb1cc03d23a2d87d1d172e277b v1.14.0
sigstore/gh-action-sigstore-python 5b79a39c381910c090341a2c9b0bf022c8b387e1 v3.4.0

3. pip-audit in CI — fail-closed

New audit job in test.yml runs pip-audit --skip-editable against resolved
deps and fails CI on a known vuln. Rationale: conclave is security-positioned,
the dep surface is tiny (httpx + a few well-maintained libs) so false-positive
churn is low, and there is an --ignore-vuln escape hatch documented in RELEASING.md.
Currently: no known vulnerabilities.

4. Dependency lockfile

requirements-dev.lock — hash-pinned dev + runtime tree via
uv pip compile --universal --generate-hashes --python-version 3.11 --extra dev pyproject.toml -o requirements-dev.lock.

5. RELEASING.md runbook

One-time PyPI Trusted-Publisher setup for conclave-cli, cut-a-release checklist
(bump version→1.0.0 in both pyproject.toml and src/conclave/__init__.py,
finalize CHANGELOG, tag, publish Release), post-release verification (Sigstore
bundle, PEP 740 attestations), rollback/yank.

6. Test-infra fix (CI unblock)

tests/test_logging.py asserted an exact len(logger.handlers) == 1. Under
pytest 9.1.0 the logging plugin attaches LogCaptureHandlers to every logger,
inflating the count to 3 and failing CI (and a fresh local resolve) independent of
source changes. The two assertions now count only conclave's own handler, excluding
pytest's capture handlers — preserving intent, robust to the runner. Production
logging is unchanged (outside pytest it installs exactly one StreamHandler).

Owner action required (one-time, manual)

Configure the conclave-cli PyPI Trusted Publisher before the first release
(RELEASING.md §0). Until then the publish job fails closed — nothing is published.

Invariants

ruff check + ruff format --check pass; build emits correctly-named artifacts;
191/191 tests pass; coverage 88.91% (floor 75). No version bump, no tag, no publish.

…ep audit

Distribution + release-engineering for the v1.0 cut (readiness review must-dos
1, 2 scaffolding, and 6):

- pyproject: [project].name -> conclave-cli (PyPI `conclave` is an unrelated
  project). Command (`conclave`), import package (`conclave`), and repo are
  unchanged. Adds [project.urls]. Version left at 0.3.0 (the 1.0.0 bump is the
  release commit per RELEASING.md).
- README: install is now `pip install conclave-cli`, with a note on the
  install-name vs command/import split; editable source install kept for dev.
- .github/workflows/release.yml: OIDC Trusted-Publishing publish workflow,
  triggered on `release: published`. build (python -m build) -> pypi-publish
  (pypa/gh-action-pypi-publish, no token, PEP 740 attestations) -> sign
  (Sigstore keyless, attaches .sigstore bundles to the Release). Every `uses:`
  pinned to a full commit SHA with a `# vX.Y.Z` comment. Inert until a Release
  is published AND the conclave-cli Trusted Publisher is configured.
- test.yml: new fail-closed `pip-audit` job auditing the resolved deps.
- requirements-dev.lock: hash-pinned dev + runtime tree (uv pip compile
  --generate-hashes) for reproducible installs.
- RELEASING.md: operator runbook (one-time Trusted-Publisher setup, cut-a-release
  checklist, post-release verification, rollback/yank).
- DOCUMENTATION_INDEX.md: index the new release-eng artifacts + version history.
…andlers

pytest 9.x's logging plugin attaches LogCaptureHandler instances to every
logger during a test, inflating raw len(logger.handlers). The two handler-count
assertions in test_logging.py asserted an exact total of 1 and now see 3 under
pytest 9.1.0, failing in CI (and on a fresh local resolve) regardless of source
changes. Filter capture handlers out so the tests assert on the single handler
get_logger actually installs -- preserving their intent while being robust to
the runner. Production logging code is unchanged (outside pytest it adds exactly
one StreamHandler).
@ernestprovo23

Copy link
Copy Markdown
Member Author

Superseded by #45 (integrated into the v1.0.0 release commit).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant