Skip to content

Commit 2a9acec

Browse files
docs: CHANGELOG の基点を現行タグにする
1 parent 6931681 commit 2a9acec

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

.github/workflows/release-on-tag.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,16 @@ jobs:
3535
run: |
3636
TAG="${GITHUB_REF_NAME}"
3737
VERSION="${TAG#v}"
38+
# 版番号を正規表現に埋めるので 2 つ手当てする。
39+
#
40+
# 1. ドットをエスケープする。素のままだと `.` がワイルドカードになる
41+
# 2. 末尾に境界を置く。**前方一致のままだと 1.0.1 が 1.0.17 に当たる。**
42+
# しかも awk は上から順に拾うので、降順の CHANGELOG では
43+
# 1.0.17 の節を開いて 1.0.2 の見出しで閉じ、そのあと 1.0.1 でまた開く。
44+
# 結果、1.0.1 のリリースノートに 1.0.17 の内容が混ざって公開されていた
45+
ESC=$(printf '%s' "$VERSION" | sed 's/\./\\./g')
3846
if [ -f CHANGELOG.md ]; then
39-
awk "/^## \[?${VERSION}/{flag=1; next} /^## \[?[0-9]/{flag=0} flag" CHANGELOG.md > /tmp/notes.md
47+
awk "/^## \\[?${ESC}\\]?([^0-9.]|\$)/{flag=1; next} /^## \\[?[0-9]/{flag=0} flag" CHANGELOG.md > /tmp/notes.md
4048
fi
4149
if [ -s /tmp/notes.md ]; then
4250
gh release create "$TAG" --title "$TAG" --notes-file /tmp/notes.md

scripts/compute-next-version.sh

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,31 @@ REST="${CURRENT#*.}"
169169
MINOR="${REST%%.*}"
170170
PATCH="${CURRENT##*.}"
171171

172+
# CHANGELOG の [Unreleased] に宣言された「挙動の破壊」を読む。
173+
#
174+
# **シンボル差分は挙動の破壊を見ない。** 今まで値を返していた関数が throw するように
175+
# なっても、型は 1 文字も変わらないので removed=0 added=0 になる。しかし利用者のコードは
176+
# 実行時に壊れるので、SemVer 上これは破壊的変更(SemVer 8 項は「後方互換でない変更」であって
177+
# 「シグネチャの変更」ではない)。
178+
#
179+
# 実例: structured-data で YAML のタグ・alias を「黙って捨てる」から「throw する」に変えた回。
180+
# シンボル差分は minor と算出したが、`!!str 42` を渡していた利用者は全員壊れる。
181+
#
182+
# そこで CHANGELOG に宣言の口を 1 つだけ開ける。**上げることしかできない。**
183+
# 下げられないので、§0.4.3 が潰した「儀式的な major」は復活しない
184+
# (依存のピンを上げただけの回は、この印を書かない限り patch のまま)。
185+
UNRELEASED_BREAKING=false
186+
if [ -f "$REPO/CHANGELOG.md" ]; then
187+
if awk '/^## \[?[Uu]nreleased\]?/{f=1;next} /^## \[?[0-9]/{f=0} f' "$REPO/CHANGELOG.md" \
188+
| grep -qiE '^\s*(###\s*Removed|.*\bBREAKING\b)'; then
189+
UNRELEASED_BREAKING=true
190+
fi
191+
fi
192+
172193
# 0.x は minor が破壊的軸(SemVer 4 項: 0.y.z の互換性は保証されない)。
173194
# 1.0.0 未満で major を繰り上げると「安定版を出した」という別の意味になってしまうため、
174195
# 破壊的変更は minor、非破壊は patch に写す。oss-doctor の dep-generation-gap と同じ規則。
175-
if [ "$REMOVED" -gt 0 ] || [ -n "$PUBLIC_DEP_BREAK" ]; then
196+
if [ "$REMOVED" -gt 0 ] || [ -n "$PUBLIC_DEP_BREAK" ] || [ "$UNRELEASED_BREAKING" = true ]; then
176197
BREAKING=true
177198
else
178199
BREAKING=false
@@ -182,6 +203,8 @@ if [ -n "$PUBLIC_DEP_BREAK" ]; then
182203
REASON="public dependency の世代変化:$PUBLIC_DEP_BREAK"
183204
elif [ "$REMOVED" -gt 0 ]; then
184205
REASON="public シンボルの削除・変更 ${REMOVED}"
206+
elif [ "$UNRELEASED_BREAKING" = true ]; then
207+
REASON="CHANGELOG が挙動の破壊を宣言(シグネチャ差分には映らない)"
185208
elif [ "$ADDED" -gt 0 ]; then
186209
REASON="public シンボルの追加 ${ADDED}"
187210
else

0 commit comments

Comments
 (0)