This project aims at streamlining the distribution of releases on Github.
I made it because it sucks to have to download a file from a server, only to upload it to Github from the desktop.
It also sucks to download a file from github to your desktop, and then SCP it to a server.
This thing works nicely from an SSH session.
-- @j0057 on Wednesday, August 13, 2014
from the command-line:
# create a prerelease
$ githubrelease release jcfr/sandbox create 1.0.0 --prerelease
# upload assets
$ githubrelease asset jcfr/sandbox upload 1.0.0 "dist/*"
# publish the release
$ githubrelease release jcfr/sandbox publish 1.0.0
# or all together: create with custom name, upload assets, and publish
$ githubrelease release jcfr/sandbox create 2.0.0 --publish --name "Awesome 2.0" "dist/*"
... or even from python:
from github_release import gh_release_create
gh_release_create("jcfr/sandbox ", "2.0.0", publish=True, name="Awesome 2.0", asset_pattern="dist/*")
That said, if you are looking for a full fledged GitHub API support for Python, you should probably look into project like github3py or PyGithub
- githubrelease
- examples
- features
- installing
- configuring
- using the cli
- using the module
- testing
- maintainers: how to make a release ?
- license
- create release, pre-release, or draft release
- update any release metadata including referenced commit
- support wildcard expression (or list of wildcard expressions):
- for upload or download of assets
- for selectively deleting assets
- report download and upload progress
- allow deleting individual asset from a release
- retry upload in case of server failure
- gracefully handle release with invalid assets (the ones with new state)
- authentication through
GITHUB_TOKEN
environment variable or~/.netrc
file - pure python, only depends on requests and click
Released stable version can be installed from pypi using:
pip install githubrelease
Bleeding edge version can be installed using:
pip intall githubrelease -f https://github.com/j0057/github-release/releases/tag/latest
First, generate a new token. It
should have at least the repo
scope.
Then, there are three options:
- Set the
GITHUB_TOKEN
environment variable:
export GITHUB_TOKEN=YOUR_TOKEN
/path/to/command
- Pass the
--github-token
CLI argument. For example:
$ githubrelease --github-token YOUR_TOKEN release jcfr/sandbox create --prerelease 1.0.0
- Put the key in
~/.netrc
, which should have mode 0600 (-rw-------
):
machine api.github.com
login YOUR_TOKEN
password x-oauth-basic
machine uploads.github.com
login YOUR_TOKEN
password x-oauth-basic
where YOUR_TOKEN
should be replaced with the generated token.
The package installs one CLI named githubrelease
.
$ githubrelease
Usage: githubrelease [OPTIONS] COMMAND [ARGS]...
A CLI to easily manage GitHub releases, assets and references.
Options:
--github-token TEXT [default: GITHUB_TOKEN env. variable]
--progress / --no-progress Display progress bar (default: yes).
--help Show this message and exit.
Commands:
asset Manage release assets (upload, download, ...)...
ref Manage references (list, create, delete, ...)...
release Manage releases (list, create, delete, ...)...
Run 'githubrelease COMMAND --help' for more information on a command.
For backward compatibility, it also installs github-release
and github-asset
This command deals with releases. The general usage is:
githubrelease release username/reponame command [tag] [options]
It understands the following commands:
command | parameters | description |
---|---|---|
list | list all releases | |
info | tagname | list one release |
create | tagname [options] | create a release |
edit | tagname [options] | Edit a release |
delete | tagname | delete a release |
publish | tagname [--prerelease] | make release public |
unpublish | tagname [--prerelease] | make release draft |
release-notes | tagname | use $EDITOR to edit release notes |
Optional parameters:
- create:
--name NAME
--body BODY
--publish
--prerelease
--target-commitish TARGET_COMMITISH
--help
[ASSET_PATTERN]...
- edit:
--tag-name TAG_NAME
--target-commitish TARGET_COMMITISH
--name NAME
--body BODY
--draft/--publish
--prerelease/--release
--dry-run
--verbose
--help
- delete:
--keep-pattern KEEP_PATTERN
--type [all, draft, prerelease, release]
--older-than HOURS
--dry-run
--verbose
--help
[ASSET_PATTERN]...
This command deals with release assets. The general usage is:
githubrelease asset username/reponame command [tag] [filename] [options]
It understands the following commands:
command | parameters | description |
---|---|---|
list | list all assets | |
upload | tagname filename... | upload files to a release |
download | download all files from all releases to current directory | |
download | tagname | download all files from a release to current directory |
download | tagname filename | download file to current directory |
delete | tagname filename [options] | delete a file from a release |
Optional parameters:
- delete:
--keep-pattern KEEP_PATTERN
Remarks:
When specifying filenames, shell-like wildcards are supported, but make sure to quote using single quotes, i.e. don't let the shell expand the wildcard pattern.
For the download
command, you also need to specify a tagname of '*'
Examples:
# upload all example-project-1.4* files in /home/me/pkg
$ githubrelease asset octocat/example-project upload 1.4 '/home/me/pkg/example-project-1.4*'
# download all wheels from all releases
$ githubrelease asset octocat/example-project download '*' '*.whl'
# download all files from release 1.4
$ githubrelease asset octocat/example-project download 1.4
# download all files from example-project
$ githubrelease asset octocat/example-project download
This command deals with git references. The general usage is:
githubrelease ref username/reponame command [options]
It understands the following commands:
command | parameters | description |
---|---|---|
create | ref sha | create reference (e.g heads/foo, tags/foo) |
list | [--tags] [--pattern PATTERN] | list all references |
delete | pattern [--tags] [--keep-pattern KEEP_PATTERN] | delete selected references |
The python API mirrors the command-line interface. Most of the available function names follows this pattern:
gh_<COMMAND>_<COMMAND>
where the first <COMMAND>
is either release
,
asset
or ref
and the second one is any command respectively
documented above.
The parameters accepted by each function also mirrors the command-line interface. The usual signature is:
gh_<COMMAND>_<COMMAND>(repo_name, [param, [param,]] [option, [option]])
For example, here is the signature for gh_release_create
:
def gh_release_create(repo_name, tag_name,
name=None, publish=False, prerelease=False, target_commitish=None):
The type of each parameters or options can usually be inferred from its name. If not, consider looking at github_release.py.
repo_name -> str
tag_name -> str
name -> str
publish -> bool
prerelease -> bool
target_commitish -> str
There are tests running automatically on TravisCI:
- coding style checks
- integration tests
Since the integration tests are expecting GITHUB_TOKEN
to be set, they will
NOT be executed when pull request from fork are submitted. Indeed, setting
GITHUB_TOKEN
is required by the tests to reset and update github-release-bot/github-release-test-py2
and github-release-bot/github-release-test-py3.
To execute the integration tests locally, and make sure your awesome contribution is working as expected, you will have to:
- create a test repository with at least one commit (e.g
yourname/github-release-test
) - set environment variable
INTEGRATION_TEST_REPO_NAME=yourname/github-release-test
- execute
python setup.py test
To execute a specific test, the following also works:
export GITHUB_TOKEN=YOUR_TOKEN
export INTEGRATION_TEST_REPO_NAME=yourname/github-release-test
$ pytest tests/test_integration_release_create.py::test_create_release
Moving forward, the plan would be to leverage tools like betamax allowing to intercept every request made and attempting to find a matching request that has already been intercepted and recorded.
-
Configure
~/.pypirc
as described here. -
Make sure the cli and module work as expected.
-
Choose the next release version number:
release="X.Y.Z"
-
Review CHANGES.md, replace Next Release into X.Y.Z, commit and push. Consider using
[ci skip]
in commit message:sed -i -e "s/Next Release/${release}/" CHANGES.md sed -i -e "s/============/=====/" CHANGES.md git add CHANGES.md git commit -m "CHANGES.md: Replace \"Next Release\" with \"${release}\" [ci skip] "
Review commit, then push:
git push origin master
-
Tag the release. Requires a GPG key with signatures:
git tag -s -m "githubrelease ${release}" ${release} origin/master
And push:
git push origin ${release}
-
Create the source tarball and binary wheels:
rm -rf dist/ python setup.py sdist bdist_wheel
-
Upload the packages to the testing PyPI instance:
twine upload --sign -r pypitest dist/*
-
Check the PyPI testing package page.
-
Upload the packages to the PyPI instance::
twine upload --sign dist/*
-
Check the PyPI package page.
-
Create a virtual env, and make sure the package can be installed:
mkvirtualenv test-githubrelease-install pip install githubrelease
-
Create github release and upload packages:
export GITHUB_TOKEN=YOUR_TOKEN githubrelease release j0057/github-release create ${release} --name ${release} --publish ./dist/*
-
Update release notes by copying relevant content from CHANGES.md
export EDITOR=vim githubrelease release j0057/github-release release-notes ${release}
-
Cleanup
deactivate rmvirtualenv test-githubrelease-install
And update
CHANGES.md
:sed -i '1i Next Release\n============\n' CHANGES.md git add CHANGES.md git commit -m "Begin ${release} development * CHANGES.md: Add \"Next Release\" section [ci skip] " git push origin master
-
Why do I get a
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url https://api.github.com/repos/...
?It probably means that the GitHub token you specified is invalid.
Written by Joost Molenaar (@j0057) and Jean-Christophe Fillion-Robin (@jcfr)
It is covered by the Apache License, Version 2.0:
http://www.apache.org/licenses/LICENSE-2.0
The license file was added at revision 0393859 on 2017-02-12, but you may consider that the license applies to all prior revisions as well.