Skip to content

Auto-publish .dev releases on every push to main#1472

Open
mikasenghaas wants to merge 4 commits into
mainfrom
devx/auto-dev-tags
Open

Auto-publish .dev releases on every push to main#1472
mikasenghaas wants to merge 4 commits into
mainfrom
devx/auto-dev-tags

Conversation

@mikasenghaas
Copy link
Copy Markdown
Member

@mikasenghaas mikasenghaas commented May 26, 2026

Summary

Split the release pipeline into two independent flows so dev and stable releases never share infrastructure:

  • Dev releases (.github/workflows/devx_tag.yml) — self-contained. On every push to main, the workflow enumerates v* tags to pick the next vX.Y.(Z+1).dev1 (from a stable parent) or vX.Y.Z.dev(N+1) (from a dev parent), creates a lightweight tag at main HEAD via the git-refs API, checks out the tag, overrides verifiers/__init__.py's __version__ to the dev value in the workflow checkout only (uncommitted), runs uv build, and publishes to PyPI via Trusted Publisher (pypi-prod environment, OIDC). No release-notes file, no GitHub Release — dev releases are just "tag + build + push to PyPI". Modeled on prime-rl's devx_tag.yaml.
  • Stable releases (.github/workflows/tag-and-release.yml) — unchanged in shape, but reserved for non-dev tags only. Push trigger excludes v*.dev*, auto-tag-on-main skips with an explanatory message when verifiers/__init__.py is bumped to a .dev value, and the dispatched / pushed-tag flow errors on .dev tags. Still requires assets/release/RELEASE_<tag>.md and still creates a GitHub Release.

verifiers/__init__.py's __version__ is treated as the latest stable release version and is only ever modified by a stable release-prep PR. devx_tag.yml never touches it. As part of this PR __version__ is reset from the legacy 0.1.15.dev11 to 0.1.14 (the actual latest stable on PyPI) so the invariant holds from day one.

devx_tag.yml defers to the stable flow when a push already modifies verifiers/__init__.py, so a stable release-prep PR never produces two tags for the same SHA. After a stable cut, the next push to main automatically produces the first .dev1 of the next patch cycle without touching main.

Docs in assets/release/release_workflow.md and .github/workflows/README.md are rewritten around the two flows and the new __init__.py = latest stable invariant.

Breaking

  • tag-and-release.yml no longer accepts .dev tags via push trigger or workflow_dispatch. Use devx_tag.yml instead (runs automatically on every push to main; can also be dispatched manually).
  • Manually bumping verifiers/__init__.py to a vX.Y.Z.devN value is no longer how dev releases ship. auto-tag-on-main now skips that case with an explanatory log line so it does not race with devx_tag.yml. The convention going forward is: __version__ only ever changes when shipping a stable release.
  • New dev tags do not produce a GitHub Release entry. Dev releases are consumed via PyPI (pip install verifiers==X.Y.Z.devN or pip install verifiers --pre).
  • A git checkout vX.Y.Z.devN will show __version__ equal to the latest stable, not the dev value, because the dev override is never committed. The wheel installed from PyPI still reports the dev version correctly.
  • verifiers/__init__.py is reset from 0.1.15.dev11 to 0.1.14. Source installs (e.g. pip install -e . from a main clone) will now report 0.1.14 instead of 0.1.15.dev11. Wheels installed from PyPI continue to report their own dev/stable version.

Setup required

Before merging, add a PyPI Trusted Publisher entry for the new workflow:

  • Project: verifiers
  • Owner: PrimeIntellect-ai
  • Repository: verifiers
  • Workflow file: devx_tag.yml
  • Environment: pypi-prod

(The existing entry for tag-and-release.yml stays in place for stable releases.)

Test plan

  • Add the PyPI Trusted Publisher entry for devx_tag.yml + pypi-prod before merging.
  • After merge, verify the next push to main produces a vX.Y.Z.devN tag (lightweight, pointing at main HEAD) and that the DevX Tag workflow publishes the wheel to PyPI labeled with that version.
  • Verify a stable release-prep PR that bumps verifiers/__init__.py to a non-dev version is handled only by tag-and-release.yml's auto-tag-on-main and that devx_tag.yml skips it.
  • Verify workflow_dispatch on tag-and-release.yml with a .devN tag errors with "Dev tags are not accepted by this workflow".

Note

High Risk
Changes production PyPI publishing and tagging on every merge to main; misconfiguration or tag logic bugs could publish wrong versions or collide with stable releases.

Overview
Splits dev and stable publishing into separate GitHub Actions flows and documents the maintainer workflow end-to-end.

A new devx_tag.yml runs on every push to main (and manual dispatch): it skips when verifiers/__init__.py changed (stable prep), computes the next vX.Y.Z.devN tag from existing v* tags, creates a lightweight tag at HEAD, patches __version__ only in the CI checkout for uv build, and publishes to PyPI via OIDC—no GitHub Release or RELEASE_*.md.

tag-and-release.yml is narrowed to stable releases: tag pushes ignore v*.dev*, auto-tag-on-main refuses a dev __version__ bump, and manual/tag resolution errors on dev tags. assets/release/release_workflow.md and .github/workflows/README.md describe the two pipelines and PyPI Trusted Publisher setup for both workflows.

verifiers/__init__.py is reset to 0.1.14 as the on-main stable version string (replacing 0.1.15.dev11), matching the model where dev numbers live on tags/wheels, not on main.

Reviewed by Cursor Bugbot for commit 713fa05. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Auto-publish .dev releases to PyPI on every push to main

  • Adds devx_tag.yml, a new workflow that runs on every push to main, computes the next vX.Y.Z.devN tag, creates it at the push SHA, builds a wheel and sdist, and publishes them to PyPI via OIDC Trusted Publisher.
  • Skips the dev release flow when the push modifies verifiers/init.py, which always reflects the latest stable version and is not bumped for dev releases.
  • Updates tag-and-release.yml to exclude v*.dev* tags and exit early if __version__ is set to a dev value, so only stable vX.Y.Z tags go through the stable release path.
  • Resets __version__ to 0.1.14 (from 0.1.15.dev11) to reflect the latest stable release in the repo.

Macroscope summarized 713fa05.

Adds .github/workflows/devx_tag.yml, modeled on prime-rl's devx_tag.yaml.
On every push to main (and on workflow_dispatch), it:

- enumerates v* tags to compute the next dev tag (vX.Y.(Z+1).dev1 from a
  stable parent, vX.Y.Z.dev(N+1) from a dev parent),
- builds a synthetic commit on top of the current main HEAD that bumps
  verifiers/__init__.py to the new version and writes a stub release
  notes file at assets/release/RELEASE_<tag>.md (auto-generated from the
  git log since the previous tag),
- annotates and pushes the tag without touching the main branch,
- dispatches tag-and-release.yml for that tag so the existing build +
  PyPI publish + GitHub Release pipeline runs unchanged.

When a push already modifies verifiers/__init__.py the workflow skips,
deferring to tag-and-release.yml's auto-tag-on-main job (so manual
stable releases or legacy release-prep PRs never produce two tags for
the same SHA).

Documents the new flow in assets/release/release_workflow.md and lists
the workflow in .github/workflows/README.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
@macroscopeapp
Copy link
Copy Markdown

macroscopeapp Bot commented May 26, 2026

Approvability

Verdict: Needs human review

Unable to check for correctness in 713fa05. This PR adds automatic PyPI publishing on every push to main, which is a significant production deployment infrastructure change. Additionally, there's an unresolved medium-severity comment about a potential race condition in the skip logic that could cause duplicate tag creation.

You can customize Macroscope's approvability policy. Learn more.

mikasenghaas and others added 2 commits May 26, 2026 13:35
Dev releases (devx_tag.yml) are now self-contained: compute next dev
tag, build a synthetic commit that bumps verifiers/__init__.py, push
the tag, then build and publish to PyPI via Trusted Publisher
(pypi-prod environment, OIDC). No release-notes file, no GitHub
Release — dev releases are just "tag + push to PyPI".

Stable releases (tag-and-release.yml) keep the existing
assets/release/RELEASE_<tag>.md + GitHub Release flow, and explicitly
reject .dev tags so the split is enforced end-to-end:

- push tag trigger excludes v*.dev*
- auto-tag-on-main skips with an explanatory message if __init__.py is
  bumped to a .dev value (since dev versions are owned by devx_tag.yml)
- workflow_dispatch / pushed-tag flow errors on .dev tags

Docs in assets/release/release_workflow.md and
.github/workflows/README.md are reworked to describe the two
independent flows.

Co-authored-by: Cursor <cursoragent@cursor.com>
verifiers/__init__.py's __version__ is now treated as the latest
stable release version. devx_tag.yml never touches it. The dev flow
collapses to prime-rl's exact pattern: create a lightweight tag at
main HEAD, then override __init__.py in the workflow checkout only
(uncommitted) before building so the wheel carries the dev version.

Source installs from main therefore always report the latest stable
version. The dev version only exists on the published wheel — there is
no drift to chase between main's __version__ and PyPI.

Updated docs in assets/release/release_workflow.md and the workflows
README to describe the invariant.

Co-authored-by: Cursor <cursoragent@cursor.com>
if [ -z "$BEFORE_SHA" ] || [ "$BEFORE_SHA" = "0000000000000000000000000000000000000000" ]; then
echo "skip=false" >> "$GITHUB_OUTPUT"
exit 0
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid before skips init guard

Medium Severity

When github.event.before is empty or the all-zero SHA, the skip step sets skip=false and exits before checking whether verifiers/__init__.py changed. A force-push or first push to main that lands stable release prep can still get a .dev tag and PyPI publish while auto-tag-on-main skips tagging for the same reason.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 18ff1cd. Configure here.

@mikasenghaas mikasenghaas changed the title Auto-publish .dev releases on every push to main Derive verifiers version from git tags; auto-publish dev releases on every push to main May 26, 2026
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 51406cb. Configure here.

Comment thread pyproject.toml Outdated
verifiers/__init__.py's __version__ is the single source of truth for
the latest *stable* release. The legacy manual flow had been updating
it to dev values (most recently 0.1.15.dev11); under the new split
release pipeline only stable releases bump this file, so reset it to
the actual latest stable on PyPI.

tag-and-release.yml's auto-tag-on-main will see this as a downgrade,
try to create v0.1.14, find it already exists, and no-op. devx_tag.yml
sees __init__.py modified in this push and defers.

Co-authored-by: Cursor <cursoragent@cursor.com>
@mikasenghaas mikasenghaas changed the title Derive verifiers version from git tags; auto-publish dev releases on every push to main Auto-publish .dev releases on every push to main May 26, 2026
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