It's all about the answers!

Ask a question

Accessing BuildResult files from "Request Rebuild..." action


Steve White (4021213) | asked Mar 18 '13, 12:27 p.m.
I have been able to create a BuildResultPage contributor/provider which displays the files that were published via the build engine.
What I would like to do is also be able to reference those file(s) from within the "Request Rebuild..." action for our custom dialog section. In the Rebuild Dialog there is a reference to the BuildResult, which is not null. What I can't figure out is how to get a IBuildResultContext, which best I can tell is what the ResultPage uses to get access to the files associated with the BuildResult. This is passed to the ResultPage when it is constructed from how I am understanding the build source.
Is it possible to do want I am attempting? 
If yes, what object/methods do I need to get the IBuildResultContext so I can get the contributions using getContributions or is this even necessary? 
Is there another way of doing what I want too do?

Accepted answer


permanent link
Nick Edgar (6.5k711) | answered Jul 25 '13, 11:59 a.m.
JAZZ DEVELOPER
Steve, re the comments from earlier today, yes you want to get the properties from the build request corresponding to the build result.  It has a copy of the properties from the build definition (plus any overrides) at request time.  

It's a common idiom in the RTC APIs to have to fetch an item holding the actual data (e.g. IBuildRequest) given its handle which is essentially a pointer to a given item + optionally a specific state of the item (e.g. IBuildRequestHandle).  For client-side code, use the fetch methods on IItemManager, obtained from ITeamRepository.itemManager().

But it turns out that you don't need to in the context of a build result page contribution. The contribution provider's site has that info, and you can pass it along to your page when you create it.  The relevant code for our Properties page is in /com.ibm.team.build.ui/src/com/ibm/team/build/internal/ui/editors/result/properties/BuildPropertiesContributionProvider.java:

    @Override

    public void initializeContributionProvider(IProgressMonitor monitor) throws Exception {

        IBuildRequest request = getStartRequest(getBuildResultContext().getBuildResultRecord().getBuildRequests());

        if (request != null) {

            fBuildProperties = request.getBuildDefinitionInstance().getProperties();

        } else {

            fBuildProperties = new ArrayList<IBuildProperty>();

        }

    }


    private IBuildRequest getStartRequest(IBuildRequest[] allRequests) {

        for (IBuildRequest currentRequest : allRequests) {

            if (currentRequest.getBuildAction().getAction().equals(IBuildAction.REQUEST_BUILD)) {

                return currentRequest;

            }

        }

        // Log a message, but don't treat this as an error. It is unexpected,

        // but we can handle it.

        BuildUIPlugin.log(NLS.bind(Messages.BuildPropertiesContributionProvider_NO_REQUEST,

                BuildResultTextHelper.getLabel(getBuildResultContext().getBuildResult())));

        return null;

    }


    @Override

    public AbstractBuildResultPage getBuildResultPage() {

        return new BuildPropertiesPage(getBuildResultEditor(), getExtensionId(),

                Messages.BuildPropertiesContributionProvider_TAB_TEXT, getExtendedContributionIds(),

                getBuildResultContext(), fBuildProperties);

    }


Steve White selected this answer as the correct answer

Comments
Steve White commented Jul 25 '13, 5:14 p.m.

Nick, thanks. That is exactly the code logic I was using as a guide, but I didn't see that getBuildResultContext() was part of the common super class, so I was attempting the following logic which didn't work.:
 List allRequests = getBuildResult().getBuildRequests();
 IBuildRequest buildRequest = getStartRequest( (IBuildRequest[])allRequests.toArray() );
Once I change my code to use getBuildResultContext().getBuildResultRecord().getBuildRequests())
I was able to get the properties.

Thanks again, you've been a great help thru this process in answering my questions
-Steve


Nick Edgar commented Jul 29 '13, 2:46 p.m.
JAZZ DEVELOPER

Good to hear you were able to get it going, Steve. 

2 other answers



permanent link
Nick Edgar (6.5k711) | answered Mar 19 '13, 10:14 a.m.
JAZZ DEVELOPER
Hi Steve.  In the request dialog, sections are contributed via the requestBuildDialogSections extension point.
The built in ones are defined with:

   <extension

         point="com.ibm.team.build.ui.requestBuildDialogSections">

      <requestBuildDialogSection

            class="com.ibm.team.build.internal.ui.dialogs.ScmOptionsSection$Factory"

            order="100"/>

      <requestBuildDialogSection

            class="com.ibm.team.build.internal.ui.dialogs.PropertiesSection$Factory"

            order="200"/>

   </extension>


The class given must implement com.ibm.team.build.ui.dialogs.requestbuild.IRequestBuildSectionFactory, and its create method is passed a com.ibm.team.build.ui.dialogs.requestbuild.RequestBuildSectionSite.  RequestBuildSectionSite has getTeamRepository(), getBuildResult(), isRebuild() and other methods.

RequestBuildSectionSite is similar to IBuildResultContext in that it provides contextual info from the containing UI, but IBuildResultContext is specific to the build result editor context.



Comments
Steve White commented Mar 19 '13, 11:26 a.m.

Nick, thanks for the info. I already have a dialog section implemented as part of our solution, which is how our user base will enter our specific build data. We will be displaying our build wizard from this section.
   @Override
   protected void createSectionContent( Section section )
   {
      ITeamRepository repos = getSite().getTeamRepository();
      IBuildRequest request = getSite().getBuildRequest();
      IBuildResult result = getSite().getBuildResult();
      builddef = getSite().getBuildDefinition();
    
I couldn't see within those objects where I could retrieve the files(contributions) that were published by the engine to the BuildResult via artifactFilePublisher. I can get those files via the BuildResultContributionProvider I implemented for the BuildResultEditor, but I still don't see how I can get those files from the objects available in the dialog section.

cont'd in next comment


Steve White commented Mar 19 '13, 11:27 a.m.

The flow is this:
The initial request flows to the engine which processes the build and one result of that is a file which is a serialized image of the Build object. For rebuild or view we use that file to repopulate the build object for view/rebuild wizard.
We do not want to create a ton of generic properties in the request. I have another question on the forum about that specific issue(see link below), which appears we would need to open a feature, so we are considering other short term solutions to pass the file on the initial request. But as for the BuildResult, we can already publish the file to it, but as stated above I don't see how I can obtain that file with the objects available in the dialog section, proabably because I don't have a full understanding of those objects, but I don't see any methods that would do that as provided in BuildRAesultcontext(getContributions)
Can you point me to the logic within BuildResult that I would need to retrieve the files that were published by the engine? Basically the equivalent of IBuildResultContext().getBuildResultContributions(getContributionIds())



Steve White commented Mar 19 '13, 11:27 a.m.

https://jazz.net/forum/questions/106107/is-there-a-way-to-send-a-file-in-a-buildrequestbuilddefintion-to-the-build-engine?utm_campaign=forum&utm_medium=email&utm_source=forum-new-comment&utm_content=forum-question


Nick Edgar commented Mar 19 '13, 12:10 p.m.
JAZZ DEVELOPER

In the editor context, the editor fetches the contributions of interest for you.  In the request dialog, you'd need to do this yourself using:

com.ibm.team.build.client.ITeamBuildClient.getBuildResultContributions(IBuildResultHandle, String, IProgressMonitor)
(there's also a multi-type-id variant).
Use:
com.ibm.team.build.client.ClientFactory.getTeamBuildClient(ITeamRepository)
to get the client interface.  Once you have the IBuildResultContribution item(s), the rest of the processing should be the same as in the result editor extension.



Nick Edgar commented Mar 19 '13, 12:20 p.m. | edited Mar 19 '13, 12:22 p.m.
JAZZ DEVELOPER

Using contributions in this way could also be used for the other issue of communicating a file to the build.  The corresponding API is:

com.ibm.team.build.client.ITeamBuildClient.addBuildResultContribution(IBuildResultHandle, IBuildResultContribution, IProgressMonitor)
See also:
com.ibm.team.build.common.BuildItemFactory.createBuildResultContribution()
and the type id constants on com.ibm.team.build.common.model.IBuildResultContribution.

It's a bit odd to contribute a file (actually a content blob) to a build before it's run, but the API doesn't actually check the build state. It'll get cleaned up when the build is deleted too.

You can use the artifactFileRetriever or logFileRetriever Ant task to retrieve the content, depending on the contribution type.  Unfortunately we don't have a task that allows an arbitrary contribution type, so if you want to use your own you'd need to write the fetching code yourself.




Steve White commented Mar 19 '13, 12:52 p.m.

Nick thanks. So for Rebuild it looks like its possible to get the file from the Result using  the solution you provided above.
But for an initial Build Request, the BuildRequest BuildResult and BuildResultHandle are all null in createSectionContent, validate2 and applyProperties where we get control.
So how would I be able to use ITeamBuildClient.addBuildResultContribution(IBuildResultHandle, IBuildResultContribution, IProgressMonitor)
if the BuildResultHandle is null. Would I first somehow create the handle?
I see a createBuildResult() in the factory class, but not a handle. I assume I would also have too create a BuildResult as well and set that in the BuildRequest?

The reason we are passing a file is because the object can exceed the size limit for a Build Property.


Nick Edgar commented Mar 19 '13, 1:07 p.m.
JAZZ DEVELOPER

Sorry, I neglected the fact that we don't actually notify the section extensions after the request has been submitted.  The request is submitted in com.ibm.team.build.internal.ui.dialogs.RequestBuildDialog.requestBuildJobImpl(IBuildDefinition, ITeamRepository, IProgressMonitor).  Unfortunately, I don't see any way for you to intercept this and get the request or result after it has been submitted, at least not using the standard request dialog.  If you have control over the action that brings up the request dialog, you could provide your own subclass and override RequestBuildDialog.requestBuild.



Steve White commented Jul 11 '13, 11:59 a.m.

Nick, is it possible to add a property to the build result from the build agent running a ANT script? I don't see a way. All I see is the ANT script can only read properties.
I am storing our custom Build object on a sever via ftp and I want to store that directory in the Build result as a property so when I do a Rebuild the request will have that property and then my custom build section can ftp the file to repopulate our custom build wizard with the original build request data. Since each build has a unique ID the ftp dir will be unique for each build. This is the solution I have come up with since there is no access to the Build Result context from the Rebuild request. From testing I can see that a property that is added in the Build Request appears in the Build Result and the Rebuild request Props, but as I mentioned I don't see a way add a property from ANT via the build agent. For our build solution to work for Rebuild I need a way to retrieve our Build Obj (a serialized file) during The Rebuild Request dialog.
Thanks,
-Steve

showing 5 of 8 show 3 more comments

permanent link
Nick Edgar (6.5k711) | answered Jul 15 '13, 2:02 p.m.
JAZZ DEVELOPER
edited Jul 15 '13, 2:03 p.m.
Hi Steve, re your July 11 comment, there's no way to add/change properties on an existing build (the only opportunity to override them is when issuing the build request).  However, it should be possible to use build result contributions to do what you want.

From the Ant script, I suggest using the linkPublisher Ant task to publish a link to the FTP file (you might well want this traceability anyway).  Then, in the (re)build dialog, you can retrieve that contribution and its corresponding URL.  It basically comes down to:
  • query for link type contributions using com.ibm.team.build.client.ITeamBuildClient.getBuildResultContributions(IBuildResultHandle, String, IProgressMonitor), using constant com.ibm.team.build.common.model.IBuildResultContribution.LINK_EXTENDED_CONTRIBUTION_ID as the link type id
  • select the one that corresponds to your custom build object, since there may be more than one link (e.g. by matching label on the IBuildResultContribution), or checking for "ftp:" prefix, or both
  • you can extract the URL using com.ibm.team.build.common.model.IBuildResultContribution.getExtendedContributionProperty(String), using property name constant com.ibm.team.build.common.model.IBuildResultContribution.PROPERTY_NAME_URL
See also forum thread: https://jazz.net/forum/questions/116496/retrieve-build-log
for the case where the content is uploaded to the jazz repo, not an external reference.


Comments
Steve White commented Jul 25 '13, 8:23 a.m.

Nick, I have another question related to this. In the Results view I have a custom resultsPage which extends AbstractBuildResultPage. within that page I would like to get the properties for the buildRequest builddef (the properties listed in the props tab). AbstractBuildResultPage has a method getBuildResult which I can get a IBuildDefintionHandle, but I don't know how to get the BuildDef  form the handle and thus use the getProperties. I see the properteis tab logic gets all the requests to find the starting request to obtain the builddef instnace thus properties. BuildResult has a getBuildRequests method, so I am attemtping to use that and the above logic to get to the properties. What is the best way for me to retrieve the properties?


Steve White commented Jul 25 '13, 8:55 a.m.

P.S. my thought of using BuildResult.getBuildRequests() is not working as I had hoped because It returns a List of IBuildRequestHandle. I'm not clear on how to get from a Handle to an instance of the object. I.E. IBuildDefintionHandle to IBuildDef, IBuildRequestHandle to IBuildRequest.

Your answer


Register or 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.