{"action":"created","comment":{"url":"https://api.github.com/repos/databricks/databricks-cli/pulls/comments/202846314","pull_request_review_id":137622204,"id":202846314,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwMjg0NjMxNA==","diff_hunk":"@@ -0,0 +1,354 @@\n+# Databricks CLI\n+# Copyright 2018 Databricks, Inc.\n+#\n+# Licensed under the Apache License, Version 2.0 (the \"License\"), except\n+# that the use of services to which certain application programming\n+# interfaces (each, an \"API\") connect requires that the user first obtain\n+# a license for the use of the APIs from Databricks, Inc. (\"Databricks\"),\n+# by creating an account at www.databricks.com and agreeing to either (a)\n+# the Community Edition Terms of Service, (b) the Databricks Terms of\n+# Service, or (c) another written agreement between Licensee and Databricks\n+# for the use of the APIs.\n+#\n+# You may not use this file except in compliance with the License.\n+# You may obtain a copy of the License at\n+#\n+#    http://www.apache.org/licenses/LICENSE-2.0\n+#\n+# Unless required by applicable law or agreed to in writing, software\n+# distributed under the License is distributed on an \"AS IS\" BASIS,\n+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+# See the License for the specific language governing permissions and\n+# limitations under the License.\n+\n+import os\n+import json\n+from datetime import datetime\n+import time\n+import copy\n+\n+import click\n+\n+from databricks_cli.jobs.api import JobsApi\n+from databricks_cli.version import version as CLI_VERSION\n+from databricks_cli.stack.exceptions import StackError\n+\n+MS_SEC = 1000\n+\n+# Resource Services\n+JOBS_SERVICE = 'jobs'\n+\n+# Config Outer Fields\n+STACK_NAME = 'name'\n+STACK_RESOURCES = 'resources'\n+STACK_DEPLOYED = 'deployed'\n+\n+# Resource Fields\n+RESOURCE_ID = 'id'\n+RESOURCE_SERVICE = 'service'\n+RESOURCE_PROPERTIES = 'properties'\n+\n+# Deployed Resource Fields\n+RESOURCE_PHYSICAL_ID = 'physical_id'\n+RESOURCE_DEPLOY_OUTPUT = 'deploy_output'\n+RESOURCE_DEPLOY_TIMESTAMP = 'timestamp'\n+CLI_VERSION_KEY = 'cli_version'\n+\n+\n+class StackApi(object):\n+    def __init__(self, api_client):\n+        self.jobs_client = JobsApi(api_client)\n+\n+    def deploy(self, config_path):  # overwrite to be added\n+        \"\"\"\n+        Deploys a stack given stack JSON configuration template at path config_path.\n+\n+        Loads the JSON template as well as status JSON if stack has been deployed before.\n+        Changes working directory to the same directory as where the config file is, then\n+        calls on deploy_config to do the stack deployment. Finally stores the new status\n+        file from the deployment.\n+\n+        :param config_path: Path to stack JSON configuration template. Must have the fields of\n+        'name', the name of the stack and 'resources', a list of stack resources.\n+        :return: None.\n+        \"\"\"\n+        config_dir = os.path.dirname(os.path.abspath(config_path))\n+        cli_cwd = os.getcwd()\n+        os.chdir(config_dir)  # Switch current working directory to where json config is stored\n+        try:\n+            stack_config = self._load_json(config_path)\n+            status_path = self._generate_stack_status_path(config_path)\n+            stack_status = self._load_json(status_path)\n+            new_stack_status = self.deploy_config(stack_config, stack_status)\n+\n+            self._save_json(status_path, new_stack_status)\n+            os.chdir(cli_cwd)\n+        except Exception:\n+            # For any exception during deployment, set cwd back to what it was.\n+            os.chdir(cli_cwd)\n+            raise\n+\n+    def deploy_config(self, stack_config, stack_status=None):\n+        \"\"\"\n+        Deploys a stack given stack JSON configuration template at path config_path.\n+\n+        After going through each of the resources and deploying them, stores status JSON\n+        of deployment with deploy status of each resource deployment.\n+        For each resource deployment, stack_status is used to get the associated resource status\n+        of a resource from the last deployment.\n+\n+        :param stack_config: Must have the fields of\n+        'name', the name of the stack and 'resources', a list of stack resources.\n+        :param stack_status: Must have the fields of\n+        :return:\n+        \"\"\"\n+        self._validate_config(stack_config)\n+        if stack_status:\n+            self._validate_status(stack_status)\n+            resource_id_to_status = self._get_resource_to_status_map(stack_status)\n+        else:\n+            resource_id_to_status = {}\n+\n+        stack_name = stack_config[STACK_NAME]\n+        click.echo('Deploying stack %s' % stack_name)\n+        resource_statuses = []\n+\n+        for resource_config in stack_config[STACK_RESOURCES]:\n+            click.echo()\n+            click.echo(\"Deploying resource\")\n+            # Retrieve resource deployment info from the last deployment.\n+            resource_map_key = (resource_config[RESOURCE_ID], resource_config[RESOURCE_SERVICE])\n+            resource_status = resource_id_to_status[resource_map_key] \\\n+                if resource_map_key in resource_id_to_status else None\n+            # Deploy resource, get resource_status\n+            new_resource_status = self._deploy_resource(resource_config, resource_status)\n+            resource_statuses.append(new_resource_status)\n+\n+        # stack deploy status is original config with deployed resource statuses added\n+        new_stack_status = copy.deepcopy(stack_config)\n+        new_stack_status.update({STACK_DEPLOYED: resource_statuses})\n+        new_stack_status.update({CLI_VERSION_KEY: CLI_VERSION})\n+\n+        # Validate that the status has been created correctly\n+        self._validate_status(new_stack_status)\n+\n+        return new_stack_status\n+\n+    def _deploy_resource(self, resource_config, resource_status=None):  # overwrite to be added\n+        \"\"\"\n+        Deploys a resource given a resource information extracted from the stack JSON configuration\n+        template.\n+\n+        :param resource_config: A dict of the resource with fields of RESOURCE_ID, RESOURCE_SERVICE\n+        and RESOURCE_PROPERTIES.\n+        ex. {'id': 'example-resource', 'service': 'jobs', 'properties': {...}}\n+        :param resource_status: A dict of the resource's deployment info from the last\n+        deployment. Will be None if this is the first deployment.\n+        ex. {'id': 'example-resource', 'service': 'jobs', 'physical_id': {...}}\n+        :return: dict resource_status- A dictionary of deployment information of the\n+        resource to be stored at deploy time. It includes the resource id of the resource along\n+        with the physical id and deploy output of the resource.\n+        ex. {'id': 'example-resource', 'service': 'jobs', 'physical_id': {'job_id': 123},\n+        'timestamp': 123456789, 'deploy_output': {..}}\n+        \"\"\"\n+        resource_id = resource_config[RESOURCE_ID]\n+        resource_service = resource_config[RESOURCE_SERVICE]\n+        resource_properties = resource_config[RESOURCE_PROPERTIES]\n+        physical_id = resource_status[RESOURCE_PHYSICAL_ID] if resource_status else None\n+\n+        if resource_service == JOBS_SERVICE:\n+            click.echo(\"Deploying job '%s' with properties: \\n%s \\n\" % (resource_id, json.dumps(\n+                resource_properties, indent=2, separators=(',', ': '))), nl=False)\n+            physical_id, deploy_output = self._deploy_job(resource_properties,\n+                                                          physical_id)\n+        else:\n+            raise StackError(\"Resource service '%s' not supported\" % resource_service)\n+\n+        new_resource_status = {RESOURCE_ID: resource_id, RESOURCE_SERVICE: resource_service,\n+                               RESOURCE_DEPLOY_TIMESTAMP: datetime.now(),\n+                               RESOURCE_PHYSICAL_ID: physical_id,\n+                               RESOURCE_DEPLOY_OUTPUT: deploy_output}\n+        return new_resource_status\n+\n+    def _deploy_job(self, resource_properties, physical_id=None):\n+        \"\"\"\n+        Deploys a job resource by either creating a job if the job isn't kept track of through\n+        the physical_id of the job or updating an existing job. The job is created or updated using\n+        the the settings specified in the inputted job_settings.\n+\n+        :param resource_properties: A dict of the Databricks JobSettings data structure\n+        :param physical_id: A dict object containing 'job_id' field of job identifier in Databricks\n+        server\n+\n+        :return: tuple of (physical_id, deploy_output), where physical_id contains a 'job_id' field\n+        of the physical job_id of the job on databricks. deploy_output is the output of the job\n+        from databricks when a GET request is called for it.\n+        \"\"\"\n+        job_settings = resource_properties  # resource_properties of jobs are solely job settings.\n+\n+        if physical_id:\n+            job_id = physical_id['job_id']\n+            self._update_job(job_settings, physical_id['job_id'])\n+        else:\n+            job_id = self._put_job(job_settings)\n+        click.echo(\"Job deployed on Databricks with job_id %s\" % job_id)\n+        physical_id = {'job_id': job_id}\n+        deploy_output = self.jobs_client.get_job(job_id)\n+        return physical_id, deploy_output\n+\n+    def _put_job(self, job_settings):\n+        \"\"\"\n+        Given settings of the job in job_settings, create a new job. For purposes of idempotency\n+        and to reduce leaked resources in alpha versions of stack deployment, if a job exists\n+        with the same name, that job will be updated. If multiple jobs are found with the same name,\n+        the deployment will abort.\n+\n+        :param job_settings:\n+        :return: job_id, Physical ID of job on Databricks server.\n+        \"\"\"\n+        if 'name' not in job_settings:\n+            raise StackError(\"Please supply 'name' in job resource 'resource_properties'\")\n+        job_name = job_settings['name']\n+        jobs_same_name = self.jobs_client._list_jobs_by_name(job_name)\n+        if len(jobs_same_name) > 1:\n+            raise StackError(\"Multiple jobs with the same name '%s' already exist, aborting\"\n+                             \" stack deployment\" % job_name)\n+        elif len(jobs_same_name) == 1:\n+            existing_job = jobs_same_name[0]\n+            creator_name = existing_job['creator_user_name']\n+            timestamp = existing_job['created_time'] / MS_SEC  # Convert to readable date.\n+            date_created = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')\n+            click.echo(\"Warning: Job exists with same name '%s' created by %s on %s. Job will \"\n+                       \"be overwritten\" % (job_name, creator_name, date_created))\n+            click.echo(\"Updating Job\")\n+            # Calling jobs_client.reset_job directly so as to not call same level function.\n+            self.jobs_client.reset_job({'job_id': existing_job['job_id'],\n+                                        'new_settings': job_settings})\n+            return existing_job['job_id']\n+        else:\n+            click.echo(\"Creating new job\")\n+            job_id = self.jobs_client.create_job(job_settings)['job_id']\n+            return job_id\n+\n+    def _update_job(self, job_settings, job_id):\n+        \"\"\"\n+        Given job settings and an existing job_id of a job, update the job settings on databricks.\n+\n+        :param job_settings: job settings to update the job with.\n+        :param job_id: physical job_id of job in databricks server.\n+        \"\"\"\n+        click.echo(\"Updating Job\")\n+        self.jobs_client.reset_job({'job_id': job_id, 'new_settings': job_settings})\n+\n+    def _validate_config(self, stack_config):\n+        \"\"\"\n+        Validate fields within a stack configuration. This ensures that an inputted configuration\n+        has the necessary fields for stack deployment to function well.\n+\n+        :param stack_config: dict- stack config that is inputted by the user.\n+        :return: None. Raises errors to stop deployment if there is a problem.\n+        \"\"\"\n+        if STACK_NAME not in stack_config:\n+            raise StackError(\"'%s' not in configuration\" % STACK_NAME)","path":"databricks_cli/stack/api.py","position":252,"original_position":252,"commit_id":"832db011f06f08c251c09dac089e3e465c5febd6","original_commit_id":"832db011f06f08c251c09dac089e3e465c5febd6","user":{"login":"alinxie","id":13651069,"node_id":"MDQ6VXNlcjEzNjUxMDY5","avatar_url":"https://avatars0.githubusercontent.com/u/13651069?v=4","gravatar_id":"","url":"https://api.github.com/users/alinxie","html_url":"https://github.com/alinxie","followers_url":"https://api.github.com/users/alinxie/followers","following_url":"https://api.github.com/users/alinxie/following{/other_user}","gists_url":"https://api.github.com/users/alinxie/gists{/gist_id}","starred_url":"https://api.github.com/users/alinxie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alinxie/subscriptions","organizations_url":"https://api.github.com/users/alinxie/orgs","repos_url":"https://api.github.com/users/alinxie/repos","events_url":"https://api.github.com/users/alinxie/events{/privacy}","received_events_url":"https://api.github.com/users/alinxie/received_events","type":"User","site_admin":false},"body":"Should i change all the string formats to this?","created_at":"2018-07-16T22:36:13Z","updated_at":"2018-07-16T22:36:13Z","html_url":"https://github.com/databricks/databricks-cli/pull/137#discussion_r202846314","pull_request_url":"https://api.github.com/repos/databricks/databricks-cli/pulls/137","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/databricks/databricks-cli/pulls/comments/202846314"},"html":{"href":"https://github.com/databricks/databricks-cli/pull/137#discussion_r202846314"},"pull_request":{"href":"https://api.github.com/repos/databricks/databricks-cli/pulls/137"}},"in_reply_to_id":202831850},"pull_request":{"url":"https://api.github.com/repos/databricks/databricks-cli/pulls/137","id":199839307,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk5ODM5MzA3","html_url":"https://github.com/databricks/databricks-cli/pull/137","diff_url":"https://github.com/databricks/databricks-cli/pull/137.diff","patch_url":"https://github.com/databricks/databricks-cli/pull/137.patch","issue_url":"https://api.github.com/repos/databricks/databricks-cli/issues/137","number":137,"state":"open","locked":false,"title":"Stack CLI deploy jobs","user":{"login":"alinxie","id":13651069,"node_id":"MDQ6VXNlcjEzNjUxMDY5","avatar_url":"https://avatars0.githubusercontent.com/u/13651069?v=4","gravatar_id":"","url":"https://api.github.com/users/alinxie","html_url":"https://github.com/alinxie","followers_url":"https://api.github.com/users/alinxie/followers","following_url":"https://api.github.com/users/alinxie/following{/other_user}","gists_url":"https://api.github.com/users/alinxie/gists{/gist_id}","starred_url":"https://api.github.com/users/alinxie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alinxie/subscriptions","organizations_url":"https://api.github.com/users/alinxie/orgs","repos_url":"https://api.github.com/users/alinxie/repos","events_url":"https://api.github.com/users/alinxie/events{/privacy}","received_events_url":"https://api.github.com/users/alinxie/received_events","type":"User","site_admin":false},"body":"Reading a stack configuration template JSON file along with deploying jobs from the configuration and storing a Stack deployment status JSON in the same and a specified file if needed.","created_at":"2018-07-06T20:22:19Z","updated_at":"2018-07-16T22:36:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f44371e7654aa5f04ff421f9c0ba6a07d3b240df","assignee":{"login":"xuanwang14","id":19397936,"node_id":"MDQ6VXNlcjE5Mzk3OTM2","avatar_url":"https://avatars2.githubusercontent.com/u/19397936?v=4","gravatar_id":"","url":"https://api.github.com/users/xuanwang14","html_url":"https://github.com/xuanwang14","followers_url":"https://api.github.com/users/xuanwang14/followers","following_url":"https://api.github.com/users/xuanwang14/following{/other_user}","gists_url":"https://api.github.com/users/xuanwang14/gists{/gist_id}","starred_url":"https://api.github.com/users/xuanwang14/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuanwang14/subscriptions","organizations_url":"https://api.github.com/users/xuanwang14/orgs","repos_url":"https://api.github.com/users/xuanwang14/repos","events_url":"https://api.github.com/users/xuanwang14/events{/privacy}","received_events_url":"https://api.github.com/users/xuanwang14/received_events","type":"User","site_admin":false},"assignees":[{"login":"xuanwang14","id":19397936,"node_id":"MDQ6VXNlcjE5Mzk3OTM2","avatar_url":"https://avatars2.githubusercontent.com/u/19397936?v=4","gravatar_id":"","url":"https://api.github.com/users/xuanwang14","html_url":"https://github.com/xuanwang14","followers_url":"https://api.github.com/users/xuanwang14/followers","following_url":"https://api.github.com/users/xuanwang14/following{/other_user}","gists_url":"https://api.github.com/users/xuanwang14/gists{/gist_id}","starred_url":"https://api.github.com/users/xuanwang14/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuanwang14/subscriptions","organizations_url":"https://api.github.com/users/xuanwang14/orgs","repos_url":"https://api.github.com/users/xuanwang14/repos","events_url":"https://api.github.com/users/xuanwang14/events{/privacy}","received_events_url":"https://api.github.com/users/xuanwang14/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":830499237,"node_id":"MDU6TGFiZWw4MzA0OTkyMzc=","url":"https://api.github.com/repos/databricks/databricks-cli/labels/LGTM","name":"LGTM","color":"0e8a16","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/databricks/databricks-cli/pulls/137/commits","review_comments_url":"https://api.github.com/repos/databricks/databricks-cli/pulls/137/comments","review_comment_url":"https://api.github.com/repos/databricks/databricks-cli/pulls/comments{/number}","comments_url":"https://api.github.com/repos/databricks/databricks-cli/issues/137/comments","statuses_url":"https://api.github.com/repos/databricks/databricks-cli/statuses/832db011f06f08c251c09dac089e3e465c5febd6","head":{"label":"alinxie:stack_deploy_jobs","ref":"stack_deploy_jobs","sha":"832db011f06f08c251c09dac089e3e465c5febd6","user":{"login":"alinxie","id":13651069,"node_id":"MDQ6VXNlcjEzNjUxMDY5","avatar_url":"https://avatars0.githubusercontent.com/u/13651069?v=4","gravatar_id":"","url":"https://api.github.com/users/alinxie","html_url":"https://github.com/alinxie","followers_url":"https://api.github.com/users/alinxie/followers","following_url":"https://api.github.com/users/alinxie/following{/other_user}","gists_url":"https://api.github.com/users/alinxie/gists{/gist_id}","starred_url":"https://api.github.com/users/alinxie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alinxie/subscriptions","organizations_url":"https://api.github.com/users/alinxie/orgs","repos_url":"https://api.github.com/users/alinxie/repos","events_url":"https://api.github.com/users/alinxie/events{/privacy}","received_events_url":"https://api.github.com/users/alinxie/received_events","type":"User","site_admin":false},"repo":{"id":134108034,"node_id":"MDEwOlJlcG9zaXRvcnkxMzQxMDgwMzQ=","name":"databricks-cli","full_name":"alinxie/databricks-cli","owner":{"login":"alinxie","id":13651069,"node_id":"MDQ6VXNlcjEzNjUxMDY5","avatar_url":"https://avatars0.githubusercontent.com/u/13651069?v=4","gravatar_id":"","url":"https://api.github.com/users/alinxie","html_url":"https://github.com/alinxie","followers_url":"https://api.github.com/users/alinxie/followers","following_url":"https://api.github.com/users/alinxie/following{/other_user}","gists_url":"https://api.github.com/users/alinxie/gists{/gist_id}","starred_url":"https://api.github.com/users/alinxie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alinxie/subscriptions","organizations_url":"https://api.github.com/users/alinxie/orgs","repos_url":"https://api.github.com/users/alinxie/repos","events_url":"https://api.github.com/users/alinxie/events{/privacy}","received_events_url":"https://api.github.com/users/alinxie/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/alinxie/databricks-cli","description":"Command Line Interface for Databricks","fork":true,"url":"https://api.github.com/repos/alinxie/databricks-cli","forks_url":"https://api.github.com/repos/alinxie/databricks-cli/forks","keys_url":"https://api.github.com/repos/alinxie/databricks-cli/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alinxie/databricks-cli/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alinxie/databricks-cli/teams","hooks_url":"https://api.github.com/repos/alinxie/databricks-cli/hooks","issue_events_url":"https://api.github.com/repos/alinxie/databricks-cli/issues/events{/number}","events_url":"https://api.github.com/repos/alinxie/databricks-cli/events","assignees_url":"https://api.github.com/repos/alinxie/databricks-cli/assignees{/user}","branches_url":"https://api.github.com/repos/alinxie/databricks-cli/branches{/branch}","tags_url":"https://api.github.com/repos/alinxie/databricks-cli/tags","blobs_url":"https://api.github.com/repos/alinxie/databricks-cli/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alinxie/databricks-cli/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alinxie/databricks-cli/git/refs{/sha}","trees_url":"https://api.github.com/repos/alinxie/databricks-cli/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alinxie/databricks-cli/statuses/{sha}","languages_url":"https://api.github.com/repos/alinxie/databricks-cli/languages","stargazers_url":"https://api.github.com/repos/alinxie/databricks-cli/stargazers","contributors_url":"https://api.github.com/repos/alinxie/databricks-cli/contributors","subscribers_url":"https://api.github.com/repos/alinxie/databricks-cli/subscribers","subscription_url":"https://api.github.com/repos/alinxie/databricks-cli/subscription","commits_url":"https://api.github.com/repos/alinxie/databricks-cli/commits{/sha}","git_commits_url":"https://api.github.com/repos/alinxie/databricks-cli/git/commits{/sha}","comments_url":"https://api.github.com/repos/alinxie/databricks-cli/comments{/number}","issue_comment_url":"https://api.github.com/repos/alinxie/databricks-cli/issues/comments{/number}","contents_url":"https://api.github.com/repos/alinxie/databricks-cli/contents/{+path}","compare_url":"https://api.github.com/repos/alinxie/databricks-cli/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alinxie/databricks-cli/merges","archive_url":"https://api.github.com/repos/alinxie/databricks-cli/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alinxie/databricks-cli/downloads","issues_url":"https://api.github.com/repos/alinxie/databricks-cli/issues{/number}","pulls_url":"https://api.github.com/repos/alinxie/databricks-cli/pulls{/number}","milestones_url":"https://api.github.com/repos/alinxie/databricks-cli/milestones{/number}","notifications_url":"https://api.github.com/repos/alinxie/databricks-cli/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alinxie/databricks-cli/labels{/name}","releases_url":"https://api.github.com/repos/alinxie/databricks-cli/releases{/id}","deployments_url":"https://api.github.com/repos/alinxie/databricks-cli/deployments","created_at":"2018-05-20T00:31:51Z","updated_at":"2018-07-12T22:38:14Z","pushed_at":"2018-07-16T22:00:36Z","git_url":"git://github.com/alinxie/databricks-cli.git","ssh_url":"git@github.com:alinxie/databricks-cli.git","clone_url":"https://github.com/alinxie/databricks-cli.git","svn_url":"https://github.com/alinxie/databricks-cli","homepage":"","size":39017,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":3,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":3,"watchers":0,"default_branch":"master"}},"base":{"label":"databricks:master","ref":"master","sha":"63919270d47e7954218a6eaaf62e3d0a013a0261","user":{"login":"databricks","id":4998052,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ5OTgwNTI=","avatar_url":"https://avatars2.githubusercontent.com/u/4998052?v=4","gravatar_id":"","url":"https://api.github.com/users/databricks","html_url":"https://github.com/databricks","followers_url":"https://api.github.com/users/databricks/followers","following_url":"https://api.github.com/users/databricks/following{/other_user}","gists_url":"https://api.github.com/users/databricks/gists{/gist_id}","starred_url":"https://api.github.com/users/databricks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/databricks/subscriptions","organizations_url":"https://api.github.com/users/databricks/orgs","repos_url":"https://api.github.com/users/databricks/repos","events_url":"https://api.github.com/users/databricks/events{/privacy}","received_events_url":"https://api.github.com/users/databricks/received_events","type":"Organization","site_admin":false},"repo":{"id":93211371,"node_id":"MDEwOlJlcG9zaXRvcnk5MzIxMTM3MQ==","name":"databricks-cli","full_name":"databricks/databricks-cli","owner":{"login":"databricks","id":4998052,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ5OTgwNTI=","avatar_url":"https://avatars2.githubusercontent.com/u/4998052?v=4","gravatar_id":"","url":"https://api.github.com/users/databricks","html_url":"https://github.com/databricks","followers_url":"https://api.github.com/users/databricks/followers","following_url":"https://api.github.com/users/databricks/following{/other_user}","gists_url":"https://api.github.com/users/databricks/gists{/gist_id}","starred_url":"https://api.github.com/users/databricks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/databricks/subscriptions","organizations_url":"https://api.github.com/users/databricks/orgs","repos_url":"https://api.github.com/users/databricks/repos","events_url":"https://api.github.com/users/databricks/events{/privacy}","received_events_url":"https://api.github.com/users/databricks/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/databricks/databricks-cli","description":"Command Line Interface for Databricks","fork":false,"url":"https://api.github.com/repos/databricks/databricks-cli","forks_url":"https://api.github.com/repos/databricks/databricks-cli/forks","keys_url":"https://api.github.com/repos/databricks/databricks-cli/keys{/key_id}","collaborators_url":"https://api.github.com/repos/databricks/databricks-cli/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/databricks/databricks-cli/teams","hooks_url":"https://api.github.com/repos/databricks/databricks-cli/hooks","issue_events_url":"https://api.github.com/repos/databricks/databricks-cli/issues/events{/number}","events_url":"https://api.github.com/repos/databricks/databricks-cli/events","assignees_url":"https://api.github.com/repos/databricks/databricks-cli/assignees{/user}","branches_url":"https://api.github.com/repos/databricks/databricks-cli/branches{/branch}","tags_url":"https://api.github.com/repos/databricks/databricks-cli/tags","blobs_url":"https://api.github.com/repos/databricks/databricks-cli/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/databricks/databricks-cli/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/databricks/databricks-cli/git/refs{/sha}","trees_url":"https://api.github.com/repos/databricks/databricks-cli/git/trees{/sha}","statuses_url":"https://api.github.com/repos/databricks/databricks-cli/statuses/{sha}","languages_url":"https://api.github.com/repos/databricks/databricks-cli/languages","stargazers_url":"https://api.github.com/repos/databricks/databricks-cli/stargazers","contributors_url":"https://api.github.com/repos/databricks/databricks-cli/contributors","subscribers_url":"https://api.github.com/repos/databricks/databricks-cli/subscribers","subscription_url":"https://api.github.com/repos/databricks/databricks-cli/subscription","commits_url":"https://api.github.com/repos/databricks/databricks-cli/commits{/sha}","git_commits_url":"https://api.github.com/repos/databricks/databricks-cli/git/commits{/sha}","comments_url":"https://api.github.com/repos/databricks/databricks-cli/comments{/number}","issue_comment_url":"https://api.github.com/repos/databricks/databricks-cli/issues/comments{/number}","contents_url":"https://api.github.com/repos/databricks/databricks-cli/contents/{+path}","compare_url":"https://api.github.com/repos/databricks/databricks-cli/compare/{base}...{head}","merges_url":"https://api.github.com/repos/databricks/databricks-cli/merges","archive_url":"https://api.github.com/repos/databricks/databricks-cli/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/databricks/databricks-cli/downloads","issues_url":"https://api.github.com/repos/databricks/databricks-cli/issues{/number}","pulls_url":"https://api.github.com/repos/databricks/databricks-cli/pulls{/number}","milestones_url":"https://api.github.com/repos/databricks/databricks-cli/milestones{/number}","notifications_url":"https://api.github.com/repos/databricks/databricks-cli/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/databricks/databricks-cli/labels{/name}","releases_url":"https://api.github.com/repos/databricks/databricks-cli/releases{/id}","deployments_url":"https://api.github.com/repos/databricks/databricks-cli/deployments","created_at":"2017-06-02T23:38:47Z","updated_at":"2018-07-13T03:23:50Z","pushed_at":"2018-07-16T20:03:50Z","git_url":"git://github.com/databricks/databricks-cli.git","ssh_url":"git@github.com:databricks/databricks-cli.git","clone_url":"https://github.com/databricks/databricks-cli.git","svn_url":"https://github.com/databricks/databricks-cli","homepage":"","size":193,"stargazers_count":57,"watchers_count":57,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":36,"mirror_url":null,"archived":false,"open_issues_count":34,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":36,"open_issues":34,"watchers":57,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/databricks/databricks-cli/pulls/137"},"html":{"href":"https://github.com/databricks/databricks-cli/pull/137"},"issue":{"href":"https://api.github.com/repos/databricks/databricks-cli/issues/137"},"comments":{"href":"https://api.github.com/repos/databricks/databricks-cli/issues/137/comments"},"review_comments":{"href":"https://api.github.com/repos/databricks/databricks-cli/pulls/137/comments"},"review_comment":{"href":"https://api.github.com/repos/databricks/databricks-cli/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/databricks/databricks-cli/pulls/137/commits"},"statuses":{"href":"https://api.github.com/repos/databricks/databricks-cli/statuses/832db011f06f08c251c09dac089e3e465c5febd6"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"alinxie"}}