Skip to content
This repository was archived by the owner on Dec 2, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions github/GithubObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,13 @@ def parseDatetime(s):
return datetime.datetime.strptime(
f"{s[:-1]}000{s[-1]}", "%Y-%m-%dT%H:%M:%S.%fZ"
)
if len(s) >= 29:
# Milliseconds and timezone included
return datetime.datetime.strptime(s[:19], "%Y-%m-%dT%H:%M:%S") + (
1 if s[23] == "-" else -1
) * datetime.timedelta(hours=int(s[24:26]), minutes=int(s[27:29]))
elif len(s) >= 25:
# Timezone included, but no milliseconds
return datetime.datetime.strptime(s[:19], "%Y-%m-%dT%H:%M:%S") + (
1 if s[19] == "-" else -1
) * datetime.timedelta(hours=int(s[20:22]), minutes=int(s[23:25]))
Expand Down
237 changes: 237 additions & 0 deletions github/Job.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
############################ Copyrights and license ############################
# #
# Copyright 2021 Denis Blanchette <dblanchette@coveo.com> #
# #
# This file is part of PyGithub. #
# http://pygithub.readthedocs.io/ #
# #
# PyGithub is free software: you can redistribute it and/or modify it under #
# the terms of the GNU Lesser General Public License as published by the Free #
# Software Foundation, either version 3 of the License, or (at your option) #
# any later version. #
# #
# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
# details. #
# #
# You should have received a copy of the GNU Lesser General Public License #
# along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
# #
################################################################################

import github.GithubObject


class JobStep(github.GithubObject.NonCompletableGithubObject):
def __repr__(self):
return super().get__repr__({"id": self.id})

@property
def completed_at(self):
"""
:type: datetime.datetime
"""
return self._completed_at.value

@property
def conclusion(self):
"""
:type: string
"""
return self._conclusion.value

@property
def name(self):
"""
:type: string
"""
return self._name.value

@property
def number(self):
"""
:type: integer
"""
return self._number.value

@property
def started_at(self):
"""
:type: datetime.datetime
"""
return self._started_at.value

@property
def status(self):
"""
:type: string
"""
return self._status.value

def _initAttributes(self):
self._completed_at = github.GithubObject.NotSet
self._conclusion = github.GithubObject.NotSet
self._id = github.GithubObject.NotSet
self._number = github.GithubObject.NotSet
self._started_at = github.GithubObject.NotSet
self._status = github.GithubObject.NotSet

def _useAttributes(self, attributes):
if "name" in attributes:
self._name = self._makeStringAttribute(attributes["name"])
if "completed_at" in attributes: # pragma no branch
assert attributes["completed_at"] is None or isinstance(
attributes["completed_at"], str
), attributes["completed_at"]
self._completed_at = self._makeDatetimeAttribute(attributes["completed_at"])
if "conclusion" in attributes: # pragma no branch
self._conclusion = self._makeStringAttribute(attributes["conclusion"])
if "number" in attributes: # pragma no branch
self._number = self._makeIntAttribute(attributes["number"])
if "started_at" in attributes: # pragma no branch
assert attributes["started_at"] is None or isinstance(
attributes["started_at"], str
), attributes["started_at"]
self._started_at = self._makeDatetimeAttribute(attributes["started_at"])
if "status" in attributes: # pragma no branch
self._status = self._makeStringAttribute(attributes["status"])


class Job(github.GithubObject.CompletableGithubObject):
def __repr__(self):
return super().get__repr__({"id": self.id})

@property
def completed_at(self):
"""
:type: datetime.datetime
"""
self._completeIfNotSet(self._completed_at)
return self._completed_at.value

@property
def conclusion(self):
"""
:type: string
"""
self._completeIfNotSet(self._conclusion)
return self._conclusion.value

@property
def head_sha(self):
"""
:type: string
"""
self._completeIfNotSet(self._head_sha)
return self._head_sha.value

@property
def id(self):
"""
:type: integer
"""
self._completeIfNotSet(self._id)
return self._id.value

@property
def name(self):
"""
:type: string
"""
self._completeIfNotSet(self._name)
return self._name.value

@property
def node_id(self):
"""
:type: string
"""
self._completeIfNotSet(self._node_id)
return self._node_id.value

@property
def run_id(self):
"""
:type: integer
"""
self._completeIfNotSet(self._run_id)
return self._run_id.value

@property
def run_url(self):
"""
:type: string
"""
self._completeIfNotSet(self._run_url)
return self._run_url.value

@property
def started_at(self):
"""
:type: datetime.datetime
"""
self._completeIfNotSet(self._started_at)
return self._started_at.value

@property
def status(self):
"""
:type: string
"""
self._completeIfNotSet(self._status)
return self._status.value

@property
def steps(self):
"""
:type: list of :class:`github.JobStep.JobStep`
"""
self._completeIfNotSet(self._steps)
return self._steps.value

def _initAttributes(self):
self._completed_at = github.GithubObject.NotSet
self._conclusion = github.GithubObject.NotSet
self._head_sha = github.GithubObject.NotSet
self._id = github.GithubObject.NotSet
self._id = github.GithubObject.NotSet
self._name = github.GithubObject.NotSet
self._node_id = github.GithubObject.NotSet
self._run_id = github.GithubObject.NotSet
self._run_url = github.GithubObject.NotSet
self._started_at = github.GithubObject.NotSet
self._status = github.GithubObject.NotSet
self._steps = github.GithubObject.NotSet

def _useAttributes(self, attributes):
if "id" in attributes:
self._id = self._makeIntAttribute(attributes["id"])
if "completed_at" in attributes: # pragma no branch
assert attributes["completed_at"] is None or isinstance(
attributes["completed_at"], str
), attributes["completed_at"]
self._completed_at = self._makeDatetimeAttribute(attributes["completed_at"])
if "conclusion" in attributes: # pragma no branch
self._conclusion = self._makeStringAttribute(attributes["conclusion"])
if "head_sha" in attributes: # pragma no branch
self._head_sha = self._makeStringAttribute(attributes["head_sha"])
if "id" in attributes: # pragma no branch
self._id = self._makeIntAttribute(attributes["id"])
if "name" in attributes: # pragma no branch
self._name = self._makeStringAttribute(attributes["name"])
if "node_id" in attributes: # pragma no branch
self._node_id = self._makeStringAttribute(attributes["node_id"])
if "run_id" in attributes: # pragma no branch
self._run_id = self._makeIntAttribute(attributes["run_id"])
if "run_url" in attributes: # pragma no branch
self._run_url = self._makeStringAttribute(attributes["run_url"])
if "started_at" in attributes: # pragma no branch
assert attributes["started_at"] is None or isinstance(
attributes["started_at"], str
), attributes["started_at"]
self._started_at = self._makeDatetimeAttribute(attributes["started_at"])
if "status" in attributes: # pragma no branch
self._status = self._makeStringAttribute(attributes["status"])
if "steps" in attributes: # pragma no branch
self._steps = self._makeListOfClassesAttribute(JobStep, attributes["steps"])
48 changes: 48 additions & 0 deletions github/Job.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from datetime import datetime
from typing import Dict, Any, List

import github.GithubObject


class JobStep(github.GithubObject.CompletableGithubObject):
@property
def completed_at(self) -> datetime: ...
@property
def conclusion(self) -> str: ...
@property
def name(self) -> str: ...
@property
def number(self) -> int: ...
@property
def started_at(self) -> datetime: ...
@property
def status(self) -> str: ...
def _initAttributes(self) -> None: ...
def _useAttributes(self, attributes: Dict[str, Any]) -> None: ...


class Job(github.GithubObject.CompletableGithubObject):
@property
def check_run_url(self) -> str: ...
@property
def completed_at(self) -> datetime: ...
@property
def conclusion(self) -> str: ...
@property
def head_sha(self) -> str: ...
@property
def name(self) -> str: ...
@property
def node_id(self) -> str: ...
@property
def run_id(self) -> int: ...
@property
def run_url(self) -> str: ...
@property
def started_at(self) -> str: ...
@property
def status(self) -> str: ...
@property
def steps(self) -> List[JobStep]: ...
def _initAttributes(self) -> None: ...
def _useAttributes(self, attributes: Dict[str, Any]) -> None: ...
15 changes: 15 additions & 0 deletions github/Repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
# Copyright 2018 Yves Zumbach <yzumbach@andrew.cmu.edu> #
# Copyright 2018 Leying Chen <leyingc@andrew.cmu.edu> #
# Copyright 2020 Pascal Hofmann <mail@pascalhofmann.de> #
# Copyright 2021 Denis Blanchette <dblanchette@coveo.com> #
# #
# This file is part of PyGithub. #
# http://pygithub.readthedocs.io/ #
Expand Down Expand Up @@ -114,6 +115,7 @@
import github.Invitation
import github.Issue
import github.IssueEvent
import github.Job
import github.Label
import github.Milestone
import github.NamedUser
Expand Down Expand Up @@ -3138,6 +3140,19 @@ def get_workflow(self, id_or_name):
)
return github.Workflow.Workflow(self._requester, headers, data, completed=True)

def get_workflow_job(self, job_id):
"""
:calls: `GET /repos/{owner}/{repo}/actions/jobs/{job_id} <https://docs.github.com/en/rest/reference/actions#workflow-jobs>`_
:param job_id: int or string

:rtype: :class:`github.Job.Job`
"""
assert isinstance(job_id, int) or isinstance(job_id, str), job_id
headers, data = self._requester.requestJsonAndCheck(
"GET", f"{self.url}/actions/jobs/{job_id}"
)
return github.Job.Job(self._requester, headers, data, completed=True)

def get_workflow_runs(
self,
actor=github.GithubObject.NotSet,
Expand Down
15 changes: 15 additions & 0 deletions github/WorkflowRun.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
############################ Copyrights and license ############################
# #
# Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
# Copyright 2021 Denis Blanchette <dblanchette@coveo.com> #
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spam alert :P

# #
# This file is part of PyGithub. #
# http://pygithub.readthedocs.io/ #
Expand All @@ -23,6 +24,7 @@
from collections import namedtuple

import github.GithubObject
import github.Job
import github.PullRequest


Expand Down Expand Up @@ -218,6 +220,19 @@ def head_repository(self):
self._completeIfNotSet(self._head_repository)
return self._head_repository.value

def get_jobs(self):
"""
:calls: `GET` /repos/{owner}/{repo}/actions/runs/{run_id}/jobs <https://docs.github.com/en/rest/reference/actions#list-jobs-for-a-workflow-run>
:rtype: list of :class:`github.Job.Job`
"""
return github.PaginatedList.PaginatedList(
github.Job.Job,
self._requester,
f"{self.url}/jobs",
None,
list_item="jobs",
)

def cancel(self):
"""
:calls: `POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel <https://docs.github.com/en/rest/reference/actions#workflow-runs>`_
Expand Down
3 changes: 3 additions & 0 deletions github/WorkflowRun.pyi
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from datetime import datetime
from typing import Any, Dict, NamedTuple, List

import github.PaginatedList
from github.GitCommit import GitCommit
from github.GithubObject import CompletableGithubObject
from github.Job import Job
from github.PullRequest import PullRequest
from github.Repository import Repository

Expand Down Expand Up @@ -60,6 +62,7 @@ class WorkflowRun(CompletableGithubObject):
def repository(self) -> Repository: ...
@property
def head_repository(self) -> Repository: ...
def get_jobs(self) -> github.PaginatedList.PaginatedList[Job]: ...
def cancel(self) -> bool: ...
def rerun(self) -> bool: ...
def timing(self) -> TimingData: ...
Loading