DEV Community

Cover image for Programmatically deploy your GitHub Repo on Netlify
Giuliano1993
Giuliano1993

Posted on

Programmatically deploy your GitHub Repo on Netlify

Have you ever tried to publish a GitHub repo on Netlify programmatically?
If it ever happened to you to need or want to reach this and search the documentation for answers, chances are that, like me, you didn't find any official information about it and got lost among some forum posts, also quite confused.

After lots of research, many mistakes, and a large amount of frustration, I finally managed to deploy programmatically a repo from Github to Netlify, so I wanted to share with you how to do it and spare you hours of research!

Let's get Started

So... first of all, you will need a Netlify token and your username; to create your access token, you need to login to your Netlify account and go on user settings -> application
Here, you can create a new access token to save in your env file with your username.

Now we can start building the payload for our request, starting with a unique name for our site:

sitename = str(time.time())+"site"

payload = {
    "name":sitename,
    "subdomain":sitename}
Enter fullscreen mode Exit fullscreen mode

Using the UNIX timestamp is quite an easy way to have a unique site name for your account, but you can replace it with any other technique you choose.

After that, you will need some repository information to connect our app to the desired repo.
I covered how to get the most common information from GitHub in a previous article, so I leave you a link to that for this part and just show you quickly how to do that same thing in python

def getConfig(configName):
  configsFile = yaml.safe_load(open('./env.yaml'))
  return configsFile['configs'][configName]


def repoList():
    user = getConfig("gitUser")
    gitToken = getConfig('gitToken')
    url = f"https://api.github.com/users/{user}/repos?per_page=100"
    response = requests.get(
        url=url,
        headers={
            "Accept":"application/vnd.github+json",
            "Authorization": f"Bearer {gitToken}",
            "X-GitHub-Api-Version": "2022-11-28"
        }
    )
    return response.json()

Enter fullscreen mode Exit fullscreen mode

Once you have the list of all repositories available in your profile, you can choose which one to use for your site. When developing CLIs with python, I love to use inquirer to handle user interactions; so, to install inquirer, run:

pip install inquirer
Enter fullscreen mode Exit fullscreen mode

and let's get to choose our repo ;)

#here we save in repos the result from github call
repos = repoList.repoList()
repoChoices = []
# We then create an array of choices for the user
for i, repo in enumerate(repos):
    choice = repo['full_name']
    repoChoices.append(choice)
# we prepare the prompt 
chooseRepo = [inquirer.List('pickRepo', message="choose a repo you want to link to the site", choices=repoChoices)]
#we ask the user which repo want to use and then we save it in the repo variable
answers = inquirer.prompt(chooseRepo)
index = repoChoices.index(answers['pickRepo'])
repo = repos[index]
Enter fullscreen mode Exit fullscreen mode

The tricky part: connecting Github and Netlify

Now that we have our repo, comes the hard part; there are, in fact, a couple of parameters in the site creation API that aren't quite well explained, which are the key to succeed in our task: the deploy_key_id and the installation_id.
The deploy_key_id is a public key we created and previously configured with our repo to enable automatic deployments on other websites (like Netlify). Without it, the deployment will result in an authorization error even if we properly connect the repository. The second important parameter is the installation_id, which stands for the id of our installation of Netlify app on GitHub. This allows GitHub to enable the connection through Netlify and keep deploying on the next pushes.

You can create a deploy key with the APIs, but since this is not the article's topic, we will consider you already have a deploy key on your repo. If you don't know how to create and configure one, check this doc out. As you can see, briefly, you just need to create an SSH Key and upload it to Github trough the Settings > Deploy Key panel.
As said above, this can also be done through API, calling the POST repos/{user}/{repo}/keys endpoint, so if you want, you can try this way too.

You can then quickly get the deploy_key relative to your repo by making an API call to GitHub like this:


user = getConfig("gitUser")
gitToken = getConfig('gitToken')
# Trough this endpoint we can retrieve all the deploy_keys related to a repository
url = f"https://api.github.com/repos/{user}/{repo}/keys"
response = requests.get(
    url=url,
    headers={
        "Accept":"application/vnd.github+json",
        "Authorization": f"Bearer {gitToken}",
        "X-GitHub-Api-Version": "2022-11-28"
    },
)

# this is an oversemplification, considering you already know you have a deploy key configured.
deployKey = response.json()[0]
Enter fullscreen mode Exit fullscreen mode

What about the installation ID?
You need to connect Netlify and GitHub first; then you can get the ID of that connection; don't worry; you'll need to do this only once; that ID won't change.

To create your connection between Netlify and GitHub you just need to go on netlify user settings and configure the connection with your GitHub account (grant access to all the repos to deploy further projects easily).
After doing this, you can navigate to Github Application settings, click on configure, and copy the number appended at the end of the URL since that is your Installation ID. This process will be needed only once, and then you are set to go.

One last step

So what's left to do? We now need to create our payload and send the request to netlify!

payload['repo'] = {
        #the branch you want to deploy
        "branch": repo['default_branch'],
        #the command to launch at build time
        "cmd": "npm run build",
        "deploy_key_id": depKey['id'],
        #the directory containing our packed project
        "dir": "dist/",
        #is the repo private?  
        "private": False,
        # our provider, could be github, gitlab or bitbucket
        "provider": "github",
        #the repo name in the format Author/Name
        "repo": repo['full_name'],
        #the repo id
        "repo_id": repo['id'],
        #the netlify installation id on github
        "installation_id": getConfig('installationId')
    }
    payload["build_settings"] = payload['repo']


user = getConfig("netlifyUser")
token = getConfig("netlifyToken")
reqUrl = f"https://api.netlify.com/api/v1/{user}/sites"
response = requests.request(
    method,
    url=reqUrl,
    headers={
        "content-type": "application/json",
        "Authorization": "Bearer "+token
    },
    json=payload
)

if(response.ok):
    print("New server was correctly created")
    print("New server ID = " + response.json()['id'])
else:
    print("There was an error:")
    print(str(response.status_code) + " : " + response.reason)
    print(response.json())
Enter fullscreen mode Exit fullscreen mode

Conclusion

Here we are; we are done! Some of these functions aren't well documented, so I needed to do some research to build this, but it was totally worth it! I hope this can be useful as I looked for someone to explain this to me until some time ago! If you have any further and more accurate information, let me and the others know in the comments; it can really be helpful!

As always, I hope you appreciated this article! You can find a more complete version of this code on this repo. I'm also developing an open-source project you can use and contribute to, and you're very welcome to reach me on Github on ServerMan!
Any feedback on the article is welcome, as always! Hope you have a great time reading and learning!
Happy coding 0_1

Top comments (0)