Repository: drdoctr/doctr

Issue:
Catch exception if travis isn't set up
Just caught this when I tried to regenerate the deploy key without first enabling travis

Key generation went fine but then requests barfed when it couldn't talk to travis

```console
Traceback (most recent call last):
  File "/home/gil/anaconda/bin/doctr", line 9, in <module>
    load_entry_point('doctr==1.1.1+42.g9c5359b', 'console_scripts', 'doctr')()
  File "/home/gil/anaconda/lib/python3.5/site-packages/doctr-1.1.1+42.g9c5359b-py3.5.egg/doctr/__main__.py", line 210, in main
    return process_args(get_parser())
  File "/home/gil/anaconda/lib/python3.5/site-packages/doctr-1.1.1+42.g9c5359b-py3.5.egg/doctr/__main__.py", line 96, in process_args
    return args.func(args, parser)
  File "/home/gil/anaconda/lib/python3.5/site-packages/doctr-1.1.1+42.g9c5359b-py3.5.egg/doctr/__main__.py", line 153, in configure
    encrypted_variable = encrypt_variable(b"DOCTR_DEPLOY_ENCRYPTION_KEY=" + key, build_repo=build_repo)
  File "/home/gil/anaconda/lib/python3.5/site-packages/doctr-1.1.1+42.g9c5359b-py3.5.egg/doctr/local.py", line 45, in encrypt_variable
    r.raise_for_status()
  File "/home/gil/anaconda/lib/python3.5/site-packages/requests/models.py", line 837, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://api.travis-ci.org/repos/drdoctr/doctr/key
```

We can just catch this exception and gently remind the user to go to travis and enable the repository

Comments:

Patch:
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 87ee43d7..37c7e2f1 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -17,6 +17,7 @@ Minor Changes
 -------------
 - Add a GitHub banner to the docs. (#64)
 - Move to the GitHub organization `drdoctr <https://github.com/drdoctr>`_. (#67)
+- Check if user/org and repo are valid before generating ssh keys or pinging travis (#77)
 
 1.1.1 (2016-08-09)
 ==================
diff --git a/doctr/__init__.py b/doctr/__init__.py
index b5afeea2..a0c84a61 100644
--- a/doctr/__init__.py
+++ b/doctr/__init__.py
@@ -1,5 +1,6 @@
 from .local import (encrypt_variable, encrypt_file, GitHub_post,
-    generate_GitHub_token, upload_GitHub_deploy_key, generate_ssh_key)
+    generate_GitHub_token, upload_GitHub_deploy_key, generate_ssh_key,
+    check_repo_exists)
 from .travis import (decrypt_file, setup_deploy_key, get_token, run,
     setup_GitHub_push, gh_pages_exists, create_gh_pages, sync_from_log,
     commit_docs, push_docs, get_current_repo, find_sphinx_build_dir)
@@ -7,6 +8,7 @@ from .travis import (decrypt_file, setup_deploy_key, get_token, run,
 __all__ = [
     'encrypt_variable', 'encrypt_file', 'GitHub_post',
     'generate_GitHub_token', 'upload_GitHub_deploy_key', 'generate_ssh_key',
+    'check_repo_exists',
 
     'decrypt_file', 'setup_deploy_key', 'get_token', 'run', 'setup_GitHub_push', 'gh_pages_exists',
     'create_gh_pages', 'sync_from_log', 'commit_docs', 'push_docs', 'get_current_repo', 'find_sphinx_build_dir'
diff --git a/doctr/__main__.py b/doctr/__main__.py
index ab10378e..0e19d118 100644
--- a/doctr/__main__.py
+++ b/doctr/__main__.py
@@ -28,7 +28,7 @@ import argparse
 from textwrap import dedent
 
 from .local import (generate_GitHub_token, encrypt_variable, encrypt_file,
-    upload_GitHub_deploy_key, generate_ssh_key)
+    upload_GitHub_deploy_key, generate_ssh_key, check_repo_exists)
 from .travis import setup_GitHub_push, commit_docs, push_docs, get_current_repo
 from . import __version__
 
@@ -135,6 +135,8 @@ def configure(args, parser):
     if not deploy_repo:
         deploy_repo = build_repo
 
+    check_repo_exists(deploy_repo)
+
     N = IncrementingInt(1)
 
     header = "\n================== You should now do the following ==================\n"
diff --git a/doctr/local.py b/doctr/local.py
index 16a58ac9..8213044d 100644
--- a/doctr/local.py
+++ b/doctr/local.py
@@ -2,12 +2,12 @@
 The code that should be run locally
 """
 
-from getpass import getpass
-import base64
+import os
 import json
 import uuid
+import base64
 import subprocess
-import os
+from getpass import getpass
 
 import requests
 from requests.auth import HTTPBasicAuth
@@ -39,9 +39,10 @@ def encrypt_variable(variable, build_repo, public_key=None):
         raise ValueError("variable should be of the form 'VARIABLE=value'")
 
     if not public_key:
-        # TODO: Error handling
         r = requests.get('https://api.travis-ci.org/repos/{build_repo}/key'.format(build_repo=build_repo),
             headers={'Accept': 'application/vnd.travis-ci.2+json'})
+        if r.status_code == requests.codes.not_found:
+            raise RuntimeError('Could not find requested repo on Travis.  Is Travis enabled?')
         r.raise_for_status()
         public_key = r.json()['key']
 
@@ -172,3 +173,18 @@ def generate_ssh_key(note, keypath='github_deploy_key'):
 
     with open(keypath + ".pub") as f:
         return f.read()
+
+def check_repo_exists(deploy_repo):
+    """Checks that the deploy repository exists on GitHub before allowing
+    user to generate a key to deploy to that repo.
+    """
+    user, repo = deploy_repo.split('/')
+    search = 'https://api.github.com/search/repositories?q={repo}+user:{user}'
+    r = requests.get(search.format(user=user, repo=repo))
+
+    if r.status_code == requests.codes.unprocessable_entity:
+        raise RuntimeError('User/org "{user}" not found on GitHub.  Exiting'.format(user=user))
+    elif not r.json()['items']:
+        raise RuntimeError('No repo named "{repo}" found for user/org "{user}"'.format(repo=repo, user=user))
+
+    return True


Test patch:
diff --git a/doctr/tests/test_local.py b/doctr/tests/test_local.py
new file mode 100644
index 00000000..3a3d9455
--- /dev/null
+++ b/doctr/tests/test_local.py
@@ -0,0 +1,14 @@
+from ..local import check_repo_exists
+
+from pytest import raises
+
+def test_bad_user():
+    with raises(RuntimeError):
+        check_repo_exists('---/invaliduser')
+
+def test_bad_repo():
+    with raises(RuntimeError):
+        check_repo_exists('drdoctr/---')
+
+def test_repo_exists():
+    assert check_repo_exists('drdoctr/doctr')