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

feature: 1. display build parameters 2. auto load builds option in settings #246

Merged
merged 12 commits into from
Oct 12, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ public void setShowAllInStatusbar(boolean showAllInStatusbar) {
myState.setShowAllInStatusbar(showAllInStatusbar);
}

public boolean isAutoLoadBuilds() {
return myState.isAutoLoadBuilds();
}

public void setAutoLoadBuilds(boolean autoLoadBuilds) {
myState.setAutoLoadBuilds(autoLoadBuilds);
}

@Data
public static class State {

Expand All @@ -182,6 +190,7 @@ public static class State {
private RssSettings rssSettings = new RssSettings();
private boolean useGreenColor = false;
private boolean showAllInStatusbar = false;
private boolean autoLoadBuilds = false;
}

@Data
Expand Down
92 changes: 59 additions & 33 deletions src/main/java/org/codinjutsu/tools/jenkins/JenkinsTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.tree.TreeUtil;
import lombok.val;
import org.codinjutsu.tools.jenkins.model.Build;
import org.codinjutsu.tools.jenkins.model.BuildParameter;
import org.codinjutsu.tools.jenkins.model.Jenkins;
import org.codinjutsu.tools.jenkins.model.Job;
import org.codinjutsu.tools.jenkins.util.GuiUtil;
Expand All @@ -23,13 +25,23 @@
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.tree.*;
import java.util.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;

public class JenkinsTree implements PersistentStateComponent<JenkinsTreeState> {
private static final String LOADING = "Loading...";
private static final String UNAVAILABLE = "No Jenkins server available";
private static final TreeState NO_TREE_STATE = null;
private static final Logger LOG = Logger.getInstance(JenkinsTree.class);
@NotNull
private final JenkinsSettings jenkinsSettings;
private final Jenkins jenkins;
Expand All @@ -38,7 +50,6 @@ public class JenkinsTree implements PersistentStateComponent<JenkinsTreeState> {
private JenkinsTreeState state = new JenkinsTreeState();
@Nullable
private TreeState lastTreeState = NO_TREE_STATE;
private static final Logger LOG = Logger.getInstance(JenkinsTree.class);

public JenkinsTree(Project project, @NotNull JenkinsSettings jenkinsSettings, Jenkins jenkins) {
super();
Expand All @@ -56,17 +67,6 @@ public JenkinsTree(Project project, @NotNull JenkinsSettings jenkinsSettings, Je
this.tree.addMouseListener(new JobClickHandler());
}

@NotNull
public static DefaultMutableTreeNode fillJobTree(@NotNull Job job, @NotNull DefaultMutableTreeNode jobNode) {
jobNode.removeAllChildren();
if (job.getJobType().containNestedJobs()) {
job.getNestedJobs().stream().map(JenkinsTree::createJobTree).forEach(jobNode::add);
} else {
job.getLastBuilds().stream().map(JenkinsTree::createNode).forEach(jobNode::add);
}
return jobNode;
}

@NotNull
public static Optional<Job> getJob(TreePath treePath) {
final Class<JenkinsTreeNode.JobNode> jobNodeClass = JenkinsTreeNode.JobNode.class;
Expand All @@ -81,7 +81,7 @@ public static Optional<Job> getJob(@NotNull DefaultMutableTreeNode node) {

@NotNull
public static <T> Optional<T> getNode(@NotNull DefaultMutableTreeNode node, @NotNull Class<T> expectedClass) {
return Optional.ofNullable(node.getUserObject()).filter(expectedClass::isInstance).map(expectedClass::cast);
return Optional.ofNullable(node.getUserObject()).filter(expectedClass::isInstance).map(expectedClass::cast);
}

@NotNull
Expand All @@ -93,9 +93,14 @@ public static <T> Optional<T> getLastSelectedPath(@NotNull TreePath treePath, @N
.filter(expectedClass::isInstance).map(expectedClass::cast);
}

@NotNull
private static DefaultMutableTreeNode createNode(BuildParameter buildParameter) {
return new DefaultMutableTreeNode(new JenkinsTreeNode.BuildParameterNode(buildParameter), true);
}

@NotNull
private static DefaultMutableTreeNode createNode(Build build) {
return new DefaultMutableTreeNode(new JenkinsTreeNode.BuildNode(build), false);
return new DefaultMutableTreeNode(new JenkinsTreeNode.BuildNode(build), true);
}

@NotNull
Expand All @@ -105,7 +110,41 @@ private static DefaultMutableTreeNode createNode(Job job) {
}

@NotNull
private static DefaultMutableTreeNode createJobTree(Job job) {
private static Comparator<DefaultMutableTreeNode> wrapJobSorter(Comparator<Job> jobComparator) {
return (node1, node2) -> {
final Optional<Job> job1 = JenkinsTree.getJob(node1);
final Optional<Job> job2 = JenkinsTree.getJob(node2);
if (job1.isPresent() && job2.isPresent()) {
return jobComparator.compare(job1.get(), job2.get());
}
return 0;
};
}

@NotNull
public DefaultMutableTreeNode fillJobTree(@NotNull Job job, @NotNull DefaultMutableTreeNode jobNode) {
jobNode.removeAllChildren();
if (job.getJobType().containNestedJobs()) {
job.getNestedJobs().stream().map(this::createJobTree).forEach(jobNode::add);
} else {
job.getLastBuilds().stream().map(this::initBuildNode).forEach(jobNode::add);
}
return jobNode;
}
MCMicS marked this conversation as resolved.
Show resolved Hide resolved

@NotNull
private DefaultMutableTreeNode initBuildNode(Build build) {
MCMicS marked this conversation as resolved.
Show resolved Hide resolved
val buildNode = createNode(build);
Optional.ofNullable(build.getBuildParameterList())
MCMicS marked this conversation as resolved.
Show resolved Hide resolved
.ifPresent(buildParameters -> buildParameters.stream()
.map(JenkinsTree::createNode)
.forEach(buildNode::add)
);
return buildNode;
}

@NotNull
private DefaultMutableTreeNode createJobTree(Job job) {
return fillJobTree(job, createNode(job));
}

Expand Down Expand Up @@ -149,7 +188,7 @@ public void setJobs(@NotNull final Collection<Job> jobs) {

private void setJobs(@NotNull final Collection<Job> jobs, @NotNull DefaultMutableTreeNode rootNode) {
rootNode.removeAllChildren();
jobs.stream().map(JenkinsTree::createJobTree).forEach(rootNode::add);
jobs.stream().map(this::createJobTree).forEach(rootNode::add);
tree.setRootVisible(true);
}

Expand Down Expand Up @@ -183,8 +222,7 @@ public JenkinsTreeState getState() {
try {
state.treeState = new Element("root");
treeState.writeExternal(state.treeState);
}
catch (WriteExternalException e) {
} catch (WriteExternalException e) {
LOG.warn(e);
}
});
Expand All @@ -211,7 +249,7 @@ public void loadState(@NotNull JenkinsTreeState state) {
public void updateJobNode(@NotNull Job job) {
final DefaultTreeModel model = getModel();
findNodes(job).forEach(jobNode -> {
JenkinsTree.fillJobTree(job, jobNode);
fillJobTree(job, jobNode);
MCMicS marked this conversation as resolved.
Show resolved Hide resolved
model.nodeChanged(jobNode);
model.nodeStructureChanged(jobNode);
});
Expand Down Expand Up @@ -248,18 +286,6 @@ public void sortJobs(Comparator<Job> comparator) {
GuiUtil.runInSwingThread(() -> model.nodeStructureChanged((TreeNode) model.getRoot()));
}

@NotNull
private static Comparator<DefaultMutableTreeNode> wrapJobSorter(Comparator<Job> jobComparator) {
return (node1, node2) -> {
final Optional<Job> job1 = JenkinsTree.getJob(node1);
final Optional<Job> job2 = JenkinsTree.getJob(node2);
if (job1.isPresent() && job2.isPresent()) {
return jobComparator.compare(job1.get(), job2.get());
}
return 0;
};
}

@SuppressWarnings("java:S110")
private static class TreeWithoutDefaultSearch extends SimpleTree {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,31 @@
import com.github.cliftonlabs.json_simple.JsonObject;
import com.github.cliftonlabs.json_simple.Jsoner;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger;
import org.codinjutsu.tools.jenkins.model.*;
import org.codinjutsu.tools.jenkins.model.Build;
import org.codinjutsu.tools.jenkins.model.BuildParameter;
import org.codinjutsu.tools.jenkins.model.BuildStatusEnum;
import org.codinjutsu.tools.jenkins.model.BuildType;
import org.codinjutsu.tools.jenkins.model.Computer;
import org.codinjutsu.tools.jenkins.model.Jenkins;
import org.codinjutsu.tools.jenkins.model.Job;
import org.codinjutsu.tools.jenkins.model.JobParameter;
import org.codinjutsu.tools.jenkins.model.JobParameterType;
import org.codinjutsu.tools.jenkins.model.JobType;
import org.codinjutsu.tools.jenkins.model.View;
import org.codinjutsu.tools.jenkins.util.DateUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.Collectors;

public class JenkinsJsonParser implements JenkinsParser {
Expand Down Expand Up @@ -166,10 +184,37 @@ private Build getBuild(@Nullable JsonObject lastBuildObject) {
if (duration != null) {
builder.duration(duration);
}

// set parameter
Optional.ofNullable(getActions(lastBuildObject))
.flatMap(actions -> actions.stream()
.filter(action -> isContainParameters((JsonObject) action))
.findFirst()
)
.ifPresent(action ->
builder.buildParameterList(getBuildParameters((JsonObject) action))
);
return builder.build();
}

@Nullable
private JsonArray getActions(@NotNull JsonObject lastBuildObject) {
return lastBuildObject.getCollection(createJsonKey(ACTIONS));
}

@NotNull
private List<BuildParameter> getBuildParameters(JsonObject action) {
return action.getCollection(createJsonKey(PARAMETERS)).stream()
.map(parameter -> BuildParameter.of(
((JsonObject) parameter).getString(createJsonKey("name")),
((JsonObject) parameter).getString(createJsonKey("value"))
))
MCMicS marked this conversation as resolved.
Show resolved Hide resolved
.collect(Collectors.toList());
}

private boolean isContainParameters(JsonObject action) {
return ObjectUtils.isNotEmpty(action.getCollection(createJsonKey(PARAMETERS)));
}

@NotNull
private List<Build> getBuilds(@NotNull JsonArray buildsObjects) {
List<Build> builds = new LinkedList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public interface JenkinsParser {
String PARAMETER_CHOICE = "choices";
String CLASS = "_class";
String COMPUTER = "computer";
String ACTIONS = "actions";
String PARAMETERS = "parameters";

Jenkins createWorkspace(String jsonData);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public class UrlBuilder {
private static final String TREE_PARAM = "?tree=";
private static final String URL = "url";
private static final String BASIC_JENKINS_INFO = URL + ",description,nodeName,nodeDescription,primaryView[name,url],views[name,url,views[name,url]]";
private static final String BASIC_BUILD_INFO = URL + ",id,building,result,number,displayName,fullDisplayName,timestamp,duration";
private static final String BASIC_BUILD_INFO = URL + ",id,building,result,number,displayName,fullDisplayName," +
"timestamp,duration,actions[parameters[name,value]]";
private static final String BASIC_JOB_INFO = "name,fullName,displayName,fullDisplayName,jobs," + URL + ",color,buildable,inQueue,healthReport[description,iconUrl],lastBuild[" + BASIC_BUILD_INFO + "],lastFailedBuild[" + URL + "],lastSuccessfulBuild[" + URL + "],property[parameterDefinitions[name,type,defaultParameterValue[value],description,choices]]";
private static final String BASIC_VIEW_INFO = "name," + URL + ",jobs[" + BASIC_JOB_INFO + "]";
private static final String CLOUDBEES_VIEW_INFO = "name," + URL + ",views[jobs[" + BASIC_JOB_INFO + "]]";
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/codinjutsu/tools/jenkins/model/Build.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Value
Expand Down Expand Up @@ -56,6 +57,8 @@ public class Build {
@NotNull
@Builder.Default
private final BuildStatusEnum status = BuildStatusEnum.NULL;
@Nullable
private final List<BuildParameter> buildParameterList;
MCMicS marked this conversation as resolved.
Show resolved Hide resolved

@NotNull
public static Build createBuildFromWorkspace(String buildUrl, int number, String status, boolean isBuilding, String buildDate, Long timestamp, Long duration) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.codinjutsu.tools.jenkins.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import org.jetbrains.annotations.NotNull;

@Data
@Accessors(chain = true)
@AllArgsConstructor
public class BuildParameter {
@NotNull
private String name;
@NotNull
private String value;
MCMicS marked this conversation as resolved.
Show resolved Hide resolved

@NotNull
public static BuildParameter of(@NotNull String name, @NotNull String value) {
return new BuildParameter(name, value);
}

@Override
@NotNull
public String toString() {
return String.format("%s: %s", name, value);
}
MCMicS marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,11 @@ private void loadJobs() {
} else {
jobList = requestManager.loadJenkinsView(currentSelectedView);
}
if (jenkinsAppSettings.isAutoLoadBuilds()) {
for(Job job : jobList) {
job.setLastBuilds(requestManager.loadBuilds(job));
}
}
MCMicS marked this conversation as resolved.
Show resolved Hide resolved

jenkinsSettings.setLastSelectedView(currentSelectedView.getName());

Expand Down
Loading