From 4b7b7f9d12583fc4ba1a2450ca1d6308e7b3e788 Mon Sep 17 00:00:00 2001 From: airmang <38392618+airmang@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:53:54 +0900 Subject: [PATCH] ci(release): skip [Unreleased] section when resolving changelog version The release workflow matched the first '## [...]' heading in CHANGELOG.md, which tripped on the conventional keep-a-changelog [Unreleased] section and forced maintainers to choose between (a) deleting the Unreleased block before every tag push, or (b) keeping collected unreleased notes only after all tags shipped, neither of which matches how keep-a-changelog is meant to work. Skip the Unreleased heading explicitly in both validation and the release-notes extraction step so the first actual version heading (e.g. '## [2.9.1] - 2026-04-27') drives both the tag/version check and the release body. --- .github/workflows/release.yml | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9934f01..3f4a8f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,10 +45,17 @@ jobs: from pathlib import Path changelog = Path("CHANGELOG.md").read_text(encoding="utf-8") - match = re.search(r"^## \[([^\]]+)\]", changelog, re.MULTILINE) - if not match: + # Skip the conventional [Unreleased] heading so keep-a-changelog + # workflow (pre-collecting notes above the released version) is + # preserved alongside tag-based release automation. + matches = re.findall(r"^## \[([^\]]+)\]", changelog, re.MULTILINE) + version = next( + (m.strip() for m in matches if m.strip().lower() != "unreleased"), + None, + ) + if version is None: raise SystemExit("CHANGELOG.md에서 버전 섹션(## [x.y.z])을 찾지 못했습니다.") - print(match.group(1).strip()) + print(version) PY ) @@ -72,7 +79,15 @@ jobs: from pathlib import Path lines = Path("CHANGELOG.md").read_text(encoding="utf-8").splitlines() - start = next((i for i, line in enumerate(lines) if line.startswith("## [")), None) + # Find the first released version heading, skipping [Unreleased]. + start = next( + ( + i + for i, line in enumerate(lines) + if line.startswith("## [") and "unreleased" not in line.lower() + ), + None, + ) if start is None: raise SystemExit("CHANGELOG.md에서 릴리스 섹션을 찾지 못했습니다.")