Skip to content

Commit 25d3c5b

Browse files
authored
Update release process and notes generation (#1229)
1 parent a524b01 commit 25d3c5b

File tree

6 files changed

+61
-136
lines changed

6 files changed

+61
-136
lines changed

make_release/Readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ There are two threads you can do in parallel: publishing crates and generating r
6060
:point_right: check that there is the same number of targets compared to [last release](https://github.com/nushell/nushell/releases/latest)
6161
6262
## 3. Publish `nu` to *crates.io*
63-
- [ ] check the order of dependencies with `nushell/nu_scripts/make_release/nu_deps.nu` from the `nushell` repo
64-
- [ ] release the Nushell crates `nushell/nu_scripts/make_release/nu_release.nu` from the `nushell` repo
63+
- [ ] check that any new crates that should not be published have `package.publish = false` set in their `Cargo.toml`
64+
- [ ] release the Nushell crates with `cargo publish --workspace`
6565
- [ ] **Important!** add any new crates to the `github:nushell:publishing` group on crates.io: `cargo owner --add github:nushell:publishing -p <crate>`
6666
6767
> **Note**

make_release/notes/create-pr.nu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export def main [
3737
version: string@"nu-complete version" # the version of the release
3838
date: datetime@"nu-complete date next" # the date of the upcoming release
3939
] {
40-
let repo = ($nu.temp-path | path join (random uuid))
40+
let repo = ($nu.temp-dir | path join (random uuid))
4141
let branch = $"release-notes-($version)"
4242

4343
let blog_path = (
@@ -71,7 +71,7 @@ by opening PRs against the `release-notes-($version)` branch.
7171
}
7272
}
7373

74-
let temp_file = $nu.temp-path | path join $"(random uuid).md"
74+
let temp_file = $nu.temp-dir | path join $"(random uuid).md"
7575
[
7676
"<!-- WARNING: Changes made to this file are NOT included in the PR -->"
7777
""

make_release/notes/generate.nu

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,16 @@ use util.nu *
2121
export def get-release-notes []: record -> record {
2222
mut pr = $in
2323

24+
# Do not throw any warnings for hidden PRs
25+
let has_hide_label = "notes:hide" in $pr.labels.name
26+
let hidden = $SECTIONS | where label == "notes:hide" | only
27+
if $has_hide_label {
28+
$pr = ($pr | add-notice info "appearance only in full changelog")
29+
return ($pr | insert section $hidden)
30+
}
31+
2432
let has_ready_label = "notes:ready" in $pr.labels.name
33+
let has_hall_of_fame_label = "notes:mention" in $pr.labels.name
2534
let sections = $SECTIONS | where label in $pr.labels.name
2635
let hall_of_fame = $SECTIONS | where label == "notes:mention" | only
2736

@@ -30,7 +39,10 @@ export def get-release-notes []: record -> record {
3039
$pr.body | extract-notes
3140
} else if $has_ready_label {
3241
# If no release notes summary exists but ready label is set, treat as empty
33-
$pr = $pr | add-notice warning "no release notes section but notes:ready label"
42+
if not $has_hall_of_fame_label {
43+
# Hall of fame does not need release notes section necessarily
44+
$pr = $pr | add-notice warning "no release notes section but notes:ready label"
45+
}
3446
""
3547
} else {
3648
return ($pr | add-notice error "no release notes section")
@@ -144,26 +156,38 @@ export def generate-section []: record<section: string, prs: table> -> string {
144156
let bullet = $prs | where ($it.notes | lines | length) == 1
145157

146158
# Add header
147-
$body ++= [$"## ($section.h2)\n"]
159+
$body ++= [$"## ($section.h2) <JumpToc/>\n"]
148160

149161
# Add multi-line summaries
150-
for note in $multiline.notes {
151-
if ($note | str ends-with "\n") {
152-
$body ++= [$note]
153-
} else {
154-
$body ++= [($note ++ (char nl))]
155-
}
156-
}
162+
$body ++= $multiline | generate-multiline-notes
157163

158164
# Add single-line summaries
159165
if ($multiline | is-not-empty) and ($bullet | is-not-empty) {
160-
$body ++= [$"### ($section.h3)\n"]
166+
$body ++= [$"### ($section.h3) <JumpToc/>\n"]
161167
}
162168
$body ++= $bullet | each {|pr| "* " ++ $pr.notes ++ $" \(($pr | pr-link)\)" }
163169

164170
($body | str join (char nl)) ++ (char nl)
165171
}
166172

173+
def generate-multiline-notes []: table -> list {
174+
$in | each {|pr|
175+
let number = $pr.number
176+
let author = $pr.author.login
177+
178+
let pr_by_tag = $'<PrBy :pr="($number)" user="($author)" />'
179+
let replacer = $"### $1 <JumpToc/> ($pr_by_tag)\n"
180+
let matcher = "^### ([^\n]*)\n"
181+
let updated = ($pr.notes | str replace --all --regex $matcher $replacer)
182+
183+
if ($updated | str ends-with "\n") {
184+
$updated
185+
} else {
186+
$updated ++ (char nl)
187+
}
188+
}
189+
}
190+
167191
# Generate the "Hall of Fame" section of the release notes.
168192
export def generate-hall-of-fame []: table -> string {
169193
where section.label == "notes:mention"

make_release/notes/notice.nu

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,21 @@ export def group-notices []: table -> table {
2121
| sort-by {|i| $TYPES | where type == $i.type | only rank } message
2222
}
2323

24-
# Print all of the notices associated with a PR
25-
export def display-notices []: table -> nothing {
26-
group-notices
27-
| each {|e|
24+
# Format all of the notices associated with a PR
25+
export def format-notices []: table -> string {
26+
mut output = ""
27+
28+
mut first = true
29+
for e in ($in | group-notices) {
30+
if $first { $first = false } else { $output += "\n\n" }
2831
let color = $TYPES | where type == $e.type | only color
2932
let number = $e.items | length
30-
print $"($color)($number) PR\(s\) with ($e.message):"
31-
$e.items | each { format-pr | print $"- ($in)" }
32-
print ""
33+
$output += $"($color)($number) PR\(s\) with ($e.message):"
34+
for item in $e.items {
35+
$item | format-pr | $output += $"\n- ($in)"
36+
}
3337
}
34-
print -n (ansi reset)
38+
39+
$output += (ansi reset)
40+
$output
3541
}

make_release/notes/template.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ As part of this release, we also publish a set of optional [plugins](https://www
2424

2525
# Table of contents
2626

27-
<!-- TODO: once all the content below is finished and committed, `use nu_scripts/make_release/release-note/notes *` and run `write-toc $this_file`. -->
27+
<ReleaseToc/>
2828

29-
# Highlights and themes of this release
29+
# Highlights and themes of this release <JumpToc/>
3030

3131
<!-- NOTE: if you wanna write a section about a breaking change, when it's a very important one,
3232
please add the following snippet to have a "warning" banner :)
@@ -42,18 +42,18 @@ As part of this release, we also publish a set of optional [plugins](https://www
4242
for the list of available *containers*
4343
-->
4444

45-
# Changes
45+
# Changes <JumpToc/>
4646

4747
{changes}
4848

49-
# Notes for plugin developers
49+
# Notes for plugin developers <JumpToc/>
5050

51-
# Hall of fame
51+
# Hall of fame <JumpToc/>
5252

5353
Thanks to all the contributors below for helping us solve issues, improve documentation, refactor code, and more! :pray:
5454

5555
{hall_of_fame}
5656

57-
# Full changelog
57+
# Full changelog <JumpToc/>
5858

5959
{changelog}

make_release/notes/tools.nu

Lines changed: 3 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export def release-notes [
6565
| where not author.is_bot
6666
| sort-by mergedAt
6767
| each { get-release-notes }
68-
| tee { display-notices }
68+
| tee { format-notices }
6969
| where {|pr| "error" not-in ($pr.notices?.type? | default []) }
7070
| generate-notes $version
7171
}
@@ -75,14 +75,14 @@ export def check-prs [
7575
version: string@"nu-complete version" # the version to generate release notes for
7676
--as-table (-t) # output PR checks as a table
7777
]: [
78-
nothing -> nothing,
78+
nothing -> string,
7979
nothing -> table
8080
] {
8181
query-prs --milestone=$version
8282
| where not author.is_bot
8383
| sort-by mergedAt
8484
| each { get-release-notes }
85-
| if $as_table { group-notices } else { display-notices }
85+
| if $as_table { group-notices } else { format-notices }
8686
}
8787

8888
# Format the output of `list-prs` as a markdown table
@@ -94,108 +94,3 @@ export def pr-table [] {
9494
| to md
9595
| escape-tag
9696
}
97-
98-
const toc = '[[toc](#table-of-contents)]'
99-
100-
# Generate and write the table of contents to a release notes file
101-
export def write-toc [file: path] {
102-
let known_h1s = [
103-
"# Highlights and themes of this release",
104-
"# Changes",
105-
"# Notes for plugin developers",
106-
"# Hall of fame",
107-
"# Full changelog",
108-
]
109-
110-
let lines = open $file | lines | each { str trim -r }
111-
112-
let content_start = 2 + (
113-
$lines
114-
| enumerate
115-
| where item == '# Table of contents'
116-
| first
117-
| get index
118-
)
119-
120-
let data = (
121-
$lines
122-
| slice $content_start..
123-
| wrap line
124-
| insert level {
125-
get line | split chars | take while { $in == '#' } | length
126-
}
127-
| insert nocomment {
128-
# We assume that comments only have one `#`
129-
if ($in.level != 1) {
130-
return true
131-
}
132-
let line = $in.line
133-
134-
# Try to use the whitelist first
135-
if ($known_h1s | any {|| $line =~ $in}) {
136-
return true
137-
}
138-
139-
# We don't know so let's ask
140-
let user = ([Ignore Accept] |
141-
input list $"Is this a code comment or a markdown h1 heading:(char nl)(ansi blue)($line)(ansi reset)(char nl)Choose if we include it in the TOC!")
142-
match $user {
143-
"Accept" => {true}
144-
"Ignore" => {false}
145-
}
146-
147-
}
148-
)
149-
150-
let table_of_contents = (
151-
$data
152-
| where level in 1..=3 and nocomment == true
153-
| each {|header|
154-
let indent = '- ' | fill -w ($header.level * 2) -a right
155-
156-
mut text = $header.line | str trim -l -c '#' | str trim -l
157-
if $text ends-with $toc {
158-
$text = $text | str substring ..<(-1 * ($toc | str length)) | str trim -r
159-
}
160-
161-
let link = (
162-
$text
163-
| str downcase
164-
| str kebab-case
165-
)
166-
167-
# remove PR link from header, if applicable
168-
let regex = r#'(?x) # verbose mode
169-
(?<text>.+?) # the actual header text
170-
\s+
171-
\( # start PR link
172-
\[\#\d+\] # PR number component
173-
(?: # optional non-capturing group
174-
\(.+?\) # link to PR
175-
)? # end group
176-
\)
177-
'#
178-
let prlink = $text | parse -r $regex
179-
if ($prlink | is-not-empty) {
180-
$text = $prlink.0.text
181-
}
182-
183-
$"($indent)[_($text)_]\(#($link)-toc\)"
184-
}
185-
)
186-
187-
let content = $data | each {
188-
if $in.level in 1..=3 and not ($in.line ends-with $toc) and $in.nocomment {
189-
$'($in.line) ($toc)'
190-
} else {
191-
$in.line
192-
}
193-
}
194-
195-
[
196-
...($lines | slice ..<$content_start)
197-
...$table_of_contents
198-
...$content
199-
]
200-
| save -r -f $file
201-
}

0 commit comments

Comments
 (0)