@@ -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,100 @@ 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
+ mergedAt
143
+ number
144
+ title
145
+ url
146
+ labels(last: 100) {{
147
+ nodes {{
148
+ name
149
+ }}
150
+ }}
151
+ }}
152
+ pageInfo {{
153
+ startCursor
154
+ }}
155
+ }}
156
+ }}
157
+ }}
158
+ }}
159
+ }}"# ,
160
+ repo_name = repo_name,
161
+ version = version,
162
+ args = args
163
+ . iter( )
164
+ . map( |( k, v) | format!( "{}: {}" , k, v) )
165
+ . collect:: <Vec <_>>( )
166
+ . join( "," )
167
+ )
168
+ . replace ( " " , "" )
169
+ . replace ( "\n " , " " )
170
+ . replace ( '"' , "\\ \" " ) ;
171
+
172
+ let json_query = format ! ( "{{\" query\" : \" {}\" }}" , query) ;
173
+
174
+ let client = Client :: new ( ) ;
175
+
176
+ let json = client
177
+ . post ( "https://api.github.com/graphql" )
178
+ . headers ( headers. clone ( ) )
179
+ . body ( json_query)
180
+ . send ( )
181
+ . unwrap ( )
182
+ . json :: < json:: Value > ( )
183
+ . unwrap ( ) ;
184
+
185
+ let milestones_data = json[ "data" ] [ "repository" ] [ "milestones" ] . clone ( ) ;
186
+ assert_eq ! (
187
+ milestones_data[ "totalCount" ] . as_u64( ) . unwrap( ) ,
188
+ 1 ,
189
+ "More than one milestone matched the query \" {version}\" . Please be more specific." ,
190
+ version = version
191
+ ) ;
192
+ let pull_requests_data = milestones_data[ "nodes" ] [ 0 ] [ "pullRequests" ] . clone ( ) ;
193
+
194
+ let mut pull_requests = pull_requests_data[ "nodes" ] . as_array ( ) . unwrap ( ) . clone ( ) ;
195
+ issues. append ( & mut pull_requests) ;
196
+
197
+ match & pull_requests_data[ "pageInfo" ] [ "startCursor" ] {
198
+ json:: Value :: String ( cursor) => {
199
+ args. insert ( "before" , format ! ( "\" {}\" " , cursor) ) ;
200
+ }
201
+ json:: Value :: Null => {
202
+ break issues;
203
+ }
204
+ _ => unreachable ! ( ) ,
205
+ }
206
+ }
207
+ }
208
+
209
+ fn get_issues_by_date (
210
+ start : Date < Utc > ,
211
+ end : Date < Utc > ,
212
+ repo_name : & ' static str ,
213
+ ) -> Vec < json:: Value > {
214
+ use reqwest:: blocking:: Client ;
215
+
216
+ let headers = request_header ( ) ;
137
217
let mut args = BTreeMap :: new ( ) ;
138
218
args. insert ( "states" , String :: from ( "[MERGED]" ) ) ;
139
219
args. insert ( "last" , String :: from ( "100" ) ) ;
@@ -142,9 +222,9 @@ fn get_issues(start: Date<Utc>, end: Date<Utc>, repo_name: &'static str) -> Vec<
142
222
143
223
loop {
144
224
let query = format ! (
145
- "
225
+ r# "
146
226
query {{
147
- repository(owner: \ " rust-lang\ " , name: \ " {repo_name}\ " ) {{
227
+ repository(owner: "rust-lang", name: "{repo_name}") {{
148
228
pullRequests({args}) {{
149
229
nodes {{
150
230
mergedAt
@@ -162,7 +242,7 @@ fn get_issues(start: Date<Utc>, end: Date<Utc>, repo_name: &'static str) -> Vec<
162
242
}}
163
243
}}
164
244
}}
165
- }}" ,
245
+ }}"# ,
166
246
repo_name = repo_name,
167
247
args = args
168
248
. iter( )
@@ -229,6 +309,17 @@ fn get_issues(start: Date<Utc>, end: Date<Utc>, repo_name: &'static str) -> Vec<
229
309
}
230
310
}
231
311
312
+ fn request_header ( ) -> HeaderMap {
313
+ use reqwest:: header:: * ;
314
+ let token = env:: var ( "GITHUB_TOKEN" ) . expect ( "Set GITHUB_TOKEN to a valid token" ) ;
315
+ let mut headers = HeaderMap :: new ( ) ;
316
+ headers. insert ( CONTENT_TYPE , "application/json" . parse ( ) . unwrap ( ) ) ;
317
+ headers. insert ( ACCEPT , "application/json" . parse ( ) . unwrap ( ) ) ;
318
+ headers. insert ( AUTHORIZATION , format ! ( "Bearer {}" , token) . parse ( ) . unwrap ( ) ) ;
319
+ headers. insert ( USER_AGENT , "Rust-relnotes/0.1.0" . parse ( ) . unwrap ( ) ) ;
320
+ headers
321
+ }
322
+
232
323
fn map_to_line_items < ' a > (
233
324
prefix : & ' static str ,
234
325
iter : impl IntoIterator < Item = & ' a json:: Value > ,
0 commit comments