How to release a build artifact asset on GitHub with a script?

I am trying to figure out a one-command process for generating a build on GitHub.

What I anticipate doing is running some sort of command- make release, say, and the make release script builds up the release artifact and then uploads it to GitHub in some fashion.

However, I'm fairly confused about how to actually get a release artifact on GitHub. Source code is awesome, but not everyone wants to do their own builds. :-)


Update September 2013, you can automate a release (API in preview mode)

Update January 2014, there's an unofficial command-line app, called github-release by Nicolas Hillegeer (aktau), for creating releases and uploading (binary) artifacts.
It uses the new github releases API mentioned above. Look at the Makefile of the project to see how to automate it more still.

Example:

# create a formal release
$ github-release release \
    --user aktau \
    --repo gofinance \
    --tag v0.1.0 \
    --name "the wolf of source street" \
    --description "Not a movie, contrary to popular opinion. Still, my first release!" \
    --pre-release

This API is a little different due to the binary assets. We use the Accept header for content negotation when requesting a release asset.
Pass a standard API media type to get the API representation:

$ curl -i -H "Authorization: token TOKEN" \
     -H "Accept: application/vnd.github.manifold-preview" \
     "https://uploads.github.com/repos/hubot/singularity/releases/assets/123"

HTTP/1.1 200 OK

{
  "id": 123,
...
}

Pass “application/octet-stream” to download the binary content.

$ curl -i -H "Authorization: token TOKEN" \
     -H "Accept: application/octet-stream" \
     "https://uploads.github.com/repos/hubot/singularity/releases/assets/123"

HTTP/1.1 302 Found

Uploads are handled by a single request to a companion “uploads.github.com” service.

$ curl -H "Authorization: token TOKEN" \
     -H "Accept: application/vnd.github.manifold-preview" \
     -H "Content-Type: application/zip" \
     --data-binary @build/mac/package.zip \
     "https://uploads.github.com/repos/hubot/singularity/releases/123/assets?name=1.0.0-mac.zip"

Update 2d July 2013, you now can define a release.

release

  • Releases are accompanied by release notes and links to download the software or source code.
  • Following the conventions of many Git projects, releases are tied to Git tags. You can use an existing tag, or let releases create the tag when it's published.
  • You can also attach binary assets (such as compiled executables, minified scripts, documentation) to a release. Once published, the release details and assets are available to anyone that can view the repository.

This is what replaces the old binary upload service, which was removed in December 2012!


the make release script builds up the release artifact and then uploads it to github in some fashion.

That would mean adding it ("it" being the delivery made of one or several files, generally including binaries) to a regular local repo, and then pushing that repo to its matching GitHub repo.

That being said, the reason GitHub isn't mention in any "release" task is because Git is a source control management system, and is ill-suited for binaries.

It can have those files (binaries) of course, but isn't made to have them regularly, because of the bloated size of the repo after a while: each cloning would take longer and longer.
See What are the Git limits, and also "git - should source files and repository be on the same machine ?".


Preparation:

1) Download github-releases and put its executable in your PATH.
2) Create a token at https://github.com/settings/applications#personal-access-tokens let's say abc123

Uploading an artifact:

1) Let's say you have just compiled what you decide to call version 3.1, and want to upload it.
2) Make sure you have committed everything.
3) Run these five commands:

git tag v3.1
git push
git push --tags

github-release release --security-token abc123 --user <you> --repo <yourrepo> \
    --tag v3.1

github-release upload --security-token abc123 --user <you> --repo <yourrepo> \
    --tag v3.1 --name <thefile> --file <thefile>

You can upload several files, for instance for different operating systems.

(Based on VonC's answer, which unfortunately does not detail how to upload an artifact)


hub official Go-based GitHub CLI tool

https://github.com/github/hub

First install Go. On Ubuntu: https://askubuntu.com/questions/959932/installation-instructions-for-golang-1-9-into-ubuntu-16-04/1075726#1075726

Then install hub:

go get github.com/github/hub

There is no Ubuntu package: https://github.com/github/hub/issues/718

Then from inside your repo:

hub release create -a prebuilt.zip -m 'release title' tag-name

This:

  • prompts for your password the first time, and then automatically creates and stores an API token locally
  • creates a non annotated tag on the remote called tag-name
  • creates a release associated to that tag
  • uploads prebuilt.zip as an attachment

You can also provide your existing API token with the GITHUB_TOKEN environment variable.

For other release operations, see:

hub release --help

Tested on hub de684cb613c47572cc9ec90d4fd73eef80aef09c.

Python APIv3 upload example without any external dependencies

Usage:

GITHUB_TOKEN=<token> ./create-release username/reponame <tag-name> <path-to-upload>

Script:

#!/usr/bin/env python3

import json
import os
import sys

from urllib.parse import urlencode
from urllib.request import Request, urlopen

repo = sys.argv[1]
tag = sys.argv[2]
upload_file = sys.argv[3]

token = os.environ['GITHUB_TOKEN']
url_template = 'https://{}.github.com/repos/' + repo + '/releases'

# Create.
_json = json.loads(urlopen(Request(
    url_template.format('api'),
    json.dumps({
        'tag_name': tag,
        'name': tag,
        'prerelease': True,
    }).encode(),
    headers={
        'Accept': 'application/vnd.github.v3+json',
        'Authorization': 'token ' + token,
    },
)).read().decode())
# This is not the tag, but rather some database integer identifier.
release_id = _json['id']

# Upload.
with open(upload_file, 'br') as myfile:
    content = myfile.read()
_json = json.loads(urlopen(Request(
    url_template.format('uploads') + '/' + str(release_id) + '/assets?' \
      + urlencode({'name': os.path.split(upload_file)[1]}),
    content,
    headers={
        'Accept': 'application/vnd.github.v3+json',
        'Authorization': 'token ' + token,
        'Content-Type': 'application/zip',
    },
)).read().decode())

Both release and asset creation will fail with 422 if they already exist. Work around that by first deleting the release or asset. Here is an example.


If you use Maven, you can add GitHub's Downloads Maven Plugin ( https://github.com/github/maven-plugins/#downloads-plugin ) and simply do:

$ mvn clean install ghDownloads:upload