Skip to content

Commit

Permalink
Merge pull request #20 from rodrigolopes/master
Browse files Browse the repository at this point in the history
[FIXED JENKINS-3785] Created a Publisher to create a label on TFS.
  • Loading branch information
olivierdagenais committed Feb 7, 2014
2 parents a414f76 + fd66871 commit 10098fe
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 0 deletions.
142 changes: 142 additions & 0 deletions src/main/java/hudson/plugins/tfs/TFSLabeler.java
@@ -0,0 +1,142 @@
package hudson.plugins.tfs;

import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.*;
import hudson.plugins.tfs.commands.LabelCommand;
import hudson.plugins.tfs.model.Server;
import hudson.plugins.tfs.util.BuildVariableResolver;
import hudson.scm.SCM;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.util.VariableResolver;
import hudson.util.VariableResolver.Union;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

import java.io.IOException;
import java.util.logging.Logger;

/**
* Used to create a label in TFS after a build is completed.
* @author Rodrigo Lopes (rodrigolopes)
*/
public class TFSLabeler extends Notifier {

private String whenToLabel;
private String labelName;

private static final Logger logger = Logger.getLogger(TFSLabeler.class.getName());

@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public DescriptorImpl() {
super(TFSLabeler.class);
}

@Override
public String getDisplayName() {
return "Create a label in TFS";
}

@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}

@Override
public Publisher newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return new TFSLabeler(
req.getParameter("tfsLabeler.whenToLabel"),
req.getParameter("tfsLabeler.labelName")
);
}

}

@DataBoundConstructor
public TFSLabeler(String whenToLabel, String labelName) {
this.whenToLabel = whenToLabel;
this.labelName = labelName;
}

@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
SCM scm = build.getProject().getScm();
if (!(scm instanceof TeamFoundationServerScm)) {
listener.getLogger().println("Labels are only supported for projects using TFS SCM");
return false;
}

FilePath workspace = build.getWorkspace();

TeamFoundationServerScm tfsScm = (TeamFoundationServerScm) scm;

boolean buildSucess = Result.SUCCESS.equals(build.getResult());

String whenCreateLabel = getWhenToLabel();
if ("always".equals(whenCreateLabel) || ("success".equals(whenCreateLabel) && buildSucess)) {

final Launcher localLauncher = launcher != null ? launcher : new Launcher.LocalLauncher(listener);
final TfTool tool = new TfTool(tfsScm.getDescriptor().getTfExecutable(), localLauncher, listener, workspace);
Server server = new Server(tool, tfsScm.getServerUrl(build), tfsScm.getUserName(), tfsScm.getUserPassword());

Computer computer = Computer.currentComputer();
String normalizedLabelName = computeDynamicValue(build, getLabelName());
String tfsWorkspace = tfsScm.getWorkspaceName(build, computer);

try {
logger.info(String.format("Create label '%s' on workspace '%s'", normalizedLabelName, tfsWorkspace));
LabelCommand labelCommand = new LabelCommand(server, normalizedLabelName, tfsWorkspace, tfsScm.getLocalPath());
server.execute(labelCommand.getArguments());
} catch (Exception e) {
return false;
} finally {
server.close();
}
}

return true;
}

/**
* Replace an expression in the form ${name} in the given String
* by the value of the matching environment variable or build parameter.<Br/>
*/
private String computeDynamicValue(AbstractBuild build, String parameterizedValue)
throws IllegalStateException, InterruptedException, IOException {

final EnvVars envVars = build.getEnvironment(TaskListener.NULL);
final VariableResolver<String> environmentVariables = new VariableResolver<String>() {
public String resolve(String name) {
return envVars.get(name);
}

};
final BuildVariableResolver buildVariables = new BuildVariableResolver(build.getProject());
@SuppressWarnings("unchecked")
final Union<String> bothVariables = new VariableResolver.Union<String>(buildVariables, environmentVariables);
String value = Util.replaceMacro(parameterizedValue, bothVariables);

logger.fine("oldValue = " + parameterizedValue + "; newValue = " + value);
return value;
}

public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.STEP;
}

public String getWhenToLabel() {
return whenToLabel;
}

public String getLabelName() {
return labelName;
}
}
41 changes: 41 additions & 0 deletions src/main/java/hudson/plugins/tfs/commands/LabelCommand.java
@@ -0,0 +1,41 @@
package hudson.plugins.tfs.commands;

import hudson.plugins.tfs.util.MaskedArgumentListBuilder;

/**
* Command to create a label on TFS.
* @author Rodrigo Lopes (rodrigolopes)
*/
public class LabelCommand extends AbstractCommand {

private String labelName;
private String workspaceName;
private String projectPath;

public LabelCommand(ServerConfigurationProvider configurationProvider, String labelName, String workspaceName, String projectPath) {
super(configurationProvider);
this.labelName = labelName;
this.workspaceName = workspaceName;
this.projectPath = projectPath;
}

public MaskedArgumentListBuilder getArguments() {
MaskedArgumentListBuilder arguments = new MaskedArgumentListBuilder();
arguments.add("label");
arguments.add(labelName);
arguments.add(projectPath);
arguments.add(String.format("-version:W%s", workspaceName));
arguments.add(String.format("-comment:%s", getLabelComment()));
arguments.add("-noprompt");
arguments.add("-recursive");
addServerArgument(arguments);
addLoginArgument(arguments);
return arguments;
}

private String getLabelComment() {
// TODO 1. Solve issue with quotes and spaces
// TODO 2. Include build information in the comment.
return "Automatically_applied_by_Jenkins_TFS_plugin";
}
}
11 changes: 11 additions & 0 deletions src/main/resources/hudson/plugins/tfs/TFSLabeler/config.jelly
@@ -0,0 +1,11 @@
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<f:entry title="Label" help="/plugin/tfs/labelname.html">
<f:textbox name="tfsLabeler.labelName" value="${instance.labelName}" />
</f:entry>
<f:entry title="Always">
<f:radio name="tfsLabeler.whenToLabel" value="always" checked="${instance.whenToLabel=='always'}"/>
</f:entry>
<f:entry title="If the build is successful">
<f:radio name="tfsLabeler.whenToLabel" value="success" checked="${instance.whenToLabel=='success'}"/>
</f:entry>
</j:jelly>
3 changes: 3 additions & 0 deletions src/main/resources/hudson/plugins/tfs/TFSLabeler/global.jelly
@@ -0,0 +1,3 @@
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">

</j:jelly>
6 changes: 6 additions & 0 deletions src/main/webapp/labelname.html
@@ -0,0 +1,6 @@
<div>
<p>
The name of the label to be created.<br>
It supports the usage of environment variables for example ${BUILD_NUMBER}, ${JOB_NAME} and ${BUILD_TAG}.
</p>
</div>
24 changes: 24 additions & 0 deletions src/test/java/hudson/plugins/tfs/commands/LabelCommandTest.java
@@ -0,0 +1,24 @@
package hudson.plugins.tfs.commands;

import hudson.plugins.tfs.util.MaskedArgumentListBuilder;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class LabelCommandTest {

@Test
public void assertArguments() {
ServerConfigurationProvider config = mock(ServerConfigurationProvider.class);
when(config.getUrl()).thenReturn("https://tfs02.codeplex.com");
when(config.getUserName()).thenReturn("snd\\user_cp");
when(config.getUserPassword()).thenReturn("password");

MaskedArgumentListBuilder arguments = new LabelCommand(config, "int_build.10", "Jenkins-JOB-MASTER", ".").getArguments();
assertNotNull("Arguments were null", arguments);
assertEquals("label int_build.10 . -version:WJenkins-JOB-MASTER -comment:Automatically_applied_by_Jenkins_TFS_plugin -noprompt -recursive -server:https://tfs02.codeplex.com -login:snd\\user_cp,password", arguments.toStringWithQuote());
}
}

0 comments on commit 10098fe

Please sign in to comment.