-
-
Save josh-padnick/fdae42c07e648c798fc27dec2367da21 to your computer and use it in GitHub Desktop.
| #!/usr/bin/env bash | |
| # | |
| # This is an adaptation of code I wrote to download a private binary from GitHub. Such...pain. | |
| # Why can't GitHub just offer a standardized URL you can download a release binary from and attach | |
| # your Github Personal Access Token as a header? | |
| # | |
| # Since this code is an adaptation it hasn't been directly tested, but the code it was adapted from works | |
| # and hopefully you can get the missing piece you're after by looking here. | |
| # | |
| set -e | |
| # Parse CLI args | |
| readonly github_oauth_token="$1" | |
| readonly git_tag="$2" | |
| readonly github_repo_owner="$3" | |
| readonly github_repo_name="$4" | |
| readonly release_asset_filename="$5" | |
| readonly output_path="$6" | |
| # Get the "github tag id" of this release | |
| github_tag_id=$(curl --silent --show-error \ | |
| --header "Authorization: token $github_oauth_token" \ | |
| --request GET \ | |
| "https://api.github.com/repos/$github_repo_owner/$github_repo_name/releases" \ | |
| | jq --raw-output ".[] | select(.tag_name==\"$git_tag\").id") | |
| # Get the download URL of our desired asset | |
| download_url=$(curl --silent --show-error \ | |
| --header "Authorization: token $github_oauth_token" \ | |
| --header "Accept: application/vnd.github.v3.raw" \ | |
| --location \ | |
| --request GET \ | |
| "https://api.github.com/repos/$github_repo_owner/$github_repo_name/releases/$github_tag_id" \ | |
| | jq --raw-output ".assets[] | select(.name==\"$release_asset_filename\").url") | |
| # Get GitHub's S3 redirect URL | |
| # Why not just curl's built-in "--location" option to auto-redirect? Because curl then wants to include all the original | |
| # headers we added for the GitHub request, which makes AWS complain that we're trying strange things to authenticate. | |
| redirect_url=$(curl --silent --show-error \ | |
| --header "Authorization: token $github_oauth_token" \ | |
| --header "Accept: application/octet-stream" \ | |
| --request GET \ | |
| --write-out "%{redirect_url}" \ | |
| "$download_url") | |
| # Finally download the actual binary | |
| sudo curl --silent --show-error \ | |
| --header "Accept: application/octet-stream" \ | |
| --output "$output_path" \ | |
| --request GET \ | |
| "$redirect_url" |
ok. sorry. I have found another optimization. If you pass the filename via xargs, you can bypass that redirect problem. Other than defining the variable names, it becomes a one-liner and it'd look something like this:
curl -sL -H "Authorization: token $github_oauth_token" "https://api.github.com/repos/$github_repo_owner/$github_repo_name/releases/tags/$git_tag" | jq -r '.assets[] | select(.name == "'$release_asset_filename'").url' | xargs -I {} curl -sL -H "Authorization: token $github_oauth_token" -H 'Accept:application/octet-stream' -o $output_path {}
I made a new gist using this method here:
https://gist.github.com/mathew-fleisch/f2e0308eefe974701370f569027a7cfe
If anyone interest, give a try: https://github.com/zero88/gh-release-downloader
Actually, I can't believe I forgot to share here, but we wrote a first-class CLI tool in Go at https://github.com/gruntwork-io/fetch to do exactly what this script does and much more. It's worked well for us so far and seems to have a small, but active community of users.
also, the first curl is paged by 30 releases per page. so if the
$git_tagisn't found in the first page, that curl will return a jq error like thisjq: error (at <stdin>:4): Cannot index string with string "tag_name" jq: error (at <stdin>:4): Cannot iterate over null (null) curl: (3) <url> malformed curl: (3) <url> malformed