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 -
@aadipoddar
Copy link

Update Manager Class For C# APP using Github

Release the MSI after every release and update new version number to the readme file

Refer to the Gist:- Update Manager Class

Refer to the Repo:- Github Repo

private static async Task<string> GetLatestVersionFromGithub()
{
	string fileUrl = "url_containing_latest_version_number";

	using (HttpClient client = new HttpClient())
	{
		string cacheBuster = DateTime.UtcNow.Ticks.ToString();
		string requestUrl = $"{fileUrl}?cb={cacheBuster}";
		return await client.GetStringAsync(requestUrl);
	}
}

private static void UpdateApp(string filePath)
{
	string batchFilePath = Path.Combine(Path.GetTempPath(), "update.bat");

	string batchScript = $@"
                         @echo off
                         echo Uninstalling program...
                         msiexec /x {{product_code_of_your_app}} /qb

                         echo Starting setup file...
                         start """" ""{filePath}""                            
                         ";

	File.WriteAllText(batchFilePath, batchScript);
	Process.Start(new ProcessStartInfo(batchFilePath) { UseShellExecute = true });
	Environment.Exit(0);
}

private static async Task DownloadLatestVersion()
{
	var url = "https://github.com/{user_name}/{repo_name}/releases/latest/download/{name_of_msi}.msi";
	var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "PubEntrySetup.msi");

	using (HttpClient client = new HttpClient())
	using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
	using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
	using (Stream streamToWriteTo = File.Open(filePath, FileMode.Create))
		await streamToReadFrom.CopyToAsync(streamToWriteTo);


	UpdateApp(filePath);
}

public static async Task CheckForUpdates()
{
	string fileContent = await GetLatestVersionFromGithub();

	if (fileContent.Contains("Latest Version = "))
	{
		string latestVersion = fileContent.Substring(fileContent.IndexOf("Latest Version = ") + 17, 7);
		string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
		if (latestVersion != currentVersion)
			if (MessageBox.Show("New Version Available. Do you want to update?", "Update Available", MessageBoxButtons.YesNo) == DialogResult.Yes)
				await DownloadLatestVersion();
	}
}

@deltkastel
Copy link

deltkastel commented Feb 2, 2025

From batch scripts on Windows, you can call PowerShell without directly using its shell.:

First download grep.exe from this fairly popular but unmantained repo -because findstr sucks-

powershell iwr https://github.com/bmatzelle/gow/raw/refs/heads/master/bin/grep.exe -OutFile grep.exe

Then you can download your files like this.

set url=https://api.github.com/repos/user/repo/releases/latest
powershell irm %url% | grep -o 'https.*download.*zip' | powershell iwr -OutFile file.zip

Just replace user/repo and zip.

@Adamkaram
Copy link

for filtring and download something like beta release

curl -sL https://api.github.com/repos/telegramdesktop/tdesktop/releases
| jq -r '.[] | select(.prerelease==true) | .assets[] | select(.browser_download_url | contains("tar.xz")) | .browser_download_url'
| wget -i-

@dafanasiev
Copy link

for the latest version with a known file naming scheme:

PATCHELF_VERSION=$(curl -sLI https://github.com/NixOS/patchelf/releases/latest | grep -iP 'location.*tag' | grep -oP '\d+\.\d+\.\d+' | tail -1) \
&& curl -sL --output patchelf.tar.gz https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}-x86_64.tar.gz

@antofthy
Copy link

for the latest version with a known file naming scheme:

PATCHELF_VERSION=$(curl -sLI https://github.com/NixOS/patchelf/releases/latest | grep -iP 'location.*tag' | grep -oP '\d+\.\d+\.\d+' | tail -1) \
&& curl -sL --output patchelf.tar.gz https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}-x86_64.tar.gz

Removed the double grep, with a sed

PATCHELF_VERSION=$(curl -sLI https://github.com/NixOS/patchelf/releases/latest | sed '/location: .*\/tag\//!d; s///' | tail -1) &&
curl -sL --output patchelf.tar.gz https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}-x86_64.tar.gz

@dafanasiev
Copy link

for the latest version with a known file naming scheme:

PATCHELF_VERSION=$(curl -sLI https://github.com/NixOS/patchelf/releases/latest | grep -iP 'location.*tag' | grep -oP '\d+\.\d+\.\d+' | tail -1) \
&& curl -sL --output patchelf.tar.gz https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}-x86_64.tar.gz

Removed the double grep, with a sed

PATCHELF_VERSION=$(curl -sLI https://github.com/NixOS/patchelf/releases/latest | sed '/location: .*\/tag\//!d; s///' | tail -1) &&
curl -sL --output patchelf.tar.gz https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}-x86_64.tar.gz

++ case-insensitive location: match
++ remove regex escapes

PATCHELF_VERSION=$(curl -sLI https://github.com/NixOS/patchelf/releases/latest | sed '\|location:.*/tag/|I!d; s|||' | tail -1) \
&& curl -sL --output patchelf.tar.gz https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}-x86_64.tar.gz

@antofthy
Copy link

Actually instead of sed I could have just merge the two greps directly, using perl '\K' regex escape!

 PATCHELF_VERSION=$(curl -sLI https://github.com/NixOS/patchelf/releases/latest | grep -ioP 'location.*/tag/\K\d+\.\d+\.\d+' | tail -1) \
&& curl -sL --output patchelf.tar.gz https://github.com/NixOS/patchelf/releases/download/${PATCHELF_VERSION}/patchelf-${PATCHELF_VERSION}-x86_64.tar.gz
There are lots of ways to skin a cat, and what method you use depends
on what you want that skin for, and how messy you like the results!
                                                   -- Anthony Thyssen

@Mr-Bossman
Copy link

Not sure why everyone is using grep when sed can do everything.

curl -s https://api.github.com/repos/<user>/<repo>/releases/latest | sed -n 's/"browser_download_url": //p' | xargs wget

or

curl -s https://api.github.com/repos/<user>/<repo>/releases/latest | sed -n 's/"browser_download_url": "\(.*\)"$/\1/p' | wget -i-

@aristotaloss
Copy link

Actual 'one-liner'; you don't need tools:

https://github.com/$OWNER/$REPO/releases/latest/download/$FILENAME

Example:
https://github.com/monarch-initiative/monarch-ingest/releases/latest/download/monarch-kg.tar.gz

@maxadamo
Copy link

Actual 'one-liner'; you don't need tools:

https://github.com/$OWNER/$REPO/releases/latest/download/$FILENAME

do you really think hundreds of people are completely dumb and did not figure out something so simple? 😸
The whole point is to guess $FILENAME, becuse you don't know in advance what the latest version is.

@Mr-Bossman
Copy link

I mean in his particular case it does work bc the maintainers decided to keep the filename the same for every release. Not a portable option IMO but if you are the repo owner it works.

@aristotaloss
Copy link

@maxadamo bro pipe the fuck down

@maxadamo
Copy link

maxadamo commented Jun 22, 2025

I mean in his particular case it does work bc the maintainers decided to keep the filename the same for every release. Not a portable option IMO but if you are the repo owner it works.

That would be another topic, on another thread: "how do I download an artifact if the filename doesn't change."
The case we are discussing is very clear and it's pretty different.
And it's really unimportant if you use sed, grep, jq, because everything woks. Maybe one pipe should be enough, but if you are not seeking for extreme optimization, it's purely stylistic.

For instance I rather like the AWK approach:

REPO='jgraph/drawio-desktop'
curl -s https://api.github.com/repos/${REPO}/releases/latest | awk -F\" '/browser_download_url.*.deb/{print $(NF-1)}'

again, we are hundreds of people, not having much else todo, and playing to find different solutions, but we're not hundreds of idiots. This thread is 8 year old and if there was a simpler solution someone else would have found it in 8 years.

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