mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 10:35:51 +00:00
Merge commit '6998908d2a387f1ded356750c3ac9424f3beb04a'
Change-source: pulse-maintainer
This commit is contained in:
@@ -410,8 +410,8 @@ jobs:
|
||||
INITIAL_STATE="${WORKFLOW_OUTPUT_1}"
|
||||
if [ "$INITIAL_STATE" = "true" ]; then
|
||||
HEADER_LINE="## ✅ Release Asset Validation: PASSED"
|
||||
STATUS_LINE="**Status**: Ready for publication ✅"
|
||||
INTRO_LINE="All release assets have been validated successfully!"
|
||||
STATUS_LINE="**Status**: Release asset checks passed ✅"
|
||||
INTRO_LINE="The required release asset checks passed."
|
||||
else
|
||||
HEADER_LINE="## ✅ Release Asset Validation (Post-Publish): PASSED"
|
||||
STATUS_LINE="**Status**: Live release assets re-validated ✅"
|
||||
@@ -450,6 +450,9 @@ jobs:
|
||||
- Version strings correct ✓
|
||||
- Binary architectures validated ✓
|
||||
|
||||
Asset validation alone does not establish installed-service health,
|
||||
release convergence, clean soak or approval for stable publication.
|
||||
|
||||
<!-- VALIDATION_STATUS_END -->
|
||||
EOF
|
||||
|
||||
|
||||
@@ -449,6 +449,13 @@ may delete invalid assets and rewrite validation annotations only while a
|
||||
release is still a draft. A post-publication edit is observation, not authority
|
||||
to mutate or destroy an immutable release; failed revalidation records a
|
||||
failing status and requires an explicit corrective release path.
|
||||
Asset-validation banners report asset checks only, never publication readiness.
|
||||
Both draft and post-publication banners must explicitly distinguish asset checks
|
||||
from installed-service health, release convergence, clean soak and stable
|
||||
publication approval, while retaining the individual check summary.
|
||||
`scripts/release_control/render_release_body_test.py` executes the workflow
|
||||
wording branch for both states and verifies these reporting limits; this local
|
||||
proof does not qualify an installed service or authorise release mutation.
|
||||
The activation marker is part of that complete draft packet: its stored digest
|
||||
must be checked before publication, and customer convergence is forbidden until
|
||||
GitHub reports the release immutable and its signed release attestation verifies.
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import textwrap
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
@@ -814,5 +816,53 @@ Rollback details.
|
||||
self.assertIn("Push", blurb)
|
||||
|
||||
|
||||
class AssetValidationWordingTest(unittest.TestCase):
|
||||
def render_banner(self, draft: bool) -> str:
|
||||
source = (_REPO_ROOT / ".github/workflows/validate-release-assets.yml").read_text(encoding="utf-8")
|
||||
# Execute only the actual local wording branch and banner heredoc,
|
||||
# never the workflow's GitHub reads/writes or release mutation code.
|
||||
branch = source.split(' if [ "$INITIAL_STATE" = "true" ]; then\n', 1)[1]
|
||||
branch = 'if [ "$INITIAL_STATE" = "true" ]; then\n' + branch.split(
|
||||
"\n fi", 1
|
||||
)[0] + "\nfi\n"
|
||||
template = textwrap.dedent(source.split(
|
||||
" read -r -d '' VALIDATION_BLOCK <<'EOF' || true\n", 1
|
||||
)[1].split("\n EOF", 1)[0])
|
||||
result = subprocess.run(
|
||||
["bash", "-eu", "-c", 'INITIAL_STATE="$1"\n' + branch
|
||||
+ "printf '%s\\n' \"$HEADER_LINE\" \"$INTRO_LINE\" \"$STATUS_LINE\"",
|
||||
"wording-test", str(draft).lower()],
|
||||
check=True, capture_output=True, text=True, timeout=5,
|
||||
)
|
||||
header, intro, status = result.stdout.splitlines()
|
||||
return template.replace("HEADER_PLACEHOLDER", header).replace(
|
||||
"INTRO_PLACEHOLDER", intro
|
||||
).replace("STATUS_PLACEHOLDER", status)
|
||||
|
||||
def test_draft_reports_asset_checks_not_publication_readiness(self) -> None:
|
||||
banner = self.render_banner(True)
|
||||
self.assertIn("**Status**: Release asset checks passed", banner)
|
||||
self.assertNotIn("Ready for publication", banner)
|
||||
self.assertIn("## ✅ Release Asset Validation: PASSED", banner)
|
||||
|
||||
def test_published_release_still_reports_revalidation(self) -> None:
|
||||
banner = self.render_banner(False)
|
||||
self.assertIn("Release Asset Validation (Post-Publish): PASSED", banner)
|
||||
self.assertIn("Live release assets re-validated", banner)
|
||||
self.assertNotIn("Ready for publication", banner)
|
||||
|
||||
def test_both_banners_explain_limits_without_losing_check_summary(self) -> None:
|
||||
for draft in (True, False):
|
||||
with self.subTest(draft=draft):
|
||||
banner = self.render_banner(draft)
|
||||
self.assertIn("Asset validation alone does not establish installed-service health,", banner)
|
||||
self.assertIn("release convergence, clean soak or approval for stable publication.", banner)
|
||||
for check in ("All required assets present", "Checksums verified",
|
||||
"Version strings correct", "Binary architectures validated"):
|
||||
self.assertIn(check, banner)
|
||||
self.assertIn("<!-- VALIDATION_STATUS_START -->", banner)
|
||||
self.assertIn("<!-- VALIDATION_STATUS_END -->", banner)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user