/* This file is part of Delivery Pipeline Plugin. Delivery Pipeline Plugin is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Delivery Pipeline Plugin is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Delivery Pipeline Plugin. If not, see <http://www.gnu.org/licenses/>. */ package se.diabol.jenkins.pipeline.domain.task; import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Strings.isNullOrEmpty; import static se.diabol.jenkins.pipeline.domain.status.StatusFactory.disabled; import static se.diabol.jenkins.pipeline.domain.status.StatusFactory.idle; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Item; import hudson.model.ItemGroup; import jenkins.model.Jenkins; import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; import se.diabol.jenkins.pipeline.PipelineProperty; import se.diabol.jenkins.pipeline.domain.AbstractItem; import se.diabol.jenkins.pipeline.domain.results.StaticAnalysisResult; import se.diabol.jenkins.pipeline.domain.results.TestResult; import se.diabol.jenkins.pipeline.domain.status.SimpleStatus; import se.diabol.jenkins.pipeline.domain.status.Status; import se.diabol.jenkins.pipeline.token.TokenUtils; import se.diabol.jenkins.pipeline.util.BuildUtil; import se.diabol.jenkins.pipeline.util.ProjectUtil; import java.util.ArrayList; import java.util.List; @ExportedBean(defaultVisibility = AbstractItem.VISIBILITY) public class Task extends AbstractItem { private final String id; private final String link; private final List<TestResult> testResults; private final List<StaticAnalysisResult> staticAnalysisResults; private final Status status; private final ManualStep manual; private final String buildId; private final List<String> downstreamTasks; private final boolean initial; private final String description; private final AbstractProject project; public Task(AbstractProject project, String id, String name, Status status, String link, ManualStep manual, List<String> downstreamTasks, boolean initial, String description) { super(name); this.id = id; this.link = link; this.testResults = null; this.staticAnalysisResults = null; this.status = status; this.manual = manual; this.buildId = null; this.downstreamTasks = downstreamTasks; this.initial = initial; this.description = description; this.project = project; } public Task(Task task, String taskName, String buildId, Status status, String link, ManualStep manual, List<TestResult> testResults, List<StaticAnalysisResult> staticAnalysisResults, String description) { super(taskName); this.id = task.id; this.link = link; this.testResults = testResults; this.staticAnalysisResults = staticAnalysisResults; this.status = status; this.manual = manual; this.buildId = buildId; this.downstreamTasks = task.getDownstreamTasks(); this.initial = task.isInitial(); this.description = description; this.project = task.project; } @Exported public ManualStep getManualStep() { return manual; } @Exported public boolean isManual() { return manual != null; } @Exported public String getBuildId() { return buildId; } @Exported public String getId() { return id; } @Exported public String getLink() { return link; } @Exported public List<TestResult> getTestResults() { return testResults; } @Exported public List<StaticAnalysisResult> getStaticAnalysisResults() { return staticAnalysisResults; } @Exported public Status getStatus() { return status; } @Exported public List<String> getDownstreamTasks() { return downstreamTasks; } @Exported public String getDescription() { return description; } @Exported public boolean isRebuildable() { if (initial) { return false; } if (status.isRunning() || status.isIdle() || status.isNotBuilt() || status.isQueued() || status.isDisabled()) { return false; } else { return project.hasPermission(Item.BUILD); } } public boolean isInitial() { return initial; } public static Task getPrototypeTask(AbstractProject project, boolean initial) { PipelineProperty property = (PipelineProperty) project.getProperty(PipelineProperty.class); String taskName = property != null && !isNullOrEmpty(property.getTaskName()) ? property.getTaskName() : project.getDisplayName(); if (property == null && project.getParent() instanceof AbstractProject) { property = (PipelineProperty) ((AbstractProject) project.getParent()).getProperty(PipelineProperty.class); taskName = property != null && !isNullOrEmpty(property.getTaskName()) ? property.getTaskName() + " " + project.getName() : project.getDisplayName(); } String descriptionTemplate = property != null && !isNullOrEmpty(property.getDescriptionTemplate()) ? property.getDescriptionTemplate() : ""; Status status = project.isDisabled() ? disabled() : idle(); List<AbstractProject> downStreams = ProjectUtil.getDownstreamProjects(project); List<String> downStreamTasks = new ArrayList<String>(); for (AbstractProject downstreamProject : downStreams) { downStreamTasks.add(downstreamProject.getRelativeNameFrom(Jenkins.getInstance())); } return new Task(project, project.getRelativeNameFrom(Jenkins.getInstance()), taskName, status, project.getUrl(), ManualStep.resolveManualStep(project), downStreamTasks, initial, descriptionTemplate); } public Task getLatestTask(ItemGroup context, AbstractBuild firstBuild) { AbstractProject<?, ?> project = getProject(this, context); AbstractBuild<?, ?> build = null; if (!ProjectUtil.isQueued(project, firstBuild)) { build = BuildUtil.match(project.getBuilds(), firstBuild); } final Status taskStatus = SimpleStatus.resolveStatus(project, build, firstBuild); final ManualStep manualStep = ManualStep.getManualStepLatest(project, build, firstBuild); return new Task(this, resolveTaskName(project, getExpandedName(build)), resolveBuildId(taskStatus, build), taskStatus, resolveTaskLink(taskStatus, build), manualStep, TestResult.getResults(build), StaticAnalysisResult.getResults(build), getBuildDescription(build)); } public Task getAggregatedTask(AbstractBuild versionBuild, ItemGroup context) { AbstractProject<?, ?> taskProject = getProject(this, context); AbstractBuild<?, ?> build = BuildUtil.match(taskProject.getBuilds(), versionBuild); final Status taskStatus = SimpleStatus.resolveStatus(taskProject, build, null); final ManualStep manualStep = this.getManualStep(); return new Task(this, resolveTaskName(project, getExpandedName(build)), resolveBuildId(taskStatus, build), taskStatus, resolveTaskLink(taskStatus, build), manualStep, TestResult.getResults(build), StaticAnalysisResult.getResults(build), getBuildDescription(build)); } private String getBuildDescription(AbstractBuild<?, ?> build) { return TokenUtils.decodedTemplate(build, resolveBuildDescription(build)); } private String resolveTaskName(AbstractProject<?, ?> project, String name) { return (TokenUtils.stringIsNotEmpty(name) ? name : project.getDisplayName()); } private String getExpandedName(AbstractBuild<?, ?> build) { return TokenUtils.decodedTemplate(build, this.getName()); } private String resolveTaskLink(Status taskStatus, AbstractBuild build) { String taskLink = this.getLink(); if (build != null && !taskStatus.isIdle() && !taskStatus.isQueued()) { if (taskStatus.isRunning()) { taskLink = build.getUrl() + "console"; } else { taskLink = build.getUrl(); } } return taskLink; } private String resolveBuildId(Status taskStatus, AbstractBuild build) { String taskBuildId = null; if (build != null && !taskStatus.isIdle() && !taskStatus.isQueued()) { taskBuildId = String.valueOf(build.getNumber()); } return taskBuildId; } private String resolveBuildDescription(AbstractBuild build) { String buildDescription = this.getDescription(); if (isNullOrEmpty(buildDescription) && build != null) { buildDescription = build.getDescription(); } return buildDescription; } private AbstractProject getProject(Task task, ItemGroup context) { return ProjectUtil.getProject(task.getId(), context); } @Override public String toString() { return toStringHelper(this) .add("id", id) .add("link", link) .add("testResults", testResults) .add("staticAnalysisResults", staticAnalysisResults) .add("status", status) .add("manual", manual) .add("buildId", buildId) .add("downstreamTasks", downstreamTasks).toString(); } }