Skip to content

Instantly share code, notes, and snippets.

@lukechilds
Created August 9, 2016 19:43
Show Gist options
  • Save lukechilds/a83e1d7127b78fef38c2914c4ececc3c to your computer and use it in GitHub Desktop.
Save lukechilds/a83e1d7127b78fef38c2914c4ececc3c to your computer and use it in GitHub Desktop.
Shell - Get latest release from GitHub
get_latest_release() {
curl --silent "https://api.github.com/repos/$1/releases/latest" | # Get latest release from GitHub api
grep '"tag_name":' | # Get tag line
sed -E 's/.*"([^"]+)".*/\1/' # Pluck JSON value
}
# Usage
# $ get_latest_release "creationix/nvm"
# v0.31.4
@KEINOS
Copy link

KEINOS commented Oct 5, 2021

Indeed gh is easier to use with no work-around, but I found this gist is useful for lightweight purposes such as Docker and CIs. Thanks!

@wgzhao
Copy link

wgzhao commented Nov 5, 2021

Hi, I made a version without sed, only using grep. Maybe its useful...

curl --silent "https://api.github.com/repos/$1/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")'

Thanks, for sharing the great idea! 👍

In MacOS, the built-in grep command has not -P option.

@meramsey
Copy link

Another mostly reusable one if you just want the latest deb

owner_repo='igniterealtime/Spark'; latest_version_url="$(curl -s https://api.github.com/repos/$owner_repo/releases/latest | grep "browser_download_url.*deb" | cut -d : -f 2,3 | tr -d \")"; echo $latest_version_url; basename $latest_version_url ; wget --content-disposition $latest_version_url

Example:

❯ owner_repo='igniterealtime/Spark'; latest_version_url="$(curl -s https://api.github.com/repos/$owner_repo/releases/latest | grep "browser_download_url.*deb" | cut -d : -f 2,3 | tr -d \")"; echo $latest_version_url; basename $latest_version_url ; wget -q --content-disposition $latest_version_url
https://github.com/igniterealtime/Spark/releases/download/v3.0.0-beta/spark_3_0_0-beta.deb
spark_3_0_0-beta.deb
~  took 1m46s  at 20:14:43 

❯ 

@ChrisKader
Copy link

Example Link: https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup.exe

Replace "ep_setup.exe" with whatever object name you want.

@meramsey
Copy link

meramsey commented Jun 3, 2022

Probably not Pythonic but Python way:

import requests
url = 'https://github.com/roundcube/roundcubemail/releases/latest'
r = requests.get(url)
version = r.url.split('/')[-1]

print(version)

Source: https://gist.github.com/zeldor/604a7817f9d142e908335e041ece0718

Made into a function and returns empty for the ones without it.

def get_github_latest_release(repo_path):
    import requests

    url = f"https://github.com/{repo_path}/releases/latest"
    r = requests.get(url, headers={"Content-Type": "application/vnd.github.v3+json"})
    release = r.url.split("/")[-1]
    if release in ["releases", "latest"]:
        release = ""

    return release

works nicely for ones with releases

github_repos = [
    "https://github.com/OpenVPN/openvpn",
    "https://github.com/atom/atom",
    "https://github.com/eneshecan/whatsapp-for-linux",
    "https://github.com/igniterealtime/Openfire",
    "https://github.com/igniterealtime/Spark",
    "https://github.com/jitsi/jitsi-meet",
    "https://github.com/jitsi/jitsi-meet-prosody",
    "https://github.com/jitsi/jitsi-meet-turnserver",
    "https://github.com/jitsi/jitsi-meet-web-config",
    "https://github.com/jitsi/jitsi-videobridge2",
    "https://github.com/mumble-voip/mumble",
    "https://github.com/pjsip/pjproject/",
    "https://github.com/pydio/pydio-core",
    "https://github.com/signalapp/Signal-Desktop",
    "https://github.com/sleuthkit/autopsy",
    "https://github.com/sleuthkit/sleuthkit",
    "https://github.com/ultravnc/ultravnc",
]


def get_repo_path(link):
    return link.replace("https://github.com/", "").strip().rstrip("/")


def get_repo_pkg(repo):
    return repo.split("/")[-1]


def get_repos_dict_from_urls(urls):
    packages = {}
    for repo in github_repos:
        pkg_name = get_repo_pkg(get_repo_path(repo))
        pkg_path = get_repo_path(repo)
        packages[pkg_name] = {
            "name": pkg_name,
            "repo_path": pkg_path,
            "url": repo,
            "latest_release": get_github_latest_release(pkg_path),
        }
    return packages


packages = get_repos_dict_from_urls(github_repos)
pprint(packages)

Result:

{'Openfire': {'latest_release': 'v4.7.1',
              'name': 'Openfire',
              'repo_path': 'igniterealtime/Openfire',
              'url': 'https://github.com/igniterealtime/Openfire'},
 'Signal-Desktop': {'latest_release': 'v5.45.0',
                    'name': 'Signal-Desktop',
                    'repo_path': 'signalapp/Signal-Desktop',
                    'url': 'https://github.com/signalapp/Signal-Desktop'},
 'Spark': {'latest_release': 'v3.0.0-beta',
           'name': 'Spark',
           'repo_path': 'igniterealtime/Spark',
           'url': 'https://github.com/igniterealtime/Spark'},
 'atom': {'latest_release': 'v1.60.0',
          'name': 'atom',
          'repo_path': 'atom/atom',
          'url': 'https://github.com/atom/atom'},
 'autopsy': {'latest_release': 'autopsy-4.19.3',
             'name': 'autopsy',
             'repo_path': 'sleuthkit/autopsy',
             'url': 'https://github.com/sleuthkit/autopsy'},
 'jitsi-meet': {'latest_release': 'jitsi-meet_7287',
                'name': 'jitsi-meet',
                'repo_path': 'jitsi/jitsi-meet',
                'url': 'https://github.com/jitsi/jitsi-meet'},
 'jitsi-meet-prosody': {'latest_release': '',
                        'name': 'jitsi-meet-prosody',
                        'repo_path': 'jitsi/jitsi-meet-prosody',
                        'url': 'https://github.com/jitsi/jitsi-meet-prosody'},
 'jitsi-meet-turnserver': {'latest_release': '',
                           'name': 'jitsi-meet-turnserver',
                           'repo_path': 'jitsi/jitsi-meet-turnserver',
                           'url': 'https://github.com/jitsi/jitsi-meet-turnserver'},
 'jitsi-meet-web-config': {'latest_release': '',
                           'name': 'jitsi-meet-web-config',
                           'repo_path': 'jitsi/jitsi-meet-web-config',
                           'url': 'https://github.com/jitsi/jitsi-meet-web-config'},
 'jitsi-videobridge2': {'latest_release': '',
                        'name': 'jitsi-videobridge2',
                        'repo_path': 'jitsi/jitsi-videobridge2',
                        'url': 'https://github.com/jitsi/jitsi-videobridge2'},
 'mumble': {'latest_release': 'v1.4.230',
            'name': 'mumble',
            'repo_path': 'mumble-voip/mumble',
            'url': 'https://github.com/mumble-voip/mumble'},
 'openvpn': {'latest_release': '',
             'name': 'openvpn',
             'repo_path': 'OpenVPN/openvpn',
             'url': 'https://github.com/OpenVPN/openvpn'},
 'pjproject': {'latest_release': '2.12.1',
               'name': 'pjproject',
               'repo_path': 'pjsip/pjproject',
               'url': 'https://github.com/pjsip/pjproject/'},
 'pydio-core': {'latest_release': '',
                'name': 'pydio-core',
                'repo_path': 'pydio/pydio-core',
                'url': 'https://github.com/pydio/pydio-core'},
 'sleuthkit': {'latest_release': 'sleuthkit-4.11.1',
               'name': 'sleuthkit',
               'repo_path': 'sleuthkit/sleuthkit',
               'url': 'https://github.com/sleuthkit/sleuthkit'},
 'ultravnc': {'latest_release': '',
              'name': 'ultravnc',
              'repo_path': 'ultravnc/ultravnc',
              'url': 'https://github.com/ultravnc/ultravnc'},
 'whatsapp-for-linux': {'latest_release': 'v1.4.3',
                        'name': 'whatsapp-for-linux',
                        'repo_path': 'eneshecan/whatsapp-for-linux',
                        'url': 'https://github.com/eneshecan/whatsapp-for-linux'}}

@begin-theadventure
Copy link

begin-theadventure commented Sep 1, 2022

owner_repo='igniterealtime/Spark'; latest_version_url="$(curl -s https://api.github.com/repos/$owner_repo/releases/latest | grep "browser_download_url.*deb" | cut -d : -f 2,3 | tr -d ")"; echo $latest_version_url; basename $latest_version_url ; wget --content-disposition $latest_version_url

Thanks a lot! Although it's possible to just use curl instead of wget:
owner_repo='owner/name'; latest_version_url="$(curl -s https://api.github.com/repos/$owner_repo/releases/latest| grep "browser_download_url.*extension" | cut -d : -f 2,3 | tr -d \")"; echo $latest_version_url; basename $latest_version_url ; curl -X GET $latest_version_url -LO or -Lo name.extension

@meramsey
Copy link

meramsey commented Sep 1, 2022

owner_repo='igniterealtime/Spark'; latest_version_url="$(curl -s https://api.github.com/repos/$owner_repo/releases/latest | grep "browser_download_url.*deb" | cut -d : -f 2,3 | tr -d ")"; echo $latest_version_url; basename $latest_version_url ; wget --content-disposition $latest_version_url

Thanks a lot! Although it's possible to just use curl instead of wget: owner_repo='owner/name'; latest_version_url="$(curl -s https://api.github.com/repos/$owner_repo/releases/latest| grep "browser_download_url.*extensions" | cut -d : -f 2,3 | tr -d \")"; echo $latest_version_url; basename $latest_version_url ; curl -X GET $latest_version_url -LO or -Lo name.extension

Awesome thanks for sharing. That is cool always wondered how to do that in curl but never bothered to look. Appreciate the share and explanation.

@pitoneux
Copy link

pitoneux commented Sep 20, 2022

With the last update, the above breaks for me. I'm now using this:

latest_version_raw="$(curl -s https://api.github.com/repos/$owner_repo/releases | grep -m 1 "html_url" | rev | cut -    d/ -f1 | rev  )"
latest_version="${latest_version_raw%??}" # remove last 2 characters

@rotty3000
Copy link

rotty3000 commented Sep 26, 2022

Here's an example with wget & jq:

REPO="..."
VERSION=$(wget -q -O- https://api.github.com/repos/${REPO}/releases/latest | jq -r '.name')

@roelds
Copy link

roelds commented Jan 1, 2023

Here's an example with wget & jq:

REPO="..."
VERSION=$(wget -q -O- https://api.github.com/repos/${REPO}/releases/latest | jq -r '.name')

that works great! but if prefer tag name instead of release name, use:

.tag_name

@roelds
Copy link

roelds commented Jan 1, 2023

for how todo this on GitLab site, see my gist here:
https://gist.github.com/roelds/b2cd9cc2ba6c7887ddaf6bde2ef7ef50

@fonic
Copy link

fonic commented Aug 26, 2023

One-liner using only curl + grep:
curl --silent "https://api.github.com/repos/${REPO}/releases/latest" | grep -Po "(?<=\"tag_name\": \").*(?=\")"

@roryabraham
Copy link

roryabraham commented Aug 30, 2024

For the gh-cli inclined:

gh release list --exclude-pre-releases --json tagName,isLatest --jq '.[] | select(.isLatest) | .tagName'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment