Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 83 additions & 1 deletion doctr/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from textwrap import dedent

from .local import (generate_GitHub_token, encrypt_variable, encrypt_file,
upload_GitHub_deploy_key, generate_ssh_key, check_repo_exists, GitHub_login)
upload_GitHub_deploy_key, generate_ssh_key, check_repo_exists, GitHub_login, set_encrypted_variable)
from .travis import (setup_GitHub_push, commit_docs, push_docs,
get_current_repo, sync_from_log, find_sphinx_build_dir, run)
from . import __version__
Expand Down Expand Up @@ -122,6 +122,20 @@ def get_parser(config=None):
deploy_parser = subcommand.add_parser('deploy', help="""Deploy the docs to GitHub from Travis.""")
deploy_parser.set_defaults(func=deploy)
deploy_parser_add_argument = make_parser_with_config_adder(deploy_parser, config)

_user_fork_parser = subcommand.add_parser('fork-deploy', help="""Deploy the docs to GitHub from Travis to the current user fork""")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it use the same command (doctr deploy), so that users can enable it and have it just work with the same .travis.yml as the main repo?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it could also be doctr-configure, but this command have to be run on user machine.
I'm planning on having doctr deploy do automatically the right things is the USER_DEPLOY env variable is set.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, then it should be called doctr configure-fork or something like that. Right now this looks like the deploy command, which gets run on Travis only.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe just doctr configure --fork.

_user_fork_parser.set_defaults(func=enable_fork_build)

_user_fork_parser.add_argument("--no-upload-key", action="store_false", default=True,
dest="upload_key", help="""Don't automatically upload the deploy key to GitHub. If you select this
option, you will not be prompted for your GitHub credentials, so this option is not compatible with
private repositories.""")
_user_fork_parser.add_argument('--token', action='store_true', default=False,
help="""Push to GitHub using a personal access token. Use this if you
used 'doctr configure --token'.""")
_user_fork_parser.add_argument('--force', action='store_true', help="""Run the deploy command even
if we do not appear to be on Travis.""")

deploy_parser_add_argument('--force', action='store_true', help="""Run the deploy command even
if we do not appear to be on Travis.""")
deploy_parser_add_argument('deploy_directory', type=str, nargs='?',
Expand Down Expand Up @@ -388,6 +402,74 @@ def configure(args, parser):
in your .travis.yml.
""".format(encrypted_variable=encrypted_variable.decode('utf-8'), N=N)))

def enable_fork_build(args, parser):
if not args.force and on_travis():
parser.error("doctr appears to be running on Travis. Use "
"doctr configure --force to run anyway.")

if args.upload_key:
login_kwargs = GitHub_login()
else:
login_kwargs = {'auth': None, 'headers': None}

build_repo = input("What repo do you want to build the docs for (<yourname>/reponame, like 'drdoctr/doctr')? ")
is_private = check_repo_exists(build_repo, service='github', **login_kwargs)
check_repo_exists(build_repo, service='travis')

deploy_repo = input("What repo do you want to deploy the docs to? [{build_repo}/<branchname>] ".format(build_repo=build_repo))
if not deploy_repo:
deploy_repo = build_repo

if deploy_repo != build_repo:
check_repo_exists(deploy_repo, service='github', **login_kwargs)

N = IncrementingInt(1)

header = "\n================== You should now do the following ==================\n"

if args.token:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can leave this not implemented if you want. Tokens are less secure (they grant access to all the user's repos), and should really only be used for dedicated bot users (which won't be the case here).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks, I'll clean things up, I'm just prototyping by copy-pasting for now.

pass
#token = generate_GitHub_token(**login_kwargs)['token']
#encrypted_variable = encrypt_variable("GH_TOKEN={token}".format(token=token).encode('utf-8'),
# build_repo=build_repo, is_private=is_private, **login_kwargs)
#print(dedent("""
#A personal access token for doctr has been created.

#You can go to https://github.com/settings/tokens to revoke it."""))

#print(header)
else:
ssh_key = generate_ssh_key("doctr deploy key for {deploy_repo}".format(deploy_repo=deploy_repo), keypath='tmp_key')
import base64
with open('tmp_key', 'rb') as f:
data = ''.join(base64.encodebytes(f.read()).decode().splitlines())
# TODO remove
# key = encrypt_file('tmp_key', delete=True)
set_encrypted_variable("DOCTR_USER_DEPLOY", data, build_repo=build_repo, is_private=True, **login_kwargs)

deploy_keys_url = 'https://github.com/{deploy_repo}/settings/keys'.format(deploy_repo=deploy_repo)

if args.upload_key:

upload_GitHub_deploy_key(deploy_repo, ssh_key, **login_kwargs, title='Doctr key blah blah self deploy of {}'.format(build_repo))

print(dedent("""
The deploy key has been added for {deploy_repo}.

You can go to {deploy_keys_url} to revoke the deploy key.\
""".format(deploy_repo=deploy_repo, deploy_keys_url=deploy_keys_url, keypath='tmp_key')))
print(header)
else:
print(header)
print(dedent("""\
{N}. Go to {deploy_keys_url}
and add the following as a new key:

{ssh_key}
Be sure to allow write access for the key.
""".format(ssh_key=ssh_key, deploy_keys_url=deploy_keys_url, N=N)))


def main():
config = get_config()
return process_args(get_parser(config=config))
Expand Down
58 changes: 58 additions & 0 deletions doctr/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,64 @@
from cryptography.hazmat.primitives import serialization


def set_encrypted_variable(variable, value, build_repo, *, public_key=None, is_private=False, **login_kwargs):
"""
set the env variable `variable` encrypted using travis API.
"""

# if not isinstance(variable, str):
# raise TypeError("variable should be str")
# if not isinstance(variable, str):
# raise TypeError("values should be str")

if not public_key:
headers = {'Accept': 'application/vnd.travis-ci.2+json',
'Content-Type': 'application/json',
'User-Agent': 'MyClient/1.0.0'}
if is_private:
tok_dict = generate_GitHub_token(scopes=["read:org", "user:email", "repo"],
note="temporary token to auth against travis",
**login_kwargs)
data = {'github_token': tok_dict['token']}
token_id = tok_dict['id']
res = requests.post('https://api.travis-ci.org/auth/github', data=json.dumps(data), headers=headers)
res.raise_for_status()
access_token = res.json()['access_token']
headers['Authorization'] = 'token {}'.format(access_token)
print(res.json()['access_token'])
tld = 'org'
else:
tld = 'org'
res = requests.get('https://api.travis-ci.{tld}/repos/{build_repo}'.format(build_repo=build_repo, tld=tld),
headers=headers)
if res.status_code == requests.codes.not_found:
raise RuntimeError('Could not find requested repo on Travis. Is Travis enabled?')
if not res.status_code == requests.codes.ok and is_private:
print('del stuff')
# delete_GitHub_token(token_id, **login_kwargs)
res.raise_for_status()
repo_id = res.json()['repo']['id']
res = requests.post('https://api.travis-ci.{tld}/settings/env_vars?repository_id={repo_id}'.format(repo_id=repo_id, tld=tld),
headers=headers,
data=json.dumps({
'env_var':{
"name": variable,
"value": value,
"public": False,
"repository_id": repo_id
}
}))
if is_private:
pass #delete_GitHub_token(token_id, **login_kwargs)

res.raise_for_status()

# Remove temporary GH token





def encrypt_variable(variable, build_repo, *, public_key=None, is_private=False, **login_kwargs):
"""
Encrypt an environment variable for ``build_repo`` for Travis
Expand Down