15
15
from __future__ import annotations
16
16
17
17
import argparse
18
- import dataclasses
19
18
import logging
20
19
import pathlib
21
20
import re
22
- import subprocess
23
21
import typing
24
22
25
- if typing .TYPE_CHECKING :
26
- from collections .abc import Iterable
23
+ from util import fetch_pr_info , pr_number_from_github_ref
27
24
28
25
29
26
def main () -> None :
30
27
args = parse_args ()
31
28
logging .basicConfig (format = "%(message)s" , level = logging .INFO )
32
29
33
- calculated_result = calculate_github_issue (
30
+ github_issue = calculate_github_issue (
34
31
github_event_name = args .github_event_name ,
35
32
github_issue_for_scheduled_run = args .github_issue_for_scheduled_run ,
36
33
github_ref = args .github_ref ,
37
34
github_repository = args .github_repository ,
38
35
pr_body_github_issue_key = args .pr_body_github_issue_key ,
39
36
)
40
37
41
- github_issue = calculated_result .issue
42
- github_pr = calculated_result .pr
43
-
44
38
issue_file_text = "" if github_issue is None else str (github_issue )
45
39
logging .info ("Writing '%s' to %s" , issue_file_text , args .issue_output_file )
46
40
args .issue_output_file .write_text (issue_file_text , encoding = "utf8" , errors = "replace" )
47
41
48
- pr_file_text = "" if github_pr is None else str (github_pr )
49
- logging .info ("Writing '%s' to %s" , pr_file_text , args .pr_output_file )
50
- args .pr_output_file .write_text (pr_file_text , encoding = "utf8" , errors = "replace" )
51
-
52
-
53
- @dataclasses .dataclass (frozen = True )
54
- class CalculatedGitHubIssue :
55
- issue : int | None
56
- pr : int | None
57
-
58
42
59
43
def calculate_github_issue (
60
44
github_event_name : str ,
61
45
github_issue_for_scheduled_run : int ,
62
46
github_ref : str ,
63
47
github_repository : str ,
64
48
pr_body_github_issue_key : str ,
65
- ) -> CalculatedGitHubIssue :
49
+ ) -> int | None :
66
50
if github_event_name == "schedule" :
67
51
logging .info (
68
52
"GitHub Event name is: %s; using GitHub Issue: %s" ,
69
53
github_event_name ,
70
54
github_issue_for_scheduled_run ,
71
55
)
72
- return CalculatedGitHubIssue (
73
- issue = github_issue_for_scheduled_run ,
74
- pr = None , # scheduled runs are, by definition, not associated with a PR.
75
- )
56
+ return github_issue_for_scheduled_run
76
57
77
58
logging .info ("Extracting PR number from string: %s" , github_ref )
78
59
pr_number = pr_number_from_github_ref (github_ref )
79
60
if pr_number is None :
80
61
logging .info ("No PR number extracted" )
81
- return CalculatedGitHubIssue ( None , None )
62
+ return None
82
63
typing .assert_type (pr_number , int )
83
64
84
65
logging .info ("PR number extracted: %s" , pr_number )
85
66
logging .info ("Loading body text of PR: %s" , pr_number )
86
- pr_body_text = load_pr_body (
67
+ pr_info = fetch_pr_info (
87
68
pr_number = pr_number ,
88
69
github_repository = github_repository ,
89
70
)
90
71
91
72
logging .info ("Looking for GitHub Issue key in PR body text: %s=NNNN" , pr_body_github_issue_key )
92
73
github_issue = github_issue_from_pr_body (
93
- pr_body = pr_body_text ,
74
+ pr_body = pr_info . body ,
94
75
issue_key = pr_body_github_issue_key ,
95
76
)
96
77
97
78
if github_issue is None :
98
79
logging .info ("No GitHub Issue key found in PR body" )
99
- return CalculatedGitHubIssue ( issue = None , pr = pr_number )
80
+ return None
100
81
typing .assert_type (github_issue , int )
101
82
102
83
logging .info ("Found GitHub Issue key in PR body: %s" , github_issue )
103
- return CalculatedGitHubIssue (issue = github_issue , pr = pr_number )
104
-
105
-
106
- def pr_number_from_github_ref (github_ref : str ) -> int | None :
107
- match = re .fullmatch ("refs/pull/([0-9]+)/merge" , github_ref )
108
- return int (match .group (1 )) if match else None
109
-
110
-
111
- def load_pr_body (pr_number : int , github_repository : str ) -> str :
112
- gh_args = log_pr_body_gh_args (pr_number = pr_number , github_repository = github_repository )
113
- gh_args = tuple (gh_args )
114
- logging .info ("Running command: %s" , subprocess .list2cmdline (gh_args ))
115
- return subprocess .check_output (gh_args , encoding = "utf8" , errors = "replace" ) # noqa: S603
116
-
117
-
118
- def log_pr_body_gh_args (pr_number : int , github_repository : str ) -> Iterable [str ]:
119
- yield "gh"
120
- yield "issue"
121
- yield "view"
122
- yield str (pr_number )
123
- yield "--json"
124
- yield "body"
125
- yield "--jq"
126
- yield ".body"
127
- yield "-R"
128
- yield github_repository
84
+ return github_issue
129
85
130
86
131
87
def github_issue_from_pr_body (pr_body : str , issue_key : str ) -> int | None :
@@ -139,7 +95,6 @@ def github_issue_from_pr_body(pr_body: str, issue_key: str) -> int | None:
139
95
140
96
class ParsedArgs (typing .Protocol ):
141
97
issue_output_file : pathlib .Path
142
- pr_output_file : pathlib .Path
143
98
github_ref : str
144
99
github_repository : str
145
100
github_event_name : str
@@ -155,12 +110,6 @@ def parse_args() -> ParsedArgs:
155
110
help = "The file to which to write the calculated issue number"
156
111
"if no issue number was found, then an empty file will be written" ,
157
112
)
158
- arg_parser .add_argument (
159
- "--pr-output-file" ,
160
- required = True ,
161
- help = "The file to which to write the calculated triggering PR number"
162
- "if no PR was found, then an empty file will be written" ,
163
- )
164
113
arg_parser .add_argument (
165
114
"--github-ref" ,
166
115
required = True ,
@@ -192,7 +141,6 @@ def parse_args() -> ParsedArgs:
192
141
193
142
parse_result = arg_parser .parse_args ()
194
143
parse_result .issue_output_file = pathlib .Path (parse_result .issue_output_file )
195
- parse_result .pr_output_file = pathlib .Path (parse_result .pr_output_file )
196
144
return typing .cast ("ParsedArgs" , parse_result )
197
145
198
146
0 commit comments