|
1 | 1 | import datetime |
2 | 2 | import logging |
| 3 | +from collections import defaultdict |
3 | 4 | from collections.abc import Iterable |
4 | 5 | from pathlib import Path |
5 | 6 | from typing import Any |
|
10 | 11 | from mots.config import FileConfig |
11 | 12 | from mots.directory import Directory |
12 | 13 |
|
13 | | -from lando.main.models.jobs import BaseJob |
| 14 | +from lando.main.models.jobs import BaseJob, JobStatus |
14 | 15 | from lando.main.models.repo import Repo |
15 | 16 | from lando.main.models.revision import Revision, RevisionLandingJob |
16 | 17 |
|
@@ -312,6 +313,41 @@ def add_revisions_to_job(revisions: list[Revision], job: LandingJob): |
312 | 313 | job.sort_revisions(revisions) |
313 | 314 |
|
314 | 315 |
|
| 316 | +def get_pull_request_last_landing_job_status( |
| 317 | + repo_name: str, pull_number: int |
| 318 | +) -> JobStatus: |
| 319 | + """Return a heuristically determined status based on related jobs.""" |
| 320 | + target_repo = Repo.objects.get(name=repo_name) |
| 321 | + landing_jobs = get_jobs_for_pull(target_repo, pull_number) |
| 322 | + landing_jobs_by_status = defaultdict(list) |
| 323 | + for landing_job in landing_jobs: |
| 324 | + landing_jobs_by_status[landing_job.status].append(landing_job.id) |
| 325 | + |
| 326 | + # A LANDED status implies that the pull request has landed. A |
| 327 | + # DEFERRED status implies that the last job has been deferred. |
| 328 | + # For all other cases, there may be other permanently failed landing |
| 329 | + # jobs that are no longer relevant to the status of the pull request as |
| 330 | + # a whole. |
| 331 | + |
| 332 | + # A CREATED status implies that the latest landing job is created. |
| 333 | + # A SUBMITTED status implies that the latest landing job is submitted. |
| 334 | + # An IN_PROGRESS status implies that the latest landing job is in progress. |
| 335 | + # A FAILED status implies that the latest landing job has failed. |
| 336 | + |
| 337 | + # Return the first encountered status in this list. |
| 338 | + for _status in [ |
| 339 | + JobStatus.LANDED, |
| 340 | + JobStatus.CREATED, |
| 341 | + JobStatus.SUBMITTED, |
| 342 | + JobStatus.IN_PROGRESS, |
| 343 | + JobStatus.DEFERRED, |
| 344 | + JobStatus.FAILED, |
| 345 | + JobStatus.CANCELLED, |
| 346 | + ]: |
| 347 | + if landing_jobs_by_status[_status]: |
| 348 | + return _status |
| 349 | + |
| 350 | + |
315 | 351 | def get_jobs_for_pull(target_repo: Repo, pull_number: int) -> QuerySet[LandingJob]: |
316 | 352 | """Given a target repo and a pull number, return all landing jobs.""" |
317 | 353 | revisions = Revision.objects.filter( |
|
0 commit comments