Skip to content

Commit 8ad560e

Browse files
committed
Integrate create-pr with release notes generator
1 parent ed6457e commit 8ad560e

File tree

3 files changed

+213
-209
lines changed

3 files changed

+213
-209
lines changed

make_release/notes/create-pr.nu

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use std log
22

3+
use completions.nu *
4+
use tools.nu release-notes
5+
36
def open-pr [
47
repo: path
58
remote: string
@@ -29,13 +32,10 @@ def clean [repo: path] {
2932
}
3033

3134
# open the release note PR interactively
32-
#
33-
# # Example
34-
# [this PR](https://github.com/nushell/nushell.github.io/pull/916) has been created with the script
35-
# > ./make_release/release-note/create-pr 0.81 2023-06-06
35+
@example "Create a PR for the next release" $"create-pr ($example_version) \(($current_build_date) + 6wk\)"
3636
export def main [
37-
version: string # the version of the release, e.g. `0.80`
38-
date: datetime # the date of the upcoming release, e.g. `2023-05-16`
37+
version: string@"nu-complete version" # the version of the release
38+
date: datetime@"nu-complete date next" # the date of the upcoming release
3939
] {
4040
let repo = ($nu.temp-path | path join (random uuid))
4141
let branch = $"release-notes-($version)"
@@ -47,22 +47,19 @@ export def main [
4747
let title = $"Release notes for `($version)`"
4848
let body = $"Please add your new features and breaking changes to the release notes
4949
by opening PRs against the `release-notes-($version)` branch.
50-
5150
## TODO
52-
- [ ] PRs that need to land before the release, e.g. [deprecations]\(https://github.com/nushell/nushell/labels/deprecation\) or [removals]\(https://github.com/nushell/nushell/pulls?q=is%3Apr+is%3Aopen+label%3Aremoval-after-deprecation\)
51+
- [ ] PRs that need to land before the release, e.g. [deprecations] or [removals]
5352
- [ ] add the full changelog
5453
- [ ] categorize each PR
55-
- [ ] write all the sections and complete all the `TODO`s"
54+
- [ ] write all the sections and complete all the `TODO`s
55+
[deprecations]: https://github.com/nushell/nushell/labels/deprecation
56+
[removals]: https://github.com/nushell/nushell/pulls?q=is%3Apr+is%3Aopen+label%3Aremoval-after-deprecation"
5657

57-
log info "creating release note from template"
58-
let release_note = $env.CURRENT_FILE
59-
| path dirname
60-
| path join "template.md"
61-
| open
62-
| str replace --all "{{VERSION}}" $version
58+
log info "generating release notes"
59+
let release_note = release-notes $version
6360

6461
log info $"branch: ($branch)"
65-
log info $"blog: ($blog_path | str replace $repo "" | path split | skip 1 | path join)"
62+
log info $"blog: ($blog_path | path relative-to $repo | path basename)"
6663
log info $"title: ($title)"
6764

6865
match (["yes" "no"] | input list --fuzzy "Inspect the release note document? ") {
@@ -74,48 +71,54 @@ by opening PRs against the `release-notes-($version)` branch.
7471
}
7572

7673
let temp_file = $nu.temp-path | path join $"(random uuid).md"
77-
$release_note | save --force $temp_file
74+
[
75+
"<!-- WARNING: Changes made to this file are NOT included in the PR -->"
76+
""
77+
$release_note
78+
] | to text | save --force $temp_file
7879
^$env.EDITOR $temp_file
7980
rm --recursive --force $temp_file
8081
},
81-
"no" | "" | _ => {},
82+
"no" | "" | _ => { }
8283
}
8384

8485
match (["no" "yes"] | input list --fuzzy "Open release note PR? ") {
85-
"yes" => {},
86+
"yes" => { },
8687
"no" | "" | _ => {
8788
log warning "aborting."
8889
return
89-
},
90+
}
9091
}
9192

9293
log info "setting up nushell.github.io repo"
93-
git clone https://github.com/nushell/nushell.github.io $repo --origin nushell --branch main --single-branch
94-
git -C $repo remote set-url nushell --push [email protected]:nushell/nushell.github.io.git
94+
^git clone https://github.com/nushell/nushell.github.io $repo --origin nushell --branch main --single-branch
95+
^git -C $repo remote set-url nushell --push [email protected]:nushell/nushell.github.io.git
9596

9697
log info "creating release branch"
97-
git -C $repo checkout -b $branch
98+
^git -C $repo checkout -b $branch
9899

99100
log info "writing release note"
100101
$release_note | save --force $blog_path
101102

102103
log info "committing release note"
103-
git -C $repo add $blog_path
104-
git -C $repo commit -m $"($title)\n\n($body)"
104+
^git -C $repo add $blog_path
105+
^git -C $repo commit -m $"($title)\n\n($body)"
105106

106107
log info "pushing release note to nushell"
107-
git -C $repo push nushell $branch
108+
^git -C $repo push nushell $branch
108109

109-
let out = (do -i { gh auth status } | complete)
110+
let out = (do -i { ^gh auth status } | complete)
110111
if $out.exit_code != 0 {
111112
clean $repo
112113

113114
let pr_url = $"https://github.com/nushell/nushell.github.io/compare/($branch)?expand=1"
114115
error make --unspanned {
115-
msg: ([
116-
$out.stderr
117-
$"please open the PR manually from a browser (ansi blue_underline)($pr_url)(ansi reset)"
118-
] | str join "\n")
116+
msg: (
117+
[
118+
$out.stderr
119+
$"please open the PR manually from a browser (ansi blue_underline)($pr_url)(ansi reset)"
120+
] | str join "\n"
121+
)
119122
}
120123
}
121124

make_release/notes/mod.nu

Lines changed: 1 addition & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,3 @@
1-
use std/assert
2-
use std-rfc/iter only
3-
4-
use util.nu *
5-
use completions.nu *
6-
use notice.nu *
7-
use generate.nu *
8-
1+
export use tools.nu *
92
export use gh-release-excerpt.nu
103
export use create-pr.nu
11-
12-
# List all merged PRs since the last release
13-
@example $"List all merged for ($example_version)" $"list-prs --milestone ($example_version)"
14-
export def list-prs [
15-
repo: string = 'nushell/nushell' # the name of the repo, e.g. 'nushell/nushell'
16-
--since: datetime@"nu-complete date current" # list PRs on or after this date (defaults to 4 weeks ago if `--milestone` is not provided)
17-
--milestone: string@"nu-complete version" # only list PRs in a certain milestone
18-
--label: string # the PR label to filter by, e.g. 'good-first-issue'
19-
]: nothing -> table {
20-
query-prs $repo --since=$since --milestone=$milestone --label=$label
21-
| select author title number mergedAt url
22-
| sort-by mergedAt --reverse
23-
| update author { get login }
24-
}
25-
26-
# Construct a GitHub query for merged PRs on a repo.
27-
def query-prs [
28-
repo: string = 'nushell/nushell' # the name of the repo, e.g. 'nushell/nushell'
29-
--since: datetime@"nu-complete date current" # list PRs on or after this date (defaults to 4 weeks ago if `--milestone` is not provided)
30-
--milestone: string@"nu-complete version" # only list PRs in a certain milestone
31-
--label: string # the PR label to filter by, e.g. 'good-first-issue'
32-
]: nothing -> table {
33-
mut query_parts = []
34-
35-
if $since != null or $milestone == null {
36-
let date = $since | default ((date now) - 4wk) | format date '%Y-%m-%d'
37-
$query_parts ++= [ $'merged:>($date)' ]
38-
}
39-
40-
if $milestone != null {
41-
$query_parts ++= [ $'milestone:"($milestone)"' ]
42-
}
43-
44-
if $label != null {
45-
$query_parts ++= [ $'label:($label)' ]
46-
}
47-
48-
let query = $query_parts | str join ' '
49-
50-
(gh --repo $repo pr list --state merged
51-
--limit (inf | into int)
52-
--json author,title,number,mergedAt,url,body,labels
53-
--search $query)
54-
| from json
55-
}
56-
57-
# Generate the release notes for the specified version.
58-
export def release-notes [
59-
version: string@"nu-complete version" # the version to generate release notes for
60-
]: nothing -> string {
61-
query-prs --milestone=$version
62-
| where not author.is_bot
63-
| sort-by mergedAt
64-
| each { get-release-notes }
65-
| tee { display-notices }
66-
| where {|pr| "error" not-in ($pr.notices?.type? | default []) }
67-
| generate-notes $version
68-
}
69-
70-
# Check the release note summaries for the specified version.
71-
export def check-prs [
72-
version: string@"nu-complete version" # the version to generate release notes for
73-
]: nothing -> nothing {
74-
query-prs --milestone=$version
75-
| where not author.is_bot
76-
| sort-by mergedAt
77-
| each { get-release-notes }
78-
| display-notices
79-
}
80-
81-
# Format the output of `list-prs` as a markdown table
82-
export def pr-table [] {
83-
sort-by author number
84-
| update author { md-link $'@($in)' $'https://github.com/($in)' }
85-
| insert link { pr-link }
86-
| select author title link
87-
| to md
88-
| escape-tag
89-
}
90-
91-
const toc = '[[toc](#table-of-contents)]'
92-
93-
# Generate and write the table of contents to a release notes file
94-
export def write-toc [file: path] {
95-
let known_h1s = [
96-
"# Highlights and themes of this release",
97-
"# Changes",
98-
"# Notes for plugin developers",
99-
"# Hall of fame",
100-
"# Full changelog",
101-
]
102-
103-
let lines = open $file | lines | each { str trim -r }
104-
105-
let content_start = 2 + (
106-
$lines
107-
| enumerate
108-
| where item == '# Table of contents'
109-
| first
110-
| get index
111-
)
112-
113-
let data = (
114-
$lines
115-
| slice $content_start..
116-
| wrap line
117-
| insert level {
118-
get line | split chars | take while { $in == '#' } | length
119-
}
120-
| insert nocomment {
121-
# We assume that comments only have one `#`
122-
if ($in.level != 1) {
123-
return true
124-
}
125-
let line = $in.line
126-
127-
# Try to use the whitelist first
128-
if ($known_h1s | any {|| $line =~ $in}) {
129-
return true
130-
}
131-
132-
# We don't know so let's ask
133-
let user = ([Ignore Accept] |
134-
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!")
135-
match $user {
136-
"Accept" => {true}
137-
"Ignore" => {false}
138-
}
139-
140-
}
141-
)
142-
143-
let table_of_contents = (
144-
$data
145-
| where level in 1..=3 and nocomment == true
146-
| each {|header|
147-
let indent = '- ' | fill -w ($header.level * 2) -a right
148-
149-
let text = $header.line | str trim -l -c '#' | str trim -l
150-
let text = if $text ends-with $toc {
151-
$text | str substring ..<(-1 * ($toc | str length)) | str trim -r
152-
} else {
153-
$text
154-
}
155-
156-
let link = (
157-
$text
158-
| str downcase
159-
| str kebab-case
160-
)
161-
162-
$"($indent)[_($text)_]\(#($link)-toc\)"
163-
}
164-
)
165-
166-
let content = $data | each {
167-
if $in.level in 1..=3 and not ($in.line ends-with $toc) and $in.nocomment {
168-
$'($in.line) ($toc)'
169-
} else {
170-
$in.line
171-
}
172-
}
173-
174-
[
175-
...($lines | slice ..<$content_start)
176-
...$table_of_contents
177-
...$content
178-
]
179-
| save -r -f $file
180-
}

0 commit comments

Comments
 (0)