|
27 | 27 | from __future__ import print_function |
28 | 28 |
|
29 | 29 | import argparse |
30 | | -from fnmatch import fnmatchcase |
| 30 | +from pathlib import Path |
31 | 31 | import os |
32 | | -from subprocess import run |
33 | 32 | import sys |
34 | 33 |
|
| 34 | +from github_release_retry import github_release_retry as grr |
| 35 | + |
35 | 36 | from commoncode.fileutils import resource_iter |
36 | 37 |
|
37 | | -python_version = str(sys.version_info[0]) + str(sys.version_info[1]) |
38 | | -py_abi = '{0}cp{1}{0}'.format('*', python_version) |
| 38 | + |
| 39 | +""" |
| 40 | +Create GitHUb releases and upload files there. |
| 41 | +This depends on the `github_release_retry` utility |
| 42 | +https://github.com/google/github-release-retry |
| 43 | +""" |
39 | 44 |
|
40 | 45 |
|
41 | | -def release_asset(token, tag, repo, body_string, user, retry_limit, asset_dir): |
| 46 | +def create_or_update_release_and_upload_directory( |
| 47 | + user, |
| 48 | + repo, |
| 49 | + tag_name, |
| 50 | + token, |
| 51 | + directory, |
| 52 | + retry_limit=10, |
| 53 | + description=None |
| 54 | +): |
42 | 55 | """ |
43 | | - Release .whl,.ABOUT,.NOTICE,.LICENSE to github repository(repo) from asset_directory. |
44 | | - It takes user and token as credential and tag_name,body_string for description of |
45 | | - release. By default retry_limit is 10. |
| 56 | + Create or update a GitHub release at https://github.com/<user>/<repo> for |
| 57 | + `tag_name` tag using the optional `description` for this release. |
| 58 | + Use the provided `token` as a GitHub token for API calls authentication. |
| 59 | + Upload all files found in the `directory` tree to that GitHub release. |
| 60 | + Retry API calls up to `retry_limit` time to work around instability the |
| 61 | + GitHub API. |
46 | 62 | """ |
47 | 63 |
|
48 | | - os.environ['GITHUB_TOKEN'] = token |
49 | | - thirdparty = list(resource_iter(asset_dir, with_dirs=False)) |
50 | | - dependencies = [ |
51 | | - files |
52 | | - for files in thirdparty |
53 | | - if fnmatchcase(files, '*py3*') |
54 | | - or fnmatchcase(files, py_abi) |
55 | | - or ( |
56 | | - fnmatchcase(files, '*tar.gz*') |
57 | | - and not fnmatchcase(files, '*py2-ipaddress-3.4.1.tar.gz*') |
58 | | - ) |
59 | | - ] |
60 | | - for deps in dependencies: |
61 | | - github_args = [ |
62 | | - 'python3', |
63 | | - '-m', |
64 | | - 'github_release_retry.github_release_retry', |
65 | | - '--user', |
66 | | - user, |
67 | | - '--repo', |
68 | | - repo, |
69 | | - '--tag_name', |
70 | | - tag, |
71 | | - '--body_string', |
72 | | - body_string, |
73 | | - '--retry_limit', |
74 | | - retry_limit, |
75 | | - deps |
76 | | - ] |
77 | | - run(github_args) |
78 | | - |
79 | | - |
80 | | -def main_with_args(args: str) -> None: |
| 64 | + api = grr.GithubApi( |
| 65 | + github_api_url='https://api.github.com', |
| 66 | + user=user, |
| 67 | + repo=repo, |
| 68 | + token=token, |
| 69 | + retry_limit=retry_limit, |
| 70 | + ) |
| 71 | + release = grr.Release(tag_name=tag_name, body=description) |
| 72 | + files = [Path(r) for r in resource_iter(directory, with_dirs=False)] |
| 73 | + grr.make_release(api, release, files) |
| 74 | + |
| 75 | + |
| 76 | +def main_with_args(args): |
81 | 77 | parser = argparse.ArgumentParser( |
82 | | - description="""Creates a GitHub release (if it does not already exist) and uploads files to the release. |
83 | | -Please pass the GITHUB_TOKEN as an argument. |
84 | | -""", |
85 | | - formatter_class=argparse.RawDescriptionHelpFormatter, |
| 78 | + description=( |
| 79 | + 'Create (or update) a GitHub release and upload all the ' |
| 80 | + 'files of DIRECTORY to that release.' |
| 81 | + ), |
86 | 82 | ) |
87 | 83 |
|
88 | 84 | parser.add_argument( |
89 | 85 | '--user', |
90 | | - help='Required: The GitHub username or organization name in which the repo resides.', |
| 86 | + help='The GitHub username or organization in which the repository resides.', |
91 | 87 | type=str, |
92 | 88 | required=True, |
93 | 89 | ) |
94 | 90 |
|
95 | 91 | parser.add_argument( |
96 | | - '--token', |
97 | | - help='Required: The Github token is required to acess the repository where you want to upload.', |
| 92 | + '--repo', |
| 93 | + help=' The GitHub repository name in which to create the release.', |
98 | 94 | type=str, |
99 | 95 | required=True, |
100 | 96 | ) |
101 | 97 |
|
102 | 98 | parser.add_argument( |
103 | | - '--repo', |
104 | | - help='Required: The GitHub repo name in which to make the release.', |
| 99 | + '--tag-name', |
| 100 | + help='The name of the tag to create (or re-use) for this release.', |
105 | 101 | type=str, |
106 | 102 | required=True, |
107 | 103 | ) |
108 | 104 |
|
109 | 105 | parser.add_argument( |
110 | | - '--tag-name', |
111 | | - help='Required: The name of the tag to create or use.', |
112 | | - type=str, |
113 | | - required=True, |
| 106 | + '--directory', |
| 107 | + help='The directory that contains files to upload to the release.', |
| 108 | + type=str, |
| 109 | + required=True, |
114 | 110 | ) |
115 | 111 |
|
| 112 | + TOKEN_HELP = ( |
| 113 | + 'The Github personal acess token is used to authenticate API calls. ' |
| 114 | + 'Required unless you set the GITHUB_TOKEN environment variable as an alternative. ' |
| 115 | + 'See for details: https://github.com/settings/tokens and ' |
| 116 | + 'https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token' |
| 117 | + ) |
| 118 | + |
116 | 119 | parser.add_argument( |
117 | | - '--body-string', |
118 | | - help='Required : Text describing the release. Ignored if the release already exists.', |
| 120 | + '--token', |
| 121 | + help=TOKEN_HELP, |
119 | 122 | type=str, |
120 | | - required=True, |
| 123 | + required=False, |
121 | 124 | ) |
122 | 125 |
|
123 | 126 | parser.add_argument( |
124 | | - '--retry-limit', |
125 | | - help='The number of times to retry creating/getting the release and/or uploading each file.', |
| 127 | + '--description', |
| 128 | + help='Text description for the release. Ignored if the release exists.', |
126 | 129 | type=str, |
127 | | - default='10', |
| 130 | + required=False, |
128 | 131 | ) |
129 | 132 |
|
130 | 133 | parser.add_argument( |
131 | | - '--directory', |
132 | | - help='Required: The directory that contains files to upload to the release.', |
133 | | - type=str, |
134 | | - required=True, |
| 134 | + '--retry_limit', |
| 135 | + help=( |
| 136 | + 'Number of retries when making failing GitHub API calls. ' |
| 137 | + 'Retrying helps work around transient failures of the GitHub API.' |
| 138 | + ), |
| 139 | + type=int, |
| 140 | + default=10, |
135 | 141 | ) |
136 | 142 |
|
137 | 143 | args = parser.parse_args() |
138 | | - |
139 | | - token = args.token |
140 | | - tag_name = args.tag_name |
141 | | - repo = args.repo |
142 | | - body_string = args.body_string |
143 | | - user = args.user |
144 | | - retry_limit = args.retry_limit |
145 | | - directory = args.directory |
146 | | - |
147 | | - release_asset(token, tag_name, repo, body_string, user, retry_limit, directory) |
| 144 | + token = args.token or os.environ.get('GITHUB_TOKEN', None) |
| 145 | + if not token: |
| 146 | + print('--token required option is missing.') |
| 147 | + print(TOKEN_HELP) |
| 148 | + sys.exit(1) |
| 149 | + |
| 150 | + create_or_update_release_and_upload_directory( |
| 151 | + user=args.user, |
| 152 | + repo=args.repo, |
| 153 | + tag_name=args.tag_name, |
| 154 | + description=args.description, |
| 155 | + retry_limit=args.retry_limit, |
| 156 | + token=token, |
| 157 | + directory=args.directory, |
| 158 | + ) |
148 | 159 |
|
149 | 160 |
|
150 | | -def main() -> None: |
| 161 | +def main(): |
151 | 162 | main_with_args(sys.argv[1:]) |
152 | 163 |
|
153 | 164 |
|
|
0 commit comments