Build Configuration Combobox list (Build Trigger Modal)

Hello,

I'm writing a Custom Build Trigger to start a full build of our code after a failed Continuous Integration build. Currently, the implementation of finding the associated full build configuration relies on some very weak assumptions. It would require the two Build Configurations (our CI/Full builds are separted by Build Configs), and a certain set of build parameters must match. Ideally, I would really like a model similar to the Full Build Trigger implementation. This would allow the user to add this trigger to any configuration with much more ease. This would also make the code much more portable, allowing this to be shared. Lastly, the build configurations wouldn't necessarily have to be in the same parent project.

Does anyone know how I would go about implementing this in my editBuildTrigger file? I understand this is not part of the Open API, but we are not immediately worried about upgrading in the near future.

Thanks,

Robby

TeamCity 7.0.2 (build 21349)

PS: If you aren't familiar with the Full Build Trigger, I've attached a screenshot of the selection screen. The string before the "::" is the project, the string after is the build configuration.



Attachment(s):
FullBuildTrigger.jpg
15 comments
Comment actions Permalink

Robby,

I see you discussed this by email with my colleagues.
Please let me know if you still have any open questions.

Thanks

0
Comment actions Permalink

Michael,

I was never really able to figure anything out. Implementing grabbing the hypothetical selection in the Java source would be very easy. How to prepopulate the list has me stumped. None of the javascript I found in the Teamcity installation jumped out at me as to what I could use. I also have very little javascript experience. I'm not really sure what I should be looking at.

Thanks,

Robby

0
Comment actions Permalink

Robby,

If you are concerned with the build configurations chooser, the JSP code can look something like:

<%@ taglib prefix="props" tagdir="/WEB-INF/tags/props" %>

...

    <props:selectProperty name="dependsOn" enableFilter="true">
      <props:option value="">-- Please select a build configuration --</props:option>
      <c:forEach items="${triggerBean.buildTypes}" var="buildType">
        <props:option value="${buildType.buildTypeId}"><c:out value="${buildType.extendedName}"/></props:option>
      </c:forEach>
    </props:selectProperty>

When triggerBean is a bean you fill in the controller with the build configurations list.

0
Comment actions Permalink

Yegor,

That is exactly what I'm looking for. I'm going to start working on implementing it now. I'll post my results when I get some testing time in. I'll check back in if I have any more issues.

Thanks,

Robby

0
Comment actions Permalink

I've started looking at it from a jsp perspective and made a little progress. I have the combo box implementation, but can't get (or don't know what bean to use) the full list of non-archived configurations (BuildTypes). I seem to have found the Finish Build Trigger .jsp file, and see how they are getting this list. It is a combination of this bean and a property of the bean:

<jsp:useBean id="dependencyTriggerBean" type="jetbrains.buildServer.controllers.admin.projects.triggers.FinishBuildTriggerBean" scope="request"/>
.
.
.
<c:forEach items="${dependencyTriggerBean.availableActiveBuildTypes}" var="buildType">

I would like to use a similar approach. It seems to me that this is a custom defined bean. How would I go about defining my own bean to use within my jsp file? EDIT: Or is there a convenient bean that is available to use already?

0
Comment actions Permalink

Robby,

You can pass your own bean to JSP or just a collection of BuildTypes to display. There is no need to have some common bean as there is almost nothing to reuse.

0
Comment actions Permalink

I think I understand basically what should be done, but I'm not getting the desired results. Here is my set up.

(This is a stub of my trigger source. This is what I expect to get used by the jsp file).
    @NotNull
    private final ProjectManager myProjectManager;

public GoodCIBuildTrigger(@NotNull final PluginDescriptor pluginDescriptor,
            @NotNull final BuildCustomizerFactory promotionCustomizer,
            @NotNull final ProjectManager projectManager) {
        myPluginDescriptor = pluginDescriptor;
        myPromotionCustomizer = promotionCustomizer;
        myProjectManager = projectManager;
    }

    public List<SBuildType> getActiveBuildTypes() {
        return myProjectManager.getActiveBuildTypes();
    }

(Top of my jsp file. Full header information is included in case it links to any clues)
<%@ include file="/include.jsp" %>
<%@ page import="jetbrains.buildServer.buildTriggers.custom.GoodCITriggerUtil" %>
<%@ page import="jetbrains.buildServer.buildTriggers.custom.GoodCIBuildTrigger" %>
<%@ page import="jetbrains.buildServer.util.Dates" %>
<%@ taglib prefix="props" tagdir="/WEB-INF/tags/props" %>
<%@ taglib prefix="admin" tagdir="/WEB-INF/tags/admin" %>
<jsp:useBean id="propertiesBean" type="jetbrains.buildServer.controllers.BasePropertiesBean" scope="request"/>
<jsp:useBean id="dependencyBean" type="jetbrains.buildServer.buildTriggers.custom.GoodCIBuildTrigger" scope="request"/>

(Body of the combo box implementation)
<tr >
    <td>
        <label for="buildConfigurations">Build configuration:</label>
    </td>
    <td colspan="2">
    <props:selectProperty name="buildConfigurations" enableFilter="true">
      <props:option value="">-- Please select a build configuration --</props:option>
      <c:forEach items="${dependencyBean.getActiveBuildTypes()}>" var="buildType">
        <props:option value="${buildType.buildTypeId}"><c:out value="${buildType.extendedName}"/></props:option>
      </c:forEach>
    </props:selectProperty>
    
    <span >
        Not currently implemented. Do not use.
    </span>
    </td>
</tr>


(Text from my build-server-plugin.xml file)
<beans default-autowire="constructor">
  <bean id="dependencyBean" />
</beans>


I keep getting this error in my stacktrace when I open my edit trigger dialog:

Error message: bean dependencyBean not found within scope
TeamCity: 7.0.2 (build 21349)
Operating system: Windows 7 (6.1, x86)
Java: 1.6.0_31-b05 (Sun Microsystems Inc.)
Servlet container: Apache Tomcat/7.0.23


Trace: java.lang.InstantiationException: bean dependencyBean not found within scope
     at org.apache.jsp.plugins.goodci_002dbuild_002dtrigger.editGoodCIBuildTrigger_jsp._jspService(editGoodCIBuildTrigger_jsp.java:114)


Any suggestions? Am I overthinking this entirely?

(Also, my combobox works as expected. I'm just having issues populating it through passing the list of build configurations)

Thank,

Robby
0
Comment actions Permalink

> bean dependencyBean not found within scope

To make a bean available in the JSP you should add it to the model in doHandle method.
e.g.

  protected ModelAndView doHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response) throws Exception {
    ModelAndView result = new ModelAndView("your_jsp.jsp");
    Map<String, Object> model = result.getModel();

    model.put("dependencyBean", <bean instance here>);
    return result;
  }

0
Comment actions Permalink

I've implemented doHandle as below.

    protected ModelAndView doHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response) throws Exception {
        ModelAndView result = new ModelAndView("editGoodCIBuildTrigger.jsp");
        Map<String, Object> model = result.getModel();

        model.put("dependencyBean", new GoodCIBuildTrigger(myPluginDescriptor,
                myPromotionCustomizer, myProjectManager));
        return result;
  }

This is inside my GoodCIBuildTrigger class (as I needed access to constructor parameters). I'm not sure how/where to call this method/if it's needed to be called. (I went ahead and uploaded the updated source/jsp/etc and get the same out of scope message).



Edit: Here are the imports I'm using for HttpServletRequest, HttpServletResponse, and ModelAndView

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;

0
Comment actions Permalink

Robby,

Sorry for the delay in replying.

If the question is still actual...

Indeed, creating a trigger with custom controller is not completely trivial.
I've made a small example: you can get the atached patch and apply it over currentUrl build trigger sources (revision 5360).

Then download and apply the atttached patch (e.g. with IDEA's VCS/Apply Patch command).
This will add urlBuildTriggerBean bean into JSP.

Hope it will make this more clear.



Attachment(s):
customTriggerControllerExample.patch.zip
0
Comment actions Permalink

Yegor,

That is very helpful. With this I should be able to easily implement this with my own trigger. I'll test it out when I get to the office on Monday.

Thanks,

Robby

0
Comment actions Permalink

Edit: Moved this text to a direct reply to Yegor. Wasn't sure if he would get pinged otherwise.


0
Comment actions Permalink

I'm having one immediate problem with this implementation.  ShowTriggerParametersController does not seem to be part of the openapi,  so my environment doesn't know anything about it. Is there anything I  can swap this with to obtain the desired results? (Related,  manager.registerController complains because my environment doesn't know  about ShowTriggerParametersController). Edit: I suppose what I'm asking is what strings can replace ShowTriggerParametersController.BUILD_TYPE_SETTINGS_PARAM and ShowTriggerParametersController.SELECTED_TRIGGER_DESCRIPTOR_PARAM. I imagine manager.registerController would still work if urlBuildTriggerEditSettingsController extends BaseController instead.

Is the EDIT_URL_BUILD_TRIGGER file something I would have to make, or is that constructed from my jsp file by TeamCity?

Edit 1: I found where ShowTriggerParameterController lives (web.jar). Now I have an issue with the constructor to UrlBuildTriggerEditSettingsController. It gives me this message:

Implicit super constructor ShowTriggerParametersController() is undefined. Must explicitly invoke another constructor

Edit 2: I did a quick hack to get it to compile. Here is what I have:

public class GoodCIBuildTriggerEditSettingsController extends BaseController {
private final ProjectManager myProjectManager;
private String myPluginResourcesPath;
  
  public GoodCIBuildTriggerEditSettingsController(final ProjectManager projectManager,
                                               @NotNull final PluginDescriptor pluginDescriptor,
                                               @NotNull final WebControllerManager manager) {
    myProjectManager = projectManager;
    myPluginResourcesPath = pluginDescriptor.getPluginResourcesPath(GoodCIBuildTrigger.EDIT_GOODCI_BUILD_TRIGGER_JSP);
    manager.registerController(pluginDescriptor.getPluginResourcesPath(GoodCIBuildTrigger.EDIT_GOODCI_BUILD_TRIGGER_HTML), this);
  }

.
.
.

}

And I've added the following to my build-server.xml file

  <bean />

Which causes my trigger not to load. I have to provide values to these two new classes somehow. Is this not the right method?


Thanks,

Robby

0
Comment actions Permalink

Robby,

It might be not the easiest task to figure out what is wrong with the code. I'd suggest to try the example patch on top of the unmodified URL trigger, ensure it works and then figure out what is different in your code and the example.

As a wild guess. I'd check that your GoodCIBuildTrigger has

  public String getEditParametersUrl() {
    return myPluginDescriptor.getPluginResourcesPath(EDIT_GOODCI_BUILD_TRIGGER_HTML);
  }

0
Comment actions Permalink

Gotta love wild guesses :). I had previously been using EDIT_GOODCI_BUILD_TRIGGER_JSP before I added the custom bean. HTML works great though! Now to implement triggering based on the build selection.

Thanks for all your help Yegor,

Robby

0

Please sign in to leave a comment.