{"action":"created","comment":{"url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/comments/211766419","pull_request_review_id":148258852,"id":211766419,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMTc2NjQxOQ==","diff_hunk":"@@ -0,0 +1,502 @@\n+#!/usr/bin/env python\n+import argparse\n+import base64\n+import codecs\n+import json\n+from copy import deepcopy\n+from csv import DictReader\n+from google.cloud import storage\n+from typing import List\n+\n+\n+def get_inputs(inputs_file):\n+    \"\"\"Reads input parameter names and values from tsv file.\n+\n+    Args:\n+        inputs_file (str): Path to tsv file of parameter names and values.\n+\n+    Returns:\n+        inputs (List[dict]): A list of dicts, where each dict gives the name and value of a single parameter.\n+    \"\"\"\n+    with open(inputs_file) as f:\n+        f.readline()  # skip header\n+        reader = DictReader(f, lineterminator='\\n', delimiter='\\t', fieldnames=['parameter_name', 'parameter_value'])\n+        inputs = [line for line in reader]\n+    return inputs\n+\n+\n+def get_input_urls(inputs):\n+    \"\"\"Returns just the gs urls from the given list of inputs.\n+\n+    Args:\n+        inputs (List[dict]): A list of input parameter dicts.\n+\n+    Returns:\n+        (List[str]): list of gs urls\n+    \"\"\"\n+    return [i['parameter_value'] for i in inputs if i['parameter_value'].startswith('gs://')]\n+\n+\n+def add_md5s(inputs, input_url_to_md5):\n+    \"\"\"Adds md5 hash for each file in the given list.\n+\n+    Queries GCS for the md5 of each parameter whose value starts with 'gs://'.\n+\n+    Args:\n+        inputs (List[dict]): List of dicts containing input parameter names and values.\n+        input_url_to_md5 (dict): Dict of gs urls to corresponding md5 hashes.\n+\n+    Returns:\n+        inputs (List[dict]): A list of dicts, where each dict contains the name, value, and md5 hash (for gs urls).\n+    \"\"\"\n+    inputs_with_md5 = []\n+    for i in inputs:\n+        value = i['parameter_value']\n+        if value.startswith('gs://'):\n+            input_with_md5 = deepcopy(i)\n+            input_with_md5['checksum'] = input_url_to_md5[value]\n+            inputs_with_md5.append(input_with_md5)\n+        else:\n+            inputs_with_md5.append(deepcopy(i))\n+    return inputs_with_md5\n+\n+\n+def get_md5s(output_urls, gcs_client):\n+    \"\"\"Gets md5s.\n+\n+    Args:\n+        output_urls (List[str]): The gs urls to get md5s for.\n+        gcs_client (google.cloud.storage.Client): The client to use to get the md5s.\n+\n+    Returns:\n+        url_to_md5 (dict): Dict of gs urls to md5 hashes.\n+    \"\"\"\n+    url_to_md5 = {url: get_md5(url, gcs_client) for url in output_urls}\n+    return url_to_md5\n+\n+\n+def get_md5(gs_url, gcs_client):\n+    \"\"\"Gets md5 hash for the given gs url.\n+\n+    Args:\n+        gs_url (str): The gs url.\n+        gcs_client (google.cloud.storage.Client): the client object to use to get the md5.\n+\n+    Returns:\n+        hex_str (str): The md5 hash, hexadecimal-encoded.\n+    \"\"\"\n+    _, _, bucket_str, path_str = gs_url.split('/', 3)\n+    bucket = gcs_client.bucket(bucket_str)\n+    blob = bucket.get_blob(path_str)\n+    hex_str = base64_to_hex(blob.md5_hash)\n+    return hex_str\n+\n+\n+def base64_to_hex(base64_str):\n+    \"\"\"Converts a base64 string to the equivalent hexadecimal string.\n+\n+    Args:\n+        base64_str (str): A string representing base64-encoded data.\n+\n+    Returns:\n+        hex_str (str): A string giving the hexadecimal-encoded representation of the given data.\n+    \"\"\"\n+    base64_bytes = base64.b64decode(base64_str.strip('\\n\"\\''))\n+    hex_bytes = codecs.encode(base64_bytes, 'hex')\n+    hex_str = hex_bytes.decode('utf-8')\n+    return hex_str\n+\n+\n+def get_analysis_describedBy(schema_url, schema_type, schema_version):\n+    \"\"\"A helper function prepares the \"describedBy\" field in the analysis metadata, works for both process and protocol.\n+\n+    Args:\n+        schema_url (str): URL for retrieving HCA metadata schemas.\n+        schema_type (str): 'process' or 'protocol', indicates the type of the schema.\n+        schema_version (str): The version of the metadata schema that analysis_process/analysis_protocol conforms to.\n+\n+    Returns:\n+        schema_url_reference (str): URL for retrieving the specific HCA metadata schemas, fulfilling the\n+                                    \"describedBy\" field in the analysis metadata.\n+    \"\"\"\n+    schema_url_reference = '{schema_url}/type/{schema_type}/analysis/{schema_version}/analysis_{schema_type}'.format(\n+            schema_url=schema_url,\n+            schema_type=schema_type,\n+            schema_version=schema_version)\n+    return schema_url_reference\n+\n+\n+def get_analysis_process_core(analysis_workflow_id, **kwargs):\n+    \"\"\"Creates process_core metadata for analysis_process.\n+\n+    This defines the core entry of the analysis process, the process_id usually varies between runs, in this case, it\n+    is set to be the analysis workflow UUID, which is unique within the Cromwell execution context.\n+\n+    Args:\n+        analysis_workflow_id (str): UUID of the analysis workflow.\n+        **kwargs: Non-required but optional fields for analysis_process core. e.g. process_name, process_description.\n+\n+    Returns:\n+        analysis_process_core (dict): Dict containing process_core metadata required for analysis_process.\n+    \"\"\"\n+    analysis_process_core = {'process_id': analysis_workflow_id}\n+    for optional_key, optional_val in kwargs:\n+        analysis_process_core[optional_key] = optional_val\n+    return analysis_process_core\n+\n+\n+def get_analysis_process_type():\n+    \"\"\"Creates process_type metadata for analysis_process.\n+\n+    This defines the type of process, which refers to the process_type_ontology. The only required key of the dict\n+    should be 'text', and the value should be the name of a process type being used.\n+\n+    Returns:\n+        analysis_process_type (dict): The process_type metadata for analysis_process.\n+    \"\"\"\n+    analysis_process_type = {'text': 'analysis'}\n+    return analysis_process_type\n+\n+\n+def get_workflow_metadata(metadata_file):\n+    \"\"\"Load workflow metadata from a JSON file.\n+\n+    Args:\n+        metadata_file (str): Path to file containing metadata json for the workflow.\n+\n+    Returns:\n+        metadata (dict): A dict consisting of Cromwell workflow metadata information.\n+    \"\"\"\n+    with open(metadata_file) as f:\n+        metadata = json.load(f)\n+    return metadata\n+\n+\n+def get_workflow_tasks(workflow_metadata):\n+    \"\"\"Creates array of Cromwell workflow's task metadata for analysis_process.\n+\n+    Args:\n+        workflow_metadata (dict): A dict representing the workflow metadata.\n+\n+    Returns:\n+        sorted_output_tasks (list): Sorted array of dicts representing task metadata in the format required for\n+                                    the analysis json.\n+    \"\"\"\n+    calls = workflow_metadata['calls']\n+\n+    output_tasks = []\n+    for long_task_name in calls:\n+        task_name = long_task_name.split('.')[-1]\n+        task = calls[long_task_name][0]\n+\n+        if task.get('subWorkflowMetadata'):\n+            output_tasks.extend(get_workflow_tasks(task['subWorkflowMetadata']))  # recursively parse tasks\n+        else:\n+            runtime = task['runtimeAttributes']\n+            out_task = {\n+                'task_name'   : task_name,\n+                'cpus'        : int(runtime['cpu']),\n+                'memory'      : runtime['memory'],\n+                'disk_size'   : runtime['disks'],\n+                'docker_image': runtime['docker'],\n+                'zone'        : runtime['zones'],\n+                'start_time'  : task['start'],\n+                'stop_time'   : task['end'],\n+                'log_out'     : task['stdout'],\n+                'log_err'     : task['stderr']\n+            }\n+            output_tasks.append(out_task)\n+    sorted_output_tasks = sorted(output_tasks, key=lambda k: k['task_name'])\n+    return sorted_output_tasks\n+\n+\n+def get_format(path, extension_to_format):","path":"pipeline_tools/create_analysis_metadata.py","position":213,"original_position":213,"commit_id":"71e01139d58429a1187c9173c98e155675b02f2e","original_commit_id":"8b51ead3a324a936bae3dcb09d9c2cc87ab420b8","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":"Will do!","created_at":"2018-08-21T21:29:16Z","updated_at":"2018-08-21T21:29:16Z","html_url":"https://github.com/HumanCellAtlas/pipeline-tools/pull/70#discussion_r211766419","pull_request_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/comments/211766419"},"html":{"href":"https://github.com/HumanCellAtlas/pipeline-tools/pull/70#discussion_r211766419"},"pull_request":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70"}},"in_reply_to_id":211353894},"pull_request":{"url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70","id":208979563,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA4OTc5NTYz","html_url":"https://github.com/HumanCellAtlas/pipeline-tools/pull/70","diff_url":"https://github.com/HumanCellAtlas/pipeline-tools/pull/70.diff","patch_url":"https://github.com/HumanCellAtlas/pipeline-tools/pull/70.patch","issue_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/70","number":70,"state":"open","locked":false,"title":"[WIP] Update to new bundle structure","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":"This PR consists of 2 major parts:\r\n1. Update the pipeline-tools library to use the [`metadata-api`](https://github.com/HumanCellAtlas/metadata-api) library so we don't have to concern about the metadata schema changes directly anymore. \r\n2. Update the pipeline-tools library to adapt to the lastest bundle structure, including:\r\n    - the way we prepare inputs for the pipeline, and \r\n    - how we generates analysis JSON for Ingest service.\r\n\r\n**Note:** While removing a lot of existing code, we decide to keep using our `HttpRequests` class to talk to DSS service instead of using the `dss_client` Python API provided by the [`metadata-api`](https://github.com/HumanCellAtlas/metadata-api) library for now.\r\n\r\n**Note:** This PR only focuses on SmartSeq2 Pipeline and breaks the Optimus pipeline intentionally since the latter one is not even running in secondary-analysis service yet. But there will be another PR fixes the Optimus pipeline shortly.\r\n\r\n**Note:**  Since the [`metadata-api`](https://github.com/HumanCellAtlas/metadata-api) library only supports v5+ hca metadata schemas, from now on, we are also dropping the support for v4 metadata schema.\r\n\r\n**Note:** This PR attempts to migrate as many test cases from unittest to pytest.\r\n\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-08-16T20:46:02Z","updated_at":"2018-08-21T21:29:16Z","closed_at":null,"merged_at":null,"merge_commit_sha":"232d3ec5d0b837b24d52535718f1aab666030602","assignee":{"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},"assignees":[{"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}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70/commits","review_comments_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70/comments","review_comment_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/comments{/number}","comments_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/70/comments","statuses_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/statuses/71e01139d58429a1187c9173c98e155675b02f2e","head":{"label":"HumanCellAtlas:cw-update-to-new-bundle-structure","ref":"cw-update-to-new-bundle-structure","sha":"71e01139d58429a1187c9173c98e155675b02f2e","user":{"login":"HumanCellAtlas","id":26391798,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2MzkxNzk4","avatar_url":"https://avatars1.githubusercontent.com/u/26391798?v=4","gravatar_id":"","url":"https://api.github.com/users/HumanCellAtlas","html_url":"https://github.com/HumanCellAtlas","followers_url":"https://api.github.com/users/HumanCellAtlas/followers","following_url":"https://api.github.com/users/HumanCellAtlas/following{/other_user}","gists_url":"https://api.github.com/users/HumanCellAtlas/gists{/gist_id}","starred_url":"https://api.github.com/users/HumanCellAtlas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HumanCellAtlas/subscriptions","organizations_url":"https://api.github.com/users/HumanCellAtlas/orgs","repos_url":"https://api.github.com/users/HumanCellAtlas/repos","events_url":"https://api.github.com/users/HumanCellAtlas/events{/privacy}","received_events_url":"https://api.github.com/users/HumanCellAtlas/received_events","type":"Organization","site_admin":false},"repo":{"id":110603502,"node_id":"MDEwOlJlcG9zaXRvcnkxMTA2MDM1MDI=","name":"pipeline-tools","full_name":"HumanCellAtlas/pipeline-tools","owner":{"login":"HumanCellAtlas","id":26391798,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2MzkxNzk4","avatar_url":"https://avatars1.githubusercontent.com/u/26391798?v=4","gravatar_id":"","url":"https://api.github.com/users/HumanCellAtlas","html_url":"https://github.com/HumanCellAtlas","followers_url":"https://api.github.com/users/HumanCellAtlas/followers","following_url":"https://api.github.com/users/HumanCellAtlas/following{/other_user}","gists_url":"https://api.github.com/users/HumanCellAtlas/gists{/gist_id}","starred_url":"https://api.github.com/users/HumanCellAtlas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HumanCellAtlas/subscriptions","organizations_url":"https://api.github.com/users/HumanCellAtlas/orgs","repos_url":"https://api.github.com/users/HumanCellAtlas/repos","events_url":"https://api.github.com/users/HumanCellAtlas/events{/privacy}","received_events_url":"https://api.github.com/users/HumanCellAtlas/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/HumanCellAtlas/pipeline-tools","description":"Pipeline-tools for HCA DCP Secondary Analyses Service","fork":false,"url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools","forks_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/forks","keys_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/teams","hooks_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/hooks","issue_events_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/events{/number}","events_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/events","assignees_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/assignees{/user}","branches_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/branches{/branch}","tags_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/tags","blobs_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/statuses/{sha}","languages_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/languages","stargazers_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/stargazers","contributors_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/contributors","subscribers_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/subscribers","subscription_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/subscription","commits_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/contents/{+path}","compare_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/merges","archive_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/downloads","issues_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues{/number}","pulls_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls{/number}","milestones_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/milestones{/number}","notifications_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/labels{/name}","releases_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/releases{/id}","deployments_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/deployments","created_at":"2017-11-13T21:19:14Z","updated_at":"2018-08-02T15:20:53Z","pushed_at":"2018-08-21T04:49:46Z","git_url":"git://github.com/HumanCellAtlas/pipeline-tools.git","ssh_url":"git@github.com:HumanCellAtlas/pipeline-tools.git","clone_url":"https://github.com/HumanCellAtlas/pipeline-tools.git","svn_url":"https://github.com/HumanCellAtlas/pipeline-tools","homepage":"https://pipeline-tools.readthedocs.io","size":241,"stargazers_count":3,"watchers_count":3,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"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":0,"open_issues":1,"watchers":3,"default_branch":"master"}},"base":{"label":"HumanCellAtlas:master","ref":"master","sha":"0dd53a0c4d5b983ae7f48a392f87ece1c8e1dd99","user":{"login":"HumanCellAtlas","id":26391798,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2MzkxNzk4","avatar_url":"https://avatars1.githubusercontent.com/u/26391798?v=4","gravatar_id":"","url":"https://api.github.com/users/HumanCellAtlas","html_url":"https://github.com/HumanCellAtlas","followers_url":"https://api.github.com/users/HumanCellAtlas/followers","following_url":"https://api.github.com/users/HumanCellAtlas/following{/other_user}","gists_url":"https://api.github.com/users/HumanCellAtlas/gists{/gist_id}","starred_url":"https://api.github.com/users/HumanCellAtlas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HumanCellAtlas/subscriptions","organizations_url":"https://api.github.com/users/HumanCellAtlas/orgs","repos_url":"https://api.github.com/users/HumanCellAtlas/repos","events_url":"https://api.github.com/users/HumanCellAtlas/events{/privacy}","received_events_url":"https://api.github.com/users/HumanCellAtlas/received_events","type":"Organization","site_admin":false},"repo":{"id":110603502,"node_id":"MDEwOlJlcG9zaXRvcnkxMTA2MDM1MDI=","name":"pipeline-tools","full_name":"HumanCellAtlas/pipeline-tools","owner":{"login":"HumanCellAtlas","id":26391798,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2MzkxNzk4","avatar_url":"https://avatars1.githubusercontent.com/u/26391798?v=4","gravatar_id":"","url":"https://api.github.com/users/HumanCellAtlas","html_url":"https://github.com/HumanCellAtlas","followers_url":"https://api.github.com/users/HumanCellAtlas/followers","following_url":"https://api.github.com/users/HumanCellAtlas/following{/other_user}","gists_url":"https://api.github.com/users/HumanCellAtlas/gists{/gist_id}","starred_url":"https://api.github.com/users/HumanCellAtlas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HumanCellAtlas/subscriptions","organizations_url":"https://api.github.com/users/HumanCellAtlas/orgs","repos_url":"https://api.github.com/users/HumanCellAtlas/repos","events_url":"https://api.github.com/users/HumanCellAtlas/events{/privacy}","received_events_url":"https://api.github.com/users/HumanCellAtlas/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/HumanCellAtlas/pipeline-tools","description":"Pipeline-tools for HCA DCP Secondary Analyses Service","fork":false,"url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools","forks_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/forks","keys_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/teams","hooks_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/hooks","issue_events_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/events{/number}","events_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/events","assignees_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/assignees{/user}","branches_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/branches{/branch}","tags_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/tags","blobs_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/statuses/{sha}","languages_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/languages","stargazers_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/stargazers","contributors_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/contributors","subscribers_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/subscribers","subscription_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/subscription","commits_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/contents/{+path}","compare_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/merges","archive_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/downloads","issues_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues{/number}","pulls_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls{/number}","milestones_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/milestones{/number}","notifications_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/labels{/name}","releases_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/releases{/id}","deployments_url":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/deployments","created_at":"2017-11-13T21:19:14Z","updated_at":"2018-08-02T15:20:53Z","pushed_at":"2018-08-21T04:49:46Z","git_url":"git://github.com/HumanCellAtlas/pipeline-tools.git","ssh_url":"git@github.com:HumanCellAtlas/pipeline-tools.git","clone_url":"https://github.com/HumanCellAtlas/pipeline-tools.git","svn_url":"https://github.com/HumanCellAtlas/pipeline-tools","homepage":"https://pipeline-tools.readthedocs.io","size":241,"stargazers_count":3,"watchers_count":3,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"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":0,"open_issues":1,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70"},"html":{"href":"https://github.com/HumanCellAtlas/pipeline-tools/pull/70"},"issue":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/70"},"comments":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/issues/70/comments"},"review_comments":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70/comments"},"review_comment":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/pulls/70/commits"},"statuses":{"href":"https://api.github.com/repos/HumanCellAtlas/pipeline-tools/statuses/71e01139d58429a1187c9173c98e155675b02f2e"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"rexwangcc"}}