From 6b89f32e20468d1d17a92fb1f5f2e5d94536c71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=BC=ED=98=81?= Date: Sun, 6 Sep 2026 14:05:28 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=9D=B4=EC=8A=88=20=EB=B2=88=ED=98=B8?= =?UTF-8?q?=EB=A1=9C=20=EC=8B=9C=EC=9E=91=ED=95=98=EB=8A=94=20=EC=A4=84?= =?UTF-8?q?=EC=9D=B4=20=EB=A6=B4=EB=A6=AC=EC=8A=A4=20=EB=85=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=84=B9=EC=85=98=EC=9D=84=20=EB=81=8A=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EA=B2=8C=20=ED=95=9C=EB=8B=A4=20(159)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../render-distribution-release-notes.sh | 11 +++++- ...render-distribution-release-notes.test.mjs | 39 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/.github/scripts/render-distribution-release-notes.sh b/.github/scripts/render-distribution-release-notes.sh index 923c6759..4bf30431 100755 --- a/.github/scripts/render-distribution-release-notes.sh +++ b/.github/scripts/render-distribution-release-notes.sh @@ -20,8 +20,11 @@ extract_section() { local ascii_marker="$2" local body_file="$3" + # 제목은 「# 뒤에 공백」 이 있는 줄뿐이다(마크다운 ATX). 이 구분이 없으면 「#130 에서 …」 처럼 + # 이슈 번호로 시작하는 본문 줄이 제목으로 읽혀 섹션이 거기서 끊긴다. 그러면 Work Description + # 이 비어 배포가 「변경 내용이 하나 이상 필요합니다」 로 막힌다(#159). awk -v marker="$marker" -v ascii_marker="$ascii_marker" ' - /^#[#]*[[:space:]]*/ { + /^#+[[:space:]]/ { heading = $0 if (capturing) { exit @@ -102,7 +105,11 @@ normalized_notes="$( { point = $0 - sub(/^[[:space:]]*[-*][[:space:]]*/, "", point) + # 목록 표시는 「- 」 나 「* 」 처럼 뒤에 공백이 온다. 공백을 요구하지 않으면 + # 「**굵게** 로 시작하는 문단」 의 별표 하나를 목록 표시로 보고 잘라 낸다(#159). + sub(/^[[:space:]]*[-*][[:space:]]+/, "", point) + # 내용 없이 표시만 있는 줄. 이 줄은 비운 것으로 봐야 아래 검사가 걸러 낸다. + sub(/^[[:space:]]*[-*][[:space:]]*$/, "", point) sub(/^[[:space:]]*[0-9]+\.[[:space:]]*/, "", point) sub(/^[[:space:]]+/, "", point) sub(/[[:space:]]+$/, "", point) diff --git a/.github/scripts/render-distribution-release-notes.test.mjs b/.github/scripts/render-distribution-release-notes.test.mjs index dcbe08e8..6f25f736 100644 --- a/.github/scripts/render-distribution-release-notes.test.mjs +++ b/.github/scripts/render-distribution-release-notes.test.mjs @@ -113,3 +113,42 @@ test("수동 실행(WIF canary)은 입력값을 ; 로 나눠 릴리스 노트로 assert.match(notes, /^SlowClock 수동 배포 \(WIF canary\)\n/); assert.match(notes, /포함 이슈\n- #35\n\n변경 내용\n- WIF 인증 업로드 확인\n- 앱이 로그인 화면까지 뜬다\n$/); }); + +test("이슈 번호로 시작하는 본문 줄이 섹션을 끊지 않는다", async (t) => { + // 마크다운에서 # 뒤에 공백이 없으면 제목이 아니다. 구분하지 않으면 「#130 에서 …」 처럼 + // 이슈 번호로 문장을 시작한 PR 이 그 줄에서 섹션을 끊어 배포가 막힌다(#159 실측). + const body = + "## 📌 Issues\n\nCloses #157\n\n## 📎 Work Description\n\n" + + "#130 에서 들어간 회귀입니다.\n- 회차 식별자를 되풀이하는 일정에만 채운다\n\n" + + "## 📷 Screenshot\n\n없음\n"; + const { result, outputPath } = await runRenderer(t, { eventName: "push", body }); + const notes = await fs.readFile(outputPath, "utf8"); + + assert.equal(result.status, 0, result.stderr); + assert.match(notes, /#130 에서 들어간 회귀입니다\./); + assert.match(notes, /회차 식별자를 되풀이하는 일정에만 채운다/); +}); + +test("섹션은 다음 제목에서 끊긴다", async (t) => { + // 위 완화가 섹션 경계까지 풀어 버리면 Screenshot 문단이 변경 내용으로 섞여 들어간다. + const body = + "## 📌 Issues\n\nCloses #7\n\n## 📎 Work Description\n\n" + + "- 알람이 잠금 화면에서도 뜬다\n\n## 📷 Screenshot\n\n스크린샷 없음\n"; + const { result, outputPath } = await runRenderer(t, { eventName: "push", body }); + const notes = await fs.readFile(outputPath, "utf8"); + + assert.equal(result.status, 0, result.stderr); + assert.match(notes, /알람이 잠금 화면에서도 뜬다/); + assert.doesNotMatch(notes, /스크린샷 없음/); +}); + +test("굵은 글씨로 시작하는 문단의 별표를 잘라 내지 않는다", async (t) => { + const body = + "## 📌 Issues\n\nCloses #8\n\n## 📎 Work Description\n\n" + + "**회차 식별자는 되풀이하는 일정에만 채웁니다.** 나머지는 그대로다.\n"; + const { result, outputPath } = await runRenderer(t, { eventName: "push", body }); + const notes = await fs.readFile(outputPath, "utf8"); + + assert.equal(result.status, 0, result.stderr); + assert.match(notes, /\*\*회차 식별자는 되풀이하는 일정에만 채웁니다\.\*\*/); +});