Skip to content

Commit 30ac050

Browse files
author
CometAPI
committed
fix: compose release document normalization
1 parent f28a849 commit 30ac050

4 files changed

Lines changed: 35 additions & 51 deletions

File tree

scripts/_checks.py

Lines changed: 26 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -681,19 +681,22 @@ def _canonical_actions_run_violations(
681681
) -> list[tuple[int, str]]:
682682
"""Require every Actions URL in immutable evidence to name one canonical run."""
683683
findings: list[tuple[int, str]] = []
684-
normalized = unicodedata.normalize("NFKC", body)
685-
direct = normalized
686-
for _ in range(3):
687-
decoded = html.unescape(direct)
688-
if decoded == direct:
684+
direct = unicodedata.normalize("NFKC", body)
685+
variants = [direct]
686+
for _ in range(8):
687+
previous = variants[-1]
688+
decoded = html.unescape(previous)
689+
decoded = unquote(decoded)
690+
decoded = re.sub(r"\\([/\\.:?&=%#])", r"\1", decoded)
691+
decoded = decoded.replace("\t", "").replace("\n", "").replace("\r", "")
692+
decoded = re.sub(
693+
r"(?i)(https?://[^\s<>)\]]*)\\([^\s<>)\]]*)",
694+
lambda match: match.group(0).replace("\\", "/"),
695+
decoded,
696+
)
697+
if decoded == previous:
689698
break
690-
direct = decoded
691-
markdown_unescaped = re.sub(r"\\([/\\.:?&=%#])", r"\1", direct)
692-
browser_normalized = re.sub(
693-
r"(?i)(https?://[^\s<>)\]]*)\\([^\s<>)\]]*)",
694-
lambda match: match.group(0).replace("\\", "/"),
695-
markdown_unescaped,
696-
)
699+
variants.append(decoded)
697700

698701
path_matches = list(_ACTIONS_PATH.finditer(direct))
699702
canonical_matches = list(_CANONICAL_ACTIONS_URL.finditer(direct))
@@ -704,39 +707,18 @@ def _canonical_actions_run_violations(
704707
for path in path_matches
705708
)
706709

707-
percent_decoded = direct
708-
for _ in range(3):
709-
decoded = unquote(percent_decoded)
710-
if decoded == percent_decoded:
711-
break
712-
percent_decoded = decoded
713710
direct_paths = Counter((match.group("run"), match.group("attempt")) for match in path_matches)
714-
decoded_paths = Counter(
715-
(match.group("run"), match.group("attempt"))
716-
for match in _ACTIONS_PATH.finditer(percent_decoded)
717-
)
718-
malformed = malformed or any(
719-
count > direct_paths[identity] for identity, count in decoded_paths.items()
720-
)
721-
normalized_paths = Counter(
722-
(match.group("run"), match.group("attempt")) for match in _ACTIONS_PATH.finditer(normalized)
723-
)
724-
malformed = malformed or any(
725-
count > normalized_paths[identity] for identity, count in direct_paths.items()
726-
)
727-
unescaped_paths = Counter(
728-
(match.group("run"), match.group("attempt"))
729-
for match in _ACTIONS_PATH.finditer(markdown_unescaped)
730-
)
731-
malformed = malformed or any(
732-
count > normalized_paths[identity] for identity, count in unescaped_paths.items()
733-
)
734-
browser_paths = Counter(
735-
(match.group("run"), match.group("attempt"))
736-
for match in _ACTIONS_PATH.finditer(browser_normalized)
737-
)
711+
variant_paths = [
712+
Counter(
713+
(match.group("run"), match.group("attempt"))
714+
for match in _ACTIONS_PATH.finditer(variant)
715+
)
716+
for variant in variants
717+
]
738718
malformed = malformed or any(
739-
count > normalized_paths[identity] for identity, count in browser_paths.items()
719+
count > direct_paths[identity]
720+
for paths in variant_paths[1:]
721+
for identity, count in paths.items()
740722
)
741723

742724
if malformed:
@@ -748,12 +730,7 @@ def _canonical_actions_run_violations(
748730
"/attempts/<positive-id> suffix",
749731
)
750732
)
751-
run_values = (
752-
{run for run, _attempt in direct_paths}
753-
| {run for run, _attempt in decoded_paths}
754-
| {run for run, _attempt in unescaped_paths}
755-
| {run for run, _attempt in browser_paths}
756-
)
733+
run_values = {run for paths in variant_paths for run, _attempt in paths}
757734
if run_values - {expected_run}:
758735
findings.append(
759736
(

scripts/check_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def _visible_heading_is_unreleased(label: str) -> bool:
269269
for value in label
270270
)
271271
words = re.findall(r"[A-Za-z]+", label)
272-
return bool(words and words[0].casefold() == "unreleased")
272+
return any(word.casefold() == "unreleased" for word in words)
273273

274274

275275
def _unreleased_heading_lines(text: str) -> list[int]:

tests/test_changelog_gate.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,15 @@ def test_changelog_parser_rejects_obfuscated_mutable_versions(claim: str) -> Non
9797
"## Un&#x72;eleased",
9898
"## \uff35\uff4e\uff52\uff45\uff4c\uff45\uff41\uff53\uff45\uff44",
9999
"## Un\u034freleased",
100+
"## Current Unreleased",
101+
"Next release (Unreleased)\n-------------------------",
100102
"Unreleased\n----------",
101103
"> ## Unreleased",
102104
"<h2>Un<em>released</em></h2>",
103105
"<h2>Unreleased",
104106
"<h2>Unreleased<h2>Archive</h2>",
105107
"<h2>Unreleased</h3>",
108+
"<h2>Current Unreleased</h2>",
106109
"Intro <h2>Unreleased</h2>",
107110
],
108111
)
@@ -155,7 +158,7 @@ def test_changelog_parser_rejects_rendered_unreleased_heading_indentation(
155158
"## Un*released",
156159
"## [Current](https://example.invalid/Unreleased)",
157160
'## <span title="Unreleased">Current</span>',
158-
"## `Current Unreleased`",
161+
"## `Current release`",
159162
"## Unrelea\u0301sed",
160163
],
161164
)

tests/test_release_documents.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,10 @@ def test_release_evidence_rejects_obsolete_workflow_reference_marker(
714714
"https://github.com/cometapi-dev/cometapi-python/actions\\/runs\\/30511373822",
715715
"https://github.com/cometapi-dev/cometapi-python/actions\\runs\\30511373822",
716716
"https://github.com/cometapi-dev/cometapi-python&#92;actions&#92;runs&#92;30511373822",
717+
"https://github.com/cometapi-dev/cometapi-python%5Cactions%5Cruns%5C30511373822",
718+
"https://evil.example/?next=https://github.com/cometapi-dev/cometapi-python%5Cactions%5Cruns%5C30511373822",
719+
'<a href="https://github.com/cometapi-dev/cometapi-python/'
720+
'act&#9;ions/runs/30511373822">Required CI</a>',
717721
"https://github.com/cometapi-dev/cometapi-python/actions/runs/30511373822.evil",
718722
"https://github.com/cometapi-dev/cometapi-python/actions/runs/30511373822/attempts/0",
719723
],

0 commit comments

Comments
 (0)