private String getDotCiYml(DynamicBuild build) throws IOException {
     try {
         return build.getGithubRepositoryService().getGHFile(".ci.yml", build.getSha()).getContent();
     } catch (FileNotFoundException _){
         throw new InvalidBuildConfigurationException("No .ci.yml found.");
     }
 }
 @Override
 public Result runBuild(DynamicBuild build, BuildExecutionContext buildExecutionContext, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
     Map<String,Object> buildEnvironment = build.getEnvironmentWithChangeSet(listener);
     ShellCommands checkoutCommands = getCheckoutCommands(buildEnvironment);
     Map config = new GroovyYamlTemplateProcessor(getDotCiYml(build), buildEnvironment).getConfig();
     this.buildConfiguration = getBuildConfiguration(build.getParent().getFullName(),config,build.getBuildId(),checkoutCommands,build.getSha(),build.getNumber());
     build.setAxisList(buildConfiguration.getAxisList());
     Result result ;
     if(buildConfiguration.isParallelized()){
         ShellScriptRunner shellScriptRunner = new ShellScriptRunner(buildExecutionContext, listener);
         Result checkoutResult = shellScriptRunner.runScript(checkoutCommands);
         if(Result.FAILURE.equals(checkoutResult)) return checkoutResult;
         result = runMultiConfigbuildRunner(build, buildConfiguration, listener,launcher);
     }else{
         result = runSubBuild(new Combination(ImmutableMap.of("script", buildConfiguration.getOnlyRun())), buildExecutionContext, listener);
     }
     Result pluginResult = runPlugins(build, buildConfiguration.getPlugins(), listener, launcher);
     Result notifierResult = runNotifiers(build, buildConfiguration.getNotifiers(), listener);
     return  result.combine(pluginResult).combine(notifierResult);
 }
    private Result runMultiConfigbuildRunner(final DynamicBuild dynamicBuild, final BuildConfiguration buildConfiguration, final BuildListener listener, Launcher launcher) throws IOException, InterruptedException {
        SubBuildScheduler subBuildScheduler = new SubBuildScheduler(dynamicBuild, this, new SubBuildScheduler.SubBuildFinishListener() {
            @Override
            public void runFinished(DynamicSubBuild subBuild) throws IOException {
                for (DotCiPluginAdapter plugin : buildConfiguration.getPlugins()) {
                    plugin.runFinished(subBuild, dynamicBuild, listener);
                }
            }
        });

        try {
            Iterable<Combination> axisList = buildConfiguration.getAxisList().list();
            Result combinedResult = subBuildScheduler.runSubBuilds(axisList, listener);
            dynamicBuild.setResult(combinedResult);
            return combinedResult;
        } finally {
            try {
                subBuildScheduler.cancelSubBuilds(listener.getLogger());
            } catch (Exception e) {
                // There is nothing much we can do at this point
            }
        }
    }