{"action":"created","comment":{"url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/comments/225530159","pull_request_review_id":165142101,"id":225530159,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyNTUzMDE1OQ==","diff_hunk":"@@ -0,0 +1,425 @@\n+\"\"\"\n+TODO: add some module docs\n+\"\"\"\n+\n+import time\n+\n+import json\n+import logging\n+import requests\n+from datetime import datetime, timedelta\n+from tenacity import retry, stop_after_delay, wait_exponential\n+\n+from cromwell_tools._utilities import prepare_workflow_manifest, validate_cromwell_label\n+\n+\n+logger = logging.getLogger(__name__)\n+\n+\n+class WorkflowFailedException(Exception):\n+    pass\n+\n+\n+class WorkflowUnknownException(Exception):\n+    pass\n+\n+\n+# TODO: use functools partial for get, post (set the authenticate commands)\n+class CromwellAPI(object):\n+    \"\"\"Contains a set of classmethods that implement interfaces to cromwell REST API endpoints.\n+    \"\"\"\n+\n+    # TODO: remove this if it is not critical for mocking\n+    requests = requests\n+\n+    _abort_endpoint = '/api/workflows/v1/{uuid}/abort'\n+\n+    _status_endpoint = '/api/workflows/v1/{uuid}/status'\n+\n+    _workflow_endpoint = '/api/workflows/v1'\n+\n+    _metadata_endpoint = '/api/workflows/v1/{uuid}/metadata'\n+\n+    _health_endpoint = '/api/engine/v1/status'\n+\n+    _release_hold_endpoint = 'api/workflows/v1/{uuid}/releaseHold'\n+\n+    _query_endpoint = 'api/workflows/v1/query'\n+\n+    _failed_statuses = ('Failed', 'Aborted', 'Aborting')\n+\n+    _cromwell_exclusive_query_keys = {'end', 'includeSubworkflows', 'start', 'submission'}\n+\n+    _cromwell_inclusive_query_keys = {'additionalQueryResultFields', 'excludeLabelAnd', 'excludeLabelOr',\n+                                      'id', 'includeSubworkflows', 'label', 'labelor', 'name', 'status'}\n+\n+    _cromwell_query_keys = _cromwell_exclusive_query_keys.union(_cromwell_inclusive_query_keys)\n+\n+    @classmethod\n+    def abort(cls, uuid, auth, raise_for_status=False):\n+        \"\"\"Request Cromwell to abort a running workflow by UUID.\n+\n+        Args:\n+            uuid (str): A Cromwell workflow UUID, which is the workflow identifier.\n+            auth (cromwell_tools._cromwell_auth.CromwellAuth): The authentication class holding headers or auth\n+                information to a Cromwell server.\n+            raise_for_status (Optional[bool]): Whether to check and raise for status based on the response. (default\n+                False)\n+\n+        Raises:\n+            requests.exceptions.HTTPError: This will be raised when raise_for_status is True and Cromwell returns\n+                a response that satisfies 400 <= response.status_code < 600.\n+\n+        Returns:\n+            requests.Response: HTTP response from Cromwell.\n+        \"\"\"\n+        response = cls.requests.post(url=auth.url + cls._abort_endpoint.format(uuid=uuid),\n+                                     auth=auth.auth,\n+                                     headers=auth.header)\n+\n+        if raise_for_status:\n+            cls._check_and_raise_status(response)\n+        return response\n+\n+    @classmethod\n+    def status(cls, uuid, auth, raise_for_status=False):\n+        \"\"\"Retrieves the current state for a workflow by UUID.\n+\n+        Args:\n+            uuid (str): A Cromwell workflow UUID, which is the workflow identifier.\n+            auth (cromwell_tools._cromwell_auth.CromwellAuth): The authentication class holding headers or auth\n+                information to a Cromwell server.\n+            raise_for_status (Optional[bool]): Whether to check and raise for status based on the response. (default\n+                False)\n+\n+        Raises:\n+            requests.exceptions.HTTPError: This will be raised when raise_for_status is True and Cromwell returns\n+                a response that satisfies 400 <= response.status_code < 600.\n+\n+        Returns:\n+            requests.Response: HTTP response from Cromwell.\n+        \"\"\"\n+        response = cls.requests.get(url=auth.url + cls._status_endpoint.format(uuid=uuid),\n+                                    auth=auth.auth,\n+                                    headers=auth.header)\n+\n+        if raise_for_status:\n+            cls._check_and_raise_status(response)\n+        return response\n+\n+    @classmethod\n+    def health(cls, auth, raise_for_status=False):\n+        \"\"\"Return the current health status of any monitored subsystems of the Cromwell Server.\n+\n+        Args:\n+            auth (cromwell_tools._cromwell_auth.CromwellAuth): authentication class holding headers or auth\n+                information to a Cromwell server.\n+            raise_for_status (Optional[bool]): Whether to check and raise for status based on the response. (default\n+                False)\n+\n+        Raises:\n+            requests.exceptions.HTTPError: This will be raised when raise_for_status is True and Cromwell returns\n+                a response that satisfies 400 <= response.status_code < 600.\n+\n+        Returns:\n+            requests.Response: HTTP response from Cromwell.\n+        \"\"\"\n+        response = cls.requests.get(url=auth.url + cls._health_endpoint,\n+                                    auth=auth.auth,\n+                                    headers=auth.header)\n+\n+        if raise_for_status:\n+            cls._check_and_raise_status(response)\n+        return response\n+\n+    @classmethod\n+    @retry(reraise=True, wait=wait_exponential(multiplier=1, max=10), stop=stop_after_delay(20))\n+    def submit(cls, auth, wdl_file, inputs_json, options_json=None, inputs2_json=None, dependencies_json=None,\n+               collection_name=None, label=None, validate_labels=False):\n+        \"\"\"Submits a workflow to Cromwell.\n+\n+        # TODO: Allow more inputs files rather 2 to be consistent with the Cromwell API\n+        # TODO: Add `raise_for_status` flag to this method and remove the hard-coded `raise_for_status()` call\n+        # TODO: Purifying the methods by taking the specific retry policy out from this method\n+\n+        Args:\n+            wdl_file (_io.BytesIO or str): The workflow source file to submit for execution. From version 35,\n+                Cromwell starts to accept URL to the WDL file besides actual WDL files.\n+            inputs_json (_io.BytesIO): File-like object containing input data in JSON format.\n+            options_json (Optional[_io.BytesIO]): Cromwell configs file.\n+            inputs2_json (Optional[_io.BytesIO]): Inputs file 2.\n+            dependencies_json (Optional[_io.BytesIO]): Zip file containing dependencies.\n+            auth (cromwell_tools._cromwell_auth.CromwellAuth): authentication class holding headers or\n+                auth information to a Cromwell server.\n+            collection_name (Optional[str]): Collection in SAM that the workflow should belong to.\n+            label (Optional[Union[str, _io.BytesIO]]): JSON file containing a collection of\n+                key/value pairs for workflow labels. # TODO: verify these types are accurate\n+            validate_labels (Optional[bool]) If True, validate cromwell labels. (default False)\n+\n+        Raises:\n+            requests.exceptions.HTTPError: This will be raised when raise_for_status is True and Cromwell returns\n+                a response that satisfies 400 <= response.status_code < 600.\n+\n+        Returns:\n+            requests.Response: HTTP response from Cromwell.\n+        \"\"\"\n+        manifest = prepare_workflow_manifest(\n+                wdl_file, inputs_json, dependencies_json, options_json, inputs2_json)\n+\n+        if validate_labels and label is not None:\n+            validate_cromwell_label(label)\n+\n+        files = {\n+            'workflowSource': wdl_file,\n+            'workflowInputs': inputs_json,\n+        }\n+\n+        # TODO: these three checks should be done inside prepare workflow manifest?\n+        if 'inputs2_json' in manifest:\n+            files['workflowInputs_2'] = manifest['inputs2_json']\n+        if 'dependencies_json' in manifest:\n+            files['workflowDependencies'] = manifest['dependencies_json']\n+        if 'options_json' in manifest:\n+            files['workflowOptions'] = manifest['options_json']\n+\n+        if label:\n+            files['labels'] = label\n+        if collection_name:  # TODO: this check should happen elsewhere, related to caas\n+            files['collectionName'] = collection_name\n+\n+        response = cls.requests.post(url=auth.url + cls._workflow_endpoint,\n+                                     files=files,\n+                                     auth=auth.auth,\n+                                     headers=auth.header)\n+\n+        response.raise_for_status()\n+        return response\n+\n+    @classmethod\n+    def wait(cls, workflow_ids, timeout_minutes, auth, poll_interval_seconds=30, verbose=True):\n+        \"\"\"Wait until cromwell returns successfully for each provided workflow\n+\n+        Given a list of workflow ids, wait until cromwell returns successfully for each status, or\n+        one of the workflows fails or is aborted.\n+\n+        Args:\n+        workflow_ids (List): Workflow ids to wait for terminal status\n+        timeout_minutes (int): Maximum number of minutes to wait\n+        auth (cromwell_tools._cromwell_auth.CromwellAuth): Authentication class holding headers\n+            or auth information to a Cromwell server\n+        poll_interval_seconds (Optional[int]): Number of seconds between checks for workflow\n+            completion (default 30)\n+        verbose (Optional[bool]): If True, report to stdout when all workflows succeed\n+            (default True)\n+        \"\"\"\n+        start = datetime.now()\n+        timeout = timedelta(minutes=int(timeout_minutes))\n+\n+        while True:\n+\n+            if datetime.now() - start > timeout:\n+                msg = 'Unfinished workflows after {0} minutes.'\n+                raise Exception(msg.format(timeout))\n+\n+            all_succeeded = True\n+            for uuid in workflow_ids:\n+                response = cls.status(uuid, auth)\n+                status = cls._parse_status(response)\n+                if status in cls._failed_statuses:\n+                    raise WorkflowFailedException('Workflow {0} returned status {1}'.format(\n+                            uuid, status))\n+                elif status != 'Succeeded':\n+                    all_succeeded = False\n+\n+            if all_succeeded:\n+                if verbose:\n+                    print('All workflows succeeded!')\n+                return\n+\n+            time.sleep(poll_interval_seconds)\n+\n+    @classmethod\n+    def release_hold(cls, uuid, auth, raise_for_status=False):\n+        \"\"\"Request Cromwell to release the hold on a workflow.\n+\n+        It will switch the status of a workflow from ‘On Hold’ to ‘Submitted’ so it can be picked for running. For\n+        a workflow that was not submitted with `workflowOnHold = true`, Cromwell will ignore the request.","path":"cromwell_tools/_cromwell_api.py","position":246,"original_position":246,"commit_id":"c4b5436827d801f463c2020b9ce0013fe9075faa","original_commit_id":"c4b5436827d801f463c2020b9ce0013fe9075faa","user":{"login":"rexwangcc","id":14366016,"node_id":"MDQ6VXNlcjE0MzY2MDE2","avatar_url":"https://avatars2.githubusercontent.com/u/14366016?v=4","gravatar_id":"","url":"https://api.github.com/users/rexwangcc","html_url":"https://github.com/rexwangcc","followers_url":"https://api.github.com/users/rexwangcc/followers","following_url":"https://api.github.com/users/rexwangcc/following{/other_user}","gists_url":"https://api.github.com/users/rexwangcc/gists{/gist_id}","starred_url":"https://api.github.com/users/rexwangcc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rexwangcc/subscriptions","organizations_url":"https://api.github.com/users/rexwangcc/orgs","repos_url":"https://api.github.com/users/rexwangcc/repos","events_url":"https://api.github.com/users/rexwangcc/events{/privacy}","received_events_url":"https://api.github.com/users/rexwangcc/received_events","type":"User","site_admin":false},"body":"Great catch, this docstring is lying, the post request will raise 403 and, this function will return the errored response or raise the error to the users(if raise_for_status==True).","created_at":"2018-10-16T13:06:48Z","updated_at":"2018-10-16T13:17:03Z","html_url":"https://github.com/broadinstitute/cromwell-tools/pull/39#discussion_r225530159","pull_request_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/comments/225530159"},"html":{"href":"https://github.com/broadinstitute/cromwell-tools/pull/39#discussion_r225530159"},"pull_request":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39"}},"in_reply_to_id":225280910},"pull_request":{"url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39","id":221908649,"node_id":"MDExOlB1bGxSZXF1ZXN0MjIxOTA4NjQ5","html_url":"https://github.com/broadinstitute/cromwell-tools/pull/39","diff_url":"https://github.com/broadinstitute/cromwell-tools/pull/39.diff","patch_url":"https://github.com/broadinstitute/cromwell-tools/pull/39.patch","issue_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/39","number":39,"state":"open","locked":false,"title":"[WIP] Continued effort for refactoring and standardizing the Cromwell-tools API","user":{"login":"rexwangcc","id":14366016,"node_id":"MDQ6VXNlcjE0MzY2MDE2","avatar_url":"https://avatars2.githubusercontent.com/u/14366016?v=4","gravatar_id":"","url":"https://api.github.com/users/rexwangcc","html_url":"https://github.com/rexwangcc","followers_url":"https://api.github.com/users/rexwangcc/followers","following_url":"https://api.github.com/users/rexwangcc/following{/other_user}","gists_url":"https://api.github.com/users/rexwangcc/gists{/gist_id}","starred_url":"https://api.github.com/users/rexwangcc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rexwangcc/subscriptions","organizations_url":"https://api.github.com/users/rexwangcc/orgs","repos_url":"https://api.github.com/users/rexwangcc/repos","events_url":"https://api.github.com/users/rexwangcc/events{/privacy}","received_events_url":"https://api.github.com/users/rexwangcc/received_events","type":"User","site_admin":false},"body":"I still need to fix a lot of unit tests, but the main part is ready for an early review!\r\n\r\n---\r\nPlease ensure the following when opening a PR:\r\n- [x] Added or updated tests\r\n- [x] Updated documentation\r\n- [x] Applied style guidelines\r\n- [x] Considered generalizability beyond our own use case\r\n","created_at":"2018-10-10T19:39:15Z","updated_at":"2018-10-16T13:17:03Z","closed_at":null,"merged_at":null,"merge_commit_sha":"febcbbbc44a8ba9fdc0c9664d677963783de0439","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39/commits","review_comments_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39/comments","review_comment_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/comments{/number}","comments_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/39/comments","statuses_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/statuses/c4b5436827d801f463c2020b9ce0013fe9075faa","head":{"label":"broadinstitute:cw-refactor-cromwell-tools","ref":"cw-refactor-cromwell-tools","sha":"c4b5436827d801f463c2020b9ce0013fe9075faa","user":{"login":"broadinstitute","id":393552,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5MzU1Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":106469492,"node_id":"MDEwOlJlcG9zaXRvcnkxMDY0Njk0OTI=","name":"cromwell-tools","full_name":"broadinstitute/cromwell-tools","private":false,"owner":{"login":"broadinstitute","id":393552,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5MzU1Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/broadinstitute/cromwell-tools","description":"A collection of Python APIs for interacting with the Cromwell","fork":false,"url":"https://api.github.com/repos/broadinstitute/cromwell-tools","forks_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/forks","keys_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/teams","hooks_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/events","assignees_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/tags","blobs_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/subscription","commits_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/merges","archive_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/downloads","issues_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/deployments","created_at":"2017-10-10T20:46:24Z","updated_at":"2018-10-15T20:26:55Z","pushed_at":"2018-10-15T15:42:50Z","git_url":"git://github.com/broadinstitute/cromwell-tools.git","ssh_url":"git@github.com:broadinstitute/cromwell-tools.git","clone_url":"https://github.com/broadinstitute/cromwell-tools.git","svn_url":"https://github.com/broadinstitute/cromwell-tools","homepage":"https://cromwell-tools.readthedocs.io","size":327,"stargazers_count":6,"watchers_count":6,"language":"Jupyter Notebook","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":15,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":3,"open_issues":15,"watchers":6,"default_branch":"master"}},"base":{"label":"broadinstitute:master","ref":"master","sha":"2a1af5d1a6b25c1bbe4d9a9db43c744db57cfbef","user":{"login":"broadinstitute","id":393552,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5MzU1Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":106469492,"node_id":"MDEwOlJlcG9zaXRvcnkxMDY0Njk0OTI=","name":"cromwell-tools","full_name":"broadinstitute/cromwell-tools","private":false,"owner":{"login":"broadinstitute","id":393552,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5MzU1Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/393552?v=4","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/broadinstitute/cromwell-tools","description":"A collection of Python APIs for interacting with the Cromwell","fork":false,"url":"https://api.github.com/repos/broadinstitute/cromwell-tools","forks_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/forks","keys_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/teams","hooks_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/events","assignees_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/tags","blobs_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/subscription","commits_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/merges","archive_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/downloads","issues_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/cromwell-tools/deployments","created_at":"2017-10-10T20:46:24Z","updated_at":"2018-10-15T20:26:55Z","pushed_at":"2018-10-15T15:42:50Z","git_url":"git://github.com/broadinstitute/cromwell-tools.git","ssh_url":"git@github.com:broadinstitute/cromwell-tools.git","clone_url":"https://github.com/broadinstitute/cromwell-tools.git","svn_url":"https://github.com/broadinstitute/cromwell-tools","homepage":"https://cromwell-tools.readthedocs.io","size":327,"stargazers_count":6,"watchers_count":6,"language":"Jupyter Notebook","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":15,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":3,"open_issues":15,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39"},"html":{"href":"https://github.com/broadinstitute/cromwell-tools/pull/39"},"issue":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/39"},"comments":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/issues/39/comments"},"review_comments":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39/comments"},"review_comment":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/pulls/39/commits"},"statuses":{"href":"https://api.github.com/repos/broadinstitute/cromwell-tools/statuses/c4b5436827d801f463c2020b9ce0013fe9075faa"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"rexwangcc"}}