How to determine the latest release on GitHub


This post is about programmatically determining the latest version of a GitHub release. We are doing this using shell scripting.

Accessing release data on the command-line

Let’s say you want to determine the latest release of the static site generator. All release information needed can be accessed through the GitHub API. For hugo, it can be queried using the following URL:

The data behind this URL is JSON encoded. When accessing it using a web browser, a handy UI typically allows to fold/unfold sections of it. This way one can determine the interesting sections to be further processed.

On the command-line, a HTTP client such as curl allows to access this information like this:

curl 2>/dev/null

All information related to the HTTP data transfer is actually redirected to the /dev/null device. It is not needed. The actual data is provided on STDOUT. Now the JSON data needs to be processed using some JSON parser.

Enter jq

This is, where jq comes in handy. It allows to access (say: slice, filter, and map) JSON data on the command-line to allow for further processing using the typical suspects such as sed, ask, or grep. Let’s find out what the .name field of the returned data gives us:

curl 2>/dev/null \
       | jq .name

At the time of writing it is: "v0.80.0". Now, let’s assume we want to get rid of the "s and the v. This can easily be done by stripping these characters.


Stripping characters from strings on the command-line can be achieved using some builtin functions of jq:

curl 2>/dev/null \
       | jq -r '.name | ltrimstr("v")'

The -r switch to jq requests it to output raw data, resulting in stripping the quotes from the output.

Now, what remains is what we have been looking for: 0.80.0

Bonus: using it in Ansible playbooks

The following shows an Ansible playbook which downloads the latest release of for ARM based systems and installs it in the /usr/local/bin directory:

- name: Make gohugo available
  hosts: all
    - name: Install needed packages
      become: true
          - jq
          - curl
        state: present
    - name: Get hugo latest release version
        cmd: curl | jq -r '.name | ltrimstr("v")'
      register: hugo_version
    - name: Get hugo latest release
        url:{{ hugo_version.stdout }}/hugo_{{ hugo_version.stdout }}_Linux-ARM.tar.gz
        dest: /tmp/hugo.tar.gz
    - name: Unarchive hugo latest release
        src: /tmp/hugo.tar.gz
        remote_src: true
        dest: /usr/local/bin

Sure, this playbook is not perfect. But it should give a good idea of how using jq can help to automatize repetitive tasks when combined with Ansible.

comments powered by Disqus