/*******************************************************************************
* Copyright (c) 2009 Thales Corporate Services SAS *
* Author : Gregory Boissinot *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal*
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
* THE SOFTWARE. *
*******************************************************************************/
package com.thalesgroup.hudson.plugins.clearcaserelease.biz;
import com.thalesgroup.hudson.plugins.clearcaserelease.ClearcaseReleaseBuildBadgeAction;
import com.thalesgroup.hudson.plugins.clearcaserelease.ClearcaseReleaseCancelAction;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.*;
import hudson.plugins.clearcase.ClearCaseUcmSCM;
import hudson.plugins.clearcase.HudsonClearToolLauncher;
import hudson.plugins.clearcase.PluginImpl;
import hudson.plugins.clearcase.ucm.UcmMakeBaselineComposite;
import hudson.util.ArgumentListBuilder;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ClearcaseReleaseActionImpl {
protected final FilePath workspaceRoot;
public ClearcaseReleaseActionImpl(FilePath workspaceRoot) {
this.workspaceRoot = workspaceRoot;
}
/**
* The promotion level possibilities
*/
private static enum BASELINE_PROMOTION_LEVEL {
RELEASED("RELEASED"),
BUILT("BUILT");
private String level;
private BASELINE_PROMOTION_LEVEL(String level) {
this.level = level;
}
public String getLevel() {
return this.level;
}
}
/**
* Retieve the Clearcase launcher
*
* @param listener the Hudson listener
* @param launcher the Hudson launcher
* @return the Clearcase launcher
*/
private HudsonClearToolLauncher getHudsonClearToolLauncher(TaskListener listener, Launcher launcher) {
HudsonClearToolLauncher clearToolLauncher = new HudsonClearToolLauncher(
PluginImpl.BASE_DESCRIPTOR.getCleartoolExe(), "clearcase-release", listener, workspaceRoot, launcher);
return clearToolLauncher;
}
/**
* Get the status of a given UCM baseline
*
* @param baseLine the UCM baseline
* @param pvob the UCM P_VOB
* @param clearToolLauncher : the clearcase object for launching commands
* @param filePath the location where to launch the clearcase command
* @return the baseline status : INITIAL, BUILT, REJECTED, RELEASED or OTHERS
* @throws java.io.IOException
* @throws InterruptedException
*/
//cleartool lsbl -fmt "%[plevel]p" P_TracMngt_Rqtf_CoreModel_V3.0.1@\P_ORC
//RELEASED
private String getStatusBaseLine(
String baseLine,
String pvob,
HudsonClearToolLauncher clearToolLauncher,
FilePath filePath)
throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsbl");
cmd.add("-fmt");
cmd.add("\"%[plevel]p\"");
cmd.add(baseLine + "@" + File.separator + pvob);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
clearToolLauncher.run(cmd.toCommandArray(), null, baos, filePath);
baos.close();
String componentName = baos.toString();
return componentName;
}
/**
* Change the level of an UCM baseline (composite or not)
*
* @param baselineNameWithPVOB the given baseline with the P_VOB
* @param status the new baseline status
* @param clearToolLauncher the clearcase object launcher
* @param filePath the location where to launch the clearcase coommand
* @throws InterruptedException
* @throws IOException
*/
//cleartool chbl -level RELEASED C_hudson-test-2_2009-10-29_18-36-07@\P_ORC
private void changeLevelBaseline(String baselineNameWithPVOB,
String status,
HudsonClearToolLauncher clearToolLauncher,
FilePath filePath)
throws InterruptedException, IOException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("chbl");
cmd.add("-level");
cmd.add(status);
cmd.add(baselineNameWithPVOB);
clearToolLauncher.run(cmd.toCommandArray(), null, null, filePath);
}
/**
* Get the read/write components for a given stream
*
* @param streamPVOB the stream name with the P_VOB
* @param clearToolLauncher the clearcase launcher object
* @param filePath the location where to launch the clearcase command
* @return the component name
* @throws IOException
* @throws InterruptedException
*/
/*
cleartool lsstream -fmt "%[mod_comps]CXp" P_LinkMgt_V4.0.0_int@\P_ORC
-->component:TracMgt_Rqtf_QueryGen@\P_ORC, component:PapeeteReqtifyConnector@\P_ORC, component:LinkMgt_Reqtify@\P_ORC
*/
private List<String> getModComponentsFromStream(
String streamPVOB,
HudsonClearToolLauncher clearToolLauncher,
FilePath filePath)
throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsstream");
cmd.add("-fmt");
cmd.add("\"%[mod_comps]p\"");
cmd.add(streamPVOB);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
clearToolLauncher.run(cmd.toCommandArray(), null, baos, filePath);
baos.close();
String reusltClt = baos.toString();
return Arrays.asList(reusltClt.split(" "));
}
/**
* Get the latest baselines for a given stream
*
* @param streanWithPVOB an UCM stream concatened with the PVOB
* @param clearToolLauncher the clercase object launcher
* @param filePath the location where to launch the clearcase command
* @return the list of baseline name
* @throws IOException
* @throws InterruptedException
*/
/*
cleartool lsstream -fmt "%[latest_bls]p" P_LinkMgt_V4.0.0_int@\P_ORC
-->
baseline:P_TracMngt_Rqtf_CoreModel_V3.0.1@\P_ORC,
baseline:LinkManager-4.3.0-2009-10-29_11-03-52.9990@\P_ORC,
baseline:LinkManager-4.3.0-2009-10-29_11-03-52.2547@\P_ORC,
baseline:LinkManager-4.3.0-2009-10-29_11-03-52@\P_ORC
*/
private List<String> getLatestBaselines(
String streanWithPVOB,
HudsonClearToolLauncher clearToolLauncher,
FilePath filePath)
throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsstream");
cmd.add("-fmt");
cmd.add("\"%[latest_bls]CXp\"");
cmd.add(streanWithPVOB);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
clearToolLauncher.run(cmd.toCommandArray(), null, baos, filePath);
baos.close();
String resultClt = baos.toString();
//Remove the 'baseline:' prefix
resultClt = resultClt.replace("baseline:", "");
//Slit the result. Within the result, each result has a space.
return Arrays.asList(resultClt.split(", "));
}
/**
* Get the component for a given baseline
*
* @param baseLineWithPVOB the given baseline name concatened with the PVOB
* @param clearToolLauncher the clearcase launcher object
* @param filePath the location where to launch the clearcase command
* @return the component object
* @throws IOException
* @throws InterruptedException
*/
//cleartool lsbl -fmt "%[component]p" P_TracMngt_Rqtf_CoreModel_V3.0.1@\P_ORC
//TracMgt_Rqtf_CoreModel
private String getComponentFromBaseline(
String baseLineWithPVOB,
HudsonClearToolLauncher clearToolLauncher,
FilePath filePath)
throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsbl");
cmd.add("-fmt");
cmd.add("\"%[component]p\"");
cmd.add(baseLineWithPVOB);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
clearToolLauncher.run(cmd.toCommandArray(), null, baos, filePath);
baos.close();
String componentName = baos.toString();
return componentName;
}
public void performCompoisteBaselineRelease(TaskListener listener, AbstractBuild owner, String customReleasePromotionLevel) throws IOException, InterruptedException {
listener.getLogger().println("\nClearcase release preforming");
Launcher launcher = new Launcher.LocalLauncher(listener);
HudsonClearToolLauncher clearToolLauncher = getHudsonClearToolLauncher(listener, launcher);
//Get the composite baseline information
UcmMakeBaselineComposite composite = (UcmMakeBaselineComposite) owner.getProject().getPublishersList().get(hudson.plugins.clearcase.ucm.UcmMakeBaselineComposite.class);
if (composite == null) {
listener.getLogger().println("[ERROR] - No composite baseline has been configured for the job.");
} else {
String compositeBaseLine = composite.getCompositeNamePattern();
compositeBaseLine = Util.replaceMacro(compositeBaseLine, owner.getEnvironment(listener));
//Get the PVOB from the composite stream
String compositeStreamSelector = composite.getCompositeStreamSelector();
String pvob = compositeStreamSelector;
if (compositeStreamSelector.contains("@" + File.separator)) {
pvob = compositeStreamSelector.substring(compositeStreamSelector.indexOf("@" + File.separator) + 2, compositeStreamSelector.length());
}
//Check the status
listener.getLogger().println("Check the status of the composite baseline '" + compositeBaseLine + "'");
String compositeBaselineStatus = getStatusBaseLine(compositeBaseLine, pvob, clearToolLauncher, workspaceRoot);
if ("BUILT".equals(compositeBaselineStatus)) {
//Promote to the release promotion level the compiste baseline
String status = (customReleasePromotionLevel == null) ? BASELINE_PROMOTION_LEVEL.RELEASED.getLevel() : customReleasePromotionLevel;
listener.getLogger().println("Promote to the release promotion level the composite baseline '" + compositeBaseLine + "' with the level '" + status + '"');
changeLevelBaseline(compositeBaseLine + "@\\" + pvob, status, clearToolLauncher, workspaceRoot);
listener.getLogger().println("");
//Add a badge icon
String compositeBaseNameDescription = compositeBaseLine + ":RELEASED";
ClearcaseReleaseBuildBadgeAction releaseBuildBadgeAction = new ClearcaseReleaseBuildBadgeAction(compositeBaseNameDescription);
owner.addAction(releaseBuildBadgeAction);
//Add a cancel action
owner.addAction(new ClearcaseReleaseCancelAction(owner, owner.getProject(), workspaceRoot, releaseBuildBadgeAction, Arrays.asList(new String[]{compositeBaseLine + "@\\" + pvob})));
// Keep the build
owner.keepLog();
} else {
listener.getLogger().println("\nThe composite baseline '" + compositeBaseLine + "' hasn't the status BUILT.");
}
}
}
public void performCancelRelease(TaskListener listener,
Run owner,
ClearcaseReleaseBuildBadgeAction releaseBuildBadgeAction,
ClearcaseReleaseCancelAction clearcaseReleaseCancelAction,
List<String> promotedBaselines) throws IOException, InterruptedException {
listener.getLogger().println("\nClearcase release cancel preforming");
Launcher launcher = new Launcher.LocalLauncher(listener);
HudsonClearToolLauncher clearToolLauncher = getHudsonClearToolLauncher(listener, launcher);
//Cancel the release baseline
for (String promotedBaseline : promotedBaselines) {
changeLevelBaseline(promotedBaseline, BASELINE_PROMOTION_LEVEL.BUILT.getLevel(), clearToolLauncher, workspaceRoot);
listener.getLogger().println("");
}
//Remove the badge action
owner.getActions().remove(releaseBuildBadgeAction);
//Remove itself the cancel release action
owner.getActions().remove(clearcaseReleaseCancelAction);
//Unlock the owner
owner.keepLog(false);
}
public void performLatestBaselineRelease(TaskListener listener,
AbstractProject project,
Run owner,
String customReleasePromotionLevel) throws IOException, InterruptedException {
listener.getLogger().println("\nClearcase release preforming");
Launcher launcher = new Launcher.LocalLauncher(listener);
ClearCaseUcmSCM clearCaseUcmSCM = (ClearCaseUcmSCM) project.getScm();
HudsonClearToolLauncher clearToolLauncher = getHudsonClearToolLauncher(listener, launcher);
listener.getLogger().println("Performing the release of the latest baselines");
String streamWithPVOB = clearCaseUcmSCM.getStream();
String pvob = streamWithPVOB;
if (pvob.contains("@" + File.separator)) {
pvob = pvob.substring(pvob.indexOf("@" + File.separator) + 2, pvob.length());
}
//Get all the latest baselines
List<String> latestBaselines = getLatestBaselines(streamWithPVOB, clearToolLauncher, workspaceRoot);
listener.getLogger().println("");
//Get the read/write components
List<String> modComps = getModComponentsFromStream(streamWithPVOB, clearToolLauncher, workspaceRoot);
listener.getLogger().println("");
//Filtering
List<String> keepBaselines = new ArrayList<String>();
for (String latestBaseline : latestBaselines) {
//Retrieve the component of the baseline
String comp = getComponentFromBaseline(latestBaseline, clearToolLauncher, workspaceRoot);
listener.getLogger().println("");
//Keep on the a modifiable component
if (modComps.contains(comp)) {
keepBaselines.add(latestBaseline);
}
}
if (keepBaselines.size() == 0) {
listener.getLogger().println("There is not baseline to promote to RELEASE");
return;
}
//Promotion to RELEASED all the latest baseline on modifiable component
StringBuffer latestBls = new StringBuffer();
for (String latestBaselineWithPVOB : keepBaselines) {
String status = (customReleasePromotionLevel == null) ? BASELINE_PROMOTION_LEVEL.RELEASED.getLevel() : customReleasePromotionLevel;
changeLevelBaseline(latestBaselineWithPVOB, status, clearToolLauncher, workspaceRoot);
listener.getLogger().println("");
latestBls.append(";");
latestBls.append(latestBaselineWithPVOB);
}
if (latestBls.length() != 0) {
latestBls.delete(0, 1);
}
//Add a badge icon
String latestBaselinesReleaseDescription = "The latest baseline has been released";
ClearcaseReleaseBuildBadgeAction releaseBuildBadgeAction = new ClearcaseReleaseBuildBadgeAction(latestBaselinesReleaseDescription);
owner.addAction(releaseBuildBadgeAction);
ArrayList<ParameterValue> parameters = new ArrayList<ParameterValue>();
parameters.add(new StringParameterValue("LATEST_BASELINE", latestBls.toString()));
owner.addAction(new ParametersAction(parameters));
//Add a cancel action
owner.addAction(new ClearcaseReleaseCancelAction(owner, project, workspaceRoot, releaseBuildBadgeAction, keepBaselines));
// Keep the build
owner.keepLog();
}
}