feat(ci): promote a nightly fill to a draft tests release - #31
Merged
spencer-tb merged 6 commits intoJul 15, 2026
Merged
Conversation
Scheduled nightly runs of `release_fixtures.yaml` already build the mainnet `tests` feature into a release-shaped `fixtures_tests` artifact but never tag or draft anything. Add a `promote_nightly.yaml` workflow that turns the newest such artifact (or an explicit `run_id`) into a draft `tests@<version>` release without refilling: it downloads the nightly tarball, then mirrors the release job's `gh release create` invocation, targeting the exact commit the nightly built so publishing the draft creates the tag on that commit. The job runs in minutes on a hosted runner. The validation lives in (and is unit-tested via) a standalone `promote_nightly.py`, deliberately self-contained rather than sharing helpers with `check_new_commits.py`: the version must be `vX.Y.Z` and greater than the newest existing `tests@` tag, the promoted run must be a successful scheduled run with a live `fixtures_tests` artifact, and the promoted commit must be an ancestor of the branch head. Commits that landed after the nightly are listed in the step summary as not included, so the releaser can choose between promoting and dispatching a fresh full release.
Unwrap the hard-wrapped prose so one paragraph or list item is one line, matching the rest of the repo's markdown docs. Also correct the tag-timing wording: the page said the workflow creates the git tag and then drafts the release, but `gh release create --draft` only stores the tag name and target commit as draft metadata; the tag is created when the draft is published. This means an unpublished draft (a mispicked version, for example) can be edited or deleted without leaving a stray tag behind.
This was referenced Jul 15, 2026
The cached path accepts a skipped `build` in the release job's condition, but a failed `setup` also leaves `build` skipped: under `always()` a cached dispatch whose resolve step failed would start the release job with empty setup outputs and die at the artifact download (no draft is ever created, but the run ends with a red release job instead of a skipped one). Require `setup` to have succeeded explicitly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🗒️ Description
This makes the "cutting
tests@releases directly from the nightly artifact" follow-up from ethereum#3100 concrete: a newpromote_nightly.yamlworkflow turns a nightly fill into a drafttests@<version>release without refilling. Since the nightly fills the mainnettestsfeature through the exact release pipeline, itsfixtures_testsartifact is already release-shaped; promotion downloads it and mirrors the release job'sgh release createinvocation, targeting the exact commit the nightly built, so publishing the draft creates the tag on that commit. The job runs in minutes on a hosted runner; nothing is filled.By default the newest scheduled run with a live
fixtures_testsartifact is promoted: skip-runs upload no artifacts and expired fills cannot be downloaded, so both are passed over;run_idpromotes a specific run instead. Validation lives in a standalone, unit-testedpromote_nightly.py, deliberately self-contained rather than sharing helpers withcheck_new_commits.pyso the two workflows stay decoupled. It fails fast when:versionis notvX.Y.Zor does not exceed the newest existingtests@tag;fixtures_testsartifact exists (past the five-day retention: dispatch a full release instead);Commits that landed after the promoted nightly are listed in the run's step summary as not included, so the releaser can choose between promoting and dispatching a fresh full release.
Commits, in order:
feat(ci): The workflow, the resolution/validation script with its unit tests (10 new cases on the existing fake-ghharness), and a new docs section indocs/dev/releasing_tests.md.docs(ci): Unwrapdocs/dev/releasing_tests.mdand correct the tag-timing wording:gh release create --draftonly stores the tag name and target commit as draft metadata, and the git tag is created when the draft is published. This applies to the existing manual release flow too, so a mispicked version can be fixed by editing the draft, with no stray tag to delete.Notes, flagging for visibility:
promote-nightlyconcurrency group serializes promotions to prevent this.🔗 Related Issues or PRs
Targets the head branch of ethereum#3100, implementing the "cutting
tests@releases directly from the nightly artifact" follow-up listed there.✅ Checklist
just static<type>(<area>):, where<type>and<area>come from an approrpriateC-<type>, respectivelyA-<area>, label. The title should match the a target squash commit message.Cute Animal Picture