All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.tasks.BuildStep Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * 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
 *
 *
 *******************************************************************************/ 

package hudson.tasks;

import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.util.DescriptorList;
import java.io.IOException;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.WeakHashMap;

/**
 * One step of the whole build process.
 *
 * 

Persistence

These objects are persisted as a part of * {@link Project} by XStream. The save operation happens without any notice, * and the restore operation happens without calling the constructor, just like * Java serialization. * *

So generally speaking, derived classes should use instance variables only * for keeping configuration. You can still store objects you use for * processing, like a parser of some sort, but they need to be marked as * transient, and the code needs to be aware that they might be null * (which is the case when you access the field for the first time the object is * restored.) * * @author Kohsuke Kawaguchi */ public interface BuildStep { /** * Runs before the build begins. * * @return true if the build can continue, false if there was an error and * the build needs to be aborted. */ boolean prebuild(AbstractBuild build, BuildListener listener); /** * Runs the step over the given build and reports the progress to the * listener. * *

A plugin can contribute the action object to * {@link Build#getActions()} so that a 'report' becomes a part of the * persisted data of {@link Build}. This is how JUnit plugin attaches the * test report to a build page, for example. * * @return true if the build can continue, false if there was an error and * the build needs to be aborted. * * @throws InterruptedException If the build is interrupted by the user (in * an attempt to abort the build.) Normally the {@link BuildStep} * implementations may simply forward the exception it got from its * lower-level functions. * @throws IOException If the implementation wants to abort the processing * when an {@link IOException} happens, it can simply propagate the * exception to the caller. This will cause the build to fail, with the * default error message. Implementations are encouraged to catch * {@link IOException} on its own to provide a better error message, if it * can do so, so that users have better understanding on why it failed. */ boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException; /** * @deprecated as of 1.341. Use {@link #getProjectActions(AbstractProject)} * instead. */ Action getProjectAction(AbstractProject project); /** * Returns action objects if this {@link BuildStep} has actions to * contribute to a {@link Project}. * *

{@link Project} calls this method for every {@link BuildStep} that it * owns when the rendering is requested. * *

This action can have optional jobMain.jelly view, which will * be aggregated into the main panel of the job top page. The jelly file * should have an <h2> tag that shows the section title, followed by some * block elements to render the details of the section. * * @param project {@link Project} that owns this build step, since * {@link BuildStep} object doesn't usually have this "parent" pointer. * * @return can be empty but never null. */ Collection getProjectActions(AbstractProject project); /** * Declares the scope of the synchronization monitor this {@link BuildStep} * expects from outside. * *

This method is introduced for preserving compatibility with plugins * written for earlier versions of Hudson, which never run multiple builds * of the same job in parallel. Such plugins often assume that the outcome * of the previous build is completely available, which is no longer true * when we do concurrent builds. * *

To minimize the necessary code change for such plugins, * {@link BuildStep} implementations can request Hudson to externally * perform synchronization before executing them. This behavior is as * follows: * *

{@link BuildStepMonitor#BUILD}
This {@link BuildStep} is * only executed after the previous build is fully completed (thus fully * restoring the earlier semantics of one build at a time.) * *
{@link BuildStepMonitor#STEP}
This {@link BuildStep} is only * executed after the same step in the previous build is completed. For * build steps that use a weaker assumption and only rely on the output from * the same build step of the early builds, this improves the concurrency. * *
{@link BuildStepMonitor#NONE}
No external synchronization is * performed on this build step. This is the most efficient, and thus the * recommended value for newer plugins. Wherever necessary, you can * directly use {@link CheckPoint}s to perform necessary synchronizations. *
* *

Migrating Older Implementation

If you are migrating * {@link BuildStep} implementations written for earlier versions of Hudson, * here's what you can do: * *

  • Just return {@link BuildStepMonitor#BUILD} to demand the * backward compatible behavior from Hudson, and make no other changes to * the code. This will prevent users from reaping the benefits of concurrent * builds, but at least your plugin will work correctly, and therefore this * is a good easy first step.
  • If your build step doesn't use anything * from a previous build (for example, if you don't even call * {@link Run#getPreviousBuild()}), then you can return * {@link BuildStepMonitor#NONE} without making further code changes and you * are done with migration.
  • If your build step only depends on * {@link Action}s that you added in the previous build by yourself, then * you only need {@link BuildStepMonitor#STEP} scope synchronization. Return * it from this method ,and you are done with migration without any further * code changes.
  • If your build step makes more complex assumptions, * return {@link BuildStepMonitor#NONE} and use {@link CheckPoint}s directly * in your code. The general idea is to call {@link CheckPoint#block()} * before you try to access the state from the previous build.
* *

Note to caller

For plugins written against earlier versions * of Hudson, calling this method results in {@link AbstractMethodError}. * * @since 1.319 */ BuildStepMonitor getRequiredMonitorService(); /** * List of all installed builders. * * Builders are invoked to perform the build itself. * * @deprecated as of 1.286. Use {@link Builder#all()} for read access, and * use {@link Extension} for registration. */ public static final List> BUILDERS = new DescriptorList(Builder.class); /** * List of all installed publishers. * * Publishers are invoked after the build is completed, normally to perform * some post-actions on build results, such as sending notifications, * collecting results, etc. * * @see PublisherList#addNotifier(Descriptor) * @see PublisherList#addRecorder(Descriptor) * * @deprecated as of 1.286. Use {@link Publisher#all()} for read access, and * use {@link Extension} for registration. */ public static final PublisherList PUBLISHERS = new PublisherList(); /** * List of publisher descriptor. */ public static final class PublisherList extends AbstractList> { /** * {@link Descriptor}s are actually stored in here. Since * {@link PublisherList} lives longer than {@link Hudson} we cannot * directly use {@link ExtensionList}. */ private final DescriptorList core = new DescriptorList(Publisher.class); /** * For descriptors that are manually registered, remember what kind it * was since older plugins don't extend from neither {@link Recorder} * nor {@link Notifier}. */ /*package*/ static final WeakHashMap, Class/*either Recorder.class or Notifier.class*/> KIND = new WeakHashMap, Class>(); private PublisherList() { } /** * Adds a new publisher descriptor, which (generally speaking) shouldn't * alter the build result, but just report the build result by some * means, such as e-mail, IRC, etc. * *

This method adds the descriptor after all the "recorders". * * @see #addRecorder(Descriptor) */ public void addNotifier(Descriptor d) { KIND.put(d, Notifier.class); core.add(d); } /** * Adds a new publisher descriptor, which (generally speaking) alter the * build result based on some artifacts of the build. * *

This method adds the descriptor before all the "notifiers". * * @see #addNotifier(Descriptor) */ public void addRecorder(Descriptor d) { KIND.put(d, Recorder.class); core.add(d); } @Override public boolean add(Descriptor d) { return !contains(d) && core.add(d); } @Override public void add(int index, Descriptor d) { if (!contains(d)) { core.add(d); } } public Descriptor get(int index) { return core.get(index); } public int size() { return core.size(); } @Override public Iterator> iterator() { return core.iterator(); } @Override public boolean remove(Object o) { return core.remove(o); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy