diff --git a/github/GithubObject.py b/github/GithubObject.py index 95ef37e9c8..c62a66774b 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -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])) diff --git a/github/Job.py b/github/Job.py new file mode 100644 index 0000000000..3afaee75e6 --- /dev/null +++ b/github/Job.py @@ -0,0 +1,237 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2021 Denis Blanchette # +# # +# 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 . # +# # +################################################################################ + +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"]) diff --git a/github/Job.pyi b/github/Job.pyi new file mode 100644 index 0000000000..f0ab2342a7 --- /dev/null +++ b/github/Job.pyi @@ -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: ... \ No newline at end of file diff --git a/github/Repository.py b/github/Repository.py index 88b023029f..323664117d 100644 --- a/github/Repository.py +++ b/github/Repository.py @@ -65,6 +65,7 @@ # Copyright 2018 Yves Zumbach # # Copyright 2018 Leying Chen # # Copyright 2020 Pascal Hofmann # +# Copyright 2021 Denis Blanchette # # # # This file is part of PyGithub. # # http://pygithub.readthedocs.io/ # @@ -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 @@ -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} `_ + :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, diff --git a/github/WorkflowRun.py b/github/WorkflowRun.py index b9748940b8..9a39961cb9 100644 --- a/github/WorkflowRun.py +++ b/github/WorkflowRun.py @@ -1,6 +1,7 @@ ############################ Copyrights and license ############################ # # # Copyright 2020 Steve Kowalik # +# Copyright 2021 Denis Blanchette # # # # This file is part of PyGithub. # # http://pygithub.readthedocs.io/ # @@ -23,6 +24,7 @@ from collections import namedtuple import github.GithubObject +import github.Job import github.PullRequest @@ -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 + :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 `_ diff --git a/github/WorkflowRun.pyi b/github/WorkflowRun.pyi index 8874e2f5b2..b4579c6836 100644 --- a/github/WorkflowRun.pyi +++ b/github/WorkflowRun.pyi @@ -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 @@ -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: ... diff --git a/tests/Job.py b/tests/Job.py new file mode 100644 index 0000000000..e6bf7e0ef7 --- /dev/null +++ b/tests/Job.py @@ -0,0 +1,54 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2021 Denis Blanchette # +# # +# 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 . # +# # +################################################################################ +from datetime import datetime + +from . import Framework + + +class Job(Framework.TestCase): + def setUp(self): + super().setUp() + self.org = self.g.get_organization("coveo") + self.repo = self.org.get_repo("github-app") + + def testAttributes(self): + workflow_runs = self.repo.get_workflow_runs() + job = workflow_runs[0].get_jobs()[0] + + self.assertEqual(2993004021, job.id) + self.assertEqual(1002152666, job.run_id) + self.assertEqual("MDg6Q2hlY2tSdW4yOTkzMDA0MDIx", job.node_id) + self.assertEqual("ba2ad8220081ac147afaa5e53e895a9db0ceefda", job.head_sha) + self.assertEqual("completed", job.status) + self.assertEqual("success", job.conclusion) + self.assertEqual(datetime(2021, 7, 5, 19, 25, 20), job.started_at) + self.assertEqual(datetime(2021, 7, 5, 19, 26, 28), job.completed_at) + self.assertEqual("stew ci", job.name) + self.assertEqual(10, len(job.steps)) + + step = job.steps[0] + self.assertEqual("Set up job", step.name) + self.assertEqual("completed", step.status) + self.assertEqual("success", step.conclusion) + self.assertEqual(1, step.number) + self.assertEqual(datetime(2021, 7, 5, 19, 25, 20), step.started_at) + self.assertEqual(datetime(2021, 7, 5, 19, 25, 21), step.completed_at) diff --git a/tests/Migration.py b/tests/Migration.py index f503a6d275..bed934ba01 100644 --- a/tests/Migration.py +++ b/tests/Migration.py @@ -71,10 +71,10 @@ def testAttributes(self): self.migration.url, "https://api.github.com/user/migrations/25320" ) self.assertEqual( - self.migration.created_at, datetime.datetime(2018, 9, 14, 1, 35, 35) + self.migration.created_at, datetime.datetime(2018, 9, 13, 20, 5, 35) ) self.assertEqual( - self.migration.updated_at, datetime.datetime(2018, 9, 14, 1, 35, 46) + self.migration.updated_at, datetime.datetime(2018, 9, 13, 20, 5, 46) ) self.assertEqual( repr(self.migration), diff --git a/tests/ReplayData/Job.setUp.txt b/tests/ReplayData/Job.setUp.txt new file mode 100644 index 0000000000..906f4c7501 --- /dev/null +++ b/tests/ReplayData/Job.setUp.txt @@ -0,0 +1,22 @@ +https +GET +api.github.com +None +/orgs/coveo +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 05 Jul 2021 21:15:46 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"550abc775e993d16e0d54942b5867ed8323c99ec0e219b41f2e1659fa2fbc48c"'), ('Last-Modified', 'Thu, 18 Mar 2021 11:47:26 GMT'), ('X-OAuth-Scopes', 'admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, repo, user, workflow, write:discussion, write:packages'), ('X-Accepted-OAuth-Scopes', 'admin:org, read:org, repo, user, write:org'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4997'), ('X-RateLimit-Reset', '1625522471'), ('X-RateLimit-Used', '3'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EDA5:2514:1BA8C37:3631A82:60E37682')] +{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","url":"https://api.github.com/orgs/coveo","repos_url":"https://api.github.com/orgs/coveo/repos","events_url":"https://api.github.com/orgs/coveo/events","hooks_url":"https://api.github.com/orgs/coveo/hooks","issues_url":"https://api.github.com/orgs/coveo/issues","members_url":"https://api.github.com/orgs/coveo/members{/member}","public_members_url":"https://api.github.com/orgs/coveo/public_members{/member}","avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=4","description":"Coveo's Private & Open Source Lair","name":"Coveo","company":null,"blog":"https://www.coveo.com","location":"Québec, QC, Canada","email":null,"twitter_username":null,"is_verified":true,"has_organization_projects":true,"has_repository_projects":true,"public_repos":32,"public_gists":0,"followers":0,"following":0,"html_url":"https://github.com/coveo","created_at":"2014-09-02T18:52:13Z","updated_at":"2021-03-18T11:47:26Z","type":"Organization","total_private_repos":123,"owned_private_repos":123,"private_gists":0,"disk_usage":1234567,"collaborators":666,"billing_email":"redacted@coveo.com","default_repository_permission":"write","members_can_create_repositories":true,"two_factor_requirement_enabled":false,"members_can_create_pages":true,"members_can_create_public_pages":true,"members_can_create_private_pages":true,"plan":{"name":"enterprise","space":123456789,"private_repos":999999,"filled_seats":666,"seats":666}} + +https +GET +api.github.com +None +/repos/coveo/github-app +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 05 Jul 2021 21:15:46 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"f01cc10bee4cd626ffee9f8c1a1566d5c3019b7673bd84f2a2d0204bbb166ffa"'), ('Last-Modified', 'Mon, 05 Jul 2021 19:25:14 GMT'), ('X-OAuth-Scopes', 'admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, repo, user, workflow, write:discussion, write:packages'), ('X-Accepted-OAuth-Scopes', 'repo'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4996'), ('X-RateLimit-Reset', '1625522471'), ('X-RateLimit-Used', '4'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EDA6:4672:1B298CC:366DE7C:60E37682')] +{"id":371729749,"node_id":"MDEwOlJlcG9zaXRvcnkzNzE3Mjk3NDk=","name":"github-app","full_name":"coveo/github-app","private":true,"owner":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/coveo/github-app","description":null,"fork":false,"url":"https://api.github.com/repos/coveo/github-app","forks_url":"https://api.github.com/repos/coveo/github-app/forks","keys_url":"https://api.github.com/repos/coveo/github-app/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coveo/github-app/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coveo/github-app/teams","hooks_url":"https://api.github.com/repos/coveo/github-app/hooks","issue_events_url":"https://api.github.com/repos/coveo/github-app/issues/events{/number}","events_url":"https://api.github.com/repos/coveo/github-app/events","assignees_url":"https://api.github.com/repos/coveo/github-app/assignees{/user}","branches_url":"https://api.github.com/repos/coveo/github-app/branches{/branch}","tags_url":"https://api.github.com/repos/coveo/github-app/tags","blobs_url":"https://api.github.com/repos/coveo/github-app/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coveo/github-app/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coveo/github-app/git/refs{/sha}","trees_url":"https://api.github.com/repos/coveo/github-app/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coveo/github-app/statuses/{sha}","languages_url":"https://api.github.com/repos/coveo/github-app/languages","stargazers_url":"https://api.github.com/repos/coveo/github-app/stargazers","contributors_url":"https://api.github.com/repos/coveo/github-app/contributors","subscribers_url":"https://api.github.com/repos/coveo/github-app/subscribers","subscription_url":"https://api.github.com/repos/coveo/github-app/subscription","commits_url":"https://api.github.com/repos/coveo/github-app/commits{/sha}","git_commits_url":"https://api.github.com/repos/coveo/github-app/git/commits{/sha}","comments_url":"https://api.github.com/repos/coveo/github-app/comments{/number}","issue_comment_url":"https://api.github.com/repos/coveo/github-app/issues/comments{/number}","contents_url":"https://api.github.com/repos/coveo/github-app/contents/{+path}","compare_url":"https://api.github.com/repos/coveo/github-app/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coveo/github-app/merges","archive_url":"https://api.github.com/repos/coveo/github-app/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coveo/github-app/downloads","issues_url":"https://api.github.com/repos/coveo/github-app/issues{/number}","pulls_url":"https://api.github.com/repos/coveo/github-app/pulls{/number}","milestones_url":"https://api.github.com/repos/coveo/github-app/milestones{/number}","notifications_url":"https://api.github.com/repos/coveo/github-app/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coveo/github-app/labels{/name}","releases_url":"https://api.github.com/repos/coveo/github-app/releases{/id}","deployments_url":"https://api.github.com/repos/coveo/github-app/deployments","created_at":"2021-05-28T14:37:57Z","updated_at":"2021-07-05T19:25:14Z","pushed_at":"2021-07-05T19:25:12Z","git_url":"git://github.com/coveo/github-app.git","ssh_url":"git@github.com:coveo/github-app.git","clone_url":"https://github.com/coveo/github-app.git","svn_url":"https://github.com/coveo/github-app","homepage":null,"size":362,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":3,"license":null,"forks":0,"open_issues":3,"watchers":0,"default_branch":"main","permissions":{"admin":true,"push":true,"pull":true},"temp_clone_token":"ABL6D67GKEBABCEF4U4TA4N456","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"delete_branch_on_merge":true,"organization":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"network_count":0,"subscribers_count":0} + diff --git a/tests/ReplayData/Job.testAttributes.txt b/tests/ReplayData/Job.testAttributes.txt new file mode 100644 index 0000000000..2122441798 --- /dev/null +++ b/tests/ReplayData/Job.testAttributes.txt @@ -0,0 +1,22 @@ +https +GET +api.github.com +None +/repos/coveo/github-app/actions/runs +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 05 Jul 2021 21:15:47 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"7f70fe37649478bc440f647425ef49d2e86ff2375f8344096a9dda52c9f18a71"'), ('X-OAuth-Scopes', 'admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, repo, user, workflow, write:discussion, write:packages'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Link', '; rel="next", ; rel="last"'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4995'), ('X-RateLimit-Reset', '1625522471'), ('X-RateLimit-Used', '5'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EDA9:46CB:19FE366:355E039:60E37682')] +{"total_count":146,"workflow_runs":[{"id":1002152666,"name":"github-runners","node_id":"WFR_lAHOAIO4CM4WKCVVzju7oto","head_branch":"main","head_sha":"ba2ad8220081ac147afaa5e53e895a9db0ceefda","run_number":146,"event":"push","status":"completed","conclusion":"success","workflow_id":9600289,"check_suite_id":3163145406,"check_suite_node_id":"MDEwOkNoZWNrU3VpdGUzMTYzMTQ1NDA2","url":"https://api.github.com/repos/coveo/github-app/actions/runs/1002152666","html_url":"https://github.com/coveo/github-app/actions/runs/1002152666","pull_requests":[],"created_at":"2021-07-05T19:25:13Z","updated_at":"2021-07-05T19:26:31Z","jobs_url":"https://api.github.com/repos/coveo/github-app/actions/runs/1002152666/jobs","logs_url":"https://api.github.com/repos/coveo/github-app/actions/runs/1002152666/logs","check_suite_url":"https://api.github.com/repos/coveo/github-app/check-suites/3163145406","artifacts_url":"https://api.github.com/repos/coveo/github-app/actions/runs/1002152666/artifacts","cancel_url":"https://api.github.com/repos/coveo/github-app/actions/runs/1002152666/cancel","rerun_url":"https://api.github.com/repos/coveo/github-app/actions/runs/1002152666/rerun","workflow_url":"https://api.github.com/repos/coveo/github-app/actions/workflows/9600289","head_commit":{"id":"ba2ad8220081ac147afaa5e53e895a9db0ceefda","tree_id":"a28dd9c2a980ff357b97f331bd5cc4beb3c68452","message":"Mergepullrequest#24fromcoveo/feature/better-dev-functions\n\nrefactordevfunctions","timestamp":"2021-07-05T19:25:11Z","author":{"name":"JonathanPiché","email":"jonapich@users.noreply.github.com"},"committer":{"name":"GitHub","email":"noreply@github.com"}},"repository":{"id":371729749,"node_id":"MDEwOlJlcG9zaXRvcnkzNzE3Mjk3NDk=","name":"github-app","full_name":"coveo/github-app","private":true,"owner":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/coveo/github-app","description":null,"fork":false,"url":"https://api.github.com/repos/coveo/github-app","forks_url":"https://api.github.com/repos/coveo/github-app/forks","keys_url":"https://api.github.com/repos/coveo/github-app/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coveo/github-app/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coveo/github-app/teams","hooks_url":"https://api.github.com/repos/coveo/github-app/hooks","issue_events_url":"https://api.github.com/repos/coveo/github-app/issues/events{/number}","events_url":"https://api.github.com/repos/coveo/github-app/events","assignees_url":"https://api.github.com/repos/coveo/github-app/assignees{/user}","branches_url":"https://api.github.com/repos/coveo/github-app/branches{/branch}","tags_url":"https://api.github.com/repos/coveo/github-app/tags","blobs_url":"https://api.github.com/repos/coveo/github-app/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coveo/github-app/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coveo/github-app/git/refs{/sha}","trees_url":"https://api.github.com/repos/coveo/github-app/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coveo/github-app/statuses/{sha}","languages_url":"https://api.github.com/repos/coveo/github-app/languages","stargazers_url":"https://api.github.com/repos/coveo/github-app/stargazers","contributors_url":"https://api.github.com/repos/coveo/github-app/contributors","subscribers_url":"https://api.github.com/repos/coveo/github-app/subscribers","subscription_url":"https://api.github.com/repos/coveo/github-app/subscription","commits_url":"https://api.github.com/repos/coveo/github-app/commits{/sha}","git_commits_url":"https://api.github.com/repos/coveo/github-app/git/commits{/sha}","comments_url":"https://api.github.com/repos/coveo/github-app/comments{/number}","issue_comment_url":"https://api.github.com/repos/coveo/github-app/issues/comments{/number}","contents_url":"https://api.github.com/repos/coveo/github-app/contents/{+path}","compare_url":"https://api.github.com/repos/coveo/github-app/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coveo/github-app/merges","archive_url":"https://api.github.com/repos/coveo/github-app/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coveo/github-app/downloads","issues_url":"https://api.github.com/repos/coveo/github-app/issues{/number}","pulls_url":"https://api.github.com/repos/coveo/github-app/pulls{/number}","milestones_url":"https://api.github.com/repos/coveo/github-app/milestones{/number}","notifications_url":"https://api.github.com/repos/coveo/github-app/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coveo/github-app/labels{/name}","releases_url":"https://api.github.com/repos/coveo/github-app/releases{/id}","deployments_url":"https://api.github.com/repos/coveo/github-app/deployments"},"head_repository":{"id":371729749,"node_id":"MDEwOlJlcG9zaXRvcnkzNzE3Mjk3NDk=","name":"github-app","full_name":"coveo/github-app","private":true,"owner":{"login":"coveo","id":8632328,"node_id":"MDEyOk9yZ2FuaXphdGlvbjg2MzIzMjg=","avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=4","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/coveo/github-app","description":null,"fork":false,"url":"https://api.github.com/repos/coveo/github-app","forks_url":"https://api.github.com/repos/coveo/github-app/forks","keys_url":"https://api.github.com/repos/coveo/github-app/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coveo/github-app/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coveo/github-app/teams","hooks_url":"https://api.github.com/repos/coveo/github-app/hooks","issue_events_url":"https://api.github.com/repos/coveo/github-app/issues/events{/number}","events_url":"https://api.github.com/repos/coveo/github-app/events","assignees_url":"https://api.github.com/repos/coveo/github-app/assignees{/user}","branches_url":"https://api.github.com/repos/coveo/github-app/branches{/branch}","tags_url":"https://api.github.com/repos/coveo/github-app/tags","blobs_url":"https://api.github.com/repos/coveo/github-app/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coveo/github-app/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coveo/github-app/git/refs{/sha}","trees_url":"https://api.github.com/repos/coveo/github-app/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coveo/github-app/statuses/{sha}","languages_url":"https://api.github.com/repos/coveo/github-app/languages","stargazers_url":"https://api.github.com/repos/coveo/github-app/stargazers","contributors_url":"https://api.github.com/repos/coveo/github-app/contributors","subscribers_url":"https://api.github.com/repos/coveo/github-app/subscribers","subscription_url":"https://api.github.com/repos/coveo/github-app/subscription","commits_url":"https://api.github.com/repos/coveo/github-app/commits{/sha}","git_commits_url":"https://api.github.com/repos/coveo/github-app/git/commits{/sha}","comments_url":"https://api.github.com/repos/coveo/github-app/comments{/number}","issue_comment_url":"https://api.github.com/repos/coveo/github-app/issues/comments{/number}","contents_url":"https://api.github.com/repos/coveo/github-app/contents/{+path}","compare_url":"https://api.github.com/repos/coveo/github-app/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coveo/github-app/merges","archive_url":"https://api.github.com/repos/coveo/github-app/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coveo/github-app/downloads","issues_url":"https://api.github.com/repos/coveo/github-app/issues{/number}","pulls_url":"https://api.github.com/repos/coveo/github-app/pulls{/number}","milestones_url":"https://api.github.com/repos/coveo/github-app/milestones{/number}","notifications_url":"https://api.github.com/repos/coveo/github-app/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coveo/github-app/labels{/name}","releases_url":"https://api.github.com/repos/coveo/github-app/releases{/id}","deployments_url":"https://api.github.com/repos/coveo/github-app/deployments"}}]} + +https +GET +api.github.com +None +/repos/coveo/github-app/actions/runs/1002152666/jobs +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Mon, 05 Jul 2021 21:15:47 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"7644cae12590e0d3cd78a94ade8e0d13ef638fb8caf83314937c0ee1d173349e"'), ('X-OAuth-Scopes', 'admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, repo, user, workflow, write:discussion, write:packages'), ('X-Accepted-OAuth-Scopes', ''), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4994'), ('X-RateLimit-Reset', '1625522471'), ('X-RateLimit-Used', '6'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EDAA:1CC0:F29F4E:232E863:60E37683')] +{"total_count":1,"jobs":[{"id":2993004021,"run_id":1002152666,"run_url":"https://api.github.com/repos/coveo/github-app/actions/runs/1002152666","node_id":"MDg6Q2hlY2tSdW4yOTkzMDA0MDIx","head_sha":"ba2ad8220081ac147afaa5e53e895a9db0ceefda","url":"https://api.github.com/repos/coveo/github-app/actions/jobs/2993004021","html_url":"https://github.com/coveo/github-app/runs/2993004021","status":"completed","conclusion":"success","started_at":"2021-07-05T19:25:20Z","completed_at":"2021-07-05T19:26:28Z","name":"stew ci","steps":[{"name":"Set up job","status":"completed","conclusion":"success","number":1,"started_at":"2021-07-05T15:25:20.000-04:00","completed_at":"2021-07-05T15:25:21.000-04:00"},{"name":"Clear local workspace","status":"completed","conclusion":"success","number":2,"started_at":"2021-07-05T15:25:21.000-04:00","completed_at":"2021-07-05T15:25:21.000-04:00"},{"name":"Checkout repository","status":"completed","conclusion":"success","number":3,"started_at":"2021-07-05T15:25:21.000-04:00","completed_at":"2021-07-05T15:25:24.000-04:00"},{"name":"Setup python 3.9","status":"completed","conclusion":"success","number":4,"started_at":"2021-07-05T15:25:24.000-04:00","completed_at":"2021-07-05T15:25:24.000-04:00"},{"name":"Upgrade pip and friends","status":"completed","conclusion":"success","number":5,"started_at":"2021-07-05T15:25:24.000-04:00","completed_at":"2021-07-05T15:25:26.000-04:00"},{"name":"Install coveo-stew","status":"completed","conclusion":"success","number":6,"started_at":"2021-07-05T15:25:26.000-04:00","completed_at":"2021-07-05T15:25:41.000-04:00"},{"name":"Add python tools to path","status":"completed","conclusion":"success","number":7,"started_at":"2021-07-05T15:25:41.000-04:00","completed_at":"2021-07-05T15:25:41.000-04:00"},{"name":"Launch \"stew ci\"","status":"completed","conclusion":"success","number":8,"started_at":"2021-07-05T15:25:41.000-04:00","completed_at":"2021-07-05T15:26:28.000-04:00"},{"name":"Post Checkout repository","status":"completed","conclusion":"success","number":16,"started_at":"2021-07-05T15:26:28.000-04:00","completed_at":"2021-07-05T15:26:28.000-04:00"},{"name":"Complete job","status":"completed","conclusion":"success","number":20,"started_at":"2021-07-05T15:26:28.000-04:00","completed_at":"2021-07-05T15:26:28.000-04:00"}],"check_run_url":"https://api.github.com/repos/coveo/github-app/check-runs/2993004021"}]} + diff --git a/tests/SelfHostedActionsRunnerRegistrationToken.py b/tests/SelfHostedActionsRunnerRegistrationToken.py index e8293cf279..d46ba74611 100644 --- a/tests/SelfHostedActionsRunnerRegistrationToken.py +++ b/tests/SelfHostedActionsRunnerRegistrationToken.py @@ -35,6 +35,6 @@ def testAttributes(self): self.assertEqual("INSERTABEAUTIFULTOKENHERE", token.token) # 2021-07-05T17:07:52.961-04:00. The returned datetime is naïve, but represents a time in UTC. self.assertEqual( - datetime(2021, 7, 1, 17, 7, 52, tzinfo=None), + datetime(2021, 7, 5, 21, 7, 52, tzinfo=None), token.expires_at, )