Skip to content
This repository was archived by the owner on Feb 13, 2020. It is now read-only.

Commit

Permalink
Add TypetalkSendStep
Browse files Browse the repository at this point in the history
  • Loading branch information
ikikko committed Jun 11, 2016
1 parent 1fcb3d8 commit bd6144d
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 27 deletions.
9 changes: 7 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ dependencies {
testCompile 'org.spockframework:spock-core:0.7-groovy-1.8',
'cglib:cglib-nodep:2.2.2',
'org.objenesis:objenesis:1.3'
jenkinsPlugins 'org.jenkins-ci.plugins.workflow:workflow-step-api:2.0@jar',
'org.jenkins-ci.plugins.workflow:workflow-job:2.0@jar'
jenkinsTest 'org.jenkins-ci.plugins:ant:1.2@jar',
'org.jenkins-ci.plugins:mailer:1.1@jar'
'org.jenkins-ci.plugins:mailer:1.1@jar',
'org.jenkins-ci.plugins.workflow:workflow-step-api:2.0@jar',
'org.jenkins-ci.plugins.workflow:workflow-job:2.0@jar',
'org.jenkins-ci.plugins.workflow:workflow-api:2.0@jar' // dependency for workflow-job
}

jenkinsPlugin {
coreVersion = '1.509'
coreVersion = '1.651.2'
shortName = 'typetalk'
displayName = 'Typetalk Plugin'
url = 'https://wiki.jenkins-ci.org/display/JENKINS/Typetalk+Plugin'
Expand Down
15 changes: 3 additions & 12 deletions src/main/java/org/jenkinsci/plugins/typetalk/TypetalkNotifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
Expand Down Expand Up @@ -42,13 +41,14 @@ public BuildStepMonitor getRequiredMonitorService() {
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {

if (successFromPreviousBuild(build)) {
ResultSupport resultSupport = new ResultSupport();
if (resultSupport.successFromPreviousBuild(build)) {
return true;
}

listener.getLogger().println("Notifying build result to Typetalk...");

TypetalkMessage typetalkMessage = new ResultSupport().convertBuildToMessage(build);
TypetalkMessage typetalkMessage = resultSupport.convertBuildToMessage(build);
String message = typetalkMessage.buildMessageWithBuild(build);
Long topicId = Long.valueOf(topicNumber);

Expand All @@ -57,15 +57,6 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
return true;
}

private boolean successFromPreviousBuild(AbstractBuild<?, ?> build) {
if (build.getPreviousBuild() == null) {
return build.getResult().equals(Result.SUCCESS);
} else {
return build.getResult().equals(Result.SUCCESS)
&& build.getPreviousBuild().getResult().equals(Result.SUCCESS);
}
}

@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) super.getDescriptor();
Expand Down
95 changes: 95 additions & 0 deletions src/main/java/org/jenkinsci/plugins/typetalk/TypetalkSendStep.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package org.jenkinsci.plugins.typetalk;

import hudson.Extension;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Run;
import hudson.model.TaskListener;
import org.jenkinsci.plugins.typetalk.api.Typetalk;
import org.jenkinsci.plugins.typetalk.support.ResultSupport;
import org.jenkinsci.plugins.typetalk.support.TypetalkMessage;
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 javax.inject.Inject;

public class TypetalkSendStep extends AbstractStepImpl {

private final @Nonnull String name;
private final @Nonnull Long topicId;

@Nonnull
public String getName() {
return name;
}

@Nonnull
public Long getTopicId() {
return topicId;
}

@DataBoundConstructor
public TypetalkSendStep(@Nonnull String name, @Nonnull Long topicId) {
this.name = name;
this.topicId = topicId;
}

@Extension
public static class DescriptorImpl extends AbstractStepDescriptorImpl {

public DescriptorImpl() {
super(TypetalkSendStepExecution.class);
}

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

@Override
public String getDisplayName() {
return "Notify Typetalk when the build fails";
}
}

public static class TypetalkSendStepExecution extends AbstractSynchronousNonBlockingStepExecution<Void> {

private static final long serialVersionUID = 1L;

@Inject
transient TypetalkSendStep step;

@StepContextParameter
transient TaskListener listener;

@StepContextParameter
transient Run run;

/**
* Almost same as {@link TypetalkNotifier#perform(AbstractBuild, Launcher, BuildListener)}
*/
@Override
protected Void run() throws Exception {
ResultSupport resultSupport = new ResultSupport();
if (resultSupport.successFromPreviousBuild(run)) {
return null;
}

listener.getLogger().println("Notifying build result to Typetalk...");

TypetalkMessage typetalkMessage = new ResultSupport().convertBuildToMessage(run);
String message = typetalkMessage.buildMessageWithBuild(run);

Typetalk.createFromName(step.name).postMessage(step.topicId, message);

return null;
}

}

}
Original file line number Diff line number Diff line change
@@ -1,40 +1,54 @@
package org.jenkinsci.plugins.typetalk.support;

import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Result;
import hudson.model.Run;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;

public class ResultSupport {

public TypetalkMessage convertBuildToMessage(AbstractBuild build) {
if (build.getResult().equals(Result.ABORTED)) {
public boolean successFromPreviousBuild(Run build) {
if (build.getPreviousBuild() == null) {
return (inProgressPipeline(build) || build.getResult().equals(Result.SUCCESS));
} else {
return (inProgressPipeline(build) || build.getResult().equals(Result.SUCCESS))
&& build.getPreviousBuild().getResult().equals(Result.SUCCESS);
}
}

public TypetalkMessage convertBuildToMessage(Run build) {
if (inProgressPipeline(build) || build.getResult().equals(Result.SUCCESS)) {
if (recoverSuccess(build)) {
return new TypetalkMessage(Emoji.SMILEY, "Build recovery");
} else {
return new TypetalkMessage(Emoji.SMILEY, "Build success");
}
} else if (build.getResult().equals(Result.ABORTED)) {
return new TypetalkMessage(Emoji.ASTONISHED, "Build aborted");
} else if (build.getResult().equals(Result.NOT_BUILT)) {
return new TypetalkMessage(Emoji.ASTONISHED, "Not built");
} else if (build.getResult().equals(Result.FAILURE)) {
return new TypetalkMessage(Emoji.RAGE, "Build failure");
} else if (build.getResult().equals(Result.UNSTABLE)) {
return new TypetalkMessage(Emoji.CRY, "Build unstable");
} else if (build.getResult().equals(Result.SUCCESS)) {
if (recoverSuccess(build)) {
return new TypetalkMessage(Emoji.SMILEY, "Build recovery");
} else {
return new TypetalkMessage(Emoji.SMILEY, "Build success");
}
}

throw new IllegalArgumentException("Unknown build result.");
}

public boolean recoverSuccess(AbstractBuild build) {
public boolean recoverSuccess(Run build) {
if (build.getPreviousBuild() == null) {
return false;
} else {
return build.getResult().equals(Result.SUCCESS)
return (inProgressPipeline(build) || build.getResult().equals(Result.SUCCESS))
&& build.getPreviousBuild().getResult().isWorseThan(Result.SUCCESS);
}
}

private boolean inProgressPipeline(Run build) {
return build instanceof WorkflowRun && build.getResult() == null;
}

public Emoji convertProjectToEmoji(AbstractProject project) {
switch (project.getIconColor()) {
case RED:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Run;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;

Expand All @@ -25,7 +26,7 @@ public TypetalkMessage(Emoji emoji, String message) {
this.message = message;
}

public String buildMessageWithBuild(AbstractBuild<?, ?> build) {
public String buildMessageWithBuild(Run build) {
final String rootUrl = Jenkins.getInstance().getRootUrl();
if (StringUtils.isEmpty(rootUrl)) {
throw new IllegalStateException("Root URL isn't configured yet. Cannot compute absolute URL.");
Expand All @@ -36,7 +37,7 @@ public String buildMessageWithBuild(AbstractBuild<?, ?> build) {
builder.append(" ");
builder.append(message);
builder.append(" [ ");
builder.append(build.getProject().getDisplayName());
builder.append(build.getParent().getDisplayName());
builder.append(" ]");
builder.append("\n");
builder.append(rootUrl);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">

<f:entry title="${%Credential}">
<select class="setting-input" name="credential.name" description="Select configured credential">
<j:forEach var="credential" items="${app.getDescriptor('org.jenkinsci.plugins.typetalk.TypetalkNotifier').credentials}">
<f:option selected="${credential.name.equals(instance.name)}">${credential.name}</f:option>
</j:forEach>
</select>
</f:entry>

<f:entry title="${%Topic Number}" field="topicId">
<f:textbox />
</f:entry>

</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div>
Use 'catchError' step in order to notify a build error certainly. An example is the following below.
<p></p>
<pre>
catchError {
sh 'compile'
sh 'test'
sh 'package'
sh 'deploy'
}
typetalkSend name: 'demo', topicId: 1
</pre>
</div>

0 comments on commit bd6144d

Please sign in to comment.