diff --git a/github_deploy/__init__.py b/github_deploy/__init__.py index 0260537..8db66d3 100644 --- a/github_deploy/__init__.py +++ b/github_deploy/__init__.py @@ -1 +1 @@ -__path__ = __import__('pkgutil').extend_path(__path__, __name__) \ No newline at end of file +__path__ = __import__("pkgutil").extend_path(__path__, __name__) diff --git a/github_deploy/commands/__init__.py b/github_deploy/commands/__init__.py index 0260537..8db66d3 100644 --- a/github_deploy/commands/__init__.py +++ b/github_deploy/commands/__init__.py @@ -1 +1 @@ -__path__ = __import__('pkgutil').extend_path(__path__, __name__) \ No newline at end of file +__path__ = __import__("pkgutil").extend_path(__path__, __name__) diff --git a/github_deploy/commands/_http_utils.py b/github_deploy/commands/_http_utils.py new file mode 100644 index 0000000..d736fe7 --- /dev/null +++ b/github_deploy/commands/_http_utils.py @@ -0,0 +1,64 @@ +import ssl +import certifi + +import asyncclick as click + +from github_deploy.commands._constants import REPOS_URL + + +async def get(*, session, url, headers=None, skip_missing=False): + ssl_context = ssl.create_default_context(cafile=certifi.where()) + + async with session.get( + url, + headers=headers, + timeout=70, + ssl_context=ssl_context, + raise_for_status=not skip_missing, + ) as response: + if skip_missing and response.status == 404: + return {} + + value = await response.json() + return value + + +async def put(*, session, url, data, headers=None): + ssl_context = ssl.create_default_context(cafile=certifi.where()) + + async with session.put( + url, + json=data, + headers=headers, + timeout=70, + ssl_context=ssl_context, + raise_for_status=True, + ) as response: + value = await response.json() + return value + + +async def delete(*, session, url, data, headers=None): + ssl_context = ssl.create_default_context(cafile=certifi.where()) + + async with session.delete( + url, + json=data, + headers=headers, + timeout=70, + ssl_context=ssl_context, + raise_for_status=True, + ) as response: + value = await response.json() + return value + + +async def list_repos(*, session, org, token): + headers = { + "Authorization": "token {token}".format(token=token), + "Accept": "application/vnd.github.v3+json", + } + url = REPOS_URL.format(org=org) + click.echo("Retrieving repos at {}".format(url)) + response = await get(session=session, url=url, headers=headers) + return response diff --git a/github_deploy/commands/_utils.py b/github_deploy/commands/_utils.py index 67cdb6b..109bd3f 100644 --- a/github_deploy/commands/_utils.py +++ b/github_deploy/commands/_utils.py @@ -3,4 +3,8 @@ def get_repo(*, org, project): def can_upload(*, repo, include_private): - return True if include_private and repo['private'] == True else not repo['private'] + return ( + True + if include_private and repo["private"] is True + else not repo["private"] + ) diff --git a/github_deploy/commands/delete.py b/github_deploy/commands/delete.py index f85c9c0..8ead88e 100644 --- a/github_deploy/commands/delete.py +++ b/github_deploy/commands/delete.py @@ -1,46 +1,13 @@ import asyncio -import ssl import aiohttp import asyncclick as click -import certifi -from github_deploy.commands._constants import BASE_URL, REPOS_URL +from github_deploy.commands._constants import BASE_URL +from github_deploy.commands._http_utils import delete, get, list_repos from github_deploy.commands._utils import get_repo -async def get(*, session, url, headers=None, skip_missing=False): - ssl_context = ssl.create_default_context(cafile=certifi.where()) - - async with session.get( - url, - headers=headers, - timeout=70, - ssl_context=ssl_context, - raise_for_status=not skip_missing, - ) as response: - if skip_missing and response.status == 404: - return {} - - value = await response.json() - return value - - -async def delete(*, session, url, data, headers=None): - ssl_context = ssl.create_default_context(cafile=certifi.where()) - - async with session.delete( - url, - json=data, - headers=headers, - timeout=70, - ssl_context=ssl_context, - raise_for_status=True, - ) as response: - value = await response.json() - return value - - async def delete_content( *, session, @@ -63,7 +30,9 @@ async def delete_content( url = BASE_URL.format(repo=repo, path=dest) async with semaphore: - response = await delete(session=session, url=url, data=data, headers=headers) + response = await delete( + session=session, url=url, data=data, headers=headers + ) return response @@ -74,15 +43,16 @@ async def check_exists(*, session, repo, dest, token, semaphore, skip_missing): async with semaphore: response = await get( - session=session, url=url, headers=headers, skip_missing=skip_missing + session=session, + url=url, + headers=headers, + skip_missing=skip_missing, ) return response -async def handle_file_delete( - *, repo, dest, token, semaphore, session -): +async def handle_file_delete(*, repo, dest, token, semaphore, session): check_exists_response = await check_exists( session=session, repo=repo, @@ -114,7 +84,7 @@ async def handle_file_delete( exists=exists, current_sha=current_sha, ) - + if delete_response: return click.style( "Successfully deleted contents at {repo}/{dest}".format( @@ -124,7 +94,7 @@ async def handle_file_delete( fg="green", bold=True, ) - + return click.style( "No content found at {repo}/{dest}".format(repo=repo, dest=dest), fg="blue", @@ -132,17 +102,6 @@ async def handle_file_delete( ) -async def list_repos(*, session, org, token): - headers = { - "Authorization": "token {token}".format(token=token), - "Accept": "application/vnd.github.v3+json", - } - url = REPOS_URL.format(org=org) - click.echo("Retrieving repos at {}".format(url)) - response = await get(session=session, url=url, headers=headers) - return response - - @click.command() @click.option( "--org", @@ -154,7 +113,7 @@ async def list_repos(*, session, org, token): prompt=click.style("Enter your personal access token", bold=True), help="Personal Access token with read and write access to org.", hide_input=True, - envvar='TOKEN', + envvar="TOKEN", ) @click.option( "--dest", @@ -178,11 +137,18 @@ async def main(org, token, dest): ] click.echo( click.style( - "Found '{}' repositories non archived repositories".format(len(repos)), + "Found '{}' repositories non archived repositories".format( + len(repos) + ), fg="green", ) ) - click.echo(click.style('Deleting "{path}" for all repositories:'.format(path=dest), fg="blue")) + click.echo( + click.style( + 'Deleting "{path}" for all repositories:'.format(path=dest), + fg="blue", + ) + ) click.echo("\n".join(repos)) c = click.prompt(click.style("Continue? [YN] ", fg="blue")) diff --git a/github_deploy/commands/upload.py b/github_deploy/commands/upload.py index 47d453c..fe58e6d 100644 --- a/github_deploy/commands/upload.py +++ b/github_deploy/commands/upload.py @@ -1,48 +1,15 @@ import asyncio import base64 -import ssl import aiofiles import aiohttp import asyncclick as click -import certifi -from github_deploy.commands._constants import BASE_URL, REPOS_URL +from github_deploy.commands._constants import BASE_URL +from github_deploy.commands._http_utils import put, list_repos, get from github_deploy.commands._utils import get_repo, can_upload -async def get(*, session, url, headers=None, skip_missing=False): - ssl_context = ssl.create_default_context(cafile=certifi.where()) - - async with session.get( - url, - headers=headers, - timeout=70, - ssl_context=ssl_context, - raise_for_status=not skip_missing, - ) as response: - if skip_missing and response.status == 404: - return {} - - value = await response.json() - return value - - -async def put(*, session, url, data, headers=None): - ssl_context = ssl.create_default_context(cafile=certifi.where()) - - async with session.put( - url, - json=data, - headers=headers, - timeout=70, - ssl_context=ssl_context, - raise_for_status=True, - ) as response: - value = await response.json() - return value - - async def upload_content( *, session, @@ -70,7 +37,9 @@ async def upload_content( return data = { - "message": "Updated {}".format(dest) if exists else "Added {}".format(dest), + "message": "Updated {}".format(dest) + if exists + else "Added {}".format(dest), "content": base64_content, } if exists: @@ -79,7 +48,9 @@ async def upload_content( url = BASE_URL.format(repo=repo, path=dest) async with semaphore: - response = await put(session=session, url=url, data=data, headers=headers) + response = await put( + session=session, url=url, data=data, headers=headers + ) return response @@ -90,7 +61,10 @@ async def check_exists(*, session, repo, dest, token, semaphore, skip_missing): async with semaphore: response = await get( - session=session, url=url, headers=headers, skip_missing=skip_missing + session=session, + url=url, + headers=headers, + skip_missing=skip_missing, ) return response @@ -120,7 +94,7 @@ async def handle_file_upload( path=dest, ), fg="blue", - bold=True + bold=True, ) else: @@ -154,21 +128,10 @@ async def handle_file_upload( dest=upload_response["content"]["path"], ), fg="green", - bold=True + bold=True, ) -async def list_repos(*, session, org, token): - headers = { - "Authorization": "token {token}".format(token=token), - "Accept": "application/vnd.github.v3+json", - } - url = REPOS_URL.format(org=org) - click.echo("Retrieving repos at {}".format(url)) - response = await get(session=session, url=url, headers=headers) - return response - - @click.command() @click.option( "--org", @@ -180,7 +143,7 @@ async def list_repos(*, session, org, token): prompt=click.style("Enter your personal access token", bold=True), help="Personal Access token with read and write access to org.", hide_input=True, - envvar='TOKEN', + envvar="TOKEN", ) @click.option( "--source", @@ -195,7 +158,9 @@ async def list_repos(*, session, org, token): ) @click.option( "--overwrite/--no-overwrite", - prompt=click.style("Should we overwrite existing contents at this path", fg="blue"), + prompt=click.style( + "Should we overwrite existing contents at this path", fg="blue" + ), help="Overwrite existing files.", default=False, ) @@ -217,12 +182,15 @@ async def main(org, token, source, dest, overwrite, private): repos = [ get_repo(org=org, project=r["name"]) for r in response["items"] - if not r["archived"] and can_upload(repo=r, include_private=private) + if not r["archived"] + and can_upload(repo=r, include_private=private) ] - repo_type = 'public and private' if private else 'public' + repo_type = "public and private" if private else "public" click.echo( click.style( - "Found '{}' repositories non archived {} repositories:".format(len(repos), repo_type), + "Found '{}' repositories non archived {} repositories:".format( + len(repos), repo_type + ), fg="green", ) ) @@ -238,11 +206,12 @@ async def main(org, token, source, dest, overwrite, private): ) ) deploy_msg = ( - 'Deploying "{source}" to "{path}" for all repositories'.format(source=source, path=dest) + 'Deploying "{source}" to "{path}" for all repositories'.format( + source=source, path=dest + ) if overwrite else 'Deploying "{source}" to repositories that don\'t already have contents at "{path}"'.format( - source=source, - path=dest + source=source, path=dest ) ) click.echo(click.style(deploy_msg, fg="blue")) diff --git a/github_deploy/main.py b/github_deploy/main.py index 8322d65..c7cce59 100644 --- a/github_deploy/main.py +++ b/github_deploy/main.py @@ -1,35 +1,41 @@ import asyncclick as click import os -plugin_folder = os.path.join(os.path.dirname(__file__), 'commands') +plugin_folder = os.path.join(os.path.dirname(__file__), "commands") class GithubDeploy(click.MultiCommand): - def list_commands(self, ctx): rv = [] for filename in os.listdir(plugin_folder): - if filename.endswith('.py') and not filename.startswith('__init__') and not filename.startswith('_'): + if ( + filename.endswith(".py") + and not filename.startswith("__init__") + and not filename.startswith("_") + ): rv.append(filename[:-3]) rv.sort() return rv def get_command(self, ctx, name): ns = {} - fn = os.path.join(plugin_folder, name + '.py') + fn = os.path.join(plugin_folder, name + ".py") if os.path.exists(fn): with open(fn) as f: - code = compile(f.read(), fn, 'exec') + code = compile(f.read(), fn, "exec") eval(code, ns, ns) - return ns['main'] + return ns["main"] ctx.fail("Invalid Command \"{name}\"".format(name=name)) main = GithubDeploy( - help='Deploy changes to multiple github repositories using a single command.', + help=( + "Deploy changes to multiple github repositories using " + "a single command." + ), ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/setup.py b/setup.py index 2df1eab..5369b06 100644 --- a/setup.py +++ b/setup.py @@ -34,12 +34,18 @@ "gh-deploy=github_deploy.main:main", ], }, - keywords=["yaml", "deploy", "poly repository", "github", "single configuration"], + keywords=[ + "yaml", + "deploy", + "poly repository", + "github", + "single configuration", + ], author="Tonye Jack", author_email="jtonye@ymail.com", license="MIT", packages=find_packages(), - python_requires='>=3.6', + python_requires=">=3.6", extras_require=extras_require, install_requires=[ "asyncclick",
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: