@@ -5,6 +5,7 @@ use askama::Template;
5
5
use chrono:: prelude:: * ;
6
6
use chrono:: Duration ;
7
7
8
+ use reqwest:: header:: HeaderMap ;
8
9
use serde_json as json;
9
10
10
11
type JsonRefArray < ' a > = Vec < & ' a json:: Value > ;
@@ -54,9 +55,10 @@ fn main() {
54
55
while today - end > six_weeks {
55
56
end = end + six_weeks;
56
57
}
57
-
58
58
let start = end - six_weeks;
59
- let issues = get_issues ( start, end, "rust" ) ;
59
+
60
+ let mut issues = get_issues_by_milestone ( & version, "rust" ) ;
61
+ issues. sort_by_cached_key ( |issue| issue[ "number" ] . as_u64 ( ) . unwrap ( ) ) ;
60
62
61
63
// Skips `beta-accepted` as those PRs were backported onto the
62
64
// previous stable.
@@ -84,7 +86,8 @@ fn main() {
84
86
let ( compat_unsorted, libraries_unsorted, language_unsorted, compiler_unsorted, unsorted) =
85
87
partition_prs ( rest) ;
86
88
87
- let cargo_issues = get_issues ( start, end, "cargo" ) ;
89
+ let mut cargo_issues = get_issues_by_date ( start, end, "cargo" ) ;
90
+ cargo_issues. sort_by_cached_key ( |issue| issue[ "number" ] . as_u64 ( ) . unwrap ( ) ) ;
88
91
89
92
let ( cargo_relnotes, cargo_unsorted) = {
90
93
let ( relnotes, rest) = partition_by_tag ( cargo_issues. iter ( ) , relnotes_tags) ;
@@ -119,21 +122,99 @@ fn main() {
119
122
println ! ( "{}" , relnotes. render( ) . unwrap( ) ) ;
120
123
}
121
124
122
- fn get_issues ( start : Date < Utc > , end : Date < Utc > , repo_name : & ' static str ) -> Vec < json:: Value > {
125
+ fn get_issues_by_milestone ( version : & str , repo_name : & ' static str ) -> Vec < json:: Value > {
123
126
use reqwest:: blocking:: Client ;
124
- use reqwest:: header:: * ;
125
127
126
- let token = env:: var ( "GITHUB_TOKEN" ) . expect ( "Set GITHUB_TOKEN to a valid token" ) ;
127
- let mut headers = HeaderMap :: new ( ) ;
128
- headers. insert ( CONTENT_TYPE , "application/json" . parse ( ) . unwrap ( ) ) ;
129
- headers. insert ( ACCEPT , "application/json" . parse ( ) . unwrap ( ) ) ;
130
- headers. insert (
131
- AUTHORIZATION ,
132
- format ! ( "Bearer {}" , token)
133
- . parse ( )
134
- . unwrap ( ) ,
135
- ) ;
136
- headers. insert ( USER_AGENT , "Rust-relnotes/0.1.0" . parse ( ) . unwrap ( ) ) ;
128
+ let headers = request_header ( ) ;
129
+ let mut args = BTreeMap :: new ( ) ;
130
+ args. insert ( "states" , String :: from ( "[MERGED]" ) ) ;
131
+ args. insert ( "last" , String :: from ( "100" ) ) ;
132
+ let mut issues = Vec :: new ( ) ;
133
+
134
+ loop {
135
+ let query = format ! (
136
+ r#"
137
+ query {{
138
+ repository(owner: "rust-lang", name: "{repo_name}") {{
139
+ milestones(query: "{version}", first: 1) {{
140
+ totalCount
141
+ nodes {{
142
+ pullRequests({args}) {{
143
+ nodes {{
144
+ number
145
+ title
146
+ url
147
+ labels(last: 100) {{
148
+ nodes {{
149
+ name
150
+ }}
151
+ }}
152
+ }}
153
+ pageInfo {{
154
+ startCursor
155
+ }}
156
+ }}
157
+ }}
158
+ }}
159
+ }}
160
+ }}"# ,
161
+ repo_name = repo_name,
162
+ version = version,
163
+ args = args
164
+ . iter( )
165
+ . map( |( k, v) | format!( "{}: {}" , k, v) )
166
+ . collect:: <Vec <_>>( )
167
+ . join( "," )
168
+ )
169
+ . replace ( " " , "" )
170
+ . replace ( "\n " , " " )
171
+ . replace ( '"' , "\\ \" " ) ;
172
+
173
+ let json_query = format ! ( "{{\" query\" : \" {}\" }}" , query) ;
174
+
175
+ let client = Client :: new ( ) ;
176
+
177
+ let json = client
178
+ . post ( "https://api.github.com/graphql" )
179
+ . headers ( headers. clone ( ) )
180
+ . body ( json_query)
181
+ . send ( )
182
+ . unwrap ( )
183
+ . json :: < json:: Value > ( )
184
+ . unwrap ( ) ;
185
+
186
+ let milestones_data = json[ "data" ] [ "repository" ] [ "milestones" ] . clone ( ) ;
187
+ assert_eq ! (
188
+ milestones_data[ "totalCount" ] . as_u64( ) . unwrap( ) ,
189
+ 1 ,
190
+ "More than one milestone matched the query \" {version}\" . Please be more specific." ,
191
+ version = version
192
+ ) ;
193
+ let pull_requests_data = milestones_data[ "nodes" ] [ 0 ] [ "pullRequests" ] . clone ( ) ;
194
+
195
+ let mut pull_requests = pull_requests_data[ "nodes" ] . as_array ( ) . unwrap ( ) . clone ( ) ;
196
+ issues. append ( & mut pull_requests) ;
197
+
198
+ match & pull_requests_data[ "pageInfo" ] [ "startCursor" ] {
199
+ json:: Value :: String ( cursor) => {
200
+ args. insert ( "before" , format ! ( "\" {}\" " , cursor) ) ;
201
+ }
202
+ json:: Value :: Null => {
203
+ break issues;
204
+ }
205
+ _ => unreachable ! ( ) ,
206
+ }
207
+ }
208
+ }
209
+
210
+ fn get_issues_by_date (
211
+ start : Date < Utc > ,
212
+ end : Date < Utc > ,
213
+ repo_name : & ' static str ,
214
+ ) -> Vec < json:: Value > {
215
+ use reqwest:: blocking:: Client ;
216
+
217
+ let headers = request_header ( ) ;
137
218
let mut args = BTreeMap :: new ( ) ;
138
219
args. insert ( "states" , String :: from ( "[MERGED]" ) ) ;
139
220
args. insert ( "last" , String :: from ( "100" ) ) ;
@@ -142,9 +223,9 @@ fn get_issues(start: Date<Utc>, end: Date<Utc>, repo_name: &'static str) -> Vec<
142
223
143
224
loop {
144
225
let query = format ! (
145
- "
226
+ r# "
146
227
query {{
147
- repository(owner: \ " rust-lang\ " , name: \ " {repo_name}\ " ) {{
228
+ repository(owner: "rust-lang", name: "{repo_name}") {{
148
229
pullRequests({args}) {{
149
230
nodes {{
150
231
mergedAt
@@ -162,7 +243,7 @@ fn get_issues(start: Date<Utc>, end: Date<Utc>, repo_name: &'static str) -> Vec<
162
243
}}
163
244
}}
164
245
}}
165
- }}" ,
246
+ }}"# ,
166
247
repo_name = repo_name,
167
248
args = args
168
249
. iter( )
@@ -229,6 +310,17 @@ fn get_issues(start: Date<Utc>, end: Date<Utc>, repo_name: &'static str) -> Vec<
229
310
}
230
311
}
231
312
313
+ fn request_header ( ) -> HeaderMap {
314
+ use reqwest:: header:: * ;
315
+ let token = env:: var ( "GITHUB_TOKEN" ) . expect ( "Set GITHUB_TOKEN to a valid token" ) ;
316
+ let mut headers = HeaderMap :: new ( ) ;
317
+ headers. insert ( CONTENT_TYPE , "application/json" . parse ( ) . unwrap ( ) ) ;
318
+ headers. insert ( ACCEPT , "application/json" . parse ( ) . unwrap ( ) ) ;
319
+ headers. insert ( AUTHORIZATION , format ! ( "Bearer {}" , token) . parse ( ) . unwrap ( ) ) ;
320
+ headers. insert ( USER_AGENT , "Rust-relnotes/0.1.0" . parse ( ) . unwrap ( ) ) ;
321
+ headers
322
+ }
323
+
232
324
fn map_to_line_items < ' a > (
233
325
prefix : & ' static str ,
234
326
iter : impl IntoIterator < Item = & ' a json:: Value > ,
0 commit comments