Archive for June, 2012

Switzerland Visit

Monday, June 11th, 2012

This summer we will be visiting two User Groups in Switzerland to talk about some of our tools among other things.

The events are organized in collaboration with the local User Groups of Berne and Lucerne:

If you’d like to attend the event, I’d recommend you sign up as places are limited.

Berne

Date: Tuesday 3rd July – 6 to 9 pm

Topics:

ReSharper Tips’n’ Tricks

Real World MVC

Registration, Location and more info: User Group Web Site

Lucerne

Date: Wednesday 4th July – 6 to 8:30 pm

Topics:

ALM with JetBrains Tools (covering TeamCity, YouTrack et al.)

Real World MVC

Registration, Location and more info: User Group Web Site

All registrations are handled directly by the user groups. Please contact them (via their web site) if you have any issues.

Hope to see you there!

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!