TeamCity 3.0 Help

Typical Plugins

In this section:

Custom build number

public class MyBuildNumber extends BuildServerAdapter { public MyBuildNumber(SBuildServer aBuildServer) { aBuildServer.addListener(this); } public void buildStarted(SRunningBuild build) { // Build Numbers set to "my" in build number pattern will be replaced with custom build number if ("my".equals(build.getBuildNumber())) { build.setBuildNumber(createBuildNumber(build)); } } public String createBuildNumber(SRunningBuild build) { return "my custom#"; } }

Custom VCS

See jetbrains.buildServer.vcs.VcsManager.

If custom VCS plugin requires some settings to be edited from the web UI, then it should also provide a JSP file for its settings. This JSP file should be placed into the plugin jar under the buildServerResources/ path. In the buildServerSpring.xml you should also configure webResourcesUnpacker (note that you should use your vcs name as a plugin name), see above.

In the JSP file you should use special custom tags for input fields, radio buttons and checkboxes that correspond to your VCS properties. These custom tags are located in the props tag library:

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

You can use JSP files of existing VCS plugins as an example.

Custom Notifiers

See some docs at http://code.google.com/p/buildbunny/wiki/CreateTeamcityNotifier

Custom template processing: http://www.intellij.net/forums/thread.jspa?messageID=5187731

Build Result Tabs

Create subclass of ViewLogTab and attach it to the web place: WebControllerManager.addPageExtension(WebPlace.VIEW_LOG_TAB, this)

Custom User Authentication

Custom authentication API is based on Sun JAAS API. To provide your own authentication scheme, you should provide a login module class which must implement interface javax.security.auth.spi.LoginModule and register it in the jetbrains.buildServer.serverSide.auth.LoginConfiguration.

For example:

public class CustomLoginModule implements javax.security.auth.spi.LoginModule { private Subject mySubject; private CallbackHandler myCallbackHandler; private Callback[] myCallbacks; private NameCallback myNameCallback; private PasswordCallback myPasswordCallback; public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) { // We should remember callback handler and create our own callbacks. // TeamCity authorization scheme supports two callbacks only: NameCallback and PasswordCallback. // From these callbacks you will receive username and password entered on the login page. myCallbackHandler = callbackHandler; myNameCallback = new NameCallback("login:"); myPasswordCallback = new PasswordCallback("password:", false); // remember references to newly created callbacks myCallbacks = new Callback[] {myNameCallback, myPasswordCallback}; // Subject is a place where authorized entity credentials are stored. // When user is successfully authorized, the jetbrains.buildServer.serverSide.auth.ServerPrincipal // instance should be added to the subject. Based on this information the principal server will know a real name of // the authorized entity and realm where this entity was authorized. mySubject = subject; } public boolean login() throws LoginException { // invoke callback handler so that username and password were added // to the name and password callbacks try { myCallbackHandler.handle(myCallbacks); } catch (Throwable t) { throw new LoginException(t.toString()); } // retrieve login and password final String login = myNameCallback.getName(); final String password = new String(myPasswordCallback.getPassword()); // perform authentication if (checkPassword(login, password)) { // create ServerPrincipal and put it in the subject mySubject.getPrincipals().add(new ServerPrincipal(null, login)); return true; } return false; } private boolean checkPassword(final String login, final String password) { return true; } public boolean commit() throws LoginException { // simply return true return true; } public boolean abort() throws LoginException { return true; } public boolean logout() throws LoginException { return true; } }

Now we should register this module in the server. To do so, we create a login module descriptor:

public class CustomLoginModuleDescriptor implements jetbrains.buildServer.serverSide.auth.LoginModuleDescriptor { // Spring framework will provide reference to LoginConfiguration when // the CustomLoginModuleDescriptor is instantiated public CustomLoginModuleDescriptor(LoginConfiguration loginConfiguration) { // register this descriptor in the login configuration loginConfiguration.registerLoginModule(this); } public Class<? extends LoginModule> getLoginModuleClass() { // return our custom login module class return CustomLoginModule.class; } public Map<String, ?> getOptions() { // return options which can be passed to our custom login module // for example, we could store reference to SBuildServer instance here return null; } public String getTextForLoginPage() { // return text to show on the login page which could describe // what should be entered in the user name and password fields return null; } public String getDisplayName() { // presentable name of this plugin return "My custom authentication plugin"; } }

Finally we should create build-server-plugin-ourUserAuth.xml as it is described above and write there CustomLoginModuleDescriptor bean:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans default-autowire="constructor"> <bean id="customLoginModuleDescriptor" class="some.package.CustomLoginModuleDescriptor"/> </beans>

Create a jar, put it into the WEB-INF/lib directory of the TeamCity server and restart it. When the server is started, you should be able to choose your custom plugin from the drop down list of the Administration-> Server Configuration page.

Writing a Custom Build Runner

Agent-side Part

Implement jetbrains.buildServer.agent.BuildRunner interface (you may also extend GenericProgramRunner or even JavaProgramRunner helpers for this). To log your messages, you may obtain instance of ServerLogger singleton (you may also use ServerLoggerFacade for convinience).

TBD

Server-side Part

Build agent plugin should also provide server side jar with a class implementing jetbrains.buildServer.serverSide.RunType interface. The implementation of the RunType interface must be registered in the jetbrains.buildServer.serverSide.RunTypeRegistry. You can do this in the constructor of the RunType implementation, like this:

public class CustomRunTypeImpl { ... public CustomRunType(RunTypeRegistry runTypeRegistry) { runTypeRegistry.registerRunType(this); } ... }
Last modified: 20 April 2023