
hudson.model.Build Maven / Gradle / Ivy
Show all versions of hudson-core Show documentation
/*******************************************************************************
*
* Copyright (c) 2004-2009 Oracle Corporation.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
* Kohsuke Kawaguchi, Martin Eigenbrodt
*
*
*******************************************************************************/
package hudson.model;
import hudson.tasks.BuildStep;
import hudson.tasks.BuildWrapper;
import hudson.tasks.Builder;
import hudson.tasks.Recorder;
import hudson.tasks.Notifier;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import static hudson.model.Result.FAILURE;
import static hudson.model.Result.ABORTED;
/**
* A build of a {@link Project}.
*
* Steps of a build
Roughly speaking, a {@link Build} goes through
* the following stages:
*
*
- SCM checkout
- Hudson decides which directory to use for a build,
* then the source code is checked out
*
*
- Pre-build steps
- Everyone gets their
* {@link BuildStep#prebuild(AbstractBuild, BuildListener)} invoked to indicate
* that the build is starting
*
*
- Build wrapper set up
*
- {@link BuildWrapper#setUp(AbstractBuild, Launcher, BuildListener)} is
* invoked. This is normally to prepare an environment for the build.
*
*
- Builder runs
*
- {@link Builder#perform(AbstractBuild, Launcher, BuildListener)} is
* invoked. This is where things that are useful to users happen, like calling
* Ant, Make, etc.
*
*
- Recorder runs
*
- {@link Recorder#perform(AbstractBuild, Launcher, BuildListener)} is
* invoked. This is normally to record the output from the build, such as test
* results.
*
*
- Notifier runs
*
- {@link Notifier#perform(AbstractBuild, Launcher, BuildListener)} is
* invoked. This is normally to send out notifications, based on the results
* determined so far.
*
* And beyond that, the build is considered complete, and from then on
* {@link Build} object is there to keep the record of what happened in this
* build.
*
* @author Kohsuke Kawaguchi
*/
public abstract class Build
, B extends Build
>
extends AbstractBuild
{
/**
* Creates a new build.
*/
protected Build(P project) throws IOException {
super(project);
}
protected Build(P job, Calendar timestamp) {
super(job, timestamp);
}
/**
* Loads a build from a log file.
*/
protected Build(P project, File buildDir) throws IOException {
super(project, buildDir);
}
//
//
// actions
//
//
@Override
public void run() {
run(createRunner());
}
protected Runner createRunner() {
return new RunnerImpl();
}
protected class RunnerImpl extends AbstractRunner {
protected Result doRun(BuildListener listener) throws Exception {
if (!preBuild(listener, project.getBuilders())) {
return FAILURE;
}
if (!preBuild(listener, project.getPublishers())) {
return FAILURE;
}
Result r = null;
try {
List wrappers = new ArrayList(project.getBuildWrappers().values());
ParametersAction parameters = getAction(ParametersAction.class);
if (parameters != null) {
parameters.createBuildWrappers(Build.this, wrappers);
}
for (BuildWrapper w : wrappers) {
Environment e = w.setUp((AbstractBuild, ?>) Build.this, launcher, listener);
if (e == null) {
return (r = FAILURE);
}
buildEnvironments.add(e);
}
if (!build(listener, project.getBuilders())) {
r = FAILURE;
}
} catch (InterruptedException e) {
r = ABORTED;
throw e;
} finally {
if (r != null) {
setResult(r);
}
// tear down in reverse order
boolean failed = false;
for (int i = buildEnvironments.size() - 1; i >= 0; i--) {
if (!buildEnvironments.get(i).tearDown(Build.this, listener)) {
failed = true;
}
}
// WARNING The return in the finally clause will trump any return before
if (failed) {
return FAILURE;
}
}
return r;
}
public void post2(BuildListener listener) throws IOException, InterruptedException {
if (!performAllBuildSteps(listener, project.getPublishers(), true)) {
setResult(FAILURE);
}
if (!performAllBuildSteps(listener, project.getProperties(), true)) {
setResult(FAILURE);
}
}
@Override
public void cleanUp(BuildListener listener) throws Exception {
// at this point it's too late to mark the build as a failure, so ignore return value.
performAllBuildSteps(listener, project.getPublishers(), false);
performAllBuildSteps(listener, project.getProperties(), false);
super.cleanUp(listener);
}
private boolean build(BuildListener listener, Collection steps) throws IOException, InterruptedException {
for (BuildStep bs : steps) {
if (!perform(bs, listener)) {
return false;
}
}
return true;
}
}
private static final Logger LOGGER = Logger.getLogger(Build.class.getName());
}