Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save steinwaywhw/a4cd19cda655b8249d908261a62687f8 to your computer and use it in GitHub Desktop.
Save steinwaywhw/a4cd19cda655b8249d908261a62687f8 to your computer and use it in GitHub Desktop.
One Liner to Download the Latest Release from Github Repo
  • Use curl to get the JSON response for the latest release
  • Use grep to find the line containing file URL
  • Use cut and tr to extract the URL
  • Use wget to download it
curl -s https://api.github.com/repos/jgm/pandoc/releases/latest \
| grep "browser_download_url.*deb" \
| cut -d : -f 2,3 \
| tr -d \" \
| wget -qi -
@nicman23
Copy link

nicman23 commented Sep 28, 2022

curl -sL https://github.com/revanced/revanced-integrations/releases/ | 
   xmllint -html -xpath '//a[contains(@href, "releases")]/text()' - 2> /dev/null | 
   grep -P '^v' | head -n1

@cobalt2727
Copy link

Hello! Every now and then this function fails seemingly at random, and I haven't been able to successfully determine why.

From a script to automatically update WebCord:

Downloading the most recent .deb from SpacingBat3 repository...
--2022-10-18 19:51:55--  https://api.github.com/repos/SpacingBat3/WebCord/releases/79464711,assets_url
Resolving api.github.com (api.github.com)... 140.82.113.5
Connecting to api.github.com (api.github.com)|140.82.113.5|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/json]
Saving to: ‘79464711,assets_url’

     0K .......... .......... .......                          1.35M=0.02s

2022-10-18 19:51:55 (1.35 MB/s) - ‘79464711,assets_url’ saved [28644]

FINISHED --2022-10-18 19:51:55--
Total wall clock time: 0.3s
Downloaded: 1 files, 28K in 0.02s (1.35 MB/s)
Done! Installing the package...
Waiting until APT locks are released... 

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
E: Unsupported file /tmp/*arm64.deb given on commandline
Webcord install failed

Would anyone be able to help me debug this and figure out why I'm getting whatever 79464711,assets_url is supposed to be instead of the release file?
The exact commands I'm running are

cd /tmp
curl -s https://api.github.com/repos/SpacingBat3/WebCord/releases/latest |
  grep "browser_download_url.*arm64.deb" |
  cut -d : -f 2,3 |
  tr -d \" |
  wget -i -

echo "Done! Installing the package..."
sudo apt install -y /tmp/*arm64.deb || error "Webcord install failed"

@antofthy
Copy link

antofthy commented Oct 21, 2022

While all this USED to be easy... I am now finding the returned URL for the project I am interested in has a return of
"message": "Moved Permanently"
But without a HTTP redirection, which curl could handle transparently.

Seems the owner of the project had changed on me!

As such you may have to check for this condition and adjust accordingly!

"The pain. The pain!" -- Doctor Smith, "Lost in Space"

@surfzoid
Copy link

surfzoid commented Nov 8, 2022

Hi, you should add point betwen * and deb , because, as you can see curl -s https://api.github.com/repos/surfzoid/QtVsPlayer/releases/latest
| grep "browser_download_url.*deb"

By the way, i thank you for time win

@surfzoid
Copy link

surfzoid commented Nov 8, 2022

unlucky it is not enough, why curl/grep catch debuginfo as .deb?

@NotoriousPyro
Copy link

Hello! Every now and then this function fails seemingly at random, and I haven't been able to successfully determine why.

From a script to automatically update WebCord:

Downloading the most recent .deb from SpacingBat3 repository...
--2022-10-18 19:51:55--  https://api.github.com/repos/SpacingBat3/WebCord/releases/79464711,assets_url
Resolving api.github.com (api.github.com)... 140.82.113.5
Connecting to api.github.com (api.github.com)|140.82.113.5|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/json]
Saving to: ‘79464711,assets_url’

     0K .......... .......... .......                          1.35M=0.02s

2022-10-18 19:51:55 (1.35 MB/s) - ‘79464711,assets_url’ saved [28644]

FINISHED --2022-10-18 19:51:55--
Total wall clock time: 0.3s
Downloaded: 1 files, 28K in 0.02s (1.35 MB/s)
Done! Installing the package...
Waiting until APT locks are released... 

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
E: Unsupported file /tmp/*arm64.deb given on commandline
Webcord install failed

Would anyone be able to help me debug this and figure out why I'm getting whatever 79464711,assets_url is supposed to be instead of the release file? The exact commands I'm running are

cd /tmp
curl -s https://api.github.com/repos/SpacingBat3/WebCord/releases/latest |
  grep "browser_download_url.*arm64.deb" |
  cut -d : -f 2,3 |
  tr -d \" |
  wget -i -

echo "Done! Installing the package..."
sudo apt install -y /tmp/*arm64.deb || error "Webcord install failed"

The problem is you're trying to use grep, cut and trim on json. None of which are designed for handing json in a reliable way. Use jq for reliability, as per my example above.

@NotoriousPyro
Copy link

While all this USED to be easy... I am now finding the returned URL for the project I am interested in has a return of "message": "Moved Permanently" But without a HTTP redirection, which curl could handle transparently.

Seems the owner of the project had changed on me!

As such you may have to check for this condition and adjust accordingly!

"The pain. The pain!" -- Doctor Smith, "Lost in Space"

You can use -L with curl to make it follow redirects.

@dvershinin
Copy link

Would anyone be able to help me debug this and figure out why I'm getting whatever 79464711,assets_url is supposed to be instead of the release file?

Just use lastversion. It's pretty powerful:

lastversion --assets --filter arm64.deb download https://github.com/SpacingBat3/WebCord

Downloaded webcord_3.9.2_arm64.deb: : 72872.0KB [00:18, 3860.60KB/s]

@antofthy
Copy link

antofthy commented Nov 8, 2022

While all this USED to be easy... I am now finding the returned URL for the project I am interested in has a return of "message": "Moved Permanently" But without a HTTP redirection, which curl could handle transparently.
Seems the owner of the project had changed on me!
As such you may have to check for this condition and adjust accordingly!
"The pain. The pain!" -- Doctor Smith, "Lost in Space"

You can use -L with curl to make it follow redirects.

That was the point... there were no redirects! Not in the HTTP protocol header, only in the JSON data returned.

@solbu
Copy link

solbu commented Nov 20, 2022

Just remember that this only works for repos that do a Release.
Many projects only use Tags as the release mechanism. I am one of them. :-)

@NotoriousPyro
Copy link

Well then it's not a release and those repos are not releasing anything.

@NotoriousPyro
Copy link

Tags are not releases, but releases reference a tag.

@dvershinin
Copy link

Tags are not releases. But the tags that resemble version numbers in all likelihood are releases 🫡

@NotoriousPyro
Copy link

True, but then it creates the problem you mention. Using a repo in this way creates the limitation of not being able to grab the releases... Without doing some grepping and whatnot on the tag name.

@solbu
Copy link

solbu commented Nov 20, 2022

My reason for Not doing a Release on Github (in the /username/foo-bar/releases/ page) is that I have to interact with the webgui,
as in I have to login to Github in a browser, upload whatever is part of the release and so on – just to do a release,
whereas on SourceForge I only have to do an rsync command in the terminal to do a Release, which is often automated in a script or a target in a Makefile.

@robertpatrick
Copy link

@solbu well…. There are mechanisms to create releases via the REST api. I wrote a little github-maven-plug-in that currently supports creating draft releases, uploading any binaries needed, and pushing release notes. It could easily be extended to publish the release…

@cobalt2727
Copy link

Would anyone be able to help me debug this and figure out why I'm getting whatever 79464711,assets_url is supposed to be instead of the release file?

Just use lastversion. It's pretty powerful:

lastversion --assets --filter arm64.deb download https://github.com/SpacingBat3/WebCord

Downloaded webcord_3.9.2_arm64.deb: : 72872.0KB [00:18, 3860.60KB/s]

I'll definitely look into this, thank you!

@eortegaz
Copy link

eortegaz commented Dec 9, 2022

Love a good one-liner.

If you must use wget, to make your life easier you should search for your architecture by matching uname -m from the JSON response. Don't forget to add head -1 though, otherwise you're (silently) downloading packages for all available archs.

Totally up to you, but you may want to show progress too (albeit omitting everything else) with -q --show-progress instead of suppressing all output.

The one-liner would look something like this:

    REPO="jgm/pandoc"; \
    curl -s https://api.github.com/repos/${REPO}/releases/latest | grep "browser_download_url.*$(uname -m).deb" \
    | head -1 \
    | cut -d : -f 2,3 \
    | tr -d \" \
    | wget --show-progress -qi - \
    || echo "-> Could not download the latest version of '${REPO}' for your architecture." # if you're polite

Note: Setting a variable with the user/repo should decrease the risk of messing up the url :)

@fanuch
Copy link

fanuch commented Dec 23, 2022

My hat in the ring.

VER=$(curl --silent -qI https://github.com/bakito/adguardhome-sync/releases/latest | awk -F '/' '/^location/ {print  substr($NF, 1, length($NF)-1)}'); \
wget https://github.com/bakito/adguardhome-sync/releases/download/$VER/adguardhome-sync_${VER#v}_linux_x86_64.tar.gz 

Technically two lines because I needed to use the version number both in the URL path and in the filename

Retrieve latest version using curl

curl -I https://github.com/bakito/adguardhome-sync/releases/latest

returns

HTTP/2 302 
...
location: https://github.com/bakito/adguardhome-sync/releases/tag/v0.4.10
...

So strip it out (minus the carriage return):

curl -I https://github.com/bakito/adguardhome-sync/releases/latest | awk -F '/' '/^location/ {print  substr($NF, 1, length($NF)-1)}'

returns

v0.4.10

Attach to a variable and get annoyed when filename doesn't have a leading 'v'

${VER#v}

This strips the leading v from the version number

Note

Doesn't handle different architectures but that would be the use of uname -m at the least

Thanks for the inspo in this thread - really should be easier than this ...

@bluebrown
Copy link

@robertpatrick

Hmm... https://github.com///releases/latest/download/ should work without having to rely on the GitHub REST API, no?

That works only if the publisher doesn't put the version in the artifact file name, which is more often than not the case. The api.github.com, tells you the version and download URL in the response.

@bluebrown
Copy link

My script looks pretty much like this, but you need to be careful with mono repos that publish different artifacts with different tags. Latest is useless on those.

@cinderblock
Copy link

One liner to download and pipe it to tar for extraction directly:

curl -sL $(curl -s https://api.github.com/repos/actions/runner/releases/latest | grep browser_download_url | cut -d\" -f4 | egrep 'linux-arm64-[0-9.]+tar.gz$') | tar zx

@notorand-it
Copy link

notorand-it commented Feb 9, 2023

Why on Earth would you use two different tools for the same task and put curl and wget in the same script/1-liner ?
Why fiddling with grep/tr/cut when the only reliable JSON parsing tool is jq ?

This is from my own stuff (different URL):

wget -q -O /usr/bin $(wget -q -O - 'https://api.github.com/repos/mikefarah/yq/releases/latest' | jq -r '.assets[] | select(.name=="yq_linux_amd64").browser_download_url'')

2 tools is better than 5 IMHO.
Adapting it to other needs is left to the keen reader. ;-)

@joshjohanning
Copy link

joshjohanning commented Feb 15, 2023

a note (for your repositories)

I advise using consistent file-names. I.E. don't include a versioning in the filename.
I know it sounds weird, but bear with me* for a second.
You know the .../releases/latest syntax right? did you know you can also use it to download files as well? (and not just to redirect to the latest release on Github?)
Here, try this URL for example: https://github.com/ytdl-org/youtube-dl/releases/latest/download/youtube-dl.exe.
this reduces the need to walk through Github-Releases API entirely! and simplify stuff for users and also web-services that crawls your repository (in-case you have a somewhat popular product :] ). You don't to maintain any kind of backend or domain at all and relink to to the latest binaries (for example: http://youtube-dl.org/downloads/latest/youtube-dl.exe). it is handled by github releases!
you can always include the version in a file named version.txt, or any meta-data, really. keep a consistent file-name here too.
got the idea from https://github.com/yt-dlp/yt-dlp#update

COOL! 👍

This is it

wget https://github.com/aquasecurity/tfsec/releases/latest/download/tfsec-linux-amd64

@NLZ
Copy link

NLZ commented Apr 4, 2023

Exactly what I was hoping to find. 👍

I made a slight adjustment to it for my needs.

$githubLatestReleases = 'https://api.github.com/repos/microsoft/winget-cli/releases/latest'   
$githubLatestRelease = (((Invoke-WebRequest $gitHubLatestReleases) | ConvertFrom-Json).assets.browser_download_url | select-string -Pattern 'appxbundle').Line
Invoke-WebRequest $githubLatestRelease -OutFile 'Microsoft.DesktopAppInstaller.appxbundle'

Powershell can be further simplified with invoke-restmethod's auto-parsing and then exploring the objects in the pipe

Invoke-RestMethod 'https://api.github.com/repos/microsoft/winget-cli/releases/latest' | % assets | ? name -like "*.msixbundle" | % { Invoke-WebRequest $_.browser_download_url -OutFile $_.name }

@bruteforks
Copy link

bruteforks commented Apr 19, 2023

Hmm... https://github.com/<org-name>/<repo-name>/releases/latest/download/<artifact-file-name> should work without having to rely on the GitHub REST API, no?

literally the easiest way i've found. Thank you! example

edit: here's what i ended up with

echo "Check for watchman"
if ! [ -x "$(command -v watchman)" ]; then
echo "downloading and installing latest github release"
wget $(curl -L -s https://api.github.com/repos/facebook/watchman/releases/latest | grep -o -E "https://(.*)watchman-(.*).rpm") && sudo dnf localinstall watchman-*.rpm
watchman version
else
  echo "watchman exists."	
fi

@vavavr00m
Copy link

Nothing for Windows worked for me.

The below Windows batch script sort of worked but it's downloading all latest releases. Anyone knows how to modify it to select only the *-x64.exe release?

  set repo=owner/name
  for /f "tokens=1,* delims=:" %%A in ('curl -ks https://api.github.com/repos/%repo%/releases/latest ^| find "browser_download_url"') do ( curl -kOL %%B )

@flightlesstux
Copy link

flightlesstux commented Jun 1, 2023

Nothing for Windows worked for me.

The below Windows batch script sort of worked but it's downloading all latest releases. Anyone knows how to modify it to select only the *-x64.exe release?

  set repo=owner/name
  for /f "tokens=1,* delims=:" %%A in ('curl -ks https://api.github.com/repos/%repo%/releases/latest ^| find "browser_download_url"') do ( curl -kOL %%B )

@vavavr00m could you try this?

set repo=owner/name
for /f "tokens=1,* delims=:" %%A in ('curl -ks https://api.github.com/repos/%repo%/releases/latest ^| find "browser_download_url"') do (
    set url=%%B
    set "filename=%url:*\=%"
    if "%filename:~-9%"=="-x64.exe" (
        curl -kOL %url%
    )
)

@vavavr00m
Copy link

vavavr00m commented Jun 1, 2023

@flightlesstux Thanks for your response. The %url% stored the -x86.exe release and also the script doesn't also download that file. How do I change it to pick up -x64.exe and download it?

@flightlesstux
Copy link

@vavavr00m You're welcome! This script calls a :download subroutine from the loop. The subroutine sets url and filename variables, then checks the filename and downloads the file if it matches -x64.exe.

@echo off
setlocal enabledelayedexpansion
set repo=owner/name
for /f "tokens=1,* delims=:" %%A in ('curl -ks https://api.github.com/repos/%repo%/releases/latest ^| find "browser_download_url"') do (
    call :download "%%B"
)
goto :eof

:download
set "url=%~1"
for %%i in (%url%) do set "filename=%%~nxi"
if "%filename:~-9%"=="-x64.exe" (
    curl -kOL %url%
)
goto :eof

@vavavr00m
Copy link

@flightlesstux I tried this on PowerToys. It doesn't download the -x64.exe release(s) for me and %url% output is all the browser_download_url from the PowerToys repo but nothing was downloaded:

image

Would it help to say the .bat is getting the links from a JSON? Should the script echo the URL(s) without the double quotes?

test.bat on W10:

 @echo off

 setlocal enabledelayedexpansion
 set repo=microsoft/PowerToys
 for /f "tokens=1,* delims=:" %%A in ('curl -ks https://api.github.com/repos/%repo%/releases/latest ^| find "browser_download_url"') do (
      call :download "%%B"
 )
 goto :eof

 :download
 set "url=%~1"
 for %%i in (%url%) do set "filename=%%~nxi"
 if "%filename:~-9%"=="-x64.exe" (
     curl -kOL %url%
)
goto :eof

@antofthy
Copy link

antofthy commented Jun 2, 2023

The problem is that what to search for VARIES from repo to repo.
MOST repos seem to use browser_download_url but I have also have seen repos that does not have that entry, but use tarball_url, zipball_url instead.

@si618
Copy link

si618 commented Sep 13, 2023

@fanuch

My hat in the ring.

VER=$(curl --silent -qI https://github.com/bakito/adguardhome-sync/releases/latest | awk -F '/' '/^location/ {print  substr($NF, 1, length($NF)-1)}'); \
wget https://github.com/bakito/adguardhome-sync/releases/download/$VER/adguardhome-sync_${VER#v}_linux_x86_64.tar.gz 

Thanks for the inspo in this thread - really should be easier than this ...

Agreed, and thanks for putting your hat in the ring; it was very close to what I needed 🙇‍♂️

@codelinx
Copy link

codelinx commented Sep 21, 2023

Using jq, i think this should work with most repos and allow you to saerch different values or fields as needed.

wget $(curl -s https://api.github.com/repos/bitwarden/clients/releases/latest  | \
 jq -r '.assets[] | select(.name | contains ("deb")) | .browser_download_url')
  • jq -r raw search
  • select( .name select the field to refine your download
  • | contains ("deb")) search criteria to get the download url
  • . browser_download_url' return string

NOTE: '--raw-output/-r' With this option, if the filter's result is a string then it will be written directly to standard output rather than being formatted as a JSON string with quotes

@notorand-it
Copy link

But why using wget and curl? Why not just wget or curl?

@codelinx
Copy link

But why using wget and curl? Why not just wget or curl?

This is a programmatic discussion for downloading the file(s). You cant wget/curl get the file because of links and internet things. Other issues are that the file name may change, the version, or the file you may need for your OS may change etc.

@codelinx
Copy link

But why using wget and curl? Why not just wget or curl?

you are just trolling.

@notorand-it
Copy link

notorand-it commented Sep 22, 2023

wget $(wget -q -O - https://api.github.com/repos/bitwarden/clients/releases/latest | jq -r '.assets[] | select(.name | contains ("deb")) | .browser_download_url')

I would say this is NOT trolling.
Just like this, IMHO.

@jrichardsz
Copy link

It worked at first attempt :)
Thank you so much !!

@NiceGuyIT
Copy link

dra is making huge strides in simplifying the download process.

dra helps you download release assets more easily:

  • no authentication for public repository (you cannot use gh without authentication)
  • Built-in generation of pattern to select an asset to download (with gh you need to provide glob pattern that you need to create manually).

@panscher
Copy link

@flightlesstux

The download with NotpadPlus x64.exe does not work.

`
@echo off

setlocal enabledelayedexpansion
set repo=notepad-plus-plus/notepad-plus-plus
for /f "tokens=1,* delims=:" %%A in ('curl -ks https://api.github.com/repos/%repo%/releases/latest ^| find "browser_download_url"') do (
call :download "%%B"
)
goto :eof

:download
set "url=%~1"
for %%i in (%url%) do set "filename=%%nxi"
if "%filename:
-9%"==".x64.exe" (
curl -kOL %url%
)
goto :eof
`

@notorand-it
Copy link

I am not unsubscribing because I actually want to see how far we get, and how long this conversation lasts with all these comments that everyone keeps adding. There are hundreds of ways and different languages to achieve the same result. But do we need the rosetta stone with all the programming languages on earth, and all the different approaches, or can we move on, after having received so many comments? OMG.

" different languages"?

The title reads "One Liner to Download the Latest Release from Github Repo".
I would say that the original thing aimed at using a single line command or pipeline.
So I would say it is aimed at a shell (bash/zsh/PowerShell) not any language.
Still on a single line.

IMHO, a few comments actually hit spot.
All the rest is either multi-line scripts (no. of lines > 1) or just not working.

@antofthy
Copy link

antofthy commented Dec 7, 2023

The title reads "One Liner to Download the Latest Release from Github Repo". I would say that the original thing aimed at using a single line command or pipeline. So I would say it is aimed at a shell (bash/zsh/PowerShell) not any language. Still on a single line.
IMHO, a few comments actually hit spot. All the rest is either multi-line scripts (no. of lines > 1) or just not working.

For a specific repository a single line to do the task can be created. BUT for a general repository, well, what is needed is next to impossible to do in one line, or even in a small script. There are always weird exceptions. I have seen many of them!

The general request that was made, was so general, it is also impossible to achieve. No one answer, or one simple line is itself a complete answer. So you get a multitude of answers, each of which will work for specific cases.

"Simplicity has a habit of expanding into catastrophe."
-- Anne McCaffrey, "The Ship who Sang"

In seeking the unattainable, simplicity only gets in the way.
-- Alan J. Perlis

@notorand-it
Copy link

notorand-it commented Dec 12, 2023

Fair.
A general 1-liner, even to a specific git repo, is quite difficult to achieve.
But a 1-liner that can be easily adapted to a number of cases is a different thing and is something much easier to do.
The type of things you can look for here and in any other question-and-answers web sites.

The original 1st post here, was already a Unix shell-based solution, not a question, using 5 different commands, none aimed at JSON parsing and with inexplicably replicated functions between wget and curl. If the output from GitHub were moved to "compact JSON" (no newlines at all) by GitHub itself, then most of those JSON-unaware scripts would stop working.
The original solution, as most of the subsequent replies, has likely been created by merging 2 different sources.

I have shared my (rather limited) knowledge about scripting to get a simple, minimal and reliable 1-liner that can be easily adapted to a large number of cases.
It only uses 2 tools (wget and jq) aimed exactly at their goals (downloading via HTTP and reliably parsing JSON strings).
This is according to the Unix command line art of simplicity, IMHO.

"Life is really simple, but we insist on making it complicated."
-- Confucius

"It is not a daily increase, but a daily decrease. Hack away at the inessentials."
-- Bruce Lee

"If you can't explain it to a six year old, you don't understand it yourself."
-- Albert Einstein

@TheRealMrWicked
Copy link

Here is a solution for Windows, you need to put the repo owner and name, as well as a string to identify the download, the generic version of the command is below.

for /f "tokens=1,* delims=:" %a in ('curl -s https://api.github.com/repos/<Put repo owner and repo name here>/releases/latest ^| findstr "browser_download_url" ^| findstr "<Put identifying string here>"') do (curl -kOL %b)

Example
Putting the repo as notepad-plus-plus/notepad-plus-plus and the identifying string as .x64.exe we get this command:

for /f "tokens=1,* delims=:" %a in ('curl -s https://api.github.com/repos/notepad-plus-plus/notepad-plus-plus/releases/latest ^| findstr "browser_download_url" ^| findstr ".x64.exe"') do (curl -kOL %b)

Which downloads the latest x64 installer of Notepad++ to the current directory.

@Chuckame
Copy link

Chuckame commented Jan 22, 2024

Here is the simplest way of getting the latest version with only curl and basename: Using the Forwarded url by github when accessing /latest:

basename $(curl -Ls -o /dev/null -w %{url_effective} https://github.com/<user>/<repo>/releases/latest)

Here another variant of it with only curl and a pure bash feature:

version=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/<user>/<repo>/releases/latest)
version=${version##*/}

@ivomarino
Copy link

Here is the simplest way of getting the latest version with only curl and basename: Using the Forwarded url by github when accessing /latest:

basename $(curl -Ls -o /dev/null -w %{url_effective} https://github.com/<user>/<repo>/releases/latest)

Here another variant of it with only curl and a pure bash feature:

version=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/<user>/<repo>/releases/latest)
version=${version##*/}

works great

@jessp01
Copy link

jessp01 commented Mar 12, 2024

Using jq to match a release file pattern (modsecurity-v.*.tar.gz$ in this example):

curl -sL https://api.github.com/repos/owasp-modsecurity/ModSecurity/releases/latest| \
jq -r '.assets[] | select(.name? | match("modsecurity-v.*.tar.gz$")) | .browser_download_url'

@healBvdb
Copy link

Another simple command using the fantastic Nushell
http get https://api.github.com/repos/<user>/<repo>/releases/latest | get tag_name

@JonnieCache
Copy link

JonnieCache commented May 22, 2024

here's one for getting the tag name of the latest release:

curl -s https://api.github.com/repos/<REPO>/releases/latest | jq -r '.tag_name'

this is useful for cloning the latest release, eg. with asdf:

local asdf_version=$(curl -s https://api.github.com/repos/asdf-vm/asdf/releases/latest | jq -r '.tag_name')
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch $asdf_version

@spvkgn
Copy link

spvkgn commented Jun 1, 2024

wget one-liner to get release tarball and extract its contents:

wget -qO- 'https://api.github.com/repos/<REPO>/releases/latest' | jq -r '.assets[] | select(.name | match("tar.(gz|xz)")) | .browser_download_url' | xargs wget -qO- | bsdtar -xf -

@Samueru-sama
Copy link

Better alternative that will work even if the json is pretty or not:

curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | sed 's/[()",{}]/ /g; s/ /\n/g' | grep "https.*releases/download.*deb"

Using jq -c to turn the json compact and this is what happens:

Old:

curl -s https://api.github.com/repos/jgm/pandoc/releases/latest \
| grep "browser_download_url.*deb" \
| cut -d : -f 2,3 \
| tr -d \"
 https://github.com/jgm/pandoc/releases/download/3.2/pandoc-3.2-1-amd64.deb
 https://github.com/jgm/pandoc/releases/download/3.2/pandoc-3.2-1-arm64.deb


curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | jq -c \
| grep "browser_download_url.*deb" \
| cut -d : -f 2,3 \
| tr -d \"
https://api.github.com/repos/jgm/pandoc/releases/155373146,assets_url

Alternative:

curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | sed 's/[()",{}]/ /g; s/ /\n/g' | grep "https.*releases/download.*deb"         
https://github.com/jgm/pandoc/releases/download/3.2/pandoc-3.2-1-amd64.deb
https://github.com/jgm/pandoc/releases/download/3.2/pandoc-3.2-1-arm64.deb

curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | jq -c | sed 's/[()",{}]/ /g; s/ /\n/g' | grep "https.*releases/download.*deb"
https://github.com/jgm/pandoc/releases/download/3.2/pandoc-3.2-1-amd64.deb
https://github.com/jgm/pandoc/releases/download/3.2/pandoc-3.2-1-arm64.deb

Fedora 40 recently changed wget for wget2, and this causes github the send the json compact breaking scripts that were parsing it with grep.

I use gron when it is available, otherwise the sed tricks should work most of the time.

@motdotla
Copy link

This is it

wget https://github.com/aquasecurity/tfsec/releases/latest/download/tfsec-linux-amd64

this is the best solution. thank you @joshjohanning. everything else is unnecessarily complicated for users and could trip them up because of different shell versions and lack of installed libs like jq.

add in a bit of uname magic and all your users are good to go.

curl -L -o dotenvx.tar.gz "https://github.com/dotenvx/dotenvx/releases/latest/download/dotenvx-$(uname -s)-$(uname -m).tar.gz"
tar -xzf dotenvx.tar.gz
./dotenvx help

@bruteforks
Copy link

Since this gist is still very active, here's one I've made recently:

#!/usr/bin/env bash

# Fetch the latest release version
latest_version=$(curl -s https://api.github.com/repos/microsoft/vscode-js-debug/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")')

# Remove the 'v' prefix from the version number
version=${latest_version#v}

# Construct the download URL
download_url="https://github.com/microsoft/vscode-js-debug/releases/download/${latest_version}/js-debug-dap-${latest_version}.tar.gz"

# Download the tar.gz file
curl -L -o "js-debug-dap-${version}.tar.gz" "$download_url"

@initiateit
Copy link

initiateit commented Jul 17, 2024

Just curl and grep:

curl -s https://api.github.com/repos/caddyserver/xcaddy/releases/latest | grep '"browser_download_url":' | grep 'amd64.deb' | grep -vE '(\.pem|\.sig)' | grep -o 'https://[^"]*'

https://github.com/caddyserver/xcaddy/releases/download/v0.4.2/xcaddy_0.4.2_linux_amd64.deb

curl -s https://api.github.com/repos/aptly-dev/aptly/releases/latest | grep '"browser_download_url":' | grep 'amd64.deb' | grep -o 'https://[^"]*'

https://github.com/aptly-dev/aptly/releases/download/v1.5.0/aptly_1.5.0_amd64.deb

My apologies if it borrows from other answers.

@adriangalilea
Copy link

dra is making huge strides in simplifying the download process.

@NiceGuyIT thanks for bringing it up.

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