Skip to content

ci(publish): fix Soda PyPI --skip-existing + single approval gate#2759

Merged
paulteehan merged 2 commits into
mainfrom
fix/publish-soda-pypi-and-approval
Jun 16, 2026
Merged

ci(publish): fix Soda PyPI --skip-existing + single approval gate#2759
paulteehan merged 2 commits into
mainfrom
fix/publish-soda-pypi-and-approval

Conversation

@paulteehan

@paulteehan paulteehan commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #2758 — two fixes surfaced by the first v4.14.0 publish run.

1. Fix the Soda PyPI (pypi.cloud.soda.io) upload — don't drop it

The run failed on the Soda leg:

UnsupportedConfiguration: The configured repository 'https://pypi.cloud.soda.io'
does not have support for the following features: --skip-existing

The registry wasn't the problem — the flag was. #2758 added --skip-existing
to every upload leg, but pypi.cloud.soda.io is a devpi index that rejects it.
The old release.yaml always uploaded to Soda PyPI plain (no --skip-existing),
which is why it worked.

soda-core clean releases are still needed on Soda PyPI, so we keep the leg and fix
idempotency per-registry:

  • public PyPI → keeps twine upload --skip-existing (supported).
  • pypi.cloud.soda.io → uploads plain; captures twine output and treats an
    "already exists" / 409 rejection as success, so re-runs and backfills stay safe.

⚠️ Note for registry owners: soda-core 4.x packages (soda-postgres,
soda-snowflake, …) share names with soda-library 1.x on this same index.
Publishing soda-core's 4.x there can shadow soda-library's identically-named
1.x packages for any consumer resolving from cloud PyPI. This restores the
pre-#2758 behaviour intentionally; worth confirming a consumer actually needs
soda-core clean releases from cloud before relying on it.

2. Collapse 14 approval emails into one

The matrix publish job referenced environment: production-release directly, so
each of the 14 matrix legs raised its own deployment approval → 14 emails per
release. A tiny approve gate job now carries the environment; the matrix
needs: it and no longer references the environment itself. Safe because
PYPI_API_TOKEN is a repo-level secret, so the matrix keeps secret access.

resolve → approve (production-release, ONE approval) → publish [matrix ×14]

Verification

  • YAML parses; job graph: resolveapprove (env) → publish (matrix, no env).
  • Soda PyPI leg uploads without --skip-existing (devpi-compatible) and tolerates
    duplicate-version rejections.
  • Public PyPI leg unchanged from ci: add publish-from-tag workflow for PyPI #2758.
  • --skip-existing on public PyPI + the duplicate-tolerant Soda leg make re-running
    on an already-published tag (e.g. v4.14.0) a safe no-op.

🤖 Generated with Claude Code

Two fixes to publish.yaml from the first 4.14.0 run:

1. Drop the Soda PyPI (pypi.cloud.soda.io) upload. It errored on
   `--skip-existing` (unsupported by that index), and it shouldn't be a
   target: that index serves the soda-library 1.x line that scan-launcher
   builds from, and soda-library's connectors share package names with
   soda-core's (soda-postgres, soda-snowflake, ...). Publishing soda-core's
   4.x there collides with soda-library's identically-named 1.x packages.
   Nothing consumes soda-core clean releases from cloud (launchers pull
   soda-core dev builds from the dev platform index). soda-core clean
   releases belong on public PyPI only. Removes the now-unused AWS
   secrets-manager fetch too.

2. Collapse the 14 environment approvals into one. The matrix publish job
   referenced `production-release` directly, so each of the 14 legs raised
   its own approval (14 emails). A tiny `approve` gate job now carries the
   environment; the matrix depends on it and drops the environment. Safe
   because PYPI_API_TOKEN is a repo-level secret.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reverses the "drop Soda PyPI" half of this branch — soda-core clean
releases are still needed on pypi.cloud.soda.io. The original failure was
not that the registry is wrong, but that #2758 passed --skip-existing to
every leg, and pypi.cloud.soda.io (devpi) rejects that flag:

  UnsupportedConfiguration: 'https://pypi.cloud.soda.io' does not have
  support for the following features: --skip-existing

Fix per-registry instead of removing the leg:
  - public PyPI        -> keeps `twine upload --skip-existing` (supported)
  - pypi.cloud.soda.io -> upload plain; capture output and treat an
                          "already exists" / 409 rejection as success, so
                          re-runs and backfills stay idempotent

Keeps this branch's single-approval gate (one approval email per run, not
one per matrix leg). Restores the AWS secrets fetch the Soda leg needs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@paulteehan paulteehan changed the title ci(publish): public PyPI only + single approval gate ci(publish): fix Soda PyPI --skip-existing + single approval gate Jun 16, 2026
@sonarqubecloud

Copy link
Copy Markdown

@paulteehan paulteehan merged commit 0e5aea3 into main Jun 16, 2026
20 checks passed
@paulteehan paulteehan deleted the fix/publish-soda-pypi-and-approval branch June 16, 2026 15:13
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.

2 participants