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