@nolim1t

Thoughts become things

Uploading to github through the API

You might ask why would you do this? Being theres at least 5-6 steps to do so.

However there’s a few interesting use cases that I can think of.

Potential Use cases

  • Programmatically maintaining a static page. It might sound a bit silly, but one of the key things about github pages is there is no server in between. Where the programmatically stuff comes in is through a server less implementation such as amazon lambda. If you’re feeling enterprising, you can even set it up so your static page takes input from a facebook bot.
  • Creating a mobile app to do some blogging. This is something that I’d like to do. I’ve already set up an image uploader and resizer for my blog which runs using Amazon S3 and Amazon Lambda. Serverless rocks because you can do more with less (money).
  • Scripting the updating of github in some way (combine with another automated process?)

Summary

In summary, we’re grabbing the previous commit information, creating the file, doing the commit and moving the commit to the branch. Basically the git data API.

Git data

We’ve opted to use the personal API key to make things easier, but you can also use oauth with some more steps.

How to do this?

Preconditions

export GITHUBAPIKEY=apikey
export GITHUBUSER=username
export REPO=repo

Step 1 - Get the previous commit

You will need to get the SHA of last commit. The following link gets it from master

curl -u "$GITHUBUSER:$GITHUBAPIKEY" "https://api.github.com/repos/$GITHUBUSER/$REPO/git/refs/heads/master"

Outputs

The output is the SHA for the last commit

Step 2 - Get the tree of the previous commit

You will need to get the SHA of the base tree of the last commit. Where 4fcf7b332edf0ea47e4b0647743ff20ae3319b0b is the SHA of the last commit

curl -u "$GITHUBUSER:$GITHUBAPIKEY" "https://api.github.com/repos/$GITHUBUSER/$REPO/git/commits/4fcf7b332edf0ea47e4b0647743ff20ae3319b0b"

Outputs

The output is the SHA for the base tree of the last commit

Step 3 - Create the BLOB

Build a BLOB file. This will be what the file will contain

curl -u "$GITHUBUSER:$GITHUBAPIKEY" "https://api.github.com/repos/$GITHUBUSER/$REPO/git/blobs" -X POST \
-d '{"content": "# Hello World \n\n## Title 2\n\n", "encoding": "utf-8"}'

Outputs

Grab the SHA for this. You will need it on the next step.

Step 4 - Create the NEW tree

Create the tree using the proposed filename test.md, and blob sha. You will need to use the sha from STEP 2 here to put in the JSON.

curl -u "$GITHUBUSER:$GITHUBAPIKEY" "https://api.github.com/repos/$GITHUBUSER/$REPO/git/trees" -X POST \
-d '{"base_tree": "2bde088c1885f8420a13aec8b64813fd952fc81f","tree": [{"path": "test.md", "mode": "100644", "type": "blob", "sha": "86d7a63ee2b93d3b7ea31cea733754533fef67ad"}]}'

Output

Grab the SHA for the tree you just created

Step 5 - Do the commit

Create the commit with the tree in Step 4, and the SHA from step 1 (under parents).

Also specify the commit message

curl -u "$GITHUBUSER:$GITHUBAPIKEY" "https://api.github.com/repos/$GITHUBUSER/$REPO/git/commits" -X POST \
-d '{"parents": ["4fcf7b332edf0ea47e4b0647743ff20ae3319b0b"], "tree": "4d89626b8cf25e5487983162f563c7df2e3c362f", "message": "Update the file"}'

Output

The output is the SHA for the commit. We’re not done yet!

Step 6 - Move the commit to a branch

In this case, we’re just moving it to master

curl -u "$GITHUBUSER:$GITHUBAPIKEY" "https://api.github.com/repos/$GITHUBUSER/$REPO/git/refs/heads/master" -X POST \
-d '{"ref": "refs/heads/master", "sha": "61a98b50d65b2ffe57fc24ae828e2695b0d24457"}'

Output

If all goes well, the file should reflect on github.

Does this work?

YES! In fact this post is created purely through the github API (using the exact published code above). I’m a fan of dogfooding and open source. What I publish and talk about is what I use.

./upload.js draft_post.md _posts/2017-03-08-uploading-to-github-through-the-API.md

Got code?

Yes, I have some code which does this. In fact, I’ve also got a NPM Package available which does the above (and more) so you can use this in AWS Lambda too.

Like this post? Send us a little tip via lightning ⚡️ (what is lightning ⚡️?)