Author Archive

TeamCity build status icon

Thursday, July 26th, 2012

With the upcoming version of TeamCity 7.1, it is now easier to get status updates on a build, by using TeamCity’s HTTP API . We have had this functionality in the past, however it hasn’t been straightforward to use and not the most ideal solution for things like markup pages.

With 7.1, which is currently in EAP we have simplified this. The following single line of code:

<img src=”http://evgeny-goldin.org/teamcity/app/rest/builds/buildType:(id:bt54)/statusIcon”/>

produces the status icon for the “rest-clients” project: .

The only thing you need to know about the project is the build configuration ID, which is always accessible in the URL address bar

Build Configuration id

If a build is not successful, you’ll see:  or 

The code required is:

<pre><a href="http://teamcity/viewType.html?buildTypeId=btN&guest=1">
    <img src="http://teamcity/app/rest/builds/buildType:(id:btN)/statusIcon"/>
</a>

Don’t forget to add the “guest=1″ parameters to the URL so that people clicking on the link will be taken directly to the build page. Otherwise they’ll be welcomed with a login screen. See it in action on GitHub. For more details about the options available, see the documentation page.

Happy green builds!

Get TeamCity artifacts using HTTP, Ant, Gradle and Maven

Tuesday, June 5th, 2012

In a world of Java build tools there are several options to download and use binaries produced by TeamCity build configurations. You can use plain HTTP request, Ant + Ivy, Gradle and Maven to do so. This post provides working examples for each of these options.

Build Configuration “id”

Before you retrieve artifacts of any build configuration you need to know its "id" which can be seen in a browser when corresponding configuration is browsed. As an example, we can take IntelliJ IDEA Community Edition project hosted at teamcity.jetbrains.com. Its “Community Dist” build configuration provides a number of artifacts which we’re going to use in the examples that follow. And as can be seen on the screenshot below, its "id" is "bt343".

HTTP

Anonymous HTTP access is probably the easiest way to fetch TeamCity artifacts, the URL to do so is:

http://host/guestAuth/repository/download/<btN>/<buildNumber>/<artifactName>

Fot this request to work 3 parameters need to be specified:

  • btN

    Build configuration "id", as mentioned above.

  • buildNumber

    Build number or one of predefined constants: "lastSuccessful", "lastPinned", or "lastFinished". For example, you can download periodic IDEA builds from last successful TeamCity execution.

  • artifactName

    Name of artifact like "ideaIC-118.SNAPSHOT.win.zip". Can also take a form of "artifactName!archivePath" for reading archive’s content, like IDEA’s build file. You can get a list of all artifacts produced in a certain build by requesting a special "teamcity-ivy.xml" artifact generated by TeamCity.

Ant + Ivy

All artifacts published to TeamCity are accompanied by "teamcity-ivy.xml" Ivy descriptor, effectively making TeamCity an Ivy repository. The code below downloads "core/annotations.jar" from IDEA distribution to "download/ivy" directory:

"ivyconf.xml"

<ivysettings>
    <settings defaultResolver='teamcity-repo'/>
    <resolvers>
        <url name='teamcity-repo' alwaysCheckExactRevision='yes' checkmodified='true'>
            <ivy      pattern='http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/teamcity-ivy.xml'/>
            <artifact pattern='http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/[artifact](.[ext])'/>
        </url>
    </resolvers>
</ivysettings>

"ivy.xml"

<ivy-module version="1.3">
    <info organisation="com.jetbrains" module="idea"/>
    <dependencies>
        <dependency org="org" name="bt343" rev="lastSuccessful">
            <include name="core/annotations" ext="jar"/>
        </dependency>
    </dependencies>
</ivy-module>

"build.xml"

<project name="teamcity-download" default="download" xmlns:ivy="antlib:org.apache.ivy.ant">
    <target name="download" xmlns:ivy="antlib:org.apache.ivy.ant">
        <taskdef uri="antlib:org.apache.ivy.ant" resource="org/apache/ivy/ant/antlib.xml"/>
        <ivy:configure file    = "${basedir}/ivyconf.xml"/>
        <ivy:resolve   file    = "${basedir}/ivy.xml"/>
        <ivy:retrieve  pattern = "${basedir}/download/ivy/[artifact].[ext]"/>
    </target>
</project>

Gradle

Identically to Ivy example above it is fairly easy to retrieve TeamCity artifacts with Gradle due to its built-in Ivy support. In addition to downloading the same jar file to "download/gradle" directory with a custom Gradle task we can use it as "compile" dependency for our Java class, importing IDEA’s @NotNull annotation:

"Test.java"

import org.jetbrains.annotations.NotNull;

public class Test
{
    private final String data;
    public Test ( @NotNull String data ){ this.data = data; }
}

"build.gradle"

apply plugin: 'java'

repositories {
    ivy {
        ivyPattern      'http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/teamcity-ivy.xml'
        artifactPattern 'http://teamcity.jetbrains.com/guestAuth/repository/download/[module]/[revision]/[artifact](.[ext])'
    }
}

dependencies {
    compile ( 'org:bt343:lastSuccessful' ){
        artifact {
            name = 'core/annotations'
            type = 'jar'
        }
    }
}

task copyJar( type: Copy ) {
    from configurations.compile
    into "${ project.projectDir }/download/gradle"
}

Maven

One of the ways to use Maven with TeamCity is by setting up an Artifactory repository manager and its TeamCity plugin. This way artifacts produced by your builds are deployed to Artifactory and can be served from there as from any other remote Maven repository.

However, you can still use TeamCity artifacts in Maven without any additional setups. "ivy-maven-plugin" bridges two worlds allowing you to plug Ivy resolvers into Maven’s runtime environment, download dependencies required and add them to corresponding "compile" or "test" scopes.

We can compile the same Java source from the Gradle example but using Maven this time.

"pom.xml"

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns              = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi          = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0

http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test</groupId>
    <artifactId>maven</artifactId>
    <packaging>jar</packaging>
    <version>0.1-SNAPSHOT</version>
    <name>[${project.groupId}:${project.artifactId}:${project.version}]</name>
    <description>Ivy Maven plugin example</description>

    <build>
        <plugins>
            <plugin>
                <groupId>com.github.goldin</groupId>
                <artifactId>ivy-maven-plugin</artifactId>
                <version>0.2.5</version>
                <executions>
                    <execution>
                        <id>get-ivy-artifacts</id>
                        <goals>
                            <goal>ivy</goal>
                        </goals>
                        <phase>initialize</phase>
                        <configuration>
                            <ivyconf>${project.basedir}/ivyconf.xml</ivyconf>
                            <ivy>${project.basedir}/ivy.xml</ivy>
                            <dir>${project.basedir}/download/maven</dir>
                            <scope>compile</scope>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

When this plugin runs it resolves IDEA annotations artifact using the same "ivyconf.xml" and "ivy.xml" files we’ve seen previously, copies it to "download/maven" directory and adds to "compile" scope so our Java sources can compile.

GitHub Project

All examples demonstrated are available in the GitHub project. Feel free to clone and run it:

git clone git://github.com/evgeny-goldin/teamcity-download-examples.git
cd teamcity-download-examples
chmod +x run.sh dist/ant/bin/ant gradlew dist/maven/bin/mvn
./run.sh

Resources

The links below can provide you with more details:



The list above covers options available for Java build tools. In addition to that, you can always download TeamCity artifacts using product’s Web UI or NuGet support. Which ways do you use? Would you like to see a better support for tools we have mentioned or those we didn’t? Let us know! As always, your feedback is very appreciated.

JavaScript Code Inspection Server-Side

Monday, June 4th, 2012

If you use one of our intelligent IDE’s such as Intellij IDEA Ultimate Edition, WebStorm or PhpStorm, for any kind of Web development, then you might be familiar with the powerful JavaScript inspections they offer. With over 130 validation rules, ranging from “Code style issues” to “Probable bugs” as well as built-in JSLint/JSHint integration, they constitute a powerful barrier against certain errors creeping into your JavaScript code.

Did you also know that you can have these inspections server-side as part of a continuous build process? With TeamCity you can run the same set of inspections on the server, and have the build fail, based on the criteria you define. This can be critical errors or even too many warnings.

Let’s see how it’s done. In this guide we’ll be using WebStorm, but the same process applies to any of our other platforms based on IDEA that support JavaScript.

1 – Defining a Scope

The first thing we need to do is specify a scope. Scopes define a set of sources (from all available in a project) to be inspected. Projects often contain third-party JavaScript libraries and/or minified scripts that in principle shouldn’t be analysed. As such, defining a scope allows us to specify what we do want to focus on.

Under File -> Settings in WebStorm, locate the Scope entry (you can type Scope in the search box for quick access). Click the + button and choose Add Scope -> Local, then specify its name, JavaScript in our case.

Once you do so you’ll see project’s files on the right (click the image to see a larger version).

Select JavaScript files intended for inspection (you can hold Ctrl button to select multiple files at once) and click the Include button on the right as can be seen on the screenshot below. Alternatively, you can select a directory and click the Include Recursively button. When you’re done make sure Share scope checkbox is checked. Doing so creates .idea/scopes/JavaScript.xml file containing the definition of the scope we’ve just created. This file should be committed to source control, a point we’ll get back to later in the process.

2 – Creating an Inspection Profile

The next step is to create a JavaScript-only inspection profile if you don’t want to deal with all kinds of validations at the same time. It is best to separate them and concentrate on one thing at a time – this will allow creating a dedicated TeamCity build configuration as we’re about to see.

Go back to File -> Settings and find the Inspections entry. Create a new inspection profile JS Inspection and remember that name, we’ll need it at step 6.

Uncheck all inspections except JavaScript.

Attach the scope defined at step 1 to rules you’re interested in.

3 – Defining Warnings and Errors

Every inspection rule can have a varying degree of severity, ranging from simple typos to critical errors. It is important to differentiate between warnings and errors since TeamCity allows us to treat them differently when specifying build failure conditions.

Some teams may consciously decide to pay attention (and hence fail the build) only to actual errors, which might cause browser misbehaviours at run-time. Examples include the famous last comma in array or object literal in IE issue. Other teams may treat errors and warnings equally so that neither of them ever make it to release. Whatever your preferences are, make sure inspection rules are in sync with them.

4 – Sharing and Locking Inspection Profile

When scopes and inspection profiles are defined the default location for IDE to keep this data is .idea/workspace.xml. However, this file is intended for keeping your local IDE settings and is therefore should never be committed to source control. If this file is not committed how can TeamCity read the definitions required for running server-side JavaScript inspections? That’s where sharing scopes and profiles comes into play. When you tick the corresponding Share scope or Share profile checkbox a separate file is created with your definitions: .idea/scopes/<scopeName>.xml for scopes and .idea/inspectionProfiles/<profileName>.xml for inspection profiles. These files can now be committed to source control for TeamCity to read them.

Locking inspection profile is a different story. Your IDE may have certain plugins disabled which will consequently make their inspections disappear from inspection profile screen. However, when TeamCity runs server-side code inspections it does so by firing up its own Intellij IDEA instance. This instance comes bundled with a default set of plugins and, therefore, a default set of inspections applied to your code in addition to those specified by you. As a result, it may be surprising to see TeamCity running inspections that were never part of the profile. So locking it means “Run only explicitly enabled inspections”.

As a result, you need to share and lock your inspection profile as shown on the following screenshot.

5 – Committing “.idea” directory to source control

After inspection profile is configured, shared and locked you need to check in an .idea directory into source control for TeamCity to read inspection definitions from there. Once again, the only file that should not be committed and is excluded by default is .idea/workspace.xml since it only contains your personal project settings.

6 – Configuring TeamCity Build Configuration

Once we have the inspections ready and committed to source control, we can now do the set up on the server-side. To do so, add a new Build Step and select Inspections (Java).

Configure this step similarly to the screenshot below (click the image to see a larger version).

The only thing that needs to be specified on this screen is Inspection profile name from step 2. You can now try to run your build configuration to see if there are any build errors. When all goes well you can navigate to inspection results from TeamCity “Overview” screen.

When browsing inspection result, you can open the offending line right in your IDE if you have TeamCity IDE plugin installed and logged in to your TeamCity instance.

7 – Configuring TeamCity Build Failure Conditions

Now that we can run inspections on the server, we can define build failure conditions using “Fail build on metric change” introduced in TeamCity 7. As mentioned in Step 3, inspection errors and warnings are treated as two separate metrics so we can define each of them in its own way.

The project we are using as an example contains no severe JavaScript errors, but it does contain a number of warnings which now make the build fail, and loudly!

As mentioned previously, we may decide to fail the build only in the case of actual errors to avoid the extra noise, and thus avoiding dealing with builds failing due to minor JavaScript warnings or nuances.

Summary

The process of running JavaScript inspections in TeamCity relies on the project definitions set in the IDE, that is why it is necessary to configure the previous steps and commit these to source control. Once done, the remaining steps on TeamCity are straight-forward. All you need to remember is the inspection profile name and from there on, it is up to you to define the build failure conditions.

Happy JavaScript coding!

TeamCity Build Dependencies

Tuesday, April 24th, 2012

Introduction

The subject of build dependencies is neither a trivial nor a minor one. Various build tools approach this subject from different perspectives contributing various solutions, each with its own strengths and weaknesses. Maven and Gradle users who are familiar with release and snapshot dependencies may not know about TeamCity artifact and snapshot dependencies or assume they’re somehow related to Maven (which isn’t true). So I have decided to provide an overview of how build dependencies work in TeamCity.

Non-Maven Dependencies

While Maven-based dependencies management and artifact repositories are very common and widespread in Java, there are cases where you may still find them insufficient or inadequate for your needs. For starters, you may not be developing in Java or perhaps your build tool is not providing built-in integration with Maven repositories, as is the case with Ant (or its Gant and NAnt spin-offs), SCons, Rake or MSBuild. Secondly, snapshot Maven dependencies provide their own set of challenges, making it harder to ensure correct snapshot dependency is used in a chain of builds.

In order to address these scenarios, TeamCity provides two ways to connect dependent build configurations and their outcomes: artifact and snapshot dependencies.

TeamCity Artifact Dependencies

The idea of artifact dependencies in TeamCity is very simple: download the artifacts produced by another build before the current one begins. After the artifacts are downloaded to the folder specified (checkout directory by default), your build script can use them to achieve its goals. You can find configuration details in TeamCity documentation.

Naturally, this scheme is not suitable for build tools with automatic dependencies management, but it works well with build or shell scripts accepting and expecting local paths, relative to the checkout directory. Note that the copying works not only for the produced build binaries, but for any kind of binary or text files, like the TeamCity coverage report as demonstrated on the screenshot above.

There is one important detail about specifying artifact dependencies and that is “Get artifacts from” configuration where you specify what type of build should files be taken from. Possible values of this field are “last successful”, “finished”, “pinned”, or “tagged build”, as well as the build number or “Build from the same chain”. While most values should be trivial to understand with “Last successful build” being the default and generally suitable option, the definition of “same chain” build is directly related to TeamCity snapshot dependencies.

TeamCity Snapshot Dependencies

Imagine a monolithic multi-step build process (build, test, package, deploy) which you decide to split into multiple smaller builds, invoked sequentially, forming a chain of executions. Doing so allows one to configure or trigger every chain step separately and run certain steps in parallel in order to speedup the process (like executing tests or building independent components). Most of all, it makes the overall maintenance significantly easier. However, while doing so you need to ensure every chain step uses the same consistent set of sources pulled from VCS even if newer commits are made while chain steps are running. That’s what TeamCity snapshot dependencies are for: they connect several build configurations into a single chain of execution, called build chain, with every step using the same set of sources, regardless of VCS updates. Note that the TeamCity use of the term “snapshot dependencies” may confuse people familiar with Maven snapshot dependencies which are two unrelated concepts.

Snapshot dependencies are configured similarly to artifact dependencies. You can find configuration details in TeamCity documentation.

Using Artifact and Snapshot Dependencies Together

When applicable, it is recommended to define both kinds of dependencies between build configurations, as this ensures not only a consistent set of sources used throughout a chain steps but also a consistent flow of artifacts produced. Now the definition of “Build from the same chain” in artifact dependency mentioned above becomes clear, as this is the only meaningful option in this scenario.

In a way, you can think of build chain steps running in isolation from VCS updates after the first sources’ “snapshot” is taken. Chain artifacts are either re-created from the same sources or passed through chain steps with artifact dependencies. This makes chain steps consistent, reproducible and always up-to-date (when applied to using chain artifacts), something that can’t be easily achieved with Maven snapshot dependencies.

Build Chains Visibility in TeamCity 7.0

TeamCity 7.0 took the notion of build chains to a whole new level by providing build chains a new UI, making chain steps visible and re-runnable. Once you have snapshot dependencies defined, a new “Build Chains” tab appears in project reports, providing a visual representation of all related build chains and a way to re-run any chain step manually, using the same set of sources pulled originally.

Build Chain Triggering

Having build configurations connected with snapshot dependencies and, therefore, their builds grouped into build chains not only makes them more consistent regarding the sources used, it also impacts the way builds are added to the build queue: after a certain chain step is triggered, the default behavior is to add all preceding chain steps as well, keeping their respective order, in addition to the one that was triggered initially. Let me repeat it for more clarity: triggering certain chain configuration adds preceding (those to the left of it) and not subsequent (to the right of it) configurations to the build queue, although it may seem counterintuitive at first. The idea is to mark the location where chain execution stops, which is exactly the configuration that was triggered initially; it becomes the last execution step.

To trigger subsequent chain steps upon VCS changes found in a chain configuration, you can add a VCS trigger with the “Trigger on changes in snapshot dependencies” option to the configuration that would be the last execution step. This configuration is then triggered whenever any of the preceding chain steps is updated, which schedules the whole chain for execution.

Having this behavior in mind, you therefore need to decide which configurations are triggered automatically and which should be run manually. Usually, earlier chain steps having no impact on external environment can be triggered automatically by VCS trigger but final chain steps, potentially modifying external systems, are invoked manually after a human verification of the previous chain results. The process of running the final chain steps manually is usually referred to as “promoting” previously finished builds.

Sample Build Chain: Compile, Test, Deploy

Imagine three sample build configurations, “Compile”, “Test” and “Deploy” connected into a build chain: “Deploy” is snapshot dependent on “Test” which is snapshot dependent on “Compile”.

In this sample scenario the “Compile” and “Test” configurations are triggered automatically while “Deploy” is triggered manually, following the recommendations given above. VCS changes in “Compile” configuration only trigger an execution of this chain step, while VCS changes in “Test” configuration trigger “Compile” and “Test” execution (in that order).

Once a “Compile” configuration is added to the builds queue, its sources’ timestamp is recorded on the server to be used in all subsequent chain steps. If any of the chain steps is connected to a different VCS root, its sources are also pulled according to the same timestamp.

Promoting Finished Builds

As soon as the automatic chain execution stops (after running “Test”), you can continue it by clicking the corresponding “Run” button on the “Deploy” configuration that was not triggered (see the build chain screenshot above). Alternatively, it is possible to promote a finished “Test” build through its “Build Actions” and invoke configurations which are snapshot dependent on it – “Deploy” configuration in this case.

Summary

This article has provided an overview of TeamCity artifact and snapshot dependencies, build chains, how their steps are triggered and how finished builds are promoted. I hope you now have a good understanding of how it works and of when it is appropriate (or not) to use TeamCity build dependencies in addition to those provided by build tools such as Maven.

Please, refer to the TeamCity documentation for more information about this subject:


As always, your feedback is very welcome in our forum!