Skip to content

Commit

Permalink
add jira issue step for pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
aatarasoff committed Jun 14, 2016
2 parents a79b0fd + 3a7212b commit 69621d8
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 1 deletion.
110 changes: 110 additions & 0 deletions src/main/java/hudson/plugins/jira/pipeline/IssueUpdateStep.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package hudson.plugins.jira.pipeline;

import com.google.inject.Inject;
import hudson.Extension;
import hudson.Util;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.plugins.jira.JiraSite;
import hudson.plugins.jira.Messages;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution;
import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
import org.kohsuke.stapler.DataBoundConstructor;

import javax.annotation.Nonnull;
import java.io.IOException;

/**
* Step for updating jira issue with workflow migration
*
* @author aatarasoff
*/
public class IssueUpdateStep extends AbstractStepImpl {
private final String jqlSearch;
private final String workflowActionName;
private final String comment;

@DataBoundConstructor
public IssueUpdateStep(@Nonnull String jqlSearch, @Nonnull String workflowActionName, String comment) {
this.jqlSearch = Util.fixEmptyAndTrim(jqlSearch);
this.workflowActionName = Util.fixEmptyAndTrim(workflowActionName);
this.comment = Util.fixEmptyAndTrim(comment);
}

public String getJqlSearch() {
return jqlSearch;
}

public String getWorkflowActionName() {
return workflowActionName;
}

public String getComment() {
return comment;
}

@Extension(optional = true)
public static final class DescriptorImpl extends AbstractStepDescriptorImpl {

public DescriptorImpl() {
super(IssueUpdateStep.StepExecution.class);
}

@Override
public String getFunctionName() {
return "jiraIssueUpdate";
}

@Override
public String getDisplayName() {
return Messages.IssueUpdateStep_Descriptor_DisplayName();
}
}

public static class StepExecution extends AbstractSynchronousNonBlockingStepExecution<Void> {

private static final long serialVersionUID = 1L;

@Inject
private transient IssueUpdateStep step;

@StepContextParameter
private transient TaskListener listener;

@StepContextParameter
private transient Run run;

@Override
protected Void run() throws Exception {
JiraSite site = JiraSite.get(run.getParent());

if (site == null) {
listener.getLogger().println(Messages.Updater_NoJiraSite());
run.setResult(Result.FAILURE);
}

if (StringUtils.isNotEmpty(step.getWorkflowActionName())) {
listener.getLogger().println(Messages.JiraIssueUpdateBuilder_UpdatingWithAction(step.getWorkflowActionName()));
}

listener.getLogger().println("[JIRA] JQL: " + step.getJqlSearch());

try {
if (!site.progressMatchingIssues(step.getJqlSearch(), step.workflowActionName, step.getComment(), listener.getLogger())) {
listener.getLogger().println(Messages.JiraIssueUpdateBuilder_SomeIssuesFailed());
run.setResult(Result.UNSTABLE);
}
} catch (IOException e) {
listener.getLogger().println(Messages.JiraIssueUpdateBuilder_Failed());
e.printStackTrace(listener.getLogger());
run.setResult(Result.FAILURE);
}

return null;
}
}
}
3 changes: 2 additions & 1 deletion src/main/resources/hudson/plugins/jira/Messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ SearchIssuesStep.Descriptor.DisplayName=JIRA: Search issues
IssueSelectorStep.Descriptor.DisplayName=JIRA: Issue selector
JiraCreateIssueNotifier.DisplayName=JIRA: Create issue
IssueSelector.ExplicitIssueSelector.DisplayName=Explicit selector
IssueSelector.JqlIssueSelector.DisplayName=JQL selector
IssueSelector.JqlIssueSelector.DisplayName=JQL selector
IssueUpdateStep.Descriptor.DisplayName=JIRA: Progress issues by workflow action
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry field="jqlSearch" title="JQL Search for selecting issues">
<f:textbox />
</f:entry>
<f:entry field="workflowActionName" title="Target Jira workflow name">
<f:textbox />
</f:entry>
<f:entry field="comment" title="Comment body">
<f:textbox />
</f:entry>
</j:jelly>
120 changes: 120 additions & 0 deletions src/test/java/hudson/plugins/jira/pipeline/IssueUpdateStepTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package hudson.plugins.jira.pipeline;

import com.google.inject.Inject;
import hudson.model.Job;
import hudson.model.Node;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.plugins.jira.JiraProjectProperty;
import hudson.plugins.jira.JiraSession;
import hudson.plugins.jira.JiraSite;
import org.jenkinsci.plugins.workflow.steps.StepConfigTester;
import org.jenkinsci.plugins.workflow.steps.StepContext;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.PrintStream;
import java.util.*;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* Created by aleksandr on 14.06.16.
*/
public class IssueUpdateStepTest {
@ClassRule
public static JenkinsRule jenkinsRule = new JenkinsRule();

@Inject
IssueUpdateStep.DescriptorImpl descriptor;

@Before
public void setUp() {
jenkinsRule.getInstance().getInjector().injectMembers(this);
}

@Test
public void configRoundTrip() throws Exception {
configRoundTrip("id=EXAMPLE-1", "Action 1", "comment");
}

private void configRoundTrip(String jqlSearch, String workflowActionName, String comment) throws Exception {
IssueUpdateStep configRoundTrip = new StepConfigTester(jenkinsRule)
.configRoundTrip(new IssueUpdateStep(jqlSearch, workflowActionName, comment));

assertEquals(jqlSearch, configRoundTrip.getJqlSearch());
assertEquals(workflowActionName, configRoundTrip.getWorkflowActionName());
assertEquals(comment, configRoundTrip.getComment());
}

@Test
public void testUpdateIssuesByJQL() throws Exception {
JiraSession session = mock(JiraSession.class);
JiraSite site = mock(JiraSite.class);
when(site.getSession()).thenReturn(session);

final String jqlSearch = "id=KEY";
final String workflowActionName = "Action 1";
final String comment = "dsgsags";

final List<Object> assertCalledParams = new ArrayList<Object>();

Mockito.doAnswer(new Answer<Void>() {

@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
String jqlSearchFromArgs = invocation.getArgumentAt(0, String.class);
String workflowActionNameFromArgs = invocation.getArgumentAt(1, String.class);
String commentFromArgs = invocation.getArgumentAt(2, String.class);
System.out.println("jqlSearch: " + jqlSearchFromArgs);
System.out.println("workflowActionName: " + workflowActionNameFromArgs);
System.out.println("comment: " + commentFromArgs);
assertThat(jqlSearchFromArgs, equalTo(jqlSearch));
assertThat(workflowActionNameFromArgs, equalTo(workflowActionName));
assertThat(commentFromArgs, equalTo(comment));
assertCalledParams.addAll(Arrays.asList(invocation.getArguments()));
return null;
}
}).when(site).progressMatchingIssues(Mockito.<String> anyObject(), Mockito.<String> anyObject(),
Mockito.<String> anyObject(), Mockito.<PrintStream> anyObject());

Run mockRun = mock(Run.class);
Job mockJob = mock(Job.class);
when(mockRun.getParent()).thenReturn(mockJob);

TaskListener mockTaskListener = mock(TaskListener.class);
when(mockTaskListener.getLogger()).thenReturn(mock(PrintStream.class));

JiraProjectProperty jiraProjectProperty = mock(JiraProjectProperty.class);
when(jiraProjectProperty.getSite()).thenReturn(site);
when(mockJob.getProperty(JiraProjectProperty.class)).thenReturn(jiraProjectProperty);

Map<String, Object> r = new HashMap<String, Object>();
r.put("jqlSearch", jqlSearch);
r.put("workflowActionName", workflowActionName);
r.put("comment", comment);
IssueUpdateStep step = (IssueUpdateStep) descriptor.newInstance(r);

StepContext ctx = mock(StepContext.class);
when(ctx.get(Node.class)).thenReturn(jenkinsRule.getInstance());
when(ctx.get(Run.class)).thenReturn(mockRun);
when(ctx.get(TaskListener.class)).thenReturn(mockTaskListener);

assertThat(assertCalledParams, hasSize(0));

IssueUpdateStep.StepExecution start = (IssueUpdateStep.StepExecution) step.start(ctx);
start.run();

assertThat(assertCalledParams, hasSize(4));
}
}

0 comments on commit 69621d8

Please sign in to comment.