From a1f94890f83d264a33872ef164d28ae7b92a03f6 Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Sun, 31 Aug 2025 15:45:07 -0400 Subject: [PATCH 1/6] Add extra newline between each changes subsection --- make_release/notes/generate.nu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_release/notes/generate.nu b/make_release/notes/generate.nu index ae1e35e1..bd309d4b 100644 --- a/make_release/notes/generate.nu +++ b/make_release/notes/generate.nu @@ -156,7 +156,7 @@ export def generate-section []: record -> string { } $body ++= $bullet | each {|pr| "* " ++ $pr.notes ++ $" \(($pr | pr-link)\)" } - $body | str join (char nl) + $body | str join $"(char nl)(char nl)" } # Generate the "Hall of Fame" section of the release notes. From 30f71f857859fb449ba1946a3623bc7574214c43 Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Sun, 31 Aug 2025 16:08:03 -0400 Subject: [PATCH 2/6] Fix extraction to account for comments in code blocks --- make_release/notes/generate.nu | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/make_release/notes/generate.nu b/make_release/notes/generate.nu index bd309d4b..f7371d4d 100644 --- a/make_release/notes/generate.nu +++ b/make_release/notes/generate.nu @@ -88,6 +88,31 @@ export def get-release-notes []: record -> record { $pr | insert notes $notes } +# Create closure for `reduce` to extract the whole release notes summary. +def extract_until_end []: nothing -> closure { + let terminators = ["# " "## " "---"] + {|line: string, state: record| + mut state = $state + + if $state.done { return $state } + + # check if we're entering/exiting a code block + # this might be kind of brittle + if $line has "```" { + $state.code = not $state.code + } + + let found_terminator = $terminators | any { $line starts-with $in } + if $found_terminator and not $state.code { + $state.done = true + return $state + } + + $state.out ++= [$line] + $state + } +} + # Extracts the "Release notes summary" section of the PR description export def extract-notes []: string -> string { lines @@ -96,10 +121,9 @@ export def extract-notes []: string -> string { # this should already have been checked | if ($in | is-empty) { assert false } else {} | skip 1 # remove header - # extract until next heading - | take until { - $in starts-with "# " or $in starts-with "## " or $in starts-with "---" - } + # extract until end of summary + | reduce -f {code: false, done: false, out: []} (extract_until_end) + | get out | str join (char nl) # remove HTML comments | str replace -amr '' '' From 54b219a3aaf2472e9369dc103f066cfa29a37273 Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Sun, 31 Aug 2025 16:10:24 -0400 Subject: [PATCH 3/6] Move extract_until_end --- make_release/notes/generate.nu | 50 +++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/make_release/notes/generate.nu b/make_release/notes/generate.nu index f7371d4d..bfcf0db7 100644 --- a/make_release/notes/generate.nu +++ b/make_release/notes/generate.nu @@ -88,31 +88,6 @@ export def get-release-notes []: record -> record { $pr | insert notes $notes } -# Create closure for `reduce` to extract the whole release notes summary. -def extract_until_end []: nothing -> closure { - let terminators = ["# " "## " "---"] - {|line: string, state: record| - mut state = $state - - if $state.done { return $state } - - # check if we're entering/exiting a code block - # this might be kind of brittle - if $line has "```" { - $state.code = not $state.code - } - - let found_terminator = $terminators | any { $line starts-with $in } - if $found_terminator and not $state.code { - $state.done = true - return $state - } - - $state.out ++= [$line] - $state - } -} - # Extracts the "Release notes summary" section of the PR description export def extract-notes []: string -> string { lines @@ -202,6 +177,31 @@ export def generate-full-changelog [version: string]: nothing -> string { | pr-table } +# Create closure for `reduce` to extract the whole release notes summary. +def extract_until_end []: nothing -> closure { + let terminators = ["# " "## " "---"] + {|line: string, state: record| + mut state = $state + + if $state.done { return $state } + + # check if we're entering/exiting a code block + # this might be kind of brittle + if $line has "```" { + $state.code = not $state.code + } + + let found_terminator = $terminators | any { $line starts-with $in } + if $found_terminator and not $state.code { + $state.done = true + return $state + } + + $state.out ++= [$line] + $state + } +} + # Get section labels which don't have a corresponding heading (i.e., don't appear in Changes section) def labels-without-heading [] { $SECTIONS | where h2 == null | get label From 260b32fc7f2c537d492d72a2b1a4132e6a9b124d Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Sun, 31 Aug 2025 16:14:56 -0400 Subject: [PATCH 4/6] Add assertion that query returns results --- make_release/notes/tools.nu | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/make_release/notes/tools.nu b/make_release/notes/tools.nu index 65848aa8..449d51fb 100644 --- a/make_release/notes/tools.nu +++ b/make_release/notes/tools.nu @@ -45,11 +45,16 @@ def query-prs [ let query = $query_parts | str join ' ' - (gh --repo $repo pr list --state merged - --limit (inf | into int) - --json author,title,number,mergedAt,url,body,labels - --search $query) - | from json + let results = ( + gh --repo $repo pr list --state merged + --limit (inf | into int) + --json author,title,number,mergedAt,url,body,labels + --search $query + | from json + ) + + assert ($results | is-not-empty) "Query returned no results" + $results } # Generate the release notes for the specified version. From f9d9150435ee17529a640d5ebe474de89340b6b4 Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Sun, 31 Aug 2025 16:18:17 -0400 Subject: [PATCH 5/6] Don't generate unnecessary h3 --- make_release/notes/generate.nu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make_release/notes/generate.nu b/make_release/notes/generate.nu index bfcf0db7..a77a7b97 100644 --- a/make_release/notes/generate.nu +++ b/make_release/notes/generate.nu @@ -150,7 +150,7 @@ export def generate-section []: record -> string { $body ++= $multiline.notes # Add single-line summaries - if ($multiline | is-not-empty) { + if ($multiline | is-not-empty) and ($bullet | is-not-empty) { $body ++= [$"### ($section.h3)"] } $body ++= $bullet | each {|pr| "* " ++ $pr.notes ++ $" \(($pr | pr-link)\)" } From f7132d9357d2bf2c7105ec01218967d0e97ef8a8 Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Tue, 2 Sep 2025 19:32:13 -0400 Subject: [PATCH 6/6] Remove PR link from ToC header --- make_release/notes/tools.nu | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/make_release/notes/tools.nu b/make_release/notes/tools.nu index 449d51fb..cf8e613e 100644 --- a/make_release/notes/tools.nu +++ b/make_release/notes/tools.nu @@ -153,11 +153,9 @@ export def write-toc [file: path] { | each {|header| let indent = '- ' | fill -w ($header.level * 2) -a right - let text = $header.line | str trim -l -c '#' | str trim -l - let text = if $text ends-with $toc { - $text | str substring ..<(-1 * ($toc | str length)) | str trim -r - } else { - $text + mut text = $header.line | str trim -l -c '#' | str trim -l + if $text ends-with $toc { + $text = $text | str substring ..<(-1 * ($toc | str length)) | str trim -r } let link = ( @@ -166,6 +164,22 @@ export def write-toc [file: path] { | str kebab-case ) + # remove PR link from header, if applicable + let regex = r#'(?x) # verbose mode + (?.+?) # the actual header text + \s+ + \( # start PR link + \[\#\d+\] # PR number component + (?: # optional non-capturing group + \(.+?\) # link to PR + )? # end group + \) + '# + let prlink = $text | parse -r $regex + if ($prlink | is-not-empty) { + $text = $prlink.0.text + } + $"($indent)[_($text)_]\(#($link)-toc\)" } )