Is there a link to GitHub for downloading a file in the latest release of a repository?
GithubDownloadReleaseGithub PagesGithub Problem Overview
Using GitHub's Release feature, it is possible to provide a link to download a specific version of the published software. However, every time a release is made, the gh-page also needs to be updated.
Is there a way to get a link to a specific file of whatever the latest version of a software is?
e.g., this would be a static link:
https://github.com/USER/PROJECT/releases/download/v0.0.0/package.zip
What I'd like is something like:
https://github.com/USER/PROJECT/releases/download/latest/package.zip
> NOTE: The difference between this question and > https://stackoverflow.com/questions/21439239/github-latest-release is > that this question specifically asks for getting access to the file, > not the GitHub latest release page
Github Solutions
Solution 1 - Github
A few years late, but I just implemented a simple redirect to support https://github.com/USER/PROJECT/releases/latest/download/package.zip
. That should redirected to the latest tagged package.zip
release asset. Hope it's handy!
Solution 2 - Github
Linux solution to get latest release asset download link (works only if release has one asset only)
curl -s https://api.github.com/repos/boxbilling/boxbilling/releases/latest | grep browser_download_url | cut -d '"' -f 4
Solution 3 - Github
You can do an ajax request to get latest release download URL using the GitHub Releases API. It also shows when it was released and the download count:
function GetLatestReleaseInfo() {
$.getJSON("https://api.github.com/repos/ShareX/ShareX/releases/latest").done(function(release) {
var asset = release.assets[0];
var downloadCount = 0;
for (var i = 0; i < release.assets.length; i++) {
downloadCount += release.assets[i].download_count;
}
var oneHour = 60 * 60 * 1000;
var oneDay = 24 * oneHour;
var dateDiff = new Date() - new Date(asset.updated_at);
var timeAgo;
if (dateDiff < oneDay) {
timeAgo = (dateDiff / oneHour).toFixed(1) + " hours ago";
} else {
timeAgo = (dateDiff / oneDay).toFixed(1) + " days ago";
}
var releaseInfo = release.name + " was updated " + timeAgo + " and downloaded " + downloadCount.toLocaleString() + " times.";
$(".download").attr("href", asset.browser_download_url);
$(".release-info").text(releaseInfo);
$(".release-info").fadeIn("slow");
});
}
GetLatestReleaseInfo();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="download" href="https://github.com/ShareX/ShareX/releases/latest">Download</a>
<p class="release-info"></p>
It is important for you to set the default button URL to the releases page (like <https://github.com/ShareX/ShareX/releases/latest>;) so if the browser does not support ajax (or javascript) or is too slow to get the URL, the download button will still work.
When the Ajax request completes, the URL of this button will change automatically to a direct download URL.
Edit:
I also made a downloads page that shows multiple releases which you can find here: https://getsharex.com/downloads/
Source code of it: https://github.com/ShareX/sharex.github.io/blob/master/js/downloads.js
Solution 4 - Github
From the command line using curl
and jq
, retrieves the first file of the latest release:
curl -s https://api.github.com/repos/porjo/staticserve/releases/latest | \
jq --raw-output '.assets[0] | .browser_download_url'
Solution 5 - Github
Another Linux solution using curl and wget to download a single binary file from the latest release page
curl -s -L https://github.com/bosun-monitor/bosun/releases/latest | egrep -o '/bosun-monitor/bosun/releases/download/[0-9]*/scollector-linux-armv6' | wget --base=http://github.com/ -i - -O scollector
Explanation:
curl -s -L
is to silently download the latest release HTML (after following redirect)
egrep -o '...'
uses regex to find the file you want
wget --base=http://github.com/ -i -
converts the relative path from the pipeline to absolute URL
and -O scollector
sets the desired file name.
may be able to add -N
to only download if the file is newer but S3 was giving a 403 Forbidden error.
Solution 6 - Github
Just use one of the urls below to download the latest release: (took urls from boxbilling project for example): https://api.github.com/repos/boxbilling/boxbilling/releases
Download the latest release as zip: https://api.github.com/repos/boxbilling/boxbilling/zipball
Download the latest release as tarball: https://api.github.com/repos/boxbilling/boxbilling/tarball
Click on one of the urls to download the latest release instantly. As i wrote this lines it's currently: boxbilling-boxbilling-4.20-30-g452ad1c[.zip/.tar.gz]
UPDATE: Found an other url in my logfiles (ref. to example above) https://codeload.github.com/boxbilling/boxbilling/legacy.tar.gz/master
Solution 7 - Github
As noted previously, jq is useful for this and other REST APIs.
tl;dr - more details below
Assuming you want the macOS release:
URL=$( curl -s "https://api.github.com/repos/atom/atom/releases/latest" \
| jq -r '.assets[] | select(.name=="atom-mac.zip") | .browser_download_url' )
curl -LO "$URL"
Solution for atom releases
Note each repo can have different ways of providing the desired artifact, so I will demonstrate for a well-behaved one like atom.
Get the names of the assets published
curl -s "https://api.github.com/repos/atom/atom/releases/latest" \
| jq -r '.assets[] | .name'
atom-1.15.0-delta.nupkg
atom-1.15.0-full.nupkg
atom-amd64.deb
...
Get the download URL for the desired asset
Below atom-mac is my desired asset via jq's select(.name=="atom-mac.zip")
curl -s "https://api.github.com/repos/atom/atom/releases/latest" \
| jq -r '.assets[] | select(.name=="atom-mac.zip") | .browser_download_url'
https://github.com/atom/atom/releases/download/v1.15.0/atom-mac.zip
Download the artifact
curl -LO "https://github.com/atom/atom/releases/download/v1.15.0/atom-mac.zip"
jq Playground
jq syntax can be difficult. Here's a playground for experimenting with the jq
above:
https://jqplay.org/s/h6_LfoEHLZ
Security
You should take measures to ensure the validity of the downloaded artifact via sha256sum and gpg, if at all possible.
Solution 8 - Github
A solution using (an inner) wget to get the HTML content, filter it for the zip file (with egrep) and then download the zip file (with the outer wget).
wget https://github.com/$(wget https://github.com/<USER>/<PROJECT>/releases/latest -O - | egrep '/.*/.*/.*zip' -o)
Solution 9 - Github
Not possible according to GitHub support as of 2018-05-23
Contacted [email protected] on 2018-05-23 with message:
> Can you just confirm that there is no way besides messing with API currently?
and they replied:
> Thanks for reaching out. We recommend using the API to fetch the latest release because that approach is stable, documented, and not subject to change any time soon: > > https://developer.github.com/v3/repos/releases/#get-the-latest-release
I will also keep tracking this at: https://github.com/isaacs/github/issues/658
Python solution without any dependencies
Robust and portable:
#!/usr/bin/env python3
import json
import urllib.request
_json = json.loads(urllib.request.urlopen(urllib.request.Request(
'https://api.github.com/repos/cirosantilli/linux-kernel-module-cheat/releases/latest',
headers={'Accept': 'application/vnd.github.v3+json'},
)).read())
asset = _json['assets'][0]
urllib.request.urlretrieve(asset['browser_download_url'], asset['name'])
See also:
- https://stackoverflow.com/questions/645312/what-is-the-quickest-way-to-http-get-in-python
- https://stackoverflow.com/questions/19602931/basic-http-file-downloading-and-saving-to-disk-in-python
Also consider pre-releases
/latest
does not see pre-releases, but it is easy to do since /releases
shows the latest one first:
#!/usr/bin/env python3
import json
import urllib.request
_json = json.loads(urllib.request.urlopen(urllib.request.Request(
'https://api.github.com/repos/cirosantilli/linux-kernel-module-cheat/releases',
headers={'Accept': 'application/vnd.github.v3+json'},
)).read())
asset = _json[0]['assets'][0]
urllib.request.urlretrieve(asset['browser_download_url'], asset['name'])
Solution 10 - Github
Github now supports static links for downloading individual files from the latest release: https://help.github.com/en/articles/linking-to-releases
https://github.com/USER/PROJECT/releases/latest/download/package.zip
Solution 11 - Github
This can be done in a single one-liner like so:
$ curl -s https://api.github.com/repos/slmingol/gorelease_ex/releases/latest \
| grep -wo "https.*Linux.*gz" | wget -qi -
Here we're:
- Pulling the API side of GitHub to get information about the release artifacts with the tag
latest
. - Parse that output looking for an artifact that matches the pattern
https.*Linux.*gz
. - Pass the URL to the command
wget -qi -
so that it'll get downloaded
To further reveal what's going on here's a broader grep
of the API endpoint:
$ curl -s https://api.github.com/repos/slmingol/gorelease_ex/releases/latest | grep -wo "https.*" | grep gz
https://github.com/slmingol/gorelease_ex/releases/download/0.0.78/gorelease_ex_0.0.78_Darwin_x86_64.tar.gz"
https://github.com/slmingol/gorelease_ex/releases/download/0.0.78/gorelease_ex_0.0.78_Linux_x86_64.tar.gz"
Above you can see the URLs that matched.
Further tip
You can also parameterize the grep
argument so that it'll "dynamically" determine what platform it was run on and substitute in the appropriate string based on that.
$ curl -s https://api.github.com/repos/slmingol/gorelease_ex/releases/latest \
| grep -wo "https.*$(uname).*gz" | wget -qi -
Here $(uname)
will return either Darwin, Linux, etc.
Solution 12 - Github
The Linking to releases help page does mention a "Latest Release" button, but that doesn't get you a download link.
https://github.com/reactiveui/ReactiveUI/releases/latest
For that, you need to get the latest tag first (as mentioned in "GitHub URL for latest release of the download file?"):
latestTag=$(git describe --tags `git rev-list --tags --max-count=1`)
curl -L https://github.com/reactiveui/ReactiveUI/releases/download/$latestTag/ReactiveUI-$latestTag.zip
Solution 13 - Github
in PHP - redirect to the latest release download. Simply put on your webspace
<?php
/**
* Download latest release from github release articats
* License: Public Domain
*/
define('REPO', 'imi-digital/iRobo');
$opts = [
'http' => [
'method' => 'GET',
'header' => [
'User-Agent: PHP'
]
]
];
$context = stream_context_create($opts);
$releases = file_get_contents('https://api.github.com/repos/' . REPO . '/releases', false, $context);
$releases = json_decode($releases);
$url = $releases[0]->assets[0]->browser_download_url;
header('Location: ' . $url);
Solution 14 - Github
If you want to use just curl
you can try with -w '%{url_effective}'
that prints the URL after a redirect chain (followed by curl if you invoke it with -L
). So, for example
curl -sLo /dev/null -w '%{url_effective}' https://github.com/github-tools/github/releases/latest
outputs https://github.com/github-tools/github/releases/tag/v3.1.0
.
Solution 15 - Github
The benefit of this solution is that you don't have to specify any release or tag number- it will just grab the LATEST.
TESTING:
I conducted my testing using the following Github user & repo:
"f1linux" = Github User
"pi-ap" = Repo
The arbitrary directory name the repo is saved to is set in:
--one-top-level="pi-ap"
DIRECT:
Using Firefox's "Web Developer" tools (3 bars in upper right corner), in the "Network" section I found https://api.github.com
was redirecting to https://codeload.github.com
, so by piping the curl
to tar
I was able to grab the latest versioned repo and save it to a predictable name so it could be operated on:
curl https://codeload.github.com/f1linux/pi-ap/legacy.tar.gz/master | tar xzvf - --one-top-level="pi-ap" --strip-components 1
INDIRECT:
After I achieved fully-automated downloads of the latest versioned release using a DIRECT URL, I turned my attention to achieving the same with Github's redirection:
curl -L https://api.github.com/repos/f1linux/pi-ap/tarball | tar xzvf - --one-top-level="pi-ap" --strip-components 1
Preferred Method:
However, please note as per Von's comment below that INDIRECT is the preferred method
Further Validation:
To ensure my results were reproducible to other versioned Github repos, the same tests were successfully executed for Digital Ocean's doctl
api toolkit (which is what started the whole exercise actually!):
Both DIRECT and INDIRECT work using the same form as above, just changing the username & repo:
DIRECT:
curl https://codeload.github.com/digitalocean/doctl/legacy.tar.gz/master | tar xzvf - --one-top-level="doctl" --strip-components 1
INDIRECT:
curl -L https://api.github.com/repos/digitalocean/doctl/tarball | tar xzvf - --one-top-level="doctl" --strip-components 1
Solution 16 - Github
I want to download the releases from the README.md
file in the repository description. There, I cannot execute JavaScript.
I can add links like these to the README file or github pages for all of my repositories:
https://niccokunzmann.github.io/download_latest/<USER>/<REPOSITORY>/<FILE>
Downloads the latest release file from the repository.https://niccokunzmann.github.io/download_latest/<FILE>
This works because the JavaScript referrer is set and the repository to download is determined throughdocument.referrer
. Thus, the link will also work for forks.
You can find the source code here, fork or just use my repo.
Solution 17 - Github
In case you want to use in alpine, then follow these steps
apk add curl ca-certificates wget
wget -q $(curl -s https://api.github.com/repos/<USER>/<REPOSITORY>/releases/latest | grep browser_download_url | grep "$ARCH" | cut -d '"' -f 4)
-q in wget is quite mode, if you want to see output then use without q
Solution 18 - Github
This is for Linux.
I saw the above accepted answer
A few years late, but I just implemented a simple redirect to support https://github.com/USER/PROJECT/releases/latest/download/package.zip. That should redirected to the latest tagged package.zip release asset. Hope it's handy!
by Joshua Peek but a comment noted it didn't support versioned file names.
After searching for a bit, I made up a one line call that works for versioned file names. It uses curl to get the latest file version and then makes use of the redirect support that was added to download the latest versioned file.
wget $'https://github.com/<UMBRELLA PROJECT>/<REPO NAME>/releases/latest/download/<FILE NAME START>-'$(curl -s https://github.com/<UMBRELLA PROJECT>/<REPO NAME>/releases/latest | grep -o -P '(?<=releases/tag/).*(?=\">)')$'<FILE NAME END>'
So it targets a file that's named like <REPO NAME>-linux64_arm-<VERSION NUMBER>.tar.gz
that's on the webpage https://github.com/<UMBRELLA PROJECT>/<REPO NAME>/releases/latest
after it redirects. It does this by looking for the <VERSION NUMBER>
between releases/tag/
and the ">
in the text that's returned from the curl call. So to be really explicit, <FILE NAME START>
is the <REPO NAME>-linux64_arm-
and <FILE NAME END>
is the .tar.gz
in the above example. Get the START
and END
bits by looking at what the https://github.com/<UMBRELLA PROJECT>/<REPO NAME>/releases/latest
uses as its file naming scheme.
I made this up by mimicking how grep and curl were used by others and just learned all of this now, so let me know if it's doing something real naughty that I wouldn't even fathom! Also I am saying <UMBRELLA PROJECT>
but a user name should be able to go there just fine as well. Shout out to https://stackoverflow.com/a/13245961/2403531 for the grep call, https://unix.stackexchange.com/a/10264 for the $string$concatenation.
Solution 19 - Github
In case that the repo is using just tags instead of release -- cf. jQuery -- the solutions which based on one URL does not work.
Instead, you have to query all tags, sort them and construct the download URL. I implemented such a solution for the language Go and the jQuery repo: Link to Github.
Perhaps, this helps someone.