use of org.jboss.pnc.spi.builddriver.CompletedBuild in project pnc by project-ncl.
the class DefaultBuildExecutor method runTheBuild.
private CompletableFuture<CompletedBuild> runTheBuild(DefaultBuildExecutionSession buildExecutionSession) {
CompletableFuture<CompletedBuild> waitToCompleteFuture = new CompletableFuture<>();
if (buildExecutionSession.isCanceled()) {
waitToCompleteFuture.complete(null);
return waitToCompleteFuture;
}
ProcessStageUtils.logProcessStageBegin(BuildExecutionStatus.BUILD_SETTING_UP.toString(), "Running the build ...");
buildExecutionSession.setStatus(BuildExecutionStatus.BUILD_SETTING_UP);
RunningEnvironment runningEnvironment = buildExecutionSession.getRunningEnvironment();
try {
Consumer<CompletedBuild> onComplete = value -> {
ProcessStageUtils.logProcessStageEnd(BuildExecutionStatus.BUILD_SETTING_UP.toString(), "Build completed.");
waitToCompleteFuture.complete(value);
};
Consumer<Throwable> onError = (e) -> {
ProcessStageUtils.logProcessStageEnd(BuildExecutionStatus.BUILD_SETTING_UP.toString(), "Build failed.");
waitToCompleteFuture.completeExceptionally(new BuildProcessException(e, runningEnvironment));
};
String buildAgentUrl = runningEnvironment.getBuildAgentUrl();
String liveLogWebSocketUrl = "ws" + StringUtils.addEndingSlash(buildAgentUrl).replaceAll("http(s?):", ":") + "socket/text/ro";
log.debug("Setting live log websocket url: {}", liveLogWebSocketUrl);
buildExecutionSession.setLiveLogsUri(Optional.of(new URI(liveLogWebSocketUrl)));
BuildDriver buildDriver = buildDriverFactory.getBuildDriver();
RunningBuild runningBuild = buildDriver.startProjectBuild(buildExecutionSession, runningEnvironment, onComplete, onError);
buildExecutionSession.setCancelHook(runningBuild::cancel);
buildExecutionSession.setStatus(BuildExecutionStatus.BUILD_WAITING);
} catch (Throwable e) {
throw new BuildProcessException(e, runningEnvironment);
}
return waitToCompleteFuture;
}
use of org.jboss.pnc.spi.builddriver.CompletedBuild in project pnc by project-ncl.
the class DefaultBuildExecutor method startBuilding.
@Override
public BuildExecutionSession startBuilding(BuildExecutionConfiguration buildExecutionConfiguration, Consumer<BuildExecutionStatusChangedEvent> onBuildExecutionStatusChangedEvent, String accessToken) throws ExecutorException {
DefaultBuildExecutionSession buildExecutionSession = new DefaultBuildExecutionSession(buildExecutionConfiguration, onBuildExecutionStatusChangedEvent);
String executionConfigurationId = buildExecutionConfiguration.getId();
DefaultBuildExecutionSession existing = runningExecutions.putIfAbsent(executionConfigurationId, buildExecutionSession);
if (existing != null) {
throw new AlreadyRunningException("Build execution with id: " + executionConfigurationId + " is already running.");
}
buildExecutionSession.setStartTime(new Date());
userLog.info("Starting build execution...");
buildExecutionSession.setStatus(BuildExecutionStatus.NEW);
buildExecutionSession.setAccessToken(accessToken);
DebugData debugData = new DebugData(buildExecutionConfiguration.isPodKeptOnFailure());
CompletableFuture.supplyAsync(() -> configureRepository(buildExecutionSession), executor).thenComposeAsync(repositoryConfiguration -> setUpEnvironment(buildExecutionSession, repositoryConfiguration, debugData), executor).thenComposeAsync(nul -> runTheBuild(buildExecutionSession), executor).thenApplyAsync(completedBuild -> {
buildExecutionSession.setCancelHook(null);
return optionallyEnableSsh(buildExecutionSession, completedBuild);
}, executor).thenApplyAsync(completedBuild -> retrieveBuildDriverResults(buildExecutionSession, completedBuild), executor).thenApplyAsync(nul -> retrieveRepositoryManagerResults(buildExecutionSession), executor).handleAsync((nul, e) -> {
// make sure there are no references left
buildExecutionSession.setCancelHook(null);
return completeExecution(buildExecutionSession, e);
}, executor);
// TODO re-connect running instances in case of crash
return buildExecutionSession;
}
use of org.jboss.pnc.spi.builddriver.CompletedBuild in project pnc by project-ncl.
the class LivenessProbeTest method shouldFailTheBuildWhenAgentIsNotResponding.
@Test
public void shouldFailTheBuildWhenAgentIsNotResponding() throws InterruptedException, BuildDriverException {
TermdBuildDriverModuleConfig buildDriverModuleConfig = mock(TermdBuildDriverModuleConfig.class);
doReturn(200L).when(buildDriverModuleConfig).getLivenessProbeFrequencyMillis();
doReturn(500L).when(buildDriverModuleConfig).getLivenessFailTimeoutMillis();
ClientMockFactory buildAgentClientMockFactory = new ClientMockFactory();
TermdBuildDriver driver = new TermdBuildDriver(systemConfig, buildDriverModuleConfig, buildAgentClientMockFactory);
BuildExecutionSession buildExecution = mock(BuildExecutionSession.class);
BuildExecutionConfiguration buildExecutionConfiguration = mock(BuildExecutionConfiguration.class);
doReturn(buildExecutionConfiguration).when(buildExecution).getBuildExecutionConfiguration();
RunningEnvironment runningEnvironment = mock(RunningEnvironment.class);
doReturn(Paths.get("")).when(runningEnvironment).getWorkingDirectory();
doReturn(new DebugData(false)).when(runningEnvironment).getDebugData();
doReturn("http://localhost/").when(runningEnvironment).getInternalBuildAgentUrl();
doReturn(runningEnvironment).when(buildExecution).getRunningEnvironment();
BlockingQueue<Throwable> result = new ArrayBlockingQueue(1);
Consumer<CompletedBuild> onComplete = (completedBuild) -> Assert.fail("Build should complete with error.");
Consumer<Throwable> onError = (throwable) -> {
try {
result.put(throwable);
} catch (InterruptedException e) {
Assert.fail("Error in the test. Unable to add the result to queue.");
}
};
// when
RunningBuild runningBuild = driver.startProjectBuild(buildExecution, runningEnvironment, onComplete, onError);
// then
Throwable throwable = result.poll(1, TimeUnit.SECONDS);
Assert.assertNotNull("It should complete with an exception.", throwable);
Assert.assertEquals("Build Agent has gone away.", throwable.getMessage());
}
use of org.jboss.pnc.spi.builddriver.CompletedBuild in project pnc by project-ncl.
the class TermdBuildDriverTest method shouldStartAndCancelTheExecutionImmediately.
@Test(timeout = 5_000)
public void shouldStartAndCancelTheExecutionImmediately() throws ConfigurationParseException, BuildDriverException, InterruptedException, IOException {
// given
String dirName = "test-workdir";
String logStart = "Running the command...";
String logEnd = "Command completed.";
TermdBuildDriver driver = new TermdBuildDriver(systemConfig, buildDriverModuleConfig, clientFactory);
BuildExecutionSession buildExecution = mock(BuildExecutionSession.class);
BuildExecutionConfiguration buildExecutionConfiguration = mock(BuildExecutionConfiguration.class);
doReturn("echo \"" + logStart + "\"; mvn validate; echo \"" + logEnd + "\";").when(buildExecutionConfiguration).getBuildScript();
doReturn(dirName).when(buildExecutionConfiguration).getName();
doReturn(buildExecutionConfiguration).when(buildExecution).getBuildExecutionConfiguration();
AtomicReference<CompletedBuild> buildResult = new AtomicReference<>();
// when
CountDownLatch latch = new CountDownLatch(1);
Consumer<CompletedBuild> onComplete = (completedBuild) -> {
buildResult.set(completedBuild);
latch.countDown();
};
Consumer<Throwable> onError = (throwable) -> {
logger.error("Error received: ", throwable);
fail(throwable.getMessage());
};
RunningBuild runningBuild = driver.startProjectBuild(buildExecution, localEnvironmentPointer, onComplete, onError);
runningBuild.cancel();
latch.await();
// then
assertThat(buildResult.get().getBuildResult().getBuildLog()).doesNotContain(logEnd);
assertThat(buildResult.get().getBuildResult().getBuildStatus()).isEqualTo(CANCELLED);
}
use of org.jboss.pnc.spi.builddriver.CompletedBuild in project pnc by project-ncl.
the class TermdBuildDriver method startProjectBuild.
public RunningBuild startProjectBuild(BuildExecutionSession buildExecutionSession, RunningEnvironment runningEnvironment, Consumer<CompletedBuild> onComplete, Consumer<Throwable> onError, Optional<Consumer<Status>> onStatusUpdate) throws BuildDriverException {
logger.info("[{}] Starting build for Build Execution Session {}", runningEnvironment.getId(), buildExecutionSession.getId());
TermdRunningBuild termdRunningBuild = new TermdRunningBuild(runningEnvironment, buildExecutionSession.getBuildExecutionConfiguration(), onComplete, onError);
DebugData debugData = runningEnvironment.getDebugData();
String buildScript = prepareBuildScript(termdRunningBuild, debugData);
if (!termdRunningBuild.isCanceled()) {
String terminalUrl = getBuildAgentUrl(runningEnvironment);
final RemoteInvocation remoteInvocation = new RemoteInvocation(clientFactory, terminalUrl, onStatusUpdate, httpCallbackMode, buildExecutionSession.getId(), buildExecutionSession.getAccessToken());
buildExecutionSession.setBuildStatusUpdateConsumer(remoteInvocation.getClientStatusUpdateConsumer());
FileTransfer fileTransfer = new ClientFileTransfer(remoteInvocation.getBuildAgentClient(), MAX_LOG_SIZE);
fileTransferReadTimeout.ifPresent(fileTransfer::setReadTimeout);
CompletableFuture<Void> prepareBuildFuture = CompletableFuture.supplyAsync(() -> {
logger.debug("Uploading build script to build environment ...");
return uploadTask(termdRunningBuild.getRunningEnvironment(), buildScript, fileTransfer);
}, executor).thenApplyAsync(scriptPath -> {
logger.debug("Setting the script path ...");
remoteInvocation.setScriptPath(scriptPath);
return null;
}, executor).thenRunAsync(() -> {
logger.debug("Invoking remote script ...");
invokeRemoteScript(remoteInvocation);
}, executor);
CompletableFuture<RemoteInvocationCompletion> buildLivenessFuture = prepareBuildFuture.thenComposeAsync(nul -> {
logger.debug("Starting liveness monitor ...");
return monitorBuildLiveness(remoteInvocation);
}, executor);
CompletableFuture<RemoteInvocationCompletion> buildCompletionFuture = prepareBuildFuture.thenComposeAsync(nul -> {
logger.debug("Waiting fo remote script to complete...");
return remoteInvocation.getCompletionNotifier();
}, executor);
CompletableFuture<RemoteInvocationCompletion> optionallyEnableDebug = buildCompletionFuture.thenApplyAsync(remoteInvocationCompletion -> {
Status status = remoteInvocationCompletion.getStatus();
if (status.isFinal()) {
logger.debug("Script completionNotifier completed with status {}.", status);
if ((status == FAILED || status == SYSTEM_ERROR) && debugData.isEnableDebugOnFailure()) {
debugData.setDebugEnabled(true);
remoteInvocation.enableSsh();
}
}
return remoteInvocationCompletion;
}, executor);
CompletableFuture<Object> buildFuture = CompletableFuture.anyOf(buildLivenessFuture, optionallyEnableDebug);
buildFuture.handle((result, exception) -> {
RemoteInvocationCompletion completion;
if (result != null) {
// both of combined futures return the same type
RemoteInvocationCompletion remoteInvocationCompletion = (RemoteInvocationCompletion) result;
if (remoteInvocationCompletion.getException() != null) {
logger.warn("Completing build execution.", remoteInvocationCompletion.getException());
} else {
logger.debug("Completing build execution. Status: {};", remoteInvocationCompletion.getStatus());
}
completion = remoteInvocationCompletion;
} else if (exception != null && exception.getCause() instanceof java.util.concurrent.CancellationException) {
// canceled in non build operation (completableFuture cancel), non graceful completion
logger.warn("Completing build execution. Cancelled;");
completion = new RemoteInvocationCompletion(INTERRUPTED, Optional.empty());
} else {
logger.warn("Completing build execution. System error.", exception);
completion = new RemoteInvocationCompletion(new BuildDriverException("System error.", exception));
}
termdRunningBuild.setCancelHook(null);
remoteInvocation.close();
complete(termdRunningBuild, completion, fileTransfer);
return null;
});
termdRunningBuild.setCancelHook(() -> {
// try to cancel remote execution
remoteInvocation.cancel();
ScheduledFuture<?> forceCancel_ = scheduledExecutorService.schedule(() -> {
logger.debug("Force cancelling build ...");
prepareBuildFuture.cancel(true);
}, internalCancelTimeoutMillis, TimeUnit.MILLISECONDS);
remoteInvocation.addPreClose(() -> forceCancel_.cancel(false));
});
} else {
logger.debug("Skipping script uploading (cancel flag) ...");
}
return termdRunningBuild;
}
Aggregations