ci(release): auto-tag on milestone close — dry-run default, RELEASE-gated (Track 4)#1102
Draft
100yenadmin wants to merge 2 commits into
Draft
ci(release): auto-tag on milestone close — dry-run default, RELEASE-gated (Track 4)#1102100yenadmin wants to merge 2 commits into
100yenadmin wants to merge 2 commits into
Conversation
…ated (Track 4) Versioning Phase-2: the automation behind 'complete a milestone → tag/release'. - .github/workflows/release-on-milestone-close.yml: fires on milestone:closed + workflow_dispatch (milestone + dry_run inputs). DRY-RUN DEFAULT TRUE; real tag/ release only on explicit dry_run=false OR repo-var RELEASE_AUTOMATION_LIVE=true. Minimal permissions: contents:write. No gameplay/heavy job; never touches Eva/gateway. - qa/release_gate_check.py: the unit-tested, READ-ONLY gate decision — [release-ready] marker (solves no-milestone-labels) + clean vX.Y.Z title→tag + tag-not-exists + VERSION/__version__ consistency + STATUS:RELEASE (all 11 RRI gates PASSED). Reuses generate_release_notes' DEVELOPMENT/RELEASE logic. Refuses GA on DEVELOPMENT; pre- release may opt in via --allow-prerelease-dev. - qa/test_release_gate_check.py: 15 tests (RELEASE+marker⇒go; DEVELOPMENT⇒no-go; missing-marker⇒no-go; tag-exists⇒no-go; bad-title; version-mismatch; pre-release-dev opt-in; GA-never-on-dev; READ-ONLY-on-db; + a pyyaml-free workflow YAML structural lint). - docs/roadmap/release-automation.md: marker convention + dry-run→live promotion steps.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
| version_file = None | ||
| try: | ||
| version_file = (repo_root / "VERSION").read_text(encoding="utf-8").strip() | ||
| except OSError: |
| m = re.search(r'^__version__\s*=\s*["\']([^"\']+)["\']', text, re.MULTILINE) | ||
| if m: | ||
| engine_version = m.group(1).strip() | ||
| except OSError: |
| import sys | ||
| from pathlib import Path | ||
|
|
||
| import pytest |
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.
Track 4 — Versioning Phase-2: auto-tag on milestone close
The standing repo automation behind the owner's "complete a milestone → tag/release". Built conservatively as a DRAFT, dry-run-by-default, never auto-enabled on prod without validation.
What's here (4 new files, fully additive — no existing file touched)
.github/workflows/release-on-milestone-close.ymlqa/release_gate_check.pyqa/test_release_gate_check.pydocs/roadmap/release-automation.mdThe gate design — solving "GitHub milestones don't support labels"
GitHub milestones can't carry labels, so the "ready-for-release" opt-in is an explicit
[release-ready]marker in the milestone title or description (case-insensitive, literal brackets so prose can't trip it). The full gate (all must hold for a GO):[release-ready]marker present — else NO-GO (a development milestone closing must NOT auto-tag).vX.Y.Z[-rcN]title → tag —Sprint 12,v1.0,v1.0.5 (final)are refused.X.Y.Zmust equalVERSIONandservers/engine/__version__.py.generate_release_notes.py/ the per-gate verdict reports all 11 RRI gates PASSED.DEVELOPMENT(any gate SKIPPED/FAILED/MISSING/UNKNOWN) ⇒ NO-GO. A-rcNpre-release may opt in to ship on DEVELOPMENT viaallow_prerelease_dev; a GA always requires RELEASE.The decision lives in
qa/release_gate_check.py(extracted from YAML) so it's unit-tested rather than ad-hoc shell. It reusesgenerate_release_notes' DEVELOPMENT/RELEASE logic so there is ONE definition of the flag.Dry-run safety (why merging this is safe)
dry_rundefaults totrue. A realmilestone: closedevent has no input → dry-run, unless the owner sets repo varRELEASE_AUTOMATION_LIVE=true.dry_run=falseor the live repo-var reachesgit tag+gh release create. The real step re-confirms the tag is free immediately before cutting (defense-in-depth).permissions: contents: write. No gameplay/heavy job; reads the scores ledger READ-ONLY; never touches Eva or any gateway.Validation
qa/test_release_gate_check.py: 15 passed (the four load-bearing cases + edges).test_generate_release_notes.py,test_version_consistency.py): 30 passed.actionlinton the new workflow: clean (exit 0).scripts/license_check.py: passed.scores.db/ledger: untouched.Promoting from dry-run to live (needs owner sign-off)
[release-ready]milestone (title == bumped VERSION, all-PASS RRI artifact wired in).gh workflow run "release-on-milestone-close.yml" -f milestone=vX.Y.Z -f dry_run=false) or standing (gh variable set RELEASE_AUTOMATION_LIVE --body true).gh release(pre-release iff-rc) and the generated notes body.Kept DRAFT per the conservative scope — flipping to real mode needs owner sign-off + one successful dry-run.