Repository: deis/deis

Issue:
feat(client): add --buildpack flag to `deis create`
Similar to Heroku, we should allow users to set the buildpack URL during `deis create`.



Discussion:

Resolving patch:
diff --git a/client/deis.py b/client/deis.py
--- a/client/deis.py
+++ b/client/deis.py
@@ -444,6 +444,9 @@ def apps_create(self, args):
         Options:
           --no-remote
             do not create a `deis` git remote.
+
+          -b --buildpack BUILDPACK
+            a buildpack url to use for this app
         """
         body = {}
         app_name = None
@@ -464,31 +467,36 @@ def apps_create(self, args):
         finally:
             progress.cancel()
             progress.join()
-        if response.status_code == requests.codes.created:
-            data = response.json()
-            app_id = data['id']
-            self._logger.info("done, created {}".format(app_id))
-            # set a git remote if necessary
-            try:
-                self._session.git_root()
-            except EnvironmentError:
-                return
-            hostname = urlparse.urlparse(self._settings['controller']).netloc.split(':')[0]
-            git_remote = "ssh://git@{hostname}:2222/{app_id}.git".format(**locals())
-            if args.get('--no-remote'):
-                self._logger.info('remote available at {}'.format(git_remote))
-            else:
-                try:
-                    subprocess.check_call(
-                        ['git', 'remote', 'add', '-f', 'deis', git_remote],
-                        stdout=subprocess.PIPE)
-                    self._logger.info('Git remote deis added')
-                except subprocess.CalledProcessError:
-                    self._logger.error('Could not create Deis remote')
-                    sys.exit(1)
-        else:
+        if response.status_code != requests.codes.created:
             raise ResponseError(response)
 
+        data = response.json()
+        app_id = data['id']
+        self._logger.info("done, created {}".format(app_id))
+
+        buildpack = args.get('--buildpack')
+        if buildpack:
+            self._config_set(app_id, {'BUILDPACK_URL': buildpack})
+
+        # set a git remote if necessary
+        try:
+            self._session.git_root()
+        except EnvironmentError:
+            return
+        hostname = urlparse.urlparse(self._settings['controller']).netloc.split(':')[0]
+        git_remote = "ssh://git@{hostname}:2222/{app_id}.git".format(**locals())
+        if args.get('--no-remote'):
+            self._logger.info('remote available at {}'.format(git_remote))
+        else:
+            try:
+                subprocess.check_call(
+                    ['git', 'remote', 'add', '-f', 'deis', git_remote],
+                    stdout=subprocess.PIPE)
+                self._logger.info('Git remote deis added')
+            except subprocess.CalledProcessError:
+                self._logger.error('Could not create Deis remote')
+                sys.exit(1)
+
     def apps_destroy(self, args):
         """
         Destroys an application.
@@ -1028,7 +1036,14 @@ def config_set(self, args):
         app = args.get('--app')
         if not app:
             app = self._session.app
-        body = {'values': json.dumps(dictify(args['<var>=<value>']))}
+        values = dictify(args['<var>=<value>'])
+        self._config_set(app, values)
+
+    def _config_set(self, app, values):
+        """
+        Internal logic to set environment variables for an application.
+        """
+        body = {'values': json.dumps(values)}
         sys.stdout.write('Creating config... ')
         sys.stdout.flush()
         try:


Test patch:
diff --git a/tests/apps_test.go b/tests/apps_test.go
--- a/tests/apps_test.go
+++ b/tests/apps_test.go
@@ -11,14 +11,15 @@ import (
 )
 
 var (
-	appsCreateCmd         = "apps:create {{.AppName}}"
-	appsCreateCmdNoRemote = "apps:create {{.AppName}} --no-remote"
-	appsListCmd           = "apps:list"
-	appsRunCmd            = "apps:run echo hello"
-	appsOpenCmd           = "apps:open --app={{.AppName}}"
-	appsLogsCmd           = "apps:logs --app={{.AppName}}"
-	appsInfoCmd           = "apps:info --app={{.AppName}}"
-	appsDestroyCmd        = "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
+	appsCreateCmd          = "apps:create {{.AppName}}"
+	appsCreateCmdNoRemote  = "apps:create {{.AppName}} --no-remote"
+	appsCreateCmdBuildpack = "apps:create {{.AppName}} --buildpack https://example.com"
+	appsListCmd            = "apps:list"
+	appsRunCmd             = "apps:run echo hello"
+	appsOpenCmd            = "apps:open --app={{.AppName}}"
+	appsLogsCmd            = "apps:logs --app={{.AppName}}"
+	appsInfoCmd            = "apps:info --app={{.AppName}}"
+	appsDestroyCmd         = "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
 )
 
 func randomString(n int) string {
@@ -56,9 +57,11 @@ func appsCreateTest(t *testing.T, params *utils.DeisTestConfig) {
 	if err := utils.Chdir(params.ExampleApp); err != nil {
 		t.Fatal(err)
 	}
-	cmd := appsCreateCmd
-	utils.Execute(t, cmd, params, false, "")
-	utils.Execute(t, cmd, params, true, "App with this Id already exists")
+	// TODO: move --buildpack to client unit tests
+	utils.Execute(t, appsCreateCmdBuildpack, params, false, "BUILDPACK_URL")
+	utils.Execute(t, appsDestroyCmd, params, false, "")
+	utils.Execute(t, appsCreateCmd, params, false, "")
+	utils.Execute(t, appsCreateCmd, params, true, "App with this Id already exists")
 }
 
 func appsDestroyTest(t *testing.T, params *utils.DeisTestConfig) {