Tuesday, November 15, 2011

TeamCity.ServiceMessages Write API

Today I published TeamCity.ServiceMessages v2.0 package which provides API for generating TeamCity specific service messages. Service messages are described in the documentation page at http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity

Introduction

Do you know what service messages are? Service Messages are strings in the following format:
##teamcity[hello message='teamcity']

TeamCity uses Service Messages to provide simple API for a build scripts integration, i.e. build status reporting, artifacts publishing, tests reporting and more.

For precise description of the format and service messages usage in TeamCity, take a loot at Build Script Interaction with TeamCity article. Service Messages introduce a communication protocol for map-like data exchange between processes using stream, socket, HTTP or pipe.

Basic read-write API for service messages was implemented in TeamCity.ServiceMessages library v1.0. There are blog posts describing it here and here.

Reporting Tests

...

public void ReportTests(...) {
  //Create a TeamCity message logger. 
  using (var writer = new TeamCityServiceMessages().CreateWriter())
  {
    using (var block = writer.OpenBlock("Big log from TeamCity Service Messages block"))
    {
      //Let's open a test suite
      using(var suite = block.OpenTestSuite("MyFavoriteTests.dll"))
      {
        //Let's report ignored test
        using (var test = suite.OpenTest("This.Would.Log.Ignored.Test"))
        {       
          test.WriteIgnored();
        }
        //Let's report failed test
        using (var test = suite.OpenTest("This.Would.Log.Failed.Test"))
        {
          test.WriteFailed("Assert failed", "Assert failed stacktrace and more details");
        }
        //Let's report successful test with some output
        using (var test = suite.OpenTest("This.Would.Log.Successful.Test"))
        {
          test.WriteStdOutput("This is a test output to be shown in TeamCity UI");
        }
      } 
    }
  }
}
Thanks to C# using construction that asserts service messages write API is used in the right way. As you open a block you may only use created object to continue logging until you dispose it. TeamCity.ServiceMessages library contains assertions to avoid generating invalid service message sequences.

Reporting Dynamic Build Artifact

public void ReportCustomArtifact(string path) {
  using (var writer = new TeamCityServiceMessages().CreateWriter(x => builder.AppendLine(x)))
  {
     writer.PublishArtifact(path);
  }
} 

Reporting Custom Build Number

public void ReportNewBuildNumber(string buildNumber) {
  using (var writer = new TeamCityServiceMessages().CreateWriter(x => builder.AppendLine(x)))
  {
     writer.WriteBuildNumber(buildNumber);
  }
} 

What's Next

There is a big number of other TeamCity service message that are supported by the implementation. To find more information, see JetBrains.TeamCity.ServiceMessages.Write.Special.ITeamCityWriter and it's parent interfaces. Here are some of supported messages:
  • Set build number
  • Set build parameter
  • Write message, warning or error
  • Publish build artifacts
  • Publish build statistics value
  • Open/Close block
  • Open/Close test suite
  • Open/Close test
  • Open/Close compilation block
  • and more...

API Changes since v1.0

I moved IServiceMessage interface from JetBrains.TeamCity.ServiceMessages.Read namespace to JetBrains.TeamCity.ServiceMessages namespace.

Usage

The library is compiled for .NET 3.5. It is available as NuGet package:
PM> Install-Package TeamCity.ServiceMessages

Sources are available at GitHub. I setup a build configuration at TeamCity.CodeBetter.Com.

Thanks to TeamCity support for NuGet, it automatically publishes the library as NuGet package to NuGet.org.

No comments: