|
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 * |
9 | 2 | export use gh-release-excerpt.nu |
10 | 3 | 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