Complete Guide: CI/CD Pipeline with TeamCity and Kotlin DSL
Imagine: a Node.js online store with three environments (dev, staging, production). Each build from scratch, dependencies pulled from npm without cache, tests run sequentially. Deployment took 40 minutes, and rollback meant manually uploading an archive via SSH. After an audit, we configured TeamCity: parallel steps, node_modules caching, automated tests in containers. Build time dropped to 8 minutes — 5x faster. Developers stopped waiting, and releases became daily. This time savings directly lowers TCO and accelerates feature delivery to production. Our team with 10 years of experience will set up CI/CD turnkey: from server installation to documentation. The setup cost starts at $2,000 for a basic pipeline, with potential savings of $4,000 per month in developer time — that's $48,000 per year.
Typical Technical Challenges
N+1 queries in tests — TeamCity collects coverage reports and finds bottlenecks at the CI stage. Dirty environments — each build on a clean Docker agent, conflicts eliminated. Slow builds — parallel steps and dependency caching (npm cache, Maven local) reduce time by up to 70%. For a typical Node.js project, a cached build takes 2–3 minutes instead of 10. Mean time to recovery drops to 15 minutes thanks to automatic rollbacks. A TeamCity CI/CD setup is 2x faster than Jenkins for parallel builds.
Pipeline Setup: Kotlin DSL and Steps
We use Kotlin DSL — configuration as code, versioned in Git and subject to code review. According to JetBrains, Kotlin DSL provides type safety and IDE autocompletion for build configurations. TeamCity supports complex pipelines with parallel steps. Below is a typical pipeline for a Node.js application:
// .teamcity/settings.kts
import jetbrains.buildServer.configs.kotlin.*
import jetbrains.buildServer.configs.kotlin.buildSteps.*
import jetbrains.buildServer.configs.kotlin.triggers.*
version = "latest"
project {
buildType(Build)
buildType(Test)
buildType(Deploy)
buildTypesOrder = arrayListOf(Build, Test, Deploy)
}
object Build : BuildType({
name = "Build"
vcs { root(DslContext.settingsRoot) }
steps {
nodeJS {
shellScript = "npm ci && npm run build"
}
}
artifactRules = "dist/** => dist.zip"
})
object Test : BuildType({
name = "Test"
dependencies {
snapshot(Build) {}
}
steps {
script {
scriptContent = """
npm ci
npm test -- --coverage --ci
""".trimIndent()
}
}
failureConditions {
testFailure = true
errorMessage = true
}
})
object Deploy : BuildType({
name = "Deploy to Production"
type = Type.DEPLOYMENT
dependencies {
snapshot(Test) {}
artifacts(Build) {
artifactRules = "dist.zip => ."
}
}
params {
param("deploy.env", "production")
}
steps {
script {
scriptContent = """
unzip dist.zip -d /var/www/app/
sudo systemctl reload nginx
""".trimIndent()
}
}
triggers {
vcs {
branchFilter = "+:refs/heads/main"
}
}
})
Deployment via SSH
For PHP projects (Laravel, Symfony), we added an SSH step:
sshExec {
commands = """
cd /var/www/app
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
sudo systemctl reload php8.3-fpm
""".trimIndent()
// targetUrl and credentials are configured via TeamCity parameters
}
Docker Build in TeamCity
Containerization unifies the environment and eliminates "it works on my machine" errors.
steps {
dockerCommand {
commandType = build {
source = file { path = "Dockerfile" }
namesAndTags = "myapp:%build.counter%"
commandArgs = "--no-cache"
}
}
dockerCommand {
commandType = push {
namesAndTags = "myapp:%build.counter%"
}
}
}
Parameters and Templates
Multi-environment projects (staging, production) are configured via templates. One template — three environments, minimal code.
template("DeployTemplate") {
params {
param("env.name", "")
param("env.url", "")
param("ssh.host", "")
}
steps {
script {
scriptContent = "deploy.sh %env.name% %env.url%"
}
}
}
object DeployStaging : BuildType({
templates(DeployTemplate)
params {
param("env.name", "staging")
param("env.url", "https://staging.example.com")
param("ssh.host", "staging.server.com")
}
})
Why TeamCity Beats Jenkins?
TeamCity is faster with parallel builds — by a factor of 2, thanks to its built-in artifact storage and smart scheduler. Kotlin DSL offers type safety and IDE autocompletion, while Jenkins Pipeline uses Groovy with dynamic typing, often leading to runtime errors. Native templates and environment parameters in TeamCity simplify scaling to dozens of projects. For clarity:
| Criteria | TeamCity | Jenkins |
|---|---|---|
| Configuration | Kotlin DSL (static typing) | Groovy (dynamic) |
| Parallel builds | Built-in scheduler, 2x faster | Requires tuning |
| Environment templates | Native parameters and templates | Via libraries |
| Artifacts | Built-in storage | Plugin |
Order TeamCity setup and get a ready pipeline with documentation in 5–7 days. The TeamCity CI/CD setup process is straightforward and can save your team 30–40 hours per month.
How to Set Up TeamCity CI/CD in 5 Steps
- Install TeamCity server and agents — Use Docker or bare metal. Mount volumes for data and logs.
- Configure VCS roots — Connect to Git repository and set up VCS triggers.
- Define build configurations — Write Kotlin DSL scripts for build, test, and deploy steps.
- Set up environment templates — Create parameterized templates for dev, staging, and production.
- Enable notifications and documentation — Configure Slack/email alerts and document the pipeline.
Deployment for multiple environments is configured using templates with parameters. Each environment is a separate build type linked to the template. VCS triggers on main run automatic deployment to staging; production only via manual UI trigger. This prevents accidental production deployments.
Common CI/CD Setup Mistakes
- Ignoring artifactRules — artifacts don't reach the next build, deployment breaks
- Lack of agent isolation — library conflicts cause unpredictable test failures
- Hardcoded credentials — keys in code, security leak. Use TeamCity parameters and password storage
- Too long pipelines — all steps in one build, no parallelization. Split into Build -> Test -> Deploy
- No notifications — team learns of build failure hours later
Which Projects Require CI/CD Automation?
Any project where releases happen more than once a month and deployment is manual. Especially if the team has more than two developers. TeamCity pays for itself by reducing build time and eliminating human errors. Our clients — from fintech startups to enterprise portals — save 10 to 40 hours per month on deployment operations.
What's Included in the Work
- Audit of current build and deployment process (1 day)
- Installation of TeamCity server and agents (Docker or bare metal) — 1 day
- VCS triggers, build, test, and artifact configuration
- Environment templates (dev/staging/production)
- Build status notifications (Slack, email)
- Pipeline testing and bug fixing
- Documentation and training for your team
- One-month warranty after delivery
Timelines and Cost
Cost is calculated individually after project analysis. Estimated timelines:
| Component | Time |
|---|---|
| Installation and basic configuration | 1 day |
| Kotlin DSL and templates | 1–2 days |
| Integration with VCS and tests | 1 day |
| Deployment to environments | 1–2 days |
| Notifications and documentation | 1 day |
Contact us for a consultation on TeamCity setup for your project. We'll help automate deployment without headaches.







