|
17 | 17 | GitHubActivityQueryBuilder,
|
18 | 18 | GitHubAttentionQueryBuilder,
|
19 | 19 | GitHubSearch,
|
| 20 | + MarkdownContent, |
20 | 21 | MultiRepositoryInquiry,
|
21 | 22 | PullRequestMetadata,
|
22 | 23 | )
|
@@ -127,13 +128,22 @@ def print(self):
|
127 | 128 | print(self.markdown_significant)
|
128 | 129 |
|
129 | 130 |
|
130 |
| -class GitHubActionsReport: |
| 131 | +class GitHubActionsRequest: |
131 | 132 | """
|
132 |
| - Report about failed outcomes of GitHub Actions workflow runs. |
| 133 | + Fetch outcomes of GitHub Actions workflow runs. |
| 134 | +
|
| 135 | + Possible event types are: dynamic, pull_request, push, schedule |
133 | 136 | """
|
134 | 137 |
|
135 | 138 | DELTA_HOURS = 24
|
136 | 139 |
|
| 140 | + event_section_map = OrderedDict( |
| 141 | + schedule="Schedule", |
| 142 | + pull_request="Pull requests", |
| 143 | + # push="Pushes", |
| 144 | + dynamic="Dynamic", |
| 145 | + ) |
| 146 | + |
137 | 147 | def __init__(self, inquiry: MultiRepositoryInquiry):
|
138 | 148 | self.inquiry = inquiry
|
139 | 149 | self.session = HttpClient.session
|
@@ -164,41 +174,75 @@ def fetch(self, filter: ActionsFilter) -> t.List[ActionsOutcome]: # noqa:A002
|
164 | 174 | runs = munchify(response.json()).workflow_runs
|
165 | 175 | for run in runs:
|
166 | 176 | outcome = ActionsOutcome(
|
| 177 | + id=run.id, |
| 178 | + event=run.event, |
167 | 179 | status=run.status,
|
168 |
| - repository=repository, |
| 180 | + conclusion=run.conclusion, |
| 181 | + repository=run.repository, |
169 | 182 | name=run.display_title,
|
170 | 183 | url=run.html_url,
|
171 | 184 | started=run.run_started_at,
|
| 185 | + head_branch=run.head_branch, |
172 | 186 | )
|
173 | 187 | outcomes.append(outcome)
|
174 | 188 | return outcomes
|
175 | 189 |
|
176 |
| - def to_markdown(self, filter: ActionsFilter) -> str: # noqa:A002 |
177 |
| - return "\n".join([item.markdown for item in self.fetch(filter=filter)]) |
| 190 | + @property |
| 191 | + def runs_failed(self): |
| 192 | + return self.fetch(filter=ActionsFilter(status="failure", created=f">{self.yesterday}")) |
178 | 193 |
|
179 | 194 | @property
|
180 |
| - def markdown(self): |
181 |
| - items_scheduled = self.to_markdown( |
182 |
| - ActionsFilter(event="schedule", status="failure", created=f">{self.yesterday}") |
183 |
| - ) |
184 |
| - items_pull_requests = self.to_markdown( |
185 |
| - ActionsFilter(event="pull_request", status="failure", created=f">{self.yesterday}") |
186 |
| - ) |
187 |
| - items_dynamic = self.to_markdown( |
188 |
| - ActionsFilter(event="dynamic", status="failure", created=f">{self.yesterday}") |
| 195 | + def runs_pr_success(self): |
| 196 | + return self.fetch( |
| 197 | + filter=ActionsFilter( |
| 198 | + event="pull_request", status="success", created=f">{self.yesterday}" |
| 199 | + ) |
189 | 200 | )
|
190 |
| - return dedent(f""" |
191 |
| -# CI failures report {dt.datetime.now().strftime("%Y-%m-%d")} |
192 |
| -A report about GitHub Actions workflow runs that failed recently (now-{self.DELTA_HOURS}h). |
193 | 201 |
|
194 |
| -## Scheduled |
195 |
| -{items_scheduled or "n/a"} |
196 | 202 |
|
197 |
| -## Pull requests |
198 |
| -{items_pull_requests or "n/a"} |
| 203 | +class GitHubActionsReport: |
| 204 | + """ |
| 205 | + Report about failed outcomes of GitHub Actions workflow runs. |
| 206 | + """ |
| 207 | + |
| 208 | + def __init__(self, inquiry: MultiRepositoryInquiry): |
| 209 | + self.inquiry = inquiry |
| 210 | + self.request = GitHubActionsRequest(inquiry) |
| 211 | + self.runs_failed = self.request.runs_failed |
| 212 | + self.runs_pr_success = self.request.runs_pr_success |
| 213 | + |
| 214 | + @property |
| 215 | + def runs(self): |
| 216 | + """ |
| 217 | + All failed runs, modulo subsequent succeeding PR runs. |
| 218 | + """ |
| 219 | + for run in self.runs_failed: |
| 220 | + if run.event == "pull_request" and self.is_pr_successful(run): |
| 221 | + continue |
| 222 | + yield run |
199 | 223 |
|
200 |
| -## Dynamic |
201 |
| -{items_dynamic or "n/a"} |
| 224 | + def is_pr_successful(self, run): |
| 225 | + """ |
| 226 | + Find out if a given run has others that succeeded afterward. |
| 227 | + """ |
| 228 | + for pr in self.runs_pr_success: |
| 229 | + if ( |
| 230 | + run.repository.full_name == pr.repository.full_name |
| 231 | + and run.head_branch == pr.head_branch |
| 232 | + ): |
| 233 | + if pr.conclusion == "success": |
| 234 | + return True |
| 235 | + return False |
| 236 | + |
| 237 | + @property |
| 238 | + def markdown(self): |
| 239 | + mdc = MarkdownContent(labels=self.request.event_section_map) |
| 240 | + for run in self.runs: |
| 241 | + mdc.add(run.event, run.markdown) |
| 242 | + return dedent(f""" |
| 243 | +# CI failures report {dt.datetime.now().strftime("%Y-%m-%d")} |
| 244 | +A report about GitHub Actions workflow runs that failed recently (now-{self.request.DELTA_HOURS}h). |
| 245 | +{mdc.render()} |
202 | 246 | """).strip() # noqa: E501
|
203 | 247 |
|
204 | 248 | def print(self):
|
|
0 commit comments