Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Script to upload a release asset using the GitHub API v3.
#!/usr/bin/env bash
#
# Author: Stefan Buck
# License: MIT
# https://gist.github.com/stefanbuck/ce788fee19ab6eb0b4447a85fc99f447
#
#
# This script accepts the following parameters:
#
# * owner
# * repo
# * tag
# * filename
# * github_api_token
#
# Script to upload a release asset using the GitHub API v3.
#
# Example:
#
# upload-github-release-asset.sh github_api_token=TOKEN owner=stefanbuck repo=playground tag=v0.1.0 filename=./build.zip
#
# Check dependencies.
set -e
xargs=$(which gxargs || which xargs)
# Validate settings.
[ "$TRACE" ] && set -x
CONFIG=$@
for line in $CONFIG; do
eval "$line"
done
# Define variables.
GH_API="https://api.github.com"
GH_REPO="$GH_API/repos/$owner/$repo"
GH_TAGS="$GH_REPO/releases/tags/$tag"
AUTH="Authorization: token $github_api_token"
WGET_ARGS="--content-disposition --auth-no-challenge --no-cookie"
CURL_ARGS="-LJO#"
if [[ "$tag" == 'LATEST' ]]; then
GH_TAGS="$GH_REPO/releases/latest"
fi
# Validate token.
curl -o /dev/null -sH "$AUTH" $GH_REPO || { echo "Error: Invalid repo, token or network issue!"; exit 1; }
# Read asset tags.
response=$(curl -sH "$AUTH" $GH_TAGS)
# Get ID of the asset based on given filename.
eval $(echo "$response" | grep -m 1 "id.:" | grep -w id | tr : = | tr -cd '[[:alnum:]]=')
[ "$id" ] || { echo "Error: Failed to get release id for tag: $tag"; echo "$response" | awk 'length($0)<100' >&2; exit 1; }
# Upload asset
echo "Uploading asset... "
# Construct url
GH_ASSET="https://uploads.github.com/repos/$owner/$repo/releases/$id/assets?name=$(basename $filename)"
curl "$GITHUB_OAUTH_BASIC" --data-binary @"$filename" -H "Authorization: token $github_api_token" -H "Content-Type: application/octet-stream" $GH_ASSET
@WesleyBatista

This comment has been minimized.

Copy link

commented Feb 8, 2018

Didn't tried your snippet, but $localAssetPath is not defined. It should work? maybe you meant $filename

@babelouest

This comment has been minimized.

Copy link

commented Feb 13, 2018

That's a very cool script, can you add a license to it so I could reuse it on other projects?

Thanks in advance

@stefanbuck

This comment has been minimized.

Copy link
Owner Author

commented Feb 14, 2018

@babelouest License added, thanks for the hint.

@WesleyBatista Good spot. I removed $localAssetPath, it's not really needed

@huxingyi

This comment has been minimized.

Copy link

commented Apr 15, 2018

Thanks @stefanbuck, very convenient script.

And for those who want overwrite the asset with the same filename:

… …

# Read asset tags.
response=$(curl -sH "$AUTH" $GH_TAGS)

# !!! Change start from here until the end !!!

# Get ID of the release.
eval $(echo "$response" | grep -m 1 "id.:" | grep -w id | tr : = | tr -cd '[[:alnum:]]=')
[ "$id" ] || { echo "Error: Failed to get release id for tag: $tag"; echo "$response" | awk 'length($0)<100' >&2; exit 1; }
release_id="$id"

# Get ID of the asset based on given filename.
id=""
eval $(echo "$response" | grep -C1 "name.:.\+$filename" | grep -m 1 "id.:" | grep -w id | tr : = | tr -cd '[[:alnum:]]=')
assert_id="$id"
if [ "$assert_id" = "" ]; then
    echo "No need to overwrite asset"
else
    echo "Deleting asset($assert_id)... "
    curl "$GITHUB_OAUTH_BASIC" -X "DELETE" -H "Authorization: token $github_api_token" "https://api.github.com/repos/$owner/$repo/releases/assets/$assert_id"
fi

# Upload asset
echo "Uploading asset... "

# Construct url
GH_ASSET="https://uploads.github.com/repos/$owner/$repo/releases/$release_id/assets?name=$(basename $filename)"

curl "$GITHUB_OAUTH_BASIC" --data-binary @"$filename" -H "Authorization: token $github_api_token" -H "Content-Type: application/octet-stream" $GH_ASSET

@zhanghongtong

This comment has been minimized.

Copy link

commented Nov 2, 2018

I tried uploading the file using upload_url but it didn't work.

$ echo "uploading asset to release to url : $upload_url"
uploading asset to release to url : https://uploads.github.com/repos/zhanghongtong/test-trello/releases/13626806/assets?client_id=559b37ca1dfdad45d224&client_secret=a39a8fd8b5a2ce54eaa07axxxxxxxxxxxxxx

$ curl -s  \
        -H "Content-Type: application/zip" \
        --data-binary @test.zip  \
        "$upload_url&name=test.zip&label=some-binary.zip"
{"message":"Not Found","request_id":"F743:6DD1:903D2:CCF7E:5BDBAE02","documentation_url":"https://developer.github.com/v3"}%

Any idea what is going sour here?

@pjheslin

This comment has been minimized.

Copy link

commented Apr 13, 2019

Brilliant! This is just what I needed. Thanks. I do get a message saying "curl: (3) malformed" whenever I run it, but that doesn't seem to interfere with its functioning.

@anandchakru

This comment has been minimized.

Copy link

commented Aug 6, 2019

What is basename ?

Edit: Nevermind, basename reduced the full path of the file to just filename.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.