23

I have a repo with binary files in it that I need.

I can

git checkout tags/thetagoftherelease

which seems to checkout the correct tag, but does not pull down the binary files. How can I pull down the binary files that were added to the release (the green boxes on the release)?

Added picture of binary files in a release.

enter image description here

F Lekschas
  • 12,481
  • 10
  • 60
  • 72
Tyler Pfaff
  • 4,900
  • 9
  • 47
  • 62
  • 20
    Down votes with no comments are not helpful – Tyler Pfaff Sep 18 '14 at 23:24
  • *Pull* or *checkout*? Those are two very distinct terms in Git. Also, what "green boxes"? – jub0bs Sep 18 '14 at 23:26
  • Sorry, was using pull colloquially. Green boxes as in, added binary files to a release on git. They show up as green boxes that you can manually download on github. I want to download these added binary files from the release. Checking out the release tag does not give me the binary files. – Tyler Pfaff Sep 18 '14 at 23:30
  • 2
    As I understand it, those releases are a GitHub feature and are not part of your repo. I don't think you can download them from GitHub using Git commands. – jub0bs Sep 18 '14 at 23:34
  • Thanks @Jubobs , I'll accept that as the answer if you post it. – Tyler Pfaff Sep 19 '14 at 00:03

6 Answers6

36

I've tried for days trying to find the proper answer to this, and finally I figured out how to do this via the curl command. It's a 3-step process.

First, to get a list of the assets for the latest release:

curl -H "Authorization: token YOURGITHUBTOKEN" \
    https://api.github.com/repos/NAME/REPO/releases/latest 

Then in the JSON, look up the url of the asset you want. For example it would look like:

"url": "https://api.github.com/repos/NAME/REPO/releases/assets/1275759"

Then you pass this to another curl command to retrieve the actual URL, which is actually a link to an Amazon S3 file.

curl -H "Authorization: token YOURGITHUBTOKEN" \
     -H "Accept:application/octet-stream" \
     -i https://api.github.com/repos/NAME/REPO/releases/assets/1275759

The URL will be in the "location" field of the HTTP response, and then use curl to get the file like this:

curl "https://github-cloud.s3.amazonaws.com...." -i -o FILENAME
legoscia
  • 39,593
  • 22
  • 116
  • 167
Ted
  • 592
  • 6
  • 8
  • 1
    best answer, thanks.Forget curl, use the http://httpie.org (CLI HTTP client, user-friendly curl replacement with intuitive UI, JSON support, syntax highlighting, wget-like downloads, extensions, etc.) – frekele Jul 10 '16 at 17:41
  • 2
    Make sure to use quotes to surround the s3 url. Otherwise curl won't get it apropiately. – Erick A. Montañez Feb 22 '18 at 12:00
  • 1
    What "location field in the HTTP response? Doesn't work for me – decades Aug 30 '22 at 08:43
9

Binary release assets exist outside of Git, and cannot be managed using the standard tools.

They should be available via GitHub's API, though.

  1. List the repository's release assets:

    GET /repos/:owner/:repo/releases/:id/assets
    

    This will send back a JSON document listing the release assets for the repository, e.g.

    [
      {
        "url": "https://api.github.com/repos/octocat/Hello-World/releases/assets/1",
        "browser_download_url": "https://github.com/octocat/Hello-World/releases/download/v1.0.0/example.zip",
        "id": 1,
        "name": "example.zip",
        "label": "short description",
        "state": "uploaded",
        "content_type": "application/zip",
        "size": 1024,
        "download_count": 42,
        "created_at": "2013-02-27T19:35:32Z",
        "updated_at": "2013-02-27T19:35:32Z",
        "uploader": {
          "login": "octocat",
          ...
        }
      }
    ]
    
  2. Retrieve the assts from the release you want, as defined by its id from above:

    GET /repos/:owner/:repo/releases/assets/:id
    

    If you want to download the asset's binary content, pass a media type of "application/octet-stream". The API will either redirect the client to the location, or stream it directly if possible. API clients should handle both a 200 or 302 response.

As documented, these requests are all relative to https://api.github.com.

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
4

One-Step Process:

Here's a one-liner (sans auth) I used in a script to download Digital Ocean's doctl interface from Github. It just grabs the LATEST release and unTARs it:

curl -sL $(curl -s https://api.github.com/repos/digitalocean/doctl/releases/latest | grep "http.*linux-amd64.tar.gz" | awk '{print $2}' | sed 's|[\"\,]*||g') | tar xzvf -

If not using Linux, replace "http.*linux-amd64.tar.gz" in the above with "darwin", "windows", etc and the appropriate arch.

NOTE: The above should work programmatically grabbing binaries from other Github repos, but I've only tested it with doctl. HTH-

F1Linux
  • 3,580
  • 3
  • 25
  • 24
3

This is a mini script to download an asset knowing its file name (can be easily modified to download other assets:

asseturl=$(curl -H "Authorization: token ${token}" https://api.github.com/repos/${repo}/releases/${releaseid}/assets | jq ".[] | select(.name==\"${filename}\") | .url")
curl -L -H "Authorization: token ${token}" -H "Accept:application/octet-stream" $(echo $asseturl | tr -d '"') > ${filename}
  • $token is the access token for github
  • $filename is the filename for the asset
  • $releaseid is the releaseid where the binary file is stored
pglez82
  • 489
  • 5
  • 11
  • if you dont know the `releaseid` you can filter `/repos/{owner}/{repo}/releases` by name with `curl -H "Authorization: token ${token}" https://api.github.com/repos/${owner}/${repo}/releases | jq -r ".[] | select(.name == \"${releasename}\") | .assets[] | select(.name == \"${filename}\") | .url"` – cyrf Oct 11 '21 at 19:24
2

For Ansible, you can use this tasklist (same steps as @ted):

- name: Get latest version
  uri:
    url: "https://api.github.com/repos/{{github_user}}/{{github_repo}}/releases/latest"
    return_content: yes
    headers:
      Authorization: "token {{ vault_github_deploying_token }}"
  register: github_response

- set_fact:
    binary_asset_url: "{{  github_response.json.assets|json_query(query) }}"
  vars:
    query: "[?name=='{{your_github_binary_filename}}'].url | [0]"   

- name: Get Binary asset's location
  uri:
    url: "{{ binary_asset_url }}"
    return_content: no
    follow_redirects: none
    status_code: 302
    headers:
      Authorization: "token {{ vault_github_deploying_token }}"
      Accept: "application/octet-stream"
  register: assets

- name: Download binary
  get_url:
    url: "{{ assets.location }}"
    dest: "/tmp/{{ your_github_binary_filename }}"
    mode: 0755
  • Excellent! For most releases, `your_github_binary_filename` is usually `"{{ github_repo }}.tar.gz"` – M. Davis Jun 11 '18 at 13:39
1

Note that wget cat get it directly by following download link as a browser do.

Rewrite $URL as you need. My convention is to upload with a suffix for binary version.

A sample script:

#!/bin/bash
#
# You can fetch some binary directly from release on github
#
# We encourage to build your own version from source.
#

GIT_USER=me
GIT_PROJECT=project_name
BASE_URL=https://github.com/$GIT_USER/$GIT_PROJECT/releases/download
RELEASE=v0.6.3-alpha1
BINARY=bin_file_on_release

if [[ -e $BINARY ]]
then
  echo "file in the way: '$BINARY' remove it."
  exit 1
fi

if [[ $(getconf LONG_BIT) == "64" ]]
then
    echo "I'm 64-bits"
    URL="$BASE_URL/$RELEASE/$BINARY"
else
    echo "I'm 32-bits"
    URL="$BASE_URL/$RELEASE/${BINARY}-32bits"
fi

set -e
echo "Fetching from: $URL"
wget -q -O $BINARY "$URL"
file $BINARY
chmod a+x $BINARY
Sylvain
  • 336
  • 2
  • 7