Github¶
A wrapper for Github’s APIs and a collection of scripts.
In order to use it, one needs to give it an authentication token. The token is usually given using the GITHUB_API_TOKEN environmental variable. You can optionally initialize the API with a given token:
>>> from skare3_tools import github
>>> github.init(token='c7hvg6pqi3fhqwv0wvlgp4mk9agwbqk1gxc331iz') # this is optional
REST Interface (V3)¶
A thin wrapper for Github’s REST API (V3).
It is intended to be easy to extend. It does not impose much structure on top of what is shown in their online documentation, and it should be easy to see the correspondence between both.
As an example, this is how one gets a list of releases and pull requests for a repository:
>>> from skare3_tools import github
>>> repo = github.Repository('sot/Chandra.Maneuver')
>>> releases = repo.releases()
>>> for release in releases:
... print(release['name'])
Release 3.7.2
Release 3.7.1 with one test fix for 32 bit platform compat.
Version 3.7
Version 0.6
Version 0.05
>>> prs = repo.pull_requests.create(title='Make namespace package native',
... head='namespace',
... base='master',
... body='The description goes here')
>>> prs = repo.pull_requests()
>>> for pr in prs:
... print(f"PR #{pr['number']}: {pr['title']}")
PR #1: Make namespace package native
It is also possible to use the API directly, in case there is no appropriate high-level method:
>>> from skare3_tools import github
>>> last_tag = github.GITHUB_API_V3.get('/repos/sot/Chandra.Maneuver/releases/latest').json()
>>> last_tag['tag_name']
'3.7.2'
Getting and Editing Content¶
Getting content:
>>> from skare3_tools.github import github
>>> r = github.Repository('sot/test-actions')
>>> c = r.contents('README.md')
>>> c['content']
'# test-actions\n\nA realistic package with which to test GitHub actions...'
Editing content:
>>> from skare3_tools.github import github
>>> r = github.Repository('sot/test-actions')
>>> content = """
... # test-actions
...
... A realistic package with which to test GitHub actions and play around.
... """
>>> r.contents.edit('README.md', message='changing readme', content=content)
Repository Dispatch¶
A typical use is to dispatch an event to cause an action. For example, the docs for some repositories are deployed when a repository_dispatch event of type ‘build-docs’ is triggered. This can be seen in the corresponding workflow:
name: Deploy Docs
on:
repository_dispatch:
types:
- build-docs
In this case, one can do:
>>> from skare3_tools import github
>>> r = github.Repository('sot/skare3_tools') # changing the repository name accordingly!
>>> r.dispatch_event(event_type='build-docs')
GraphQL Interface (V4)¶
This is a thin wrapper for Github’s GraphQL API (V4).
This module does not build the query for you. This is because the possibilities afforded by GraphQL are large and it makes no sense to re-invent them. The easiest way to assemble a new query is to use Github’s GraphQL Explorer. For example, to get the homepage URL of a repository:
>>> from skare3_tools.github import graphql
>>> query = """{
... repository(name: "test-actions", owner: "sot") {
... homepageUrl
... id
... }
... }"""
>>> response = graphql.GITHUB_API(query)
>>> response
{'data': {'repository': {'homepageUrl': None,
'id': 'MDEwOlJlcG9zaXRvcnkyMDkwMjE1NDQ='}}}
and to set the homepage URL of a repository:
>>> from skare3_tools.github import graphql
>>> query = """mutation {
... updateRepository(input: {repositoryId: "MDEwOlJlcG9zaXRvcnkyMDkwMjE1NDQ=",
... homepageUrl: "https://github.com/sot/test-actions"})
... {
... repository {
... id
... homepageUrl
... }
... }
... }
... """
>>> response = graphql.GITHUB_API(query)
>>> response
{'data': {'updateRepository': {'repository': {'id': 'MDEwOlJlcG9zaXRvcnkyMDkwMjE1NDQ=',
'homepageUrl': 'https://github.com/sot/test-actions'}}}}
Given the flexibility of the GraphQL interface, this module includes a small collection of common queries. Each query in the collection is a string that should be used as a jinja2 template. For example, to get a list all pull requests of a repository:
>>> import jinja2
>>> from skare3_tools.github import graphql
>>> query = jinja2.Template(graphql.REPO_PR_QUERY).render(owner='sot', name='Quaternion')
>>> response = graphql.GITHUB_API(query)
>>> response['data']['repository']['pullRequests']['nodes'][0]
{'baseRefName': 'master',
'headRefName': 'modernize',
'title': 'Add delta quaternion method and other package modernization',
'number': 2,
'state': 'MERGED'}
THere is a (possibly incomplete) list of queries (with the template parameters in parentheses):
REPO_ISSUES_QUERY(name, owner, label)
REPO_PR_QUERY(name, owner)
ORG_QUERY(owner)
REPO_QUERY(owner, name)
Github Scripts¶
Some of these scripts are superseded by Github’s own CLI, while some provide functionality specific to Ska. At the very least, the exemplify the usage of the API.
skare3-create-issue¶
Create a github issue
usage: skare3-create-issue [-h] --repository REPOSITORY
[--latest-release LATEST_RELEASE] [--title TITLE]
[--body BODY] [--label LABEL] [--token TOKEN]
Named Arguments¶
- --repository
repository name. Example: sot/chandra_aca
- --latest-release
Repository name (owner/repo). The latest release of this repodetermines the title and body of issue. Title/body are ignored.
- --title
Issue Title. Ignored if –latest-release is given
- --body
Issue Description. Ignored if –latest-release is given
- --label
Default: []
- --token, -t
Github token, or name of file that contains token
skare3-create-pr¶
Create a pull request
usage: skare3-create-pr [-h] --repository REPOSITORY --title TITLE --head HEAD
--base BASE --body BODY [--token TOKEN]
Named Arguments¶
- --repository
repository name. Example: sot/chandra_aca
- --title
- --head
branch you are merging from
- --base
branch you are merging to
- --body
- --token, -t
Github token, or name of file that contains token
skare3-merge-pr¶
Create a pull request
usage: __main__.py [-h] --repository REPOSITORY [--pull-number PULL_NUMBER]
[--head HEAD] [--base BASE] [--commit-title COMMIT_TITLE]
[--commit-message COMMIT_MESSAGE] [--sha SHA]
[--merge-method MERGE_METHOD] [--token TOKEN]
Named Arguments¶
- --repository
repository name. Example: sot/chandra_aca
- --pull-number
pull number
- --head
branch you are merging from
- --base
branch you are merging to
- --commit-title
Optional. Filled from PR.
- --commit-message
Optional. Filled from PR.
- --sha
SHA that pull request head must match to allow merge.
- --merge-method
Merge method to use. Possible values are merge, squash or rebase.
- --token, -t
Github token, or name of file that contains token
skare3-release-merge-info¶
skare3-add-secrets¶
A script to add encrypted secrets to Github repositories.
At some point, Github’s API did not have an endpoint for setting secrets. This script circumvented this limitation by using Selenium with Python together with ChromeDriver <https://sites.google.com/a/chromium.org/chromedriver>. While this is not strictly needed anymore, it is left because it is an example on how to deal with cases like this.
To use it, you need to have Chrome installed, install Selenium, and you need to get a version of ChromeDriver matching your Chrome version. I suppose it could work with other browsers but I have not tried it.
A valid YAML file looks like this:
SECRET_NAME: the secret value
- SECRET_TWO: |
another value asdf
usage: skare3-add-secrets [-h] [--secrets SECRETS] --user USER [--no-quit]
repositories [repositories ...]
Positional Arguments¶
- repositories
Named Arguments¶
- --secrets
JSON file with all secrets
Default: “secrets.json”
- --user
Github user name
- --no-quit
Do not close chrome browser at the end
Default: True