{"action":"created","comment":{"url":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments/155377278","pull_request_review_id":81687100,"id":155377278,"diff_hunk":"@@ -0,0 +1,660 @@\n+package org.broadinstitute.hellbender.utils.config;\n+\n+import com.google.common.annotations.VisibleForTesting;\n+import org.aeonbits.owner.*;\n+import org.apache.logging.log4j.Level;\n+import org.apache.logging.log4j.LogManager;\n+import org.apache.logging.log4j.Logger;\n+import org.broadinstitute.hellbender.cmdline.StandardArgumentDefinitions;\n+import org.broadinstitute.hellbender.exceptions.GATKException;\n+import org.broadinstitute.hellbender.exceptions.UserException;\n+import org.broadinstitute.hellbender.utils.Utils;\n+\n+import java.io.FileInputStream;\n+import java.io.FileNotFoundException;\n+import java.io.IOException;\n+import java.lang.reflect.InvocationTargetException;\n+import java.lang.reflect.Method;\n+import java.util.*;\n+import java.util.regex.Matcher;\n+import java.util.regex.Pattern;\n+\n+/**\n+ * A static class to contain configuration utility methods.\n+ * Created by jonn on 7/19/17.\n+ */\n+public final class ConfigUtils {\n+\n+    static private final Logger logger = LogManager.getLogger(ConfigUtils.class);\n+\n+    // This class just has static methods to help with configuration, so no need for this constructor.\n+    private ConfigUtils() {}\n+\n+    /**\n+     * A regex to use to look for variables in the Sources annotation\n+     */\n+    private static final Pattern sourcesAnnotationPathVariablePattern = Pattern.compile(\"\\\\$\\\\{(.*)}\");\n+\n+    /**\n+     * A set to keep track of the classes we've already resolved for configuration path purposes:\n+     */\n+    private static final Set<Class<? extends Config>> alreadyResolvedPathVariables = new HashSet<>();\n+\n+    /**\n+     * Value to set each variable for configuration file paths when the variable\n+     * has not been set in either Java System properties or environment properties.\n+     */\n+    @VisibleForTesting\n+    static final String NO_PATH_VARIABLE_VALUE = \"/dev/null\";\n+\n+    // =================================================================================================================\n+\n+    /**\n+     * Checks each of the given {@code filenameProperties} for if they are defined in system {@link System#getProperties()}\n+     * or environment {@link System#getenv()} properties.  If they are not, this method will set them in the\n+     * {@link ConfigFactory} to a non-existent path so the {@link ConfigFactory} will know to try to resolve them as\n+     * variables at load-time (and not as raw paths).\n+     * @param filenameProperties A {@link List} of filename properties as specified in {@link Config} {@link org.aeonbits.owner.Config.Sources} annotations to check for existence in system and environment properties.\n+     */\n+    @VisibleForTesting\n+    static void checkFileNamePropertyExistenceAndSetConfigFactoryProperties(final List<String> filenameProperties) {\n+        // Grab the system properties:\n+        final Properties systemProperties = System.getProperties();\n+\n+        // Grab the environment properties:\n+        final Map<String, String> environmentProperties = System.getenv();\n+\n+        // Make sure that if our property isn't in the system, environment, and ConfigFactory\n+        // properties, that we set it to a neutral value that will not contain\n+        // anything (so that the property will fall back into the next value).\n+        for (final String property : filenameProperties) {\n+\n+            if ( environmentProperties.keySet().contains(property) ) {\n+                logger.info(\"Config path variable found in Environment Properties: \" + property + \"=\" + environmentProperties.get(property) + \" - will search for config here.\");\n+            }\n+            else if ( systemProperties.keySet().contains(property) ) {\n+                logger.info(\"Config path variable found in System Properties: \" + property + \"=\" + systemProperties.get(property) + \" - will search for config here.\");\n+            }\n+            else if ( ConfigFactory.getProperties().keySet().contains(property) ) {\n+                logger.info(\"Config path variable found in Config Factory Properties(probably from the command-line): \" + property + \"=\" + ConfigFactory.getProperty(property) + \" - will search for config here.\");\n+            }\n+            else {\n+                logger.warn(\"Config path variable not found: \" + property +\n+                        \" - setting value to default empty variable: \" + NO_PATH_VARIABLE_VALUE);\n+                ConfigFactory.setProperty(property, NO_PATH_VARIABLE_VALUE);\n+            }\n+        }\n+    }\n+\n+    /**\n+     * Get a list of the config file variables from the given {@link Config} classes.\n+     * @param configurationClasses A list of configuration classes from which to extract variable names in their {@link org.aeonbits.owner.Config.Sources}.\n+     * @return A list of variables in the {@link org.aeonbits.owner.Config.Sources} of the given {@code configurationClasses}\n+     */\n+    @VisibleForTesting\n+    static List<String> getConfigPathVariableNamesFromConfigClasses(final List<Class<?>> configurationClasses) {\n+\n+        final List<String> configPathVariableNames = new ArrayList<>();\n+\n+        // Loop through our classes and grab any sources with variables in there:\n+        for ( final Class<?> clazz : configurationClasses ) {\n+\n+            // Make sure that we get config classes here:\n+            if ( Config.class.isAssignableFrom(clazz) ) {\n+                final Config.Sources annotation = clazz.getAnnotation(Config.Sources.class);\n+\n+                if ( annotation != null ) {\n+                    final String[] annotationValues = annotation.value();\n+\n+                    for (final String val : annotationValues) {\n+\n+                        final Matcher m = sourcesAnnotationPathVariablePattern.matcher(val);\n+                        if (m.find()) {\n+                            configPathVariableNames.add(m.group(1));\n+                        }\n+                    }\n+                }\n+            }\n+        }\n+\n+        return configPathVariableNames;\n+    }\n+\n+    /**\n+     * Get a list of the config file variables from the given {@link Config} class.\n+     * @param configClass A lconfiguration class from which to extract variable names in its {@link org.aeonbits.owner.Config.Sources}.\n+     * @return A list of variables in the {@link org.aeonbits.owner.Config.Sources} of the given {@code configClass}\n+     */\n+    @VisibleForTesting\n+    static <T extends Config> List<String> getSourcesAnnotationPathVariables(final Class<? extends T> configClass) {\n+\n+        final List<String> configPathVariableNames = new ArrayList<>();\n+\n+        final Config.Sources annotation = configClass.getAnnotation(Config.Sources.class);\n+\n+        if ( annotation != null ) {\n+            for (final String val : annotation.value()) {\n+\n+                final Matcher m = sourcesAnnotationPathVariablePattern.matcher(val);\n+                if (m.find()) {\n+                    configPathVariableNames.add(m.group(1));\n+                }\n+            }\n+        }\n+\n+        return configPathVariableNames;\n+    }\n+\n+    /**\n+     * Gets all system properties from the given {@link Config}-derived object.\n+     * System properties are denoted via the presence of the {@link SystemProperty} annotation.\n+     * @param config A {@link Config}-derived object from which to read system properties.\n+     * @param <T> A {@link Config}-derived type from which to read System Properties.\n+     * @return A properties {@link Map} representing all System Properties in the given {@code config}.\n+     */\n+    @VisibleForTesting\n+    static <T extends Config> Map<String, String> getSystemPropertiesFromConfig(final T config) {\n+\n+        final Map<String, String> properties = new HashMap<>();\n+\n+        // This is gross and uses reflection to get all methods in the given config class\n+        // and then interrogates those methods for internal data on the config parameters.\n+\n+        // We have to match our interfaces to the config interface that we're actually using.\n+        // It's not as simple as using getDeclaredMethods on the Class object because we'll get\n+        // a LOT of extraneous stuff that we don't care about.\n+        for ( final Class<?> classInterface : config.getClass().getInterfaces() ) {\n+\n+            // If we have an interface that is a child of the OWNER Config interface, then\n+            // we must have the right object.\n+            if (Config.class.isAssignableFrom(classInterface)) {\n+\n+                // Now we cycle through our interface methods, resolve parameter names,\n+                // and set the values in the system.\n+                for (final Method propertyMethod : classInterface.getDeclaredMethods()) {\n+\n+                    // Get the property name:\n+                    String propertyName = propertyMethod.getName();\n+\n+                    final Config.Key key = propertyMethod.getAnnotation(Config.Key.class);\n+                    if (key != null) {\n+                        propertyName = key.value();\n+                    }\n+\n+                    // Only set properties that have the SystemProperty annotation:\n+                    if (propertyMethod.getAnnotation(SystemProperty.class) == null)  {\n+                        continue;\n+                    }\n+\n+                    // Get the value of the property into a string:\n+                    final String propertyValue;\n+                    try {\n+                        propertyValue = String.valueOf( propertyMethod.invoke(config, new Object[]{}) );\n+                    } catch (final IllegalAccessException ex) {\n+                        throw new GATKException(\"Could not access the config getter: \" +\n+                                config.getClass().getSimpleName() + \".\" +\n+                                propertyMethod.getName(), ex);\n+\n+                    } catch (final InvocationTargetException ex) {\n+                        throw new GATKException(\"Could not invoke the config getter: \" +\n+                                config.getClass().getSimpleName() + \".\" +\n+                                propertyMethod.getName(), ex);\n+                    }\n+\n+                    // Add our property:\n+                    properties.put(propertyName, propertyValue);\n+                }\n+            }\n+        }\n+        return properties;\n+    }\n+\n+    /**\n+     * Injects the given property to the System Properties.\n+     * Validates that this property was set after setting it.\n+     * @param properties A {@link Map} of key, value pairs of properties to add to the System Properties.\n+     */\n+    @VisibleForTesting\n+    static void injectToSystemProperties(final Map<String, String> properties) {\n+\n+        for ( final String propertyName : properties.keySet() ) {\n+\n+            final String propertyValue = properties.get(propertyName);\n+\n+            System.setProperty(propertyName, propertyValue);\n+\n+            // Test for validation that it worked:\n+            final String propertyValueThatWasSet = System.getProperty(propertyName);\n+            if (propertyValueThatWasSet == null) {\n+                throw new GATKException(\"Unable to set System Property (\" + propertyName + \"=\" + propertyValue + \")!\");\n+            }\n+\n+            if (!propertyValueThatWasSet.equals(propertyValue)) {\n+                throw new GATKException(\"System Property corrupted (\" + propertyName + \"!=\" + propertyValue + \" -> \" + propertyValueThatWasSet + \")!\");\n+            }\n+        }\n+    }\n+\n+    // =================================================================================================================\n+\n+    /**\n+     * Override for {@link ConfigFactory#create(Class, Map[])} which will ensure that","path":"src/main/java/org/broadinstitute/hellbender/utils/config/ConfigUtils.java","position":241,"original_position":241,"commit_id":"471ccbc75ceb7c7b6dd5ee88faa675a278f9ebb5","original_commit_id":"471ccbc75ceb7c7b6dd5ee88faa675a278f9ebb5","user":{"login":"jonn-smith","id":11667487,"avatar_url":"https://avatars1.githubusercontent.com/u/11667487?v=4","gravatar_id":"","url":"https://api.github.com/users/jonn-smith","html_url":"https://github.com/jonn-smith","followers_url":"https://api.github.com/users/jonn-smith/followers","following_url":"https://api.github.com/users/jonn-smith/following{/other_user}","gists_url":"https://api.github.com/users/jonn-smith/gists{/gist_id}","starred_url":"https://api.github.com/users/jonn-smith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonn-smith/subscriptions","organizations_url":"https://api.github.com/users/jonn-smith/orgs","repos_url":"https://api.github.com/users/jonn-smith/repos","events_url":"https://api.github.com/users/jonn-smith/events{/privacy}","received_events_url":"https://api.github.com/users/jonn-smith/received_events","type":"User","site_admin":false},"body":"Fixed!","created_at":"2017-12-06T22:13:34Z","updated_at":"2017-12-06T22:13:34Z","html_url":"https://github.com/broadinstitute/gatk/pull/3447#discussion_r155377278","pull_request_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments/155377278"},"html":{"href":"https://github.com/broadinstitute/gatk/pull/3447#discussion_r155377278"},"pull_request":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447"}},"in_reply_to_id":155280137},"pull_request":{"url":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447","id":135887814,"html_url":"https://github.com/broadinstitute/gatk/pull/3447","diff_url":"https://github.com/broadinstitute/gatk/pull/3447.diff","patch_url":"https://github.com/broadinstitute/gatk/pull/3447.patch","issue_url":"https://api.github.com/repos/broadinstitute/gatk/issues/3447","number":3447,"state":"open","locked":false,"title":"Added in Owner style configuration file with some basic hooks.","user":{"login":"jonn-smith","id":11667487,"avatar_url":"https://avatars1.githubusercontent.com/u/11667487?v=4","gravatar_id":"","url":"https://api.github.com/users/jonn-smith","html_url":"https://github.com/jonn-smith","followers_url":"https://api.github.com/users/jonn-smith/followers","following_url":"https://api.github.com/users/jonn-smith/following{/other_user}","gists_url":"https://api.github.com/users/jonn-smith/gists{/gist_id}","starred_url":"https://api.github.com/users/jonn-smith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonn-smith/subscriptions","organizations_url":"https://api.github.com/users/jonn-smith/orgs","repos_url":"https://api.github.com/users/jonn-smith/repos","events_url":"https://api.github.com/users/jonn-smith/events{/privacy}","received_events_url":"https://api.github.com/users/jonn-smith/received_events","type":"User","site_admin":false},"body":"Added in code to pull config elements from the Owner configuration.\r\nHooked the configuration into the classes where it is necessary.\r\nAdded in a config file with defaults.\r\nAdded in utilities and consolidated hooks for configuration code.\r\nAdded in help text for configuration file options in gatk-launch.\r\n\r\nBasic configuration options have been implemented and hooked\r\ninto files where appropriate.\r\n\r\nConfiguration values in properties files cannot currently have\r\ntrailing spaces - this results in a parsing error.  There is a\r\nworkaround that has not yet been implemented.\r\n\r\nFixes #3126","created_at":"2017-08-15T20:45:20Z","updated_at":"2017-12-06T22:13:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b8f2e192610d049e0c7357532e8a266cf18adf7f","assignee":{"login":"jonn-smith","id":11667487,"avatar_url":"https://avatars1.githubusercontent.com/u/11667487?v=4","gravatar_id":"","url":"https://api.github.com/users/jonn-smith","html_url":"https://github.com/jonn-smith","followers_url":"https://api.github.com/users/jonn-smith/followers","following_url":"https://api.github.com/users/jonn-smith/following{/other_user}","gists_url":"https://api.github.com/users/jonn-smith/gists{/gist_id}","starred_url":"https://api.github.com/users/jonn-smith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonn-smith/subscriptions","organizations_url":"https://api.github.com/users/jonn-smith/orgs","repos_url":"https://api.github.com/users/jonn-smith/repos","events_url":"https://api.github.com/users/jonn-smith/events{/privacy}","received_events_url":"https://api.github.com/users/jonn-smith/received_events","type":"User","site_admin":false},"assignees":[{"login":"jonn-smith","id":11667487,"avatar_url":"https://avatars1.githubusercontent.com/u/11667487?v=4","gravatar_id":"","url":"https://api.github.com/users/jonn-smith","html_url":"https://github.com/jonn-smith","followers_url":"https://api.github.com/users/jonn-smith/followers","following_url":"https://api.github.com/users/jonn-smith/following{/other_user}","gists_url":"https://api.github.com/users/jonn-smith/gists{/gist_id}","starred_url":"https://api.github.com/users/jonn-smith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonn-smith/subscriptions","organizations_url":"https://api.github.com/users/jonn-smith/orgs","repos_url":"https://api.github.com/users/jonn-smith/repos","events_url":"https://api.github.com/users/jonn-smith/events{/privacy}","received_events_url":"https://api.github.com/users/jonn-smith/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447/commits","review_comments_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447/comments","review_comment_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments{/number}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/issues/3447/comments","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/471ccbc75ceb7c7b6dd5ee88faa675a278f9ebb5","head":{"label":"broadinstitute:jts_owner_config_file_3126","ref":"jts_owner_config_file_3126","sha":"471ccbc75ceb7c7b6dd5ee88faa675a278f9ebb5","user":{"login":"broadinstitute","id":393552,"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":27452807,"name":"gatk","full_name":"broadinstitute/gatk","owner":{"login":"broadinstitute","id":393552,"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},"private":false,"html_url":"https://github.com/broadinstitute/gatk","description":"Official code repository for GATK versions 4 and up","fork":false,"url":"https://api.github.com/repos/broadinstitute/gatk","forks_url":"https://api.github.com/repos/broadinstitute/gatk/forks","keys_url":"https://api.github.com/repos/broadinstitute/gatk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/gatk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/gatk/teams","hooks_url":"https://api.github.com/repos/broadinstitute/gatk/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/gatk/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/gatk/events","assignees_url":"https://api.github.com/repos/broadinstitute/gatk/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/gatk/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/gatk/tags","blobs_url":"https://api.github.com/repos/broadinstitute/gatk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/gatk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/gatk/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/gatk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/gatk/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/gatk/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/gatk/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/gatk/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/gatk/subscription","commits_url":"https://api.github.com/repos/broadinstitute/gatk/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/gatk/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/gatk/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/gatk/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/gatk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/gatk/merges","archive_url":"https://api.github.com/repos/broadinstitute/gatk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/gatk/downloads","issues_url":"https://api.github.com/repos/broadinstitute/gatk/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/gatk/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/gatk/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/gatk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/gatk/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/gatk/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/gatk/deployments","created_at":"2014-12-02T20:50:36Z","updated_at":"2017-12-04T16:49:26Z","pushed_at":"2017-12-06T22:12:00Z","git_url":"git://github.com/broadinstitute/gatk.git","ssh_url":"git@github.com:broadinstitute/gatk.git","clone_url":"https://github.com/broadinstitute/gatk.git","svn_url":"https://github.com/broadinstitute/gatk","homepage":"https://software.broadinstitute.org/gatk","size":167289,"stargazers_count":270,"watchers_count":270,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":107,"mirror_url":null,"archived":false,"open_issues_count":821,"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"},"forks":107,"open_issues":821,"watchers":270,"default_branch":"master"}},"base":{"label":"broadinstitute:master","ref":"master","sha":"7218a5616b5e28e935909132d26666d323f3970a","user":{"login":"broadinstitute","id":393552,"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":27452807,"name":"gatk","full_name":"broadinstitute/gatk","owner":{"login":"broadinstitute","id":393552,"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},"private":false,"html_url":"https://github.com/broadinstitute/gatk","description":"Official code repository for GATK versions 4 and up","fork":false,"url":"https://api.github.com/repos/broadinstitute/gatk","forks_url":"https://api.github.com/repos/broadinstitute/gatk/forks","keys_url":"https://api.github.com/repos/broadinstitute/gatk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/gatk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/gatk/teams","hooks_url":"https://api.github.com/repos/broadinstitute/gatk/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/gatk/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/gatk/events","assignees_url":"https://api.github.com/repos/broadinstitute/gatk/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/gatk/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/gatk/tags","blobs_url":"https://api.github.com/repos/broadinstitute/gatk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/gatk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/gatk/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/gatk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/gatk/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/gatk/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/gatk/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/gatk/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/gatk/subscription","commits_url":"https://api.github.com/repos/broadinstitute/gatk/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/gatk/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/gatk/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/gatk/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/gatk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/gatk/merges","archive_url":"https://api.github.com/repos/broadinstitute/gatk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/gatk/downloads","issues_url":"https://api.github.com/repos/broadinstitute/gatk/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/gatk/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/gatk/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/gatk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/gatk/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/gatk/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/gatk/deployments","created_at":"2014-12-02T20:50:36Z","updated_at":"2017-12-04T16:49:26Z","pushed_at":"2017-12-06T22:12:00Z","git_url":"git://github.com/broadinstitute/gatk.git","ssh_url":"git@github.com:broadinstitute/gatk.git","clone_url":"https://github.com/broadinstitute/gatk.git","svn_url":"https://github.com/broadinstitute/gatk","homepage":"https://software.broadinstitute.org/gatk","size":167289,"stargazers_count":270,"watchers_count":270,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":107,"mirror_url":null,"archived":false,"open_issues_count":821,"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"},"forks":107,"open_issues":821,"watchers":270,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447"},"html":{"href":"https://github.com/broadinstitute/gatk/pull/3447"},"issue":{"href":"https://api.github.com/repos/broadinstitute/gatk/issues/3447"},"comments":{"href":"https://api.github.com/repos/broadinstitute/gatk/issues/3447/comments"},"review_comments":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447/comments"},"review_comment":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/3447/commits"},"statuses":{"href":"https://api.github.com/repos/broadinstitute/gatk/statuses/471ccbc75ceb7c7b6dd5ee88faa675a278f9ebb5"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"jonn-smith"}}