|
| 1 | +# Copyright (c) 2022 Nordic Semiconductor ASA |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: Apache-2.0 |
| 4 | + |
| 5 | +''' |
| 6 | +Generic GitHub helper routines which may be useful to other scripts. |
| 7 | +
|
| 8 | +This file is not meant to be run directly, but rather to be imported |
| 9 | +as a module from other scripts. |
| 10 | +''' |
| 11 | + |
| 12 | +# Note that the type annotations are not currently checked by mypy. |
| 13 | +# Unless that changes, they serve as documentation, rather than |
| 14 | +# guarantees from a type checker. |
| 15 | + |
| 16 | +# stdlib |
| 17 | +import getpass |
| 18 | +import os |
| 19 | +import netrc |
| 20 | +import sys |
| 21 | +from typing import Dict |
| 22 | + |
| 23 | +# third party |
| 24 | +import github |
| 25 | + |
| 26 | +def get_github_credentials(ask: bool = True) -> Dict[str, str]: |
| 27 | + '''Get credentials for constructing a github.Github object. |
| 28 | +
|
| 29 | + This function tries to get github.com credentials from these |
| 30 | + places, in order: |
| 31 | +
|
| 32 | + 1. a ~/.netrc file, if one exists |
| 33 | + 2. a GITHUB_TOKEN environment variable |
| 34 | + 3. if the 'ask' kwarg is truthy, from the user on the |
| 35 | + at the command line. |
| 36 | +
|
| 37 | + On failure, RuntimeError is raised. |
| 38 | +
|
| 39 | + Scripts often need credentials because anonym access to |
| 40 | + api.github.com is rate limited more aggressively than |
| 41 | + authenticated access. Scripts which use anonymous access are |
| 42 | + therefore more likely to fail due to rate limiting. |
| 43 | +
|
| 44 | + The return value is a dict which can be passed to the |
| 45 | + github.Github constructor as **kwargs. |
| 46 | +
|
| 47 | + :param ask: if truthy, the user will be prompted for credentials |
| 48 | + if none are found from other sources |
| 49 | + ''' |
| 50 | + |
| 51 | + try: |
| 52 | + nrc = netrc.netrc() |
| 53 | + except (FileNotFoundError, netrc.NetrcParseError): |
| 54 | + nrc = None |
| 55 | + |
| 56 | + if nrc is not None: |
| 57 | + auth = nrc.authenticators('github.com') |
| 58 | + if auth is not None: |
| 59 | + return {'login_or_token': auth[0], 'password': auth[2]} |
| 60 | + |
| 61 | + token = os.environ.get('GITHUB_TOKEN') |
| 62 | + if token: |
| 63 | + return {'login_or_token': token} |
| 64 | + |
| 65 | + if ask: |
| 66 | + print('Missing GitHub credentials:\n' |
| 67 | + '~/.netrc file not found or has no github.com credentials, ' |
| 68 | + 'and GITHUB_TOKEN is not set in the environment. ' |
| 69 | + 'Please give your GitHub token.', |
| 70 | + file=sys.stderr) |
| 71 | + token = getpass.getpass('token: ') |
| 72 | + return {'login_or_token': token} |
| 73 | + |
| 74 | + raise RuntimeError('no credentials found') |
| 75 | + |
| 76 | +def get_github_object(ask: bool = True) -> github.Github: |
| 77 | + '''Get a github.Github object, created with credentials. |
| 78 | +
|
| 79 | + :param ask: passed to get_github_credentials() |
| 80 | + ''' |
| 81 | + return github.Github(**get_github_credentials()) |
0 commit comments