|
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 |
|
@@ -304,6 +305,41 @@ def add_revisions_to_job(revisions: list[Revision], job: LandingJob): |
304 | 305 | job.sort_revisions(revisions) |
305 | 306 |
|
306 | 307 |
|
| 308 | +def get_pull_request_last_landing_job_status( |
| 309 | + repo_name: str, pull_number: int |
| 310 | +) -> JobStatus: |
| 311 | + """Return a heuristically determined status based on related jobs.""" |
| 312 | + target_repo = Repo.objects.get(name=repo_name) |
| 313 | + landing_jobs = get_jobs_for_pull(target_repo, pull_number) |
| 314 | + landing_jobs_by_status = defaultdict(list) |
| 315 | + for landing_job in landing_jobs: |
| 316 | + landing_jobs_by_status[landing_job.status].append(landing_job.id) |
| 317 | + |
| 318 | + # A LANDED status implies that the pull request has landed. A |
| 319 | + # DEFERRED status implies that the last job has been deferred. |
| 320 | + # For all other cases, there may be other permanently failed landing |
| 321 | + # jobs that are no longer relevant to the status of the pull request as |
| 322 | + # a whole. |
| 323 | + |
| 324 | + # A CREATED status implies that the latest landing job is created. |
| 325 | + # A SUBMITTED status implies that the latest landing job is submitted. |
| 326 | + # An IN_PROGRESS status implies that the latest landing job is in progress. |
| 327 | + # A FAILED status implies that the latest landing job has failed. |
| 328 | + |
| 329 | + # Return the first encountered status in this list. |
| 330 | + for _status in [ |
| 331 | + JobStatus.LANDED, |
| 332 | + JobStatus.CREATED, |
| 333 | + JobStatus.SUBMITTED, |
| 334 | + JobStatus.IN_PROGRESS, |
| 335 | + JobStatus.DEFERRED, |
| 336 | + JobStatus.FAILED, |
| 337 | + JobStatus.CANCELLED, |
| 338 | + ]: |
| 339 | + if landing_jobs_by_status[_status]: |
| 340 | + return _status |
| 341 | + |
| 342 | + |
307 | 343 | def get_jobs_for_pull(target_repo: Repo, pull_number: int) -> QuerySet[LandingJob]: |
308 | 344 | """Given a target repo and a pull number, return all landing jobs.""" |
309 | 345 | revisions = Revision.objects.filter( |
|
0 commit comments