16
16
17
17
from typing import Optional
18
18
import argparse
19
+ import time
19
20
from github .Repository import Repository
20
21
from github .Workflow import Workflow
22
+ from github .WorkflowRun import WorkflowRun
21
23
from github .GithubException import GithubException
22
24
from library_functions import StrPath
23
25
from iterate_libraries import (
@@ -56,6 +58,46 @@ def run_gh_rest_check(
56
58
return workflow_runs [0 ].conclusion
57
59
58
60
61
+ def run_gh_rest_rerun (
62
+ lib_repo : Repository ,
63
+ user : Optional [str ] = None ,
64
+ branch : Optional [str ] = None ,
65
+ workflow_filename : Optional [str ] = "build.yml" ,
66
+ rerun_level : int = 0 ,
67
+ ) -> bool :
68
+ """Uses ``PyGithub`` to rerun the CI status of a repository
69
+
70
+ :param Repository lib_repo: The repo as a github.Repository.Repository object
71
+ :param str|None user: The user that triggered the run; if `None` is
72
+ provided, any user is acceptable
73
+ :param str|None branch: The branch name to specifically check; if `None` is
74
+ provided, all branches are allowed; this is the default
75
+ :param str|None workflow_filename: The filename of the workflow; if `None` is
76
+ provided, any workflow name is acceptable; the default is ``"build.yml"``
77
+ :param int rerun_level: The level at which rerun should occur (0 = none,
78
+ 1 = failed, 2 = all)
79
+ :return: The requested runs conclusion
80
+ :rtype: bool
81
+ """
82
+ if not rerun_level :
83
+ return False
84
+ if rerun_level == 1 :
85
+ result = (
86
+ run_gh_rest_check (lib_repo , user , branch , workflow_filename ) == "success"
87
+ )
88
+ if rerun_level == 2 or not result :
89
+ arg_dict = {}
90
+ if user is not None :
91
+ arg_dict ["actor" ] = user
92
+ if branch is not None :
93
+ arg_dict ["branch" ] = branch
94
+ workflow : Workflow = lib_repo .get_workflow (workflow_filename )
95
+ latest_run : WorkflowRun = workflow .get_runs (** arg_dict )[0 ]
96
+ latest_run .rerun ()
97
+ return True
98
+ return False
99
+
100
+
59
101
def check_build_status (
60
102
lib_repo : Repository ,
61
103
user : Optional [str ] = None ,
@@ -105,13 +147,63 @@ def check_build_status(
105
147
return None
106
148
107
149
150
+ # pylint: disable=too-many-arguments
151
+ def rerun_workflow (
152
+ lib_repo : Repository ,
153
+ user : Optional [str ] = None ,
154
+ branch : Optional [str ] = None ,
155
+ workflow_filename : Optional [str ] = "build.yml" ,
156
+ rerun_level : int = 0 ,
157
+ debug : bool = False ,
158
+ ):
159
+ """Uses ``PyGithub`` to rerun the CI of the Adafruit
160
+ CircuitPython Bundle repositories
161
+
162
+ :param Repository lib_repo: The repo as a github.Repository.Repository object
163
+ :param str|None user: The user that triggered the run; if `None` is
164
+ provided, any user is acceptable
165
+ :param str|None branch: The branch name to specifically check; if `None` is
166
+ provided, all branches are allowed; this is the default
167
+ :param str|None workflow_filename: The filename of the workflow; if `None`
168
+ is provided, any workflow name is acceptable; the defail is `"build.yml"`
169
+ :param int rerun_level: The level at which rerun should occur (0 = none,
170
+ 1 = failed, 2 = all)
171
+ :param bool debug: Whether debug statements should be printed to the standard
172
+ output
173
+ :return: The result of the workflow run, or ``None`` if it could not be
174
+ determined
175
+ :rtype: bool|None
176
+ """
177
+ if lib_repo .archived :
178
+ return False
179
+
180
+ try :
181
+ result = run_gh_rest_rerun (
182
+ lib_repo , user , branch , workflow_filename , rerun_level
183
+ )
184
+ if debug and result :
185
+ print ("***" , "Library" , lib_repo .name , "workflow was rerun!" , "***" )
186
+ return result
187
+ except GithubException :
188
+ if debug :
189
+ print (
190
+ "???" ,
191
+ "Library" ,
192
+ lib_repo .name ,
193
+ "had an issue occur" ,
194
+ "???" ,
195
+ )
196
+ return None
197
+
198
+
108
199
def check_build_statuses (
109
200
gh_token : str ,
110
201
user : Optional [str ] = None ,
111
202
branch : Optional [str ] = "main" ,
112
203
workflow_filename : Optional [str ] = "build.yml" ,
113
204
* ,
114
205
debug : bool = False ,
206
+ local_folder : str = "" ,
115
207
) -> list [RemoteLibFunc_IterResult [bool ]]:
116
208
"""Checks all the libraries in the Adafruit CircuitPython Bundle to get the
117
209
latest build status with the requested information
@@ -125,6 +217,7 @@ def check_build_statuses(
125
217
provided, any workflow name is acceptable; the defail is `"build.yml"`
126
218
:param bool debug: Whether debug statements should be printed to
127
219
the standard output
220
+ :param str local_folder: A path to a local folder containing extra repositories
128
221
:return: A list of tuples containing paired Repoistory objects and build
129
222
statuses
130
223
:rtype: list
@@ -133,6 +226,49 @@ def check_build_statuses(
133
226
return iter_remote_bundle_with_func (
134
227
gh_token ,
135
228
[(check_build_status , (user , branch , workflow_filename ), {"debug" : debug })],
229
+ local_folder = local_folder ,
230
+ )
231
+
232
+
233
+ def rerun_workflows (
234
+ gh_token : str ,
235
+ user : Optional [str ] = None ,
236
+ branch : Optional [str ] = "main" ,
237
+ workflow_filename : Optional [str ] = "build.yml" ,
238
+ rerun_level : int = 0 ,
239
+ * ,
240
+ debug : bool = False ,
241
+ local_folder : str = "" ,
242
+ ) -> list [RemoteLibFunc_IterResult [bool ]]:
243
+ """Reruns the CI of all the libraries in the Adafruit CircuitPython Bundle.
244
+
245
+ :param str gh_token: The Github token to be used for with the Github API
246
+ :param str|None user: The user that triggered the run; if `None` is
247
+ provided, any user is acceptable
248
+ :param str|None branch: The branch name to specifically check; if `None` is
249
+ provided, all branches are allowed; this is the default
250
+ :param str|None workflow_filename: The filename of the workflow; if `None` is
251
+ provided, any workflow name is acceptable; the defail is `"build.yml"`
252
+ :param int rerun_level: The level at which reruns should occur (0 = none,
253
+ 1 = failed, 2 = all)
254
+ :param bool debug: Whether debug statements should be printed to
255
+ the standard output
256
+ :param str local_folder: A path to a local folder containing extra repositories
257
+ :return: A list of tuples containing paired Repoistory objects and build
258
+ statuses
259
+ :rtype: list
260
+ """
261
+
262
+ return iter_remote_bundle_with_func (
263
+ gh_token ,
264
+ [
265
+ (
266
+ rerun_workflow ,
267
+ (user , branch , workflow_filename , rerun_level ),
268
+ {"debug" : debug },
269
+ )
270
+ ],
271
+ local_folder = local_folder ,
136
272
)
137
273
138
274
@@ -193,12 +329,52 @@ def save_build_statuses(
193
329
parser .add_argument (
194
330
"--debug" , action = "store_true" , help = "Print debug text during execution"
195
331
)
332
+ parser .add_argument (
333
+ "--rerun-level" ,
334
+ metavar = "R" ,
335
+ type = int ,
336
+ dest = "rerun_level" ,
337
+ default = 0 ,
338
+ help = "Level to rerun CI workflows (0 = none, 1 = failed, 2 = all)" ,
339
+ )
340
+ parser .add_argument (
341
+ "--local-folder" ,
342
+ metavar = "L" ,
343
+ type = str ,
344
+ dest = "local_folder" ,
345
+ default = "" ,
346
+ help = "An additional folder to check and run" ,
347
+ )
196
348
197
349
args = parser .parse_args ()
198
350
351
+ if args .rerun_level :
352
+ if args .debug :
353
+ print ("Rerunning workflows..." )
354
+ rerun_workflows (
355
+ args .gh_token ,
356
+ args .user ,
357
+ args .branch ,
358
+ args .workflow ,
359
+ args .rerun_level ,
360
+ debug = args .debug ,
361
+ local_folder = args .local_folder ,
362
+ )
363
+ if args .debug :
364
+ print ("Waiting 10 minutes to allow workflows to finish running..." )
365
+ time .sleep (600 )
366
+
367
+ if args .debug :
368
+ print ("Checking workflows statuses..." )
199
369
results = check_build_statuses (
200
- args .gh_token , args .user , args .branch , args .workflow , debug = args .debug
370
+ args .gh_token ,
371
+ args .user ,
372
+ args .branch ,
373
+ args .workflow ,
374
+ debug = args .debug ,
375
+ local_folder = args .local_folder ,
201
376
)
377
+
202
378
fail_list = [
203
379
repo_name .name for repo_name , repo_results in results if not repo_results [0 ]
204
380
]
0 commit comments