package hudson.plugins.tfs.rm;
import com.google.gson.Gson;
import hudson.Launcher;
import hudson.Extension;
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;
import hudson.tasks.Publisher;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.json.*;
/**
* @author Ankit Goyal
*/
public class ReleaseManagementCI extends Notifier{
public final String collectionUrl;
public final String projectName;
public final String releaseDefinitionName;
public final String username;
public final Secret password;
// Fields in config.jelly must match the parameter names in the "DataBoundConstructor"
@DataBoundConstructor
public ReleaseManagementCI(String collectionUrl, String projectName, String releaseDefinitionName, String username, Secret password)
{
if (collectionUrl.endsWith("/"))
{
this.collectionUrl = collectionUrl;
}
else
{
this.collectionUrl = collectionUrl + "/";
}
//this.collectionUrl = this.collectionUrl.toLowerCase().replaceFirst(".visualstudio.com", ".vsrm.visualstudio.com");
this.projectName = projectName;
this.releaseDefinitionName = releaseDefinitionName;
this.username = username;
this.password = password;
}
/*
* (non-Javadoc)
*
* @see hudson.tasks.BuildStep#getRequiredMonitorService()
*/
@Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}
/*
* (non-Javadoc)
*
* @see
* hudson.tasks.BuildStepCompatibilityLayer#perform(hudson.model.AbstractBuild
* , hudson.Launcher, hudson.model.BuildListener)
*/
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException
{
String jobName = build.getProject().getName();
int buildId = build.number;
String buildNumber = build.getDisplayName();
if (build.getResult() == Result.SUCCESS)
{
ReleaseManagementHttpClient releaseManagementHttpClient =
new ReleaseManagementHttpClient(
this.collectionUrl.toLowerCase().replaceFirst(".visualstudio.com", ".vsrm.visualstudio.com"),
this.username,
this.password);
try
{
ReleaseDefinition releaseDefinition = null;
List<ReleaseDefinition> releaseDefinitions = releaseManagementHttpClient.GetReleaseDefinitions(this.projectName);
for(final ReleaseDefinition rd : releaseDefinitions)
{
if(rd.getName().equalsIgnoreCase(this.releaseDefinitionName))
{
releaseDefinition = rd;
break;
}
}
if(releaseDefinition == null)
{
listener.getLogger().printf("No release definition found with name: %s%n", this.releaseDefinitionName);
listener.getLogger().println("Release will not be triggered.");
}
else
{
CreateRelease(releaseManagementHttpClient, releaseDefinition, jobName, buildNumber, buildId, listener);
}
}
catch (ReleaseManagementException ex)
{
ex.printStackTrace(listener.error("Failed to trigger release.%n"));
}
catch (JSONException ex)
{
ex.printStackTrace(listener.error("Failed to trigger release.%n"));
}
}
return true;
}
void CreateRelease(
ReleaseManagementHttpClient releaseManagementHttpClient,
ReleaseDefinition releaseDefinition,
String jobName,
String buildNumber,
int buildId,
BuildListener listener) throws ReleaseManagementException, JSONException
{
Artifact jenkinsArtifact = null;
for(final Artifact artifact : releaseDefinition.getArtifacts())
{
if(artifact.getType().equalsIgnoreCase("jenkins") && artifact.getDefinitionReference().getDefinition().getName().equalsIgnoreCase(jobName))
{
jenkinsArtifact = artifact;
break;
}
}
if(jenkinsArtifact == null)
{
listener.getLogger().printf("No jenkins artifact found with name: %s%n", jobName);
}
else
{
List<ReleaseArtifact> releaseArtifacts = PrepareReleaseArtifacts(
releaseDefinition,
jenkinsArtifact,
buildNumber,
buildId,
listener,
releaseManagementHttpClient);
String description = "Triggered by " + buildNumber;
ReleaseBody releaseBody = new ReleaseBody();
releaseBody.setDescription(description);
releaseBody.setDefinitionId(releaseDefinition.getId());
releaseBody.setArtifacts(releaseArtifacts);
releaseBody.setIsDraft(false);
String body = new Gson().toJson(releaseBody);
listener.getLogger().printf("Triggering release...%n");
String response = releaseManagementHttpClient.CreateRelease(this.projectName, body);
listener.getLogger().printf("Successfully triggered release.%n");
JSONObject object = new JSONObject(response);
listener.getLogger().printf("Release Name: %s%n", object.getString("name"));
listener.getLogger().printf("Release id: %s%n", object.getString("id"));
}
}
private List<ReleaseArtifact> PrepareReleaseArtifacts(ReleaseDefinition releaseDefinition, Artifact jenkinsArtifact, String buildNumber, int buildId, BuildListener listener, ReleaseManagementHttpClient releaseManagementHttpClient) throws ReleaseManagementException {
List<ReleaseArtifact> releaseArtifacts = new ArrayList<ReleaseArtifact>();
InstanceReference instanceReference = new InstanceReference();
for(final Artifact artifact : releaseDefinition.getArtifacts())
{
ReleaseArtifact releaseArtifact = new ReleaseArtifact();
if(artifact == jenkinsArtifact)
{
instanceReference.setName(buildNumber);
instanceReference.setId(Integer.toString(buildId));
}
else
{
listener.getLogger().printf("Fetching latest version for artifact: %s%n", artifact.getAlias());
ReleaseArtifactVersionsResponse response = releaseManagementHttpClient.GetVersions(this.projectName, new ArrayList<Artifact>(Arrays.asList(artifact)));
if(response.getArtifactVersions().isEmpty())
{
throw new ReleaseManagementException("Could not fetch versions for the linked artifact sources");
}
if(response.getArtifactVersions().get(0).getVersions().isEmpty())
{
throw new ReleaseManagementException("Could not fetch versions for the linked artifact: " + artifact.getAlias());
}
instanceReference.setName(response.getArtifactVersions().get(0).getVersions().get(0).getName());
instanceReference.setId(response.getArtifactVersions().get(0).getVersions().get(0).getId());
}
releaseArtifact.setAlias(artifact.getAlias());
releaseArtifact.setInstanceReference(instanceReference);
releaseArtifacts.add(releaseArtifact);
}
return releaseArtifacts;
}
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Publisher>
{
/*
* (non-Javadoc)
*
* @see hudson.tasks.BuildStepDescriptor#isApplicable(java.lang.Class)
*/
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType)
{
return true;
}
/*
* (non-Javadoc)
*
* @see hudson.model.Descriptor#getDisplayName()
*/
@Override
public String getDisplayName()
{
return "Trigger release in TFS/Team Services";
}
}
}