Jazz Forum Welcome to the Jazz Community Forum Connect and collaborate with IBM Engineering experts and users

How do you deliver the snapshot created by a build to the stream?

We are using EE dependency builds which do not have the post-build option to deliver the snapshot.

I wrote an ant task that uses the api to do the deliver, but nothing happens  --  no errors, no messages, no delivery.  With the CLI you have to add -o option to make it work.  Do I need something special using the API to duplicate the -o option?

This will make the CLI do the delivery:

 <!-- ScmDeliverSnapshot Macro -->
 <macrodef name="ScmDeliverSnapshot">
  <attribute name="property" default="scm.property.output.ScmDeliverSnapshot"/>
  <attribute name="workspace"/>
  <attribute name="stream"/>
  <sequential>
   <local name="scm.cmd"/>
   <Scm property="scm.cmd"/>
   <local name="scm.property.output.ScmDeliverSnapshot"/>
   <exec executable="${scm.cmd}" failonerror="true" outputproperty="@{property}">
    <arg value="--config"/>
    <arg value="${dir.scc}"/>
    <arg value="--non-interactive"/>
    <arg value="deliver"/>
    <arg value="-o"/>
    <arg value="-v"/>
    <arg value="-s"/>
    <arg value="@{workspace}"/>
    <arg value="-t"/>
    <arg value="@{stream}"/>
   </exec>
   <ac:propertycopy name="scmTemp" from="@{property}" override="true"/>
   <echo level="verbose">Scm: @{property}:</echo>
   <echo level="verbose">${scmTemp}</echo>
  </sequential>
 </macrodef>
But, I can't use this with EE or JBE on zOS.  CLI doesn't like the parms, must be backleveled.

Here's the deliver code which does not deliver:

// Search for stream
IWorkspaceSearchCriteria criteria = IWorkspaceSearchCriteria.FACTORY.newInstance().setKind(IWorkspaceSearchCriteria.STREAMS);
criteria.setExactName(getStreamName());
List<IWorkspaceHandle> streamWorkspaceHandles = wsManager.findWorkspaces(criteria,Integer.MAX_VALUE,null);
// Verify one stream
if (streamWorkspaceHandles.size() == 0) {
throw new TeamRepositoryException(NLS.bind(CommonMessages.COMMON_NOTFOUND_STREAMNAME,getStreamName()));
}

// Connect to stream
IWorkspaceHandle streamWorkspaceHandle = streamWorkspaceHandles.get(0);
IWorkspace streamWorkspace = (IWorkspace) repo.itemManager().fetchCompleteItem(streamWorkspaceHandle,IItemManager.DEFAULT,null);
IWorkspaceConnection streamWorkspaceConnection = wsManager.getWorkspaceConnection(streamWorkspace,null);

// Get change report
syncReport = wsConnection.compareTo(streamWorkspaceConnection,WorkspaceComparisonFlags.INCLUDE_BASELINE_INFO,Collections.EMPTY_LIST,null);

// Deliver to stream
for (Object changeHandle : syncReport.outgoingChangeSets()) {
// Check IChangeSetHandle
if (!(changeHandle instanceof IChangeSetHandle)) {continue;}

// Get change set details
IChangeSet changeSet = scmChangeset.getSnapshotChangeset((IChangeSetHandle) changeHandle);
IComponentHandle componentHandle = changeSet.getComponent();

// Deliver pending change
wsConnection.deliver(streamWorkspaceConnection,syncReport,syncReport.outgoingBaselines(componentHandle),syncReport.outgoingChangeSets(componentHandle),null);
}

The syncReport.outgoingBaselines() = 3 before and after code executes.  Completes without any message saying why deliver failed.

0 votes


Accepted answer

Permanent link

I got this to work using a JBE on zos unix system by changing macro to use <ant line=...> format:

<!-- ScmDeliverSnapshot Macro -->
<macrodef name="ScmDeliverSnapshot">
 <attribute name="failonerror" default="true"/>
 <attribute name="property" default="scm.property.output.ScmDeliverSnapshot"/>
 <attribute name="workspace"/>
 <attribute name="stream"/>
 <sequential>
  <local name="scm.cmd"/>
  <Scm property="scm.cmd"/>
  <local name="scm.property.output.ScmDeliverSnapshot"/>
  <exec executable="${scm.cmd}" failonerror="@{failonerror}" outputproperty="@{property}" osfamily="windows">
   <arg value="--config"/>
   <arg value="${dir.scc}"/>
   <arg value="--non-interactive"/>
   <arg value="deliver"/>
   <arg value="-o"/>
   <arg value="-v"/>
   <arg value="-s"/>
   <arg value="@{workspace}"/>
   <arg value="-t"/>
   <arg value="@{stream}"/>
  </exec>
  <exec executable="${scm.cmd}" failonerror="@{failonerror}" outputproperty="@{property}" os="z/OS">
   <arg line="--config ${dir.scc} --non-interactive deliver -o -v -s @{workspace} -t @{stream}"/>
  </exec>
  <local name="scm.tmp"/>
  <ac:propertycopy name="scm.tmp" from="@{property}" override="true" silent="true"/>
  <local name="current.time"/>
  <tstamp>
   <format property="current.time" pattern="yyyyMMdd HH:mm:ss.SSS"/>
  </tstamp>
  <echo level="verbose">${current.time} Scm: @{property}:</echo>
  <echo level="verbose">${scm.tmp}</echo>
 </sequential>
</macrodef>


Macro is now setup to handle windows systems and zos.

Still would like to know how to get API to handle situations like this though.

djr

Ralph Schoon selected this answer as the correct answer

0 votes

Comments

I have these examples: https://rsjazz.wordpress.com/2013/09/30/delivering-change-sets-and-baselines-to-a-stream-using-the-plain-java-client-libraries/

A snapshot is an IBaselineSet. So you have to basically deliver all the baselines. The snapshot has an owning stream and you might want to change that to the stream you deliver to.


3 other answers

Permanent link
I suspect the delivery is succeeding silently because there aren't any outgoing change sets. The build accepted all of the change sets into the build workspace when it started, so the body of your delivery loop will never run. #2 below is relevant for fixing this. 

I have some comments about your code: 
  1. streamWorkspaceHandles.size() == 0 is risky, because you may have multiple IWorkspaces with the same name. I suggest verifying that you have exactly one workspace that fits the criteria. An even better alternative would be to hard-code the UUID of the IWorkspace you want to deliver to (you could parameterize it if you want to reuse the code).
  2. The loop that does the delivery loops over each change set, so it will attempt to perform multiple deliveries of the same change sets and baselines. You can get a list of components with IChangeHistorySyncReport#localComponents() .
Also: you may want to change the snapshot owner, so that it appears in the list of snapshots for the stream. 

1 vote

Comments

I can add another check in for > 1.  UUID is inconvient in this case and the code has to handle any input stream, so hard-coding is out.

The snapshot I want to deliver is the one created by the build when accept incoming changes is on and it is not delivered by the deliver().

Using the CLI you have to use the -o to get it to work, nothing else works.

I did figure out how to get that to work on zos unix (needed to change to <arg line=>), but that has to be a separate build executed in a JBE.  I'll post updated ant code.

I don't think #2 in my answer is clear. I'll try to do a better job explaining it:


Assuming your code runs after the build workspace has accepted the changes from the stream, the body of your loop will never run. This is because the build workspace has the exact same change sets as your stream, so  syncReport.outgoingChangeSets() will alway return an empty list. Instead of looping over the change sets, you should run on the list of components in the sync report and deliver the outgoing baselines. 

Incidentally: IIRC, delivering change sets individually like this may not work in all situations because the change sets aren't ordered in the sync report. The code may attempt to deliver a change set that builds on another outgoing change set that hasn't been delivered yet. 


Permanent link
I was also struggling with a similar problem with incoming baselines and change sets and it's really important to understand that:
1) if you're dealing with changeHistorySyncReport.incomingBaselines() after a IChangeHistorySyncReport with WorkspaceComparisonFlags.INCLUDE_BASELINE_INFO then you've to consider ONLY the change sets from changeHistorySyncReport.incomingChangeSetsAfterBasis() because changeHistorySyncReport.incomingChangeSets() gives you ALL the Change Sets, even those already pointed by the baselines
2) you may accept ONLY 1 baseline per component so you may not do all in a single shot 
sourceWorkspaceConnection.accept(
AcceptFlags.DEFAULT, 
targetWorkspaceConnection, 
changeHistorySyncReport, 
incomingBaselineHandles, 
incomingChangeSetAfterBasisHandles, 
progressMonitor);

0 votes


Permanent link
 Reading the notes from Evan you could end up with a code like this where you cycle for every component of the source workspace
IChangeHistorySyncReport changeHistorySyncReport = sourceFlowNodeConnection.compareTo(
	targetFlowNodeConnection, 
	WorkspaceComparisonFlags.INCLUDE_BASELINE_INFO | WorkspaceComparisonFlags.INCLUDE_EMPTY_BASELINES, 
	Collections.EMPTY_LIST, /*excludedComponents*/
	progressMonitor);

List<IComponentHandle> componentHandles = changeHistorySyncReport.localComponents();

//FOR EVERY COMPONENT (note that some components may not be mapped in the target workspace)
for(IComponentHandle componentHandle : componentHandles) {
  
  //IMPORTANT from API desc: The order of the baselines in the result reflects the 
  //order in which they were bases in the local history,
  // in reverse chronological order.
  List<IBaselineHandle> outgoingBaselineHandles = 
    changeHistorySyncReport.outgoingBaselines(componentHandle);

	
  //IMPORTANT from API desc: The order of the change sets in the result reflects their 
  // relative order in the local history 
  for that component. 
  List<IChangeSetHandle> outgoingChangeSetAfterBasisHandles = 
    changeHistorySyncReport.outgoingChangeSetsAfterBasis(componentHandle);

  //DELIVER ONLY POSSIBILE LATEST BASELINE FOR COMPONENT AND CHANGESETS ON TOP
  if (outgoingBaselineHandles.size() > 0) {
    try {
      sourceWorkspaceConnection.deliver(
          targetWorkspaceConnection, 
          changeHistorySyncReport, 
          Collections.singletonList(outgoingBaselineHandles.get(0)), 
          outgoingChangeSetAfterBasisHandles, 
          progressMonitor);
    } catch (TeamRepositoryException e) {
      log.error("FAILED delivery last baseline and change sets",e);
      throw new SnipException("FAILED delivery last baseline and change sets",e);	
    }
  } else {
    try {
      sourceWorkspaceConnection.deliver(
          targetWorkspaceConnection, 
          changeHistorySyncReport, 
          Collections.EMPTY_LIST, 
          outgoingChangeSetAfterBasisHandles,
          progressMonitor);
    } catch (TeamRepositoryException e) {
       log.error("FAILED delivery change sets only",e);
       throw new SnipException("FAILED delivery change sets only",e);	
    }
  }
}
	

0 votes

Your answer

Register or log in to post your answer.

Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.

Search context
Follow this question

By Email: 

Once you sign in you will be able to subscribe for any updates here.

By RSS:

Answers
Answers and Comments
Question details
× 10,938
× 1,202
× 43

Question asked: Jan 20 '15, 11:27 p.m.

Question was seen: 5,675 times

Last updated: May 31 '16, 6:38 a.m.

Confirmation Cancel Confirm