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);
 }