The anatomy of a build configuration, all runner types, step execution policies, failure conditions, artifact paths, build number formats, and a hands-on multi-step Maven exercise
A build configuration (analogous to a Jenkins Job) is the central entity in TeamCity. It ties together: source code (VCS Root), what to do (Build Steps), when to do it (Triggers), success criteria (Failure Conditions), and what to save (Artifact Paths).
| Section | What it controls | Covered in |
|---|---|---|
| General Settings | Build config name, ID, description, artifact paths, build number format, build counter | This phase |
| Version Control Settings | Which VCS Root to use, checkout mode, label builds | Phase 5 |
| Build Steps | Ordered list of runners to execute | This phase |
| Triggers | What causes a build to start automatically | Phase 7 |
| Failure Conditions | What counts as a failed build beyond non-zero exit code | This phase |
| Build Features | Add-ons: coverage, PR support, commit status, etc. | Phase 10 |
| Dependencies | Snapshot and artifact dependencies on other builds | Phase 9 |
| Parameters | Config-level parameters overriding project-level ones | Phase 8 |
| Agent Requirements | Which agents are compatible with this build | Phase 6 |
A runner is the type of work a build step performs. TeamCity ships with these built-in runners:
| Field | Example | Notes |
|---|---|---|
| Maven home | %teamcity.tool.maven.DEFAULT% | Use TeamCity-managed Maven tool or absolute path on agent |
| Goals | clean package -DskipTests | Space-separated Maven goals and flags |
| Path to POM file | pom.xml | Relative to checkout dir; leave blank for root pom.xml |
| JVM options | -Xmx512m -Djava.awt.headless=true | Maven process JVM, not your app's JVM |
| Working directory | Checkout directory | Leave blank to use the VCS checkout root |
| User settings path | %system.maven.settings.file% | Custom settings.xml — use a parameter for portability |
| Incremental building | Enabled / Disabled | When enabled, TeamCity only rebuilds modules with changes |
If you set Maven Home to an absolute path (/usr/share/maven), the build will fail on any agent that doesn't have Maven at that exact path. Use %teamcity.tool.maven.DEFAULT% or define a TeamCity tool (Administration → Tools) and reference it as %teamcity.tool.maven.3.6.3%. This makes the agent requirement explicit and portable.
TeamCity automatically imports Surefire/Failsafe XML reports when using the Maven runner. No extra configuration needed. Test results appear in the Tests tab of the build. Failed tests are highlighted and show stack traces inline.
| Field | Example | Notes |
|---|---|---|
| Gradle tasks | clean build | Space-separated tasks |
| Gradle home | Leave blank (use wrapper) | Leave blank to use gradlew in source; explicit path otherwise |
| Build file | build.gradle | Leave blank for default; specify for non-standard locations |
| Gradle options | --parallel --continue | Gradle command-line options |
| JVM options | -Xmx1g | Gradle daemon JVM options |
| Init script path | tc-init.gradle | Inject TeamCity-specific init script (e.g., for test reporting) |
Leave Gradle home blank and check Use Gradle wrapper to run ./gradlew. This pins the Gradle version per project and avoids agent-level Gradle installation. The Gradle wrapper is the industry standard for reproducible builds.
The most flexible runner — runs any executable or script. Two modes:
Executable: /usr/bin/python3
Parameters: scripts/deploy.py --env staging --version %build.number%
#!/bin/bash
set -euo pipefail
echo "Build number: %build.number%"
echo "Branch: %teamcity.build.branch%"
# Run tests
npm install
npm test
# Package
npm run build
tar -czf dist-%build.number%.tar.gz dist/
By default, bash scripts continue after a failing command. Without set -e (or set -euo pipefail for stricter checking), your build step may show green even when an important command failed. Always include set -euo pipefail at the top of shell scripts in CI.
| Field | Values | Notes |
|---|---|---|
| PowerShell edition | Desktop / Core | Desktop = Windows PowerShell 5.x; Core = PowerShell 6+/7+ |
| Min required version | 5.0 | Agent must have at least this version; enforces agent requirement |
| Script execution mode | Script file / Script source | Script source: inline PowerShell in TeamCity; Script file: path in repo |
| Script arguments | -Env Staging -Version %build.number% | Passed to script as named parameters |
| Format stderr as | Error / Warning | Treat stderr output as error (fails build) or warning |
# Example inline PowerShell step
param([string]$Env = "staging", [string]$Version = "0.0.0")
Write-Host "Deploying version $Version to $Env"
$ErrorActionPreference = "Stop"
# Run .NET build
dotnet build --configuration Release /p:Version=$Version
# Run tests
dotnet test --no-build --logger trx --results-directory TestResults
Write-Host "Build complete"
Each build step has an Execute step setting that controls when it runs:
| Policy | When step runs | Use case |
|---|---|---|
| Only if build status is successful | Previous step must have succeeded | Default — compile then test only if compile passes |
| If all previous steps finished successfully | Same as above but checks all previous, not just last | Chain of steps where any failure stops the chain |
| Even if some of the previous steps failed | Always runs unless build was explicitly cancelled | Cleanup steps, notification steps, "always publish" reports |
| Always, even if build stop command was issued | Runs even during cancellation | Critical cleanup that must always run |
Set your test report publication step to Even if some of the previous steps failed. This ensures test XML files are uploaded even when tests fail — which is exactly when you need them most. Without this, a compilation failure causes all subsequent steps to be skipped, leaving you with no test output to diagnose.
Beyond a non-zero exit code, TeamCity can fail a build based on additional conditions:
| Condition | Description | Example |
|---|---|---|
| Non-zero exit code | Default. Any step exits non-zero → build fails | Always active |
| At least one test failed | Parses imported test results; fails build if any test red | Java unit tests with Surefire |
| Metric change | Fails if a build metric exceeds a threshold relative to previous build | Fail if code coverage drops by more than 5% |
| Build log contains text | Regex match against build log; fails if found | Fail if log contains "ERROR:" or "BUILD FAILURE" |
| Build log not contains text | Fail if expected text is absent | Fail if "Tests run:" is not in log (test phase was skipped) |
Go to Build Configuration → Failure Conditions → Add failure condition to add conditions beyond the default.
Artifact paths tell TeamCity which files to publish after a build. Defined in General Settings → Artifact paths. Uses Ant-style patterns.
# Syntax: source_path [=> target_path]
# source_path: relative to checkout directory or working dir
# Publish a JAR
target/myapp-*.jar
# Publish to a named subdirectory in artifacts
target/myapp-*.jar => libs
# Publish test reports
target/surefire-reports/**/* => test-reports
# Publish entire dist directory
dist/** => release
# Publish multiple patterns (one per line)
target/myapp.jar
target/surefire-reports/**/*
*.log => build-logs
Artifact paths are published after all build steps complete. They are not a step themselves. If a step fails partway through, artifacts may still be published from files that were produced before the failure. Use failure conditions + step execution policies to control when artifacts should or should not be published.
After a build completes, go to the build's Artifacts tab to download files. Artifacts are also directly accessible via URL:
http://SERVER:8111/repository/download/BuildConfigId/.lastSuccessful/path/to/file.jar
The build number is the human-readable identifier for a build. Configured in General Settings → Build number format.
| Token | Expands to | Example result |
|---|---|---|
{build.counter} | Auto-incrementing counter (starts at 1) | 42 |
%build.vcs.number% | VCS revision (Git short SHA) | a3f2c91 |
%teamcity.build.branch% | Branch name | feature/login |
| Any literal text | Literal text | 1.2. |
# Common build number patterns:
# Simple counter
{build.counter}
# Result: 42
# SemVer with counter
1.2.{build.counter}
# Result: 1.2.42
# Counter + Git SHA
{build.counter}.%build.vcs.number%
# Result: 42.a3f2c91
# Branch + counter (useful for feature branch builds)
%teamcity.build.branch%.{build.counter}
# Result: feature/login.5
The build counter increments with every new build in that build configuration, regardless of success or failure. You can reset it manually from Administration → Build Configuration → Edit → General Settings → Build counter — useful when starting a new major version.
Controls whether TeamCity wipes the agent's working directory before checking out source code.
| Setting | Behaviour | When to use |
|---|---|---|
| Use default (agent settings) | Clean if agent requests it or on first build | Default — works for most cases |
| Always clean files before build | Deletes entire working dir on every build | When stale files can cause build failures (e.g., generated code) |
| Do not clean files before build | Never wipes; incremental checkout only | When checkout time is slow; accept risk of stale files |
If your build generates files (code gen, JAXB, protobuf) and a new build doesn't regenerate them (e.g., the schema didn't change), stale generated files from a previous run may be used. This causes hard-to-reproduce failures that only appear on agents. Use "Always clean" for builds with code generation.
Create a build configuration that compiles, tests, packages, and publishes a Java project artifact.
Step 1 — Compile & Test
Runner: Maven
Goals: clean verify
Maven home: %teamcity.tool.maven.DEFAULT%
JVM options: -Xmx512m
Step 2 — Package (always runs)
Runner: Maven
Goals: package -DskipTests
Execute: Even if some previous steps failed
JVM options: -Xmx512m
Step 3 — Print build info (Command Line)
Runner: Command Line
Script:
echo "Build: %build.number%"
echo "Branch: %teamcity.build.branch%"
echo "Agent: %teamcity.agent.name%"
ls -la target/*.jar 2>/dev/null || echo "No JAR produced"
Execute: Even if some previous steps failed
Artifact paths:
target/*.jar => artifacts
target/surefire-reports/**/* => test-reports
Failure conditions — add:
ERROR → fail with warning