Getting error "'Repository' object has no attribute 'create_deployment'" when using the PyGithub API

I am trying to use PyGithub (https://pygithub.readthedocs.io/en/latest/apis.html) to get the deployment and report the status somewhere else. I have the following script:

from github import Github

# Github Enterprise with custom hostname
g = Github(base_url="https://{hostname}/api/v3", login_or_token="sometoken")
# get the repository
repo = g.get_repo("PyGithub/PyGithub")
# HTTP POST to /repos/:owner/:repo/deployments
deployment = repo.create_deployment(ref = 'master', environment = 'DEV', description= 'Deploying to the environment')
# getting the status
status = deployment.get_status(deployment.id)
# HTTP POST to /repos/:owner/:repo/deployments/:deployment_id/statuses
deployment.create_status(state = status.state, environment = 'DEV', description = 'deploying completed')

But it complains with:

'Repository' object has no attribute 'create_deployment'

while I see the function in (https://pygithub.readthedocs.io/en/latest/github_objects/Repository.html#github.Repository.Repository).

What am I missing?

I basically want to use those two endpoints. I was not able to find any other github API in python but even that would be fine as well.

Answers

First, make sure you are using an updated version of PyGithub.

The Deployments API was only added on release version 1.47.

  • Release Notes:
    "Add Deployments API (#1424) (3d93ee1)"
  • PR #1424:
    Add a new class, Deployment to describe a deployment performed utilising

GitHub. Add three methods onto Repository to list them and create them.

If you are using <1.47, then that method doesn't exist yet.

Second, I think you misunderstood parameters for deployment.get_status.

The docs are a bit unclear, but it is expecting a Deployment Status ID, not a Deployment ID. The method makes a request to the /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id} endpoint to "view a deployment status for a deployment", and the code appends the passed-in id to the /statuses/ URL:

https://github.com/PyGithub/PyGithub/blob/master/github/Deployment.py#L180

def get_status(self, id_):
    """
    :calls: `GET /repos/:owner/deployments/:deployment_id/statuses/:status_id  <https://developer.github.com/v3/repos/deployments/#get-a-deployment-status>`_
    :param id_: int
    :rtype: :class:`github.DeploymentStatus.DeploymentStatus`
    """
    assert isinstance(id_, int), id_
    headers, data = self._requester.requestJsonAndCheck(
        "GET",
        self.url + "/statuses/" + str(id_),
        headers={"Accept": self._get_accept_header()},
    )

The correct API would probably be get_statuses for listing all the deployment statuses for a particular deployment. Then grab one of those IDs and pass that to get_status to get a specific DeploymentStatus object. (Though, you could also just loop through the get_statuses list, each one is already a DeploymentStatus object). If you don't have any Deployment Status yet, then you create one with create_status:

# create a Deployment
# POST /repos/{owner}/{repo}/deployments
deployment = repo.create_deployment(ref='master', description='Deploying to the environment')

# list Deployment Statuses
# https://docs.github.com/en/rest/reference/repos#list-deployment-statuses
# GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
for status in deployment.get_statuses():
    print(status.id)  # For new deployments, this would be empty

# create a Deployment Status
# https://docs.github.com/en/rest/reference/repos#create-a-deployment-status
# POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
new_deployment_status = deployment.create_status(state='inactive', description='inactive deployment')
print(new_deployment_status.state)

# list Deployment Statuses
# https://docs.github.com/en/rest/reference/repos#list-deployment-statuses
# GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
for status in deployment.get_statuses():
    print(status.state, status.id)  # This should now the newly created status
#         'inactive',   461997990

# get a specific Deployment Status
deployment_status = deployment.get_statuses()[0]
deployment_status_0 = deployment.get_status(deployment_status.id))
Posted on by Gino Mempin