fix(pypi): swap OIDC trusted-publisher for twine + PYPI_TOKEN; port .github -> .gitea #6

Merged
devops-engineer merged 1 commits from fix/pypi-gitea-twine-no-oidc into main 2026-05-16 00:18:00 +00:00
Owner

Supersedes PR #4 (which only renamed .github -> .gitea without addressing the dead OIDC trusted-publisher path).

Why

Post-2026-05-06 (Molecule-AI GitHub org suspension), PyPI Trusted-Publisher OIDC does not work for Gitea-hosted repos — PyPI only recognises GitHub / GitLab / Google / ActiveState issuers. The current publish.yml uses pypa/gh-action-pypi-publish (OIDC) and would 4xx on every tag push.

v0.1.3 was tagged earlier today; PyPI is still on v0.1.2. This PR unblocks the v0.1.3 publish.

What changes

  • .github/workflows/{ci,publish}.yml -> .gitea/workflows/. Gitea Actions reads .gitea/ exclusively on this repo (saved memory reference_molecule_core_actions_gitea_only); the .github/ path has been silently dead since migration.
  • Replace pypa/gh-action-pypi-publish with python -m twine upload --username __token__ --password "$PYPI_TOKEN". Mirrors molecule-core/.gitea/workflows/publish-runtime.yml which has shipped runtime versions reliably since 2026-05-11.
  • Drop permissions: id-token: write and environment: pypi (both OIDC-only).
  • Add twine check dist/* to the build step (catches metadata regressions before upload).
  • Add concurrency: { group: publish-pypi, cancel-in-progress: false } so two concurrent tag pushes do not race PyPI upload.
  • Update README "Releasing" section: describe twine + SSOT model, link to operator-config/ops/PYPI_TOKEN_ROTATION.md.

SSOT integration

The PYPI_TOKEN repo secret is fanned out by /opt/molecule-bootstrap/sync-pypi-token.sh (landing in operator-config PR #48). This repo is already listed in etc/pypi-publishers.yaml. After both PRs land + the operator host runs sync-pypi-token.sh --apply, tagged pushes ship to PyPI without further intervention.

Test plan

  • python -c "import yaml; yaml.safe_load(...)" clean on both .gitea/workflows/*.yml.
  • No remaining .github/workflows/ directory (avoids confusion).
  • No remaining pypa/gh-action-pypi-publish or id-token: write references.
  • CI / test (3.11) and (3.12) green on this PR (required checks).
  • After merge: verify v0.1.3 ships to https://pypi.org/project/codex-channel-molecule/ by empty-commit-firing the workflow on the v0.1.3 tag (saved memory reference_empty_commit_is_only_rerun_mechanism_on_1_22_6) since the tag was pushed before this fix landed.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

Supersedes PR #4 (which only renamed .github -> .gitea without addressing the dead OIDC trusted-publisher path). ### Why Post-2026-05-06 (Molecule-AI GitHub org suspension), PyPI Trusted-Publisher OIDC does not work for Gitea-hosted repos — PyPI only recognises GitHub / GitLab / Google / ActiveState issuers. The current `publish.yml` uses `pypa/gh-action-pypi-publish` (OIDC) and would 4xx on every tag push. v0.1.3 was tagged earlier today; PyPI is still on v0.1.2. This PR unblocks the v0.1.3 publish. ### What changes - `.github/workflows/{ci,publish}.yml` -> `.gitea/workflows/`. Gitea Actions reads `.gitea/` exclusively on this repo (saved memory `reference_molecule_core_actions_gitea_only`); the `.github/` path has been silently dead since migration. - Replace `pypa/gh-action-pypi-publish` with `python -m twine upload --username __token__ --password "$PYPI_TOKEN"`. Mirrors `molecule-core/.gitea/workflows/publish-runtime.yml` which has shipped runtime versions reliably since 2026-05-11. - Drop `permissions: id-token: write` and `environment: pypi` (both OIDC-only). - Add `twine check dist/*` to the build step (catches metadata regressions before upload). - Add `concurrency: { group: publish-pypi, cancel-in-progress: false }` so two concurrent tag pushes do not race PyPI upload. - Update README "Releasing" section: describe twine + SSOT model, link to `operator-config/ops/PYPI_TOKEN_ROTATION.md`. ### SSOT integration The `PYPI_TOKEN` repo secret is fanned out by `/opt/molecule-bootstrap/sync-pypi-token.sh` (landing in operator-config PR #48). This repo is already listed in `etc/pypi-publishers.yaml`. After both PRs land + the operator host runs `sync-pypi-token.sh --apply`, tagged pushes ship to PyPI without further intervention. ### Test plan - [x] `python -c "import yaml; yaml.safe_load(...)"` clean on both `.gitea/workflows/*.yml`. - [x] No remaining `.github/workflows/` directory (avoids confusion). - [x] No remaining `pypa/gh-action-pypi-publish` or `id-token: write` references. - [ ] CI / test (3.11) and (3.12) green on this PR (required checks). - [ ] After merge: verify v0.1.3 ships to https://pypi.org/project/codex-channel-molecule/ by empty-commit-firing the workflow on the v0.1.3 tag (saved memory `reference_empty_commit_is_only_rerun_mechanism_on_1_22_6`) since the tag was pushed before this fix landed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hongming added 1 commit 2026-05-15 23:59:57 +00:00
fix(pypi): swap OIDC trusted-publisher for twine + PYPI_TOKEN; port .github -> .gitea
All checks were successful
CI / test (3.11) (pull_request) Successful in 2m55s
CI / test (3.12) (pull_request) Successful in 2m59s
289c65603e
Post-2026-05-06 PyPI Trusted-Publisher OIDC is dead for our repos — PyPI
only accepts GitHub/GitLab/Google/ActiveState issuers, not Gitea. This PR:

1. Renames .github/workflows/{ci,publish}.yml -> .gitea/workflows/. (Gitea
   Actions reads .gitea/ exclusively on this repo; the .github/ path was
   silently dead since the migration — saved memory
   reference_molecule_core_actions_gitea_only.)

2. Replaces `pypa/gh-action-pypi-publish` (which requires OIDC id-token
   exchange that PyPI rejects from Gitea) with `python -m twine upload
   --username __token__ --password "$PYPI_TOKEN"`. Mirrors the canonical
   pattern in molecule-core/.gitea/workflows/publish-runtime.yml that has
   been shipping successfully since 2026-05-11.

3. Drops `permissions: id-token: write` (no longer needed without OIDC).

4. Adds `twine check` to the build step (catches metadata regressions
   before upload).

5. Adds concurrency group to serialize tag-driven publishes.

6. Updates README "Releasing" section to describe the twine+SSOT model
   and link to the operator-config rotation runbook.

The PYPI_TOKEN secret is fanned out to this repo from the operator-host
SSOT by /opt/molecule-bootstrap/sync-pypi-token.sh — see operator-config
PR#48. It supersedes PR#4 (which only renamed .github -> .gitea without
fixing the OIDC issue) and unblocks the pushed v0.1.3 tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
core-devops approved these changes 2026-05-16 00:16:50 +00:00
core-devops left a comment
Member

Emergency direct-merge APPROVE per Hongming chat-side authorization (2026-05-15): bypassing peer-review rounds on OIDC->twine PyPI publish swap + .github->.gitea port. Both required CI contexts green: CI / test (3.11)=success, CI / test (3.12)=success (ci.yml run 60124 status=Success). PR author=hongming; APPROVE via core-devops persona (peer != author).

Emergency direct-merge APPROVE per Hongming chat-side authorization (2026-05-15): bypassing peer-review rounds on OIDC->twine PyPI publish swap + .github->.gitea port. Both required CI contexts green: CI / test (3.11)=success, CI / test (3.12)=success (ci.yml run 60124 status=Success). PR author=hongming; APPROVE via core-devops persona (peer != author).
devops-engineer merged commit 6963378a89 into main 2026-05-16 00:17:59 +00:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: molecule-ai/codex-channel-molecule#6
No description provided.