WorkflowRun.py
1 ############################ Copyrights and license ############################ 2 # # 3 # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> # 4 # Copyright 2022 Aleksei Fedotov <aleksei@fedotov.email> # 5 # # 6 # This file is part of PyGithub. # 7 # http://pygithub.readthedocs.io/ # 8 # # 9 # PyGithub is free software: you can redistribute it and/or modify it under # 10 # the terms of the GNU Lesser General Public License as published by the Free # 11 # Software Foundation, either version 3 of the License, or (at your option) # 12 # any later version. # 13 # # 14 # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # 15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # 16 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # 17 # details. # 18 # # 19 # You should have received a copy of the GNU Lesser General Public License # 20 # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. # 21 # # 22 ################################################################################ 23 24 from __future__ import annotations 25 26 from datetime import datetime 27 from typing import TYPE_CHECKING, Any, NamedTuple 28 29 import github.GitCommit 30 import github.PullRequest 31 import github.WorkflowJob 32 from github.GithubObject import Attribute, CompletableGithubObject, NotSet, Opt, is_optional 33 from github.PaginatedList import PaginatedList 34 35 if TYPE_CHECKING: 36 from github.Artifact import Artifact 37 from github.GitCommit import GitCommit 38 from github.PullRequest import PullRequest 39 from github.Repository import Repository 40 from github.WorkflowJob import WorkflowJob 41 42 43 class TimingData(NamedTuple): 44 billable: dict[str, dict[str, int]] 45 run_duration_ms: int 46 47 48 class WorkflowRun(CompletableGithubObject): 49 """ 50 This class represents Workflow Runs. The reference can be found here https://docs.github.com/en/rest/reference/actions#workflow-runs 51 """ 52 53 def _initAttributes(self) -> None: 54 self._id: Attribute[int] = NotSet 55 self._url: Attribute[str] = NotSet 56 self._name: Attribute[str] = NotSet 57 self._path: Attribute[str] = NotSet 58 self._head_branch: Attribute[str] = NotSet 59 self._head_sha: Attribute[str] = NotSet 60 self._run_attempt: Attribute[int] = NotSet 61 self._run_number: Attribute[int] = NotSet 62 self._created_at: Attribute[datetime] = NotSet 63 self._updated_at: Attribute[datetime] = NotSet 64 self._pull_requests: Attribute[list[PullRequest]] = NotSet 65 self._status: Attribute[str] = NotSet 66 self._conclusion: Attribute[str] = NotSet 67 self._html_url: Attribute[str] = NotSet 68 self._jobs_url: Attribute[str] = NotSet 69 self._logs_url: Attribute[str] = NotSet 70 self._display_title: Attribute[str] = NotSet 71 self._event: Attribute[str] = NotSet 72 self._run_started_at: Attribute[datetime] = NotSet 73 self._check_suite_url: Attribute[str] = NotSet 74 self._cancel_url: Attribute[str] = NotSet 75 self._rerun_url: Attribute[str] = NotSet 76 self._artifacts_url: Attribute[str] = NotSet 77 self._workflow_url: Attribute[str] = NotSet 78 self._head_commit: Attribute[GitCommit] = NotSet 79 self._repository: Attribute[Repository] = NotSet 80 self._head_repository: Attribute[Repository] = NotSet 81 82 def __repr__(self) -> str: 83 return self.get__repr__({"id": self._id.value, "url": self._url.value}) 84 85 @property 86 def id(self) -> int: 87 self._completeIfNotSet(self._id) 88 return self._id.value 89 90 @property 91 def name(self) -> str: 92 self._completeIfNotSet(self._name) 93 return self._name.value 94 95 @property 96 def head_branch(self) -> str: 97 self._completeIfNotSet(self._head_branch) 98 return self._head_branch.value 99 100 @property 101 def head_sha(self) -> str: 102 self._completeIfNotSet(self._head_sha) 103 return self._head_sha.value 104 105 @property 106 def display_title(self) -> str: 107 self._completeIfNotSet(self._display_title) 108 return self._display_title.value 109 110 @property 111 def path(self) -> str: 112 self._completeIfNotSet(self._path) 113 return self._path.value 114 115 @property 116 def run_attempt(self) -> int: 117 self._completeIfNotSet(self._run_attempt) 118 return self._run_attempt.value 119 120 @property 121 def run_number(self) -> int: 122 self._completeIfNotSet(self._run_number) 123 return self._run_number.value 124 125 @property 126 def event(self) -> str: 127 self._completeIfNotSet(self._event) 128 return self._event.value 129 130 @property 131 def run_started_at(self) -> datetime: 132 self._completeIfNotSet(self._run_started_at) 133 return self._run_started_at.value 134 135 @property 136 def status(self) -> str: 137 self._completeIfNotSet(self._status) 138 return self._status.value 139 140 @property 141 def conclusion(self) -> str: 142 self._completeIfNotSet(self._conclusion) 143 return self._conclusion.value 144 145 @property 146 def workflow_id(self) -> int: 147 self._completeIfNotSet(self._workflow_id) 148 return self._workflow_id.value 149 150 @property 151 def url(self) -> str: 152 self._completeIfNotSet(self._url) 153 return self._url.value 154 155 @property 156 def html_url(self) -> str: 157 self._completeIfNotSet(self._html_url) 158 return self._html_url.value 159 160 @property 161 def pull_requests(self) -> list[PullRequest]: 162 self._completeIfNotSet(self._pull_requests) 163 return self._pull_requests.value 164 165 @property 166 def created_at(self) -> datetime: 167 self._completeIfNotSet(self._created_at) 168 return self._created_at.value 169 170 @property 171 def updated_at(self) -> datetime: 172 self._completeIfNotSet(self._updated_at) 173 return self._updated_at.value 174 175 @property 176 def jobs_url(self) -> str: 177 self._completeIfNotSet(self._jobs_url) 178 return self._jobs_url.value 179 180 @property 181 def logs_url(self) -> str: 182 self._completeIfNotSet(self._logs_url) 183 return self._logs_url.value 184 185 @property 186 def check_suite_url(self) -> str: 187 self._completeIfNotSet(self._check_suite_url) 188 return self._check_suite_url.value 189 190 @property 191 def artifacts_url(self) -> str: 192 self._completeIfNotSet(self._artifacts_url) 193 return self._artifacts_url.value 194 195 def get_artifacts(self) -> PaginatedList[Artifact]: 196 return PaginatedList( 197 github.Artifact.Artifact, 198 self._requester, 199 self._artifacts_url.value, 200 None, 201 list_item="artifacts", 202 ) 203 204 @property 205 def cancel_url(self) -> str: 206 self._completeIfNotSet(self._cancel_url) 207 return self._cancel_url.value 208 209 @property 210 def rerun_url(self) -> str: 211 self._completeIfNotSet(self._rerun_url) 212 return self._rerun_url.value 213 214 @property 215 def workflow_url(self) -> str: 216 self._completeIfNotSet(self._workflow_url) 217 return self._workflow_url.value 218 219 @property 220 def head_commit(self) -> GitCommit: 221 self._completeIfNotSet(self._head_commit) 222 return self._head_commit.value 223 224 @property 225 def repository(self) -> Repository: 226 self._completeIfNotSet(self._repository) 227 return self._repository.value 228 229 @property 230 def head_repository(self) -> Repository: 231 self._completeIfNotSet(self._head_repository) 232 return self._head_repository.value 233 234 def cancel(self) -> bool: 235 """ 236 :calls: `POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel <https://docs.github.com/en/rest/reference/actions#workflow-runs>`_ 237 """ 238 status, _, _ = self._requester.requestJson("POST", self.cancel_url) 239 return status == 202 240 241 def rerun(self) -> bool: 242 """ 243 :calls: `POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun <https://docs.github.com/en/rest/reference/actions#workflow-runs>`_ 244 """ 245 status, _, _ = self._requester.requestJson("POST", self.rerun_url) 246 return status == 201 247 248 def timing(self) -> TimingData: 249 """ 250 :calls: `GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing <https://docs.github.com/en/rest/reference/actions#workflow-runs>`_ 251 """ 252 headers, data = self._requester.requestJsonAndCheck("GET", f"{self.url}/timing") 253 return TimingData(billable=data["billable"], run_duration_ms=data["run_duration_ms"]) # type: ignore 254 255 def delete(self) -> bool: 256 """ 257 :calls: `DELETE /repos/{owner}/{repo}/actions/runs/{run_id} <https://docs.github.com/en/rest/reference/actions#workflow-runs>`_ 258 """ 259 status, _, _ = self._requester.requestJson("DELETE", self.url) 260 return status == 204 261 262 def jobs(self, _filter: Opt[str] = NotSet) -> PaginatedList[WorkflowJob]: 263 """ 264 :calls "`GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs <https://docs.github.com/en/rest/reference/actions#list-jobs-for-a-workflow-run>`_ 265 :param _filter: string `latest`, or `all` 266 """ 267 assert is_optional(_filter, str), _filter 268 269 url_parameters = NotSet.remove_unset_items({"filter": _filter}) 270 271 return PaginatedList( 272 github.WorkflowJob.WorkflowJob, 273 self._requester, 274 self.jobs_url, 275 url_parameters, 276 list_item="jobs", 277 ) 278 279 def _useAttributes(self, attributes: dict[str, Any]) -> None: 280 if "id" in attributes: # pragma no branch 281 self._id = self._makeIntAttribute(attributes["id"]) 282 if "name" in attributes: # pragma no branch 283 self._name = self._makeStringAttribute(attributes["name"]) 284 if "head_branch" in attributes: # pragma no branch 285 self._head_branch = self._makeStringAttribute(attributes["head_branch"]) 286 if "head_sha" in attributes: # pragma no branch 287 self._head_sha = self._makeStringAttribute(attributes["head_sha"]) 288 if "display_title" in attributes: # pragma no branch 289 self._display_title = self._makeStringAttribute(attributes["display_title"]) 290 if "path" in attributes: # pragma no branch 291 self._path = self._makeStringAttribute(attributes["path"]) 292 if "run_attempt" in attributes: # pragma no branch 293 self._run_attempt = self._makeIntAttribute(attributes["run_attempt"]) 294 if "run_number" in attributes: # pragma no branch 295 self._run_number = self._makeIntAttribute(attributes["run_number"]) 296 if "event" in attributes: # pragma no branch 297 self._event = self._makeStringAttribute(attributes["event"]) 298 if "run_started_at" in attributes: # pragma no branch 299 assert attributes["run_started_at"] is None or isinstance(attributes["run_started_at"], str), attributes[ 300 "run_started_at" 301 ] 302 self._run_started_at = self._makeDatetimeAttribute(attributes["run_started_at"]) 303 if "status" in attributes: # pragma no branch 304 self._status = self._makeStringAttribute(attributes["status"]) 305 if "conclusion" in attributes: # pragma no branch 306 self._conclusion = self._makeStringAttribute(attributes["conclusion"]) 307 if "workflow_id" in attributes: # pragma no branch 308 self._workflow_id = self._makeIntAttribute(attributes["workflow_id"]) 309 if "url" in attributes: # pragma no branch 310 self._url = self._makeStringAttribute(attributes["url"]) 311 if "html_url" in attributes: # pragma no branch 312 self._html_url = self._makeStringAttribute(attributes["html_url"]) 313 if "pull_requests" in attributes: # pragma no branch 314 self._pull_requests = self._makeListOfClassesAttribute( 315 github.PullRequest.PullRequest, attributes["pull_requests"] 316 ) 317 if "created_at" in attributes: # pragma no branch 318 self._created_at = self._makeDatetimeAttribute(attributes["created_at"]) 319 if "updated_at" in attributes: # pragma no branch 320 self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"]) 321 if "jobs_url" in attributes: # pragma no branch 322 self._jobs_url = self._makeStringAttribute(attributes["jobs_url"]) 323 if "logs_url" in attributes: # pragma no branch 324 self._logs_url = self._makeStringAttribute(attributes["logs_url"]) 325 if "check_suite_url" in attributes: # pragma no branch 326 self._check_suite_url = self._makeStringAttribute(attributes["check_suite_url"]) 327 if "artifacts_url" in attributes: # pragma no branch 328 self._artifacts_url = self._makeStringAttribute(attributes["artifacts_url"]) 329 if "cancel_url" in attributes: # pragma no branch 330 self._cancel_url = self._makeStringAttribute(attributes["cancel_url"]) 331 if "rerun_url" in attributes: # pragma no branch 332 self._rerun_url = self._makeStringAttribute(attributes["rerun_url"]) 333 if "workflow_url" in attributes: # pragma no branch 334 self._workflow_url = self._makeStringAttribute(attributes["workflow_url"]) 335 if "head_commit" in attributes: # pragma no branch 336 self._head_commit = self._makeClassAttribute(github.GitCommit.GitCommit, attributes["head_commit"]) 337 if "repository" in attributes: # pragma no branch 338 self._repository = self._makeClassAttribute(github.Repository.Repository, attributes["repository"]) 339 if "head_repository" in attributes: # pragma no branch 340 self._head_repository = self._makeClassAttribute( 341 github.Repository.Repository, attributes["head_repository"] 342 )