Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-57877] - A Test Step to confirm the Builds have been Promoted. #135

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,30 @@
</build>

<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>2.3</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>2.6</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>2.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>maven-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package hudson.plugins.promoted_builds;

import com.google.common.collect.ImmutableSet;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.model.Run;
import hudson.model.TaskListener;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.workflow.steps.*;
import org.kohsuke.stapler.DataBoundConstructor;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

// A test step to check whether the promotion was successful or not.
// Later this step would be replaced by triggering a new "Promotion job"
public class AddPromotionBadgeStep extends Step{

private static final Logger LOGGER = Logger.getLogger("The Job was successfully Promoted");

// "job" AND "buildNumber" will be passed from other promotion Conditions
@CheckForNull
private String job;
private int buildNumber;

@DataBoundConstructor
public AddPromotionBadgeStep(String job, int buildNumber){
this.job = StringUtils.trimToNull(job);
this.buildNumber = buildNumber;
}

public String getJob(){
return job;
}
public void setJob(String job){
this.job = StringUtils.trimToNull(job);
}
public int getBuildNumber(){
return buildNumber;
}
public void setBuildNumber(int buildNumber){
this.buildNumber = buildNumber;
}

@Override
public StepExecution start(StepContext context) throws Exception{
return new Execution(context,getJob(),getBuildNumber());
}

@Extension
public static class DescriptorImpl extends StepDescriptor{

@Override
public String getFunctionName(){
return "addTestBadge";
}
@Override
public String getDisplayName(){
return "Add Test Promotion Step";
}

@Override
public Set<Class<?>> getRequiredContext(){
return ImmutableSet.of(Run.class,TaskListener.class);
}
}

public static class Execution extends AbstractSynchronousStepExecution<Void>{

//Escapes Serialization
private transient final String job;
private transient final int buildNumber;

Execution(@Nonnull StepContext context,@Nonnull String job,@Nonnull int buildNumber){


super(context);
this.job = StringUtils.trimToNull(job);
this.buildNumber = buildNumber;
}

@Override
protected Void run() throws Exception{
LOGGER.log(Level.FINER, "A dummy Step for Spot Promotion Check" );
return null;
}

private static final long serialVersionUID = 1L;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package hudson.plugins.promoted_builds;

import hudson.DescriptorExtensionList;
import hudson.ExtensionPoint;
import hudson.model.*;
import hudson.plugins.promoted_builds.util.JenkinsHelper;

import javax.annotation.CheckForNull;
import java.util.ArrayList;
import java.util.List;

public abstract class PipelinePromotionCondition implements ExtensionPoint, Describable<PipelinePromotionCondition> {

//for those promotions that don't satisfy the desired Promotion Conditions
@CheckForNull
public PromotionBadge isMet(Run<?,?> run, TaskListener listener){
return null;
}

//The method is used by the Conditions to label those who satisfy the presented Promotion Conditions.
public PromotionBadge isMet(PipelinePromotionProcess promotionProcess, Run<?,?> run, TaskListener listener){
return isMet(run,listener);
}

//Loads the descriptor with the URL
public PipelinePromotionConditionDescriptor getDescriptor() {
return (PipelinePromotionConditionDescriptor) JenkinsHelper.getInstance().getDescriptor(getClass());
}

//Holds a set of Descriptors
public static DescriptorExtensionList<PipelinePromotionCondition,PipelinePromotionConditionDescriptor> all() {
return JenkinsHelper.getInstance().<PipelinePromotionCondition,PipelinePromotionConditionDescriptor>getDescriptorList(PipelinePromotionCondition.class);
}

/**
* Returns a subset of {@link PipelinePromotionConditionDescriptor}s that applies to the given project.
*/
//Required Promotion Conditions to be satisfied for Promotion is being defined here.
public static List<PipelinePromotionConditionDescriptor> getApplicableTriggers(Job<?,?> p) {
List<PipelinePromotionConditionDescriptor> r = new ArrayList<PipelinePromotionConditionDescriptor>();
for (PipelinePromotionConditionDescriptor t : all()) {
if(t.isApplicable(p))
r.add(t);
}
return r;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
package hudson.plugins.promoted_builds;

import com.sun.mail.imap.ACL;
import hudson.model.*;
import hudson.plugins.promoted_builds.conditions.PipelineSelfPromotionCondition;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

import static org.jenkinsci.plugins.tokenmacro.impl.XmlFileMacro.LOGGER;

public class PipelinePromotionProcess {

@Nonnull
private final List<ParameterValue> parameters;

PipelinePromotionProcess(List<ParameterValue> parameters) {

this.parameters = parameters;
}

public List<PipelinePromotionProcess> justCheck = new ArrayList<>(parameters);


public String icon;

public String getIcon() {

return getIcon(icon);
}

@Nonnull
private static String getIcon(@CheckForNull String sIcon) {
if ((sIcon == null) || sIcon.equals(""))
return "star-gold";
else
return sIcon;
}

/**
//Probably won't work

@Override
public Job getRootProject() {

return getParent().getOwner().getRootProject();
}
// QUES: What About this JobPropertyImpl
@Override
public JobPropertyImpl getParent() {
return (JobPropertyImpl)super.getParent();
}

/**
* Gets the owner {@link AbstractProject} that configured {@link JobPropertyImpl} as
* a job property.
* @return Current owner project
*/
//(getParent) does not register
public Job<?,?> getOwner() {
return getParent().getOwner();
}


/**
* JENKINS-27716: Since 1.585, the promotion must explicitly indicate that
* it can be disabled. Otherwise, promotions which trigger automatically
* upon build completion will execute, even if they're archived.
*/
@Override public boolean supportsMakeDisabled() {
return true;
}




/**
* Checks if all the conditions to promote a build is met.
*
* @param build Build to be checked
* @return
* {@code null} if promotion conditions are not met.
* otherwise returns a list of badges that record how the promotion happened.
*/
@CheckForNull
public Status isMet(Run<?,?> run) {
List<PromotionBadge> badges = new ArrayList<PromotionBadge>();
for (PipelinePromotionProcess cond : justCheck) {
PromotionBadge b = cond.isMet(this, run);
if(b == null)
return null;
badges.add(b);
}
return new Status(this,badges);
}
// QUES: Now Goto Status?
/**
* Checks if the build is promotable, and if so, promote it.
*
* @param build Build to be promoted
* @return
* {@code null} if the build was not promoted, otherwise Future that kicks in when the build is completed.
* @throws IOException
*/


@CheckForNull
public Future<Promotion> considerPromotion2(Run<?,?> run, List<ParameterValue> params, TaskListener listener) throws IOException {

// QUES: Now Also GOTO PromotedBuildAction
PipelinePromotedBuildAction a = run.getAction(PipelinePromotedBuildAction.class);

// if it's already promoted, no need to do anything.
if(a!=null && a.contains(this))
return null;

LOGGER.fine("Considering the promotion of "+run+" via "+ getName() +" with parameters");
Status qualification = isMet(run);
if(qualification==null)
return null; // not this time

LOGGER.fine("Promotion condition of "+run+" is met: "+qualification);
Future<Promotion> f = promote2(run, new UserCause(), qualification, params); // TODO: define promotion cause
if (f==null)
LOGGER.warning(run+" qualifies for a promotion but the queueing failed.");
return f;
}


/**
* Promote the given build by using the given qualification.
*
* @param build Build to promote
* @param cause Why the build is promoted?
* @param qualification Initial promotion status
* @return Future to track the completion of the promotion.
* @throws IOException Promotion failure
*/
public Future<Promotion> promote2(Run<?,?> run, Cause cause, Status qualification) throws IOException {
return promote2(run, cause, qualification, null);
}

/**
* Promote the given build by using the given qualification.
*
* @param build Build to promote
* @param cause Why the build is promoted?
* @param qualification Initial promotion status
* @param params Promotion parameters
* @return Future to track the completion of the promotion.
* @throws IOException Promotion failure
*/
public Future<Promotion> promote2(Run<?,?> run, Cause cause, Status qualification, List<ParameterValue> params, TaskListener listener) throws IOException {
PipelinePromotedBuildAction a = run.getAction(PipelinePromotedBuildAction.class);
// build is qualified for a promotion.
if(a!=null) {
a.add(qualification);
} else {
run.addAction(new PipelinePromotedBuildAction(run,qualification));
run.save();
}

// schedule promotion activity.
return scheduleBuild2(run,cause, params);
}
//QUES: Should I leave it till here only?
// When are the real "Star" badges assigned maybe we should work till there?
/**
* @deprecated
* You need to be using {@link #scheduleBuild(AbstractBuild)}
*/


public boolean scheduleBuild(@Nonnull AbstractBuild<?,?> build) {
return scheduleBuild(build,new UserCause());
}

/**
* @param build Target build
* @param cause Promotion cause
* @return {@code true} if scheduling is successful
* @deprecated
* Use {@link #scheduleBuild2(AbstractBuild, Cause)}
*/

/**
* Schedules the promotion.
* @param build Target build
* @param cause Promotion cause
* @param params Parameters to be passed
* @return Future result or {@code null} if the promotion cannot be scheduled
*/

//QUES: Left as is!!
@CheckForNull
public Future<Promotion> scheduleBuild2(@Nonnull Run<?,?> run,
Cause cause, @CheckForNull List<ParameterValue> params) {
List<Action> actions = new ArrayList<Action>();
actions.add(Promotion.PromotionParametersAction.buildFor(run, params));
actions.add(new PipelineTargetAction(run));

// remember what build we are promoting
return super.scheduleBuild2(0, cause, actions.toArray(new Action[actions.size()]));
}

//QUES: After this it's all StaplerRequests
//Now go for (Status,PromotedBuildAction)







}
Loading