Files
hermes-agent/scripts/releases/draft_warning.py
ethernet 1c2abc0cbf docs(release): the Store submission is held and published by hand
The publication pass checks the held Store submission and prints the
Publish now step; it cannot release it. The developer guide and the draft
warning said the pass released it.
2026-09-23 17:16:19 -04:00

60 lines
2.4 KiB
Python

"""Fenced draft-body warning and its strip, shared by the entrypoint and publish.
Immutable releases take no edits after publication, so the draft carries a
caution against publishing it by hand at both ends of the body and the
publication pass strips both fenced blocks while the release is still a draft.
The helpers live here so the entrypoint and the publish step can import them
without a cycle.
"""
from __future__ import annotations
WARNING_OPEN = "<!-- hermes-release:draft-warning -->"
WARNING_CLOSE = "<!-- /hermes-release:draft-warning -->"
_WARNING = """> [!CAUTION]
> ## **DO NOT PUBLISH THIS RELEASE FROM GITHUB.**
> **This is attempt `{attempt_ref}`. Publishing it here skips the `v{version}` receipt tag, the update feeds, the Docker aliases, and the Store check. Releases are immutable, so a release published here cannot be fixed.**
>
> **Run this instead:**
> ```
> python scripts/release.py publish --version {version}
> ```
> **To drop this attempt:** `python scripts/release.py abandon --version {version}`"""
def draft_body(*, version: str, attempt_ref: str, notes: str) -> str:
"""The draft body: fenced warning block, generated notes, fenced warning block."""
block = "\n".join([WARNING_OPEN, _WARNING.format(version=version, attempt_ref=attempt_ref),
WARNING_CLOSE])
return "\n".join([block, notes, block])
def strip_draft_warning(body: str) -> str:
"""Remove each fenced warning block, fence lines included.
The fences must pair up in order; anything else means the draft body was
edited underneath the tool, and publish refuses rather than publishing a
mangled body.
"""
kept: list[str] = []
inside = False
for line in body.splitlines():
stripped = line.strip()
if inside:
if stripped == WARNING_OPEN:
raise ValueError("draft warning fences are unbalanced")
if stripped == WARNING_CLOSE:
inside = False
continue
else:
if stripped == WARNING_OPEN:
inside = True
continue
if stripped == WARNING_CLOSE:
raise ValueError("draft warning fences are unbalanced")
kept.append(line)
text = "\n".join(kept)
if inside or WARNING_OPEN in text or WARNING_CLOSE in text:
raise ValueError("draft warning fences are unbalanced")
return text