Skip to content

Commit

Permalink
Merge 8dd3844 into 7121a2d
Browse files Browse the repository at this point in the history
  • Loading branch information
grampajoe committed Feb 22, 2015
2 parents 7121a2d + 8dd3844 commit 6455a5c
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 6 deletions.
5 changes: 5 additions & 0 deletions README.rst
Expand Up @@ -75,6 +75,11 @@ happy can find it later.
logged in through Heroku CLI, i.e. your token is stored in your ``netrc``
file.

- ``--env``

(optional) Environment variable overrides, e.g. ``--env KEY=value``. For
multiple variables, this option can be passed more than once.

- ``--tarball-url``

(optional) URL of the tarball containing app.json. If this is not given,
Expand Down
5 changes: 3 additions & 2 deletions happy/__init__.py
Expand Up @@ -15,13 +15,14 @@ def __init__(self, auth_token=None):
"""
self._api = Heroku(auth_token=auth_token)

def create(self, tarball_url):
def create(self, tarball_url, env=None):
"""Creates a Heroku app-setup build.
:param tarball_url: URL of a tarball containing an ``app.json``.
:param env: Dict containing environment variable overrides.
:returns: A tuple with ``(build_id, app_name)``.
"""
data = self._api.create_build(tarball_url=tarball_url)
data = self._api.create_build(tarball_url=tarball_url, env=env)

return (data['id'], data['app']['name'])

Expand Down
12 changes: 10 additions & 2 deletions happy/cli.py
Expand Up @@ -52,19 +52,27 @@ def cli():
@cli.command(name='up')
@click.option('--tarball-url', help='URL of the tarball containing app.json.')
@click.option('--auth-token', help='Heroku API auth token.')
def up(tarball_url, auth_token):
@click.option('--env', multiple=True, help='Env override, e.g. KEY=value.')
def up(tarball_url, auth_token, env):
"""Brings up a Heroku app."""
tarball_url = tarball_url or _infer_tarball_url()

if not tarball_url:
click.echo('No tarball URL found.')
sys.exit(1)

if env:
# Split ["KEY=value", ...] into {"KEY": "value", ...}
env = {
arg.split('=')[0]: arg.split('=')[1]
for arg in env
}

happy = Happy(auth_token=auth_token)

click.echo('Creating app... ', nl=False)

build_id, app_name = happy.create(tarball_url=tarball_url)
build_id, app_name = happy.create(tarball_url=tarball_url, env=env)

click.echo(app_name)

Expand Down
6 changes: 5 additions & 1 deletion happy/heroku.py
Expand Up @@ -66,10 +66,11 @@ def api_request(self, method, endpoint, data=None, *args, **kwargs):

return response.json()

def create_build(self, tarball_url):
def create_build(self, tarball_url, env=None):
"""Creates an app-setups build. Returns response data as a dict.
:param tarball_url: URL of a tarball containing an ``app.json``.
:param env: Dict containing environment variable overrides.
:returns: Response data as a ``dict``.
"""
data = {
Expand All @@ -78,6 +79,9 @@ def create_build(self, tarball_url):
}
}

if env:
data['overrides'] = {'env': env}

return self.api_request('POST', '/app-setups', data=data)

def check_build_status(self, build_id):
Expand Down
20 changes: 20 additions & 0 deletions tests/test_cli.py
Expand Up @@ -96,6 +96,26 @@ def test_up_no_tarball_url(happy, runner):
assert 'no tarball' in result.output.lower()


def test_up_env(happy, runner):
"""Running up --env should pass environment overrides."""
with runner.isolated_filesystem():
runner.invoke(cli, [
'up',
'--env',
'FART=test',
'--env',
'BUTT=wow',
'--tarball-url=example.com',
])

args_, kwargs = happy().create.call_args

assert kwargs['env'] == {
'FART': 'test',
'BUTT': 'wow',
}


def test_up_writes_app_name(happy, runner):
"""Running up should write the app name to .happy."""
with runner.isolated_filesystem():
Expand Down
15 changes: 14 additions & 1 deletion tests/test_happy.py
Expand Up @@ -39,7 +39,20 @@ def test_create(heroku, happy):
"""Should create an app build on Heroku."""
happy.create(tarball_url='tarball-url')

heroku().create_build.assert_called_with(tarball_url='tarball-url')
heroku().create_build.assert_called_with(
env=None,
tarball_url='tarball-url',
)


def test_create_env(heroku, happy):
"""Should pass env overrides to Heroku.create_build."""
happy.create(tarball_url='tarball-url', env={'TEST': 'env'})

heroku().create_build.assert_called_with(
tarball_url='tarball-url',
env={'TEST': 'env'},
)


def test_create_returns_app_name(heroku, happy):
Expand Down
17 changes: 17 additions & 0 deletions tests/test_heroku.py
Expand Up @@ -124,6 +124,23 @@ def test_heroku_create_build(api_request):
assert result == fake_json


@mock.patch.object(Heroku, 'api_request')
def test_heroku_create_build_env(api_request):
"""Heroku.create_build should send a POST to /app-setups."""
heroku = Heroku()

result = heroku.create_build('tarball-url', env={'HELLO': 'world'})

api_request.assert_called_with(
'POST',
'/app-setups',
data={
'source_blob': {'url': 'tarball-url'},
'overrides': {'env': {'HELLO': 'world'}},
},
)


@mock.patch.object(Heroku, 'api_request')
def test_heroku_check_build_status(api_request):
"""Heroku.check_build_status should send a GET to /app-setups/:id."""
Expand Down

0 comments on commit 6455a5c

Please sign in to comment.