migrate-to-teamcity
Migrating CI/CD pipelines to TeamCity. Use when the user wants to migrate, convert, or switch to TeamCity from GitHub Actions (.github/workflows/) or Bamboo (bamboo-specs/*.yml), even if they only say "move our CI". Other CI systems (GitLab, Jenkins, CircleCI, Azure DevOps, Travi
Install
npx skills add https://github.com/JetBrains/teamcity-cli/tree/main/skills/migrate-to-teamcity
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install jetbrains-teamcity-cli@llmmart
git clone https://github.com/JetBrains/teamcity-cli.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole jetbrains/teamcity-cli collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Migrate to TeamCity
Quick Start
teamcity migrate # detect + convert + write .tc.yml files
teamcity migrate --dry-run --json # preview as structured JSON
teamcity pipeline validate f.tc.yml # schema check
teamcity project vcs create --url <repo-url> --auth anonymous -p ProjectId # create VCS root first
teamcity pipeline create name -p ProjectId -f f.tc.yml --vcs-root <VcsRootId>
teamcity run start PipelineId --watch
Run teamcity migrate from the repo root -- detection scans .github/workflows/ and bamboo-specs/ relative to the current directory.
Reading the report
- Needs review -- problems inside the generated YAML: TODO stubs, dropped steps, reusable-workflow placeholders. Fix these in the file before creating the pipeline.
- Manual setup needed -- work the converter cannot do. Sort each item onto one of two sides: YAML edits (secrets, matrix expansion, expression
runs-on,container:/services:) go beforepipeline create; server-side configuration (connections,if:-derived branch filters, triggers, notifications) comes after. The checklist below orders them. - Exit code 1 means at least one source failed to convert or one generated file failed schema validation -- files that converted cleanly are still written. Read the per-file ✓/⚠/✗ lines instead of treating exit 1 as total failure.
--jsonprints{"sources": [...], "results": [...]}to stdout; each result carriesoutputFile,yaml,needsReview,manualSetup, andvalidationError.
Gotchas
- Always
type: scriptfor./gradlewand./mvnw. TC'stype: gradle/type: mavenrunners use the agent's version, not the project's. This causes real build failures. - Schema valid does not mean pipeline works. Migration is not done until builds pass.
- Private repos: use a GitHub App connection, not a PAT. Start with
teamcity project connection create github-app -p <project>-- its output prints the authorize, App-install, andvcs createfollow-up commands. That flow opens a browser; in headless runs pass existing App credentials (--no-manifest --app-id <id> --client-id <id> --private-key-file <pem> --stdin, client secret piped to stdin) or use SSH deploy keys (teamcity project ssh uploadwith agit@github.com:URL). Public repos:--auth anonymous. - Secrets, triggers, and branch filters are always manual. The converter flags them but cannot create them -- the checklist below covers each.
- VCS root must exist before pipeline create.
teamcity pipeline createtakes--vcs-root <id>, not a URL. Create it first withteamcity project vcs create. - Default branch defaults to
main. Pass--branch refs/heads/mastertoteamcity project vcs createif the repo usesmaster. - Unknown actions/tasks become stubs. Read the action's source, write an equivalent shell script. Most actions are thin CLI wrappers. See mappings.
Workflow
Goal: get all pipeline jobs green on the TC server, not just generate valid YAML.
Copy this checklist and check off items as you complete them:
Migration progress:
- [ ] Convert: run `teamcity migrate` from the repo root
- [ ] Fix every "Needs review" item, plus "Manual setup" items needing YAML edits (matrix expansion, expression `runs-on`, container/services) -- see mappings.md and gotchas.md
- [ ] Wire up secrets in the YAML: the converter rewrites `${{ secrets.X }}` to `%X%` but does not define it -- store the value (`teamcity project token put <project> <value>`) and add `X: "credentialsJSON:<uuid>"` under the top-level `secrets:` block (see schema.md)
- [ ] Validate: `teamcity pipeline validate <file>` -- only proceed when it passes
- [ ] Create VCS root (`teamcity project vcs create`), then `teamcity pipeline create <name> -p <project> -f <file> --vcs-root <id>`
- [ ] Set up the remaining runtime "Manual setup needed" items before running: registry/cloud connections the steps reference (the first run fails without them), and any `if:`-condition items -- gate converted deploy/release steps via branch filter, execution condition, or a guard in the script so the first run cannot deploy from the wrong branch
- [ ] Run: `teamcity run start <id> --watch`; on failure read `teamcity run log <id> --failed --raw`, fix, `teamcity pipeline push`, re-run until green
- [ ] Do the trigger-only "Manual setup needed" items: triggers, notifications
- [ ] Report: what migrated and what remains manual
References
Files (teamcity-cli)
-
references
-
gotchas.md 5.2 KB
# Sharp Edges, Troubleshooting, and Manual Setup ## Workflows/jobs to skip (not portable) Some CI jobs depend on platform-specific infrastructure and cannot be meaningfully migrated: | Pattern | Why skip | |---|---| | CodeQL (`github/codeql-action`) | Requires GitHub security-events API and CodeQL cloud infrastructure | | Dependabot | GitHub-native dependency update service | | GitHub Pages deploy (`actions/deploy-pages`) | GitHub-specific hosting; use TC artifact publishing or separate deploy | | GitHub release creation (`on: release`) | The trigger is GitHub-specific; use tag-based VCS trigger in TC instead | | Bamboo deployment plans (`bamboo-specs/deployment.yml`) | No TC pipeline equivalent; model as a separate pipeline triggered on build success | The converter drops the steps it recognizes as non-portable (listed under "Needs review") and emits a no-op placeholder when a job ends up with no steps — delete those placeholders rather than trying to fill them in. Unrecognized variants (e.g. `github/codeql-action/upload-sarif`) become regular TODO stubs instead — decide per stub whether to replace or remove it. ## Expanding matrix strategies TC has no native matrix. Expand each matrix combination into a separate job. The key decision is how to pin the language/tool version: **Use `docker-image` when the job only needs one toolchain.** This is the cleanest approach for language version matrices (Go, Node, Python, etc.): ```yaml test_go_1_21: name: "test (Go 1.21)" runs-on: Linux-Large steps: - type: script docker-image: "golang:1.21" script-content: go test -v -race ./... ``` **Install via script when the job needs multiple toolchains.** If a job needs e.g. both a specific Go version AND npm (which isn't in the `golang:` image), run on the agent and install the missing tool: ```yaml build_oldstable: name: "build (oldstable)" runs-on: Linux-Large steps: - type: script name: "Install Go 1.23" script-content: | curl -fsSL "https://go.dev/dl/go1.23.8.linux-amd64.tar.gz" -o /tmp/go.tar.gz sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf /tmp/go.tar.gz - type: script script-content: npm install -g some-tool && go test ./... ``` **Use the agent default for `stable`/`latest`.** TC Cloud agents have current versions of Go, Node, Java, and Python pre-installed. Only install explicitly when you need a non-default version (e.g. Go's `oldstable` → install the previous minor release). **Naming convention:** use `<job>_<variant>` IDs — e.g. `test_1_21`, `build_stable`. Job IDs must use `_` not `-`. **When to simplify instead of expanding.** Large matrices (>6 combinations) produce unwieldy TC pipelines. Pick a representative subset: - Keep the latest + oldest supported language versions (drop middle versions) - Keep Linux as the primary OS; add macOS/Windows only if the project has platform-specific code - For test-tag/flag matrices, keep the default (no flags) + the most important variant (e.g. `-race`) - Document what was dropped and why in the manual setup notes ## Sharp edges - **`working-directory` scope differs.** In GH Actions it's relative to repo root. In TC it's relative to the checkout directory (usually the same, but verify). ### Bamboo-specific - **Variable scopes collapse.** Bamboo has project / plan / job variable scopes. TC pipelines only have pipeline / job / step parameters. Project- and plan-level Bamboo vars need to be merged into the pipeline `parameters:` block manually. - **Plan keys aren't IDs.** Bamboo `plan.key: SAMP` ≠ TC pipeline ID. The positional `<name>` argument of `teamcity pipeline create <name>` sets the display name, and TeamCity derives the pipeline ID from it. ## Troubleshooting | Failure | Cause | Fix | |---|---|---| | `Unsupported class file major version 65` | `type: gradle` using agent's old Gradle with newer JDK | Switch to `type: script` + `./gradlew` | | `command not found: node/go/python` | Tool not on agent PATH | Check agent, or add setup script | | `permission denied` on script | File not executable | Add `chmod +x` step or use `bash script.sh` | | Artifact path not found | `files-publication` path doesn't match build output | Check actual output path in build log | | Snapshot dependency failed | Upstream job failed | Fix the deepest failed upstream job first | ## Always-manual setup | Item | How | |---|---| | VCS root | `teamcity project vcs list -p <id>` or create in UI | | Secrets / GHA `${{ secrets.X }}` / Bamboo `*password*` vars | `teamcity project token put <project-id> "<value>"` | | Triggers (GHA `on:`, Bamboo `triggers:`) | Configure push/PR/schedule in TC project settings | | Branch filters (GHA `if:`, Bamboo `branches:`) | Add to VCS trigger for conditional jobs | | Cloud auth (AWS / GCP / Azure) | TC Connection in project settings | | GHA `concurrency:`, `timeout-minutes:`, `fail-fast: false` | Build configuration settings in TC UI | | Bamboo `final-tasks:` | Set "Even if some build steps have failed" on each step (UI) | | Bamboo `stages[].manual: true` | Manual trigger on the downstream pipeline (UI) | | Bamboo plan permissions | TC project roles in Administration → Roles | | Bamboo notifications | TC notification rules per user/project | -
mappings.md 12.3 KB
# Concept Mappings: CI Systems to TeamCity ## Contents - GitHub Actions to TeamCity Pipeline YAML (concepts, actions, runners) - Fixing a stub - Bamboo Specs to TeamCity Pipeline YAML (concepts, tasks, variables) - Bamboo Specs that aren't converted ## GitHub Actions to TeamCity Pipeline YAML | GitHub Actions | TeamCity | Notes | |---|---|---| | `jobs.<id>` | `jobs.<id>` | IDs must use `_` not `-` | | `steps[].run` | `steps[].script-content` | Shell commands transfer verbatim | | `steps[].uses: action` | Depends on action | See action mapping below | | `needs: [job1]` | `dependencies: [job1]` | | | `runs-on: ubuntu-latest` | `runs-on: Linux-Large` | See runner mapping below | | `env.KEY: val` | `parameters: env.KEY: val` | | | `secrets.X` | `%X%` | Add `X: "credentialsJSON:<uuid>"` under `secrets:`; create via `teamcity project token put` | | `strategy.matrix` | Separate jobs or `parallelism` | | | `container: image` | `docker-image:` on steps | | | `services:` | Docker Compose or step-level | | | `if: condition` | Branch filter or script logic | | | `timeout-minutes:` | Build configuration timeout (UI) | No YAML equivalent | | `continue-on-error: true` | Wrap the command so its exit code is ignored (`cmd || true`) or override the step's failure condition | TC fails on nonzero exit; the UI step-execution policy only controls running *after* earlier failures — it won't ignore this step's own exit code | | `concurrency: { group: ... }` | "Limit max concurrent jobs" build setting (UI) | No YAML equivalent | | `outputs:` / `${{ steps.x.outputs.y }}` | `output-parameters:` on producer + `%dep.<job>.<param>%` on consumer | Or write to a shared artifact file | | `uses: ./.github/workflows/x.yml` (reusable) | Inline OR convert separately + snapshot dependency | Stub created | | `uses: ./.github/actions/x` (composite) | Inline `steps` OR replace with single shell script | Stub created | | `on: push/pull_request` | VCS trigger (server-side) | | | `on: schedule` | Scheduled trigger (server-side) | | | `on: workflow_dispatch` | Manual trigger / parameterized | Inputs become TC build parameters with prompts | ### Action Mapping The **Converter emits** column is what `teamcity migrate` writes; **Your follow-up** is what you still have to do by hand. | Action | Converter emits | Your follow-up | |---|---|---| | `actions/checkout` | Removed -- TC VCS checkout is automatic | | | `actions/cache` | `enable-dependency-cache: true` | | | `actions/upload-artifact` | `files-publication: [{path: "..."}]` | | | `actions/download-artifact` | Nothing (simplified out); named downloads get a manual note | Artifacts arrive via the job's `dependencies:` (from `needs:`) -- ensure the upstream job publishes with `share-with-jobs: true`, and add the dependency yourself if the workflow downloaded from a job it didn't `need` | | `actions/setup-node/java/go/python` | Removed -- pre-installed on TC Cloud agents | Pinned versions surface as manual notes; ensure the agent provides them | | `gradle/actions/setup-gradle` | Removed -- `./gradlew` runs directly | | | `docker/login-action` | Comment-only placeholder step | Configure a Docker registry connection in TC project settings -- required for private registries, no login command is generated | | `docker/build-push-action` | `docker build && docker push` script | | | `JetBrains/qodana-action` | Commented pointer to native integration | Add the Qodana build feature in TC settings | | `aws-actions/configure-aws-credentials` | Nothing (simplified out); a manual note carries the wiring | Add `env.AWS_ACCESS_KEY_ID` / `env.AWS_SECRET_ACCESS_KEY` under `secrets:` and `env.AWS_DEFAULT_REGION` under the job's `parameters:` -- step-local exports would not survive across TC steps | | `softprops/action-gh-release` | `gh release create "<tag_name>" --generate-notes` plus any `files:` globs; falls back to `%teamcity.build.branch%` when `tag_name` is unset | Add `env.GH_TOKEN` under `secrets:` -- `gh` reads it from the environment, so the `env.` prefix is required | | `golangci/golangci-lint-action` | `golangci-lint run <args>` | Assumes the binary on the agent; a pinned `version:` becomes a manual note -- install it yourself | | `codecov/codecov-action` | `curl -Os https://cli.codecov.io/latest/linux/codecov && chmod +x codecov && ./codecov` | | | `goreleaser/goreleaser-action` | **Stub** (not in the registry) | Replace with `curl -sSfL https://goreleaser.com/static/run \| bash -s -- release --clean` (needs `GITHUB_TOKEN`) | | `aquasecurity/trivy-action` | `trivy <scan-type> <image-ref>` | Assumes trivy on the agent; install via the trivy install.sh if missing | | `github/codeql-action/init`, `/analyze`, `/autobuild` | **Dropped** (listed under Needs review) -- requires GitHub security-events API | Consider the Qodana build feature instead. Other codeql-action subpaths (e.g. `/upload-sarif`) stub like unknown actions | | Unknown actions | Commented stub with original inputs | Read the action's source, write the equivalent shell | ### Fixing a stub The converter emits unknown actions as commented TODO steps that preserve the original inputs: ```yaml - type: script name: "custom-deploy" script-content: |- # TODO: Replace acme/custom-deploy@v2 with equivalent commands # Action inputs: # region: eu-west-1 # target: prod echo 'TODO: implement equivalent of custom-deploy' ``` Read the action's repository -- its `action.yml` shows what it actually runs (most actions are thin CLI wrappers). Replace the step body with the equivalent commands: ```yaml - type: script name: "custom-deploy" script-content: aws deploy create-deployment --region eu-west-1 --deployment-group prod ``` Secrets referenced by the original inputs become `%PARAM%` references -- create them with `teamcity project token put`. ### Runner Mapping | GitHub Actions | TeamCity Cloud | |---|---| | `ubuntu-latest` / `ubuntu-24.04` / `ubuntu-22.04` | `Linux-Large` | | `macos-latest` / `macos-15` / `macos-14` | `Mac-Medium` | | `windows-latest` / `windows-2022` | `Windows-Medium` | | Self-hosted labels | `self-hosted` with agent requirements | Hosted agent names come from the server's pipeline schema (`runs-on` enum, e.g. `Linux-Small/Medium/Large/XLarge`, `Mac-Medium`, `Windows-Small/Medium`). When connected, the CLI derives this mapping from the live schema — check `teamcity pipeline schema` if a name is rejected. ## Bamboo Specs to TeamCity Pipeline YAML Bamboo Specs YAML lives in `bamboo-specs/*.yml` (or `bamboo.yml` in the repo root). The converter walks `stages → jobs → tasks` and turns each task into a TeamCity step. | Bamboo concept | TeamCity | Notes | |---|---|---| | `plan` (project-key, key, name) | Pipeline + project | Project must exist before `pipeline create` | | `stages[]` ordered list | Job dependencies | Stage N's jobs `dependencies:` all stage N-1 jobs | | `stages[].manual: true` | Manual approval | Surfaced as manual setup; use TC manual trigger or approval feature | | `stages[].final: true` | Final cleanup job | Set step execution policy to "Even if some build steps have failed" | | Top-level job def (e.g. `Build:`) | TC job | Job ID becomes `<Stage>_<Job>` (sanitized) | | `tasks[]` | `steps[]` | Each task transformed individually; unknowns become TODO stubs | | `final-tasks[]` | Steps with always-run policy | Surfaced as manual setup; set per-step `Even if some build steps have failed` | | `artifacts[]` | `files-publication[]` | `shared: true` → `share-with-jobs`; otherwise `publish-artifact` | | `artifact-subscriptions[]` | Artifact dependencies | Manual: add to pipeline `dependencies:` block | | `requirements[]` | `runs-on` + agent requirements | First OS-shaped entry picks the runner; non-OS entries become manual notes. With no OS requirement, OS-bound tasks (ms-build, fastlane, xcode, ...) infer it | | `docker.image` | Docker container settings | Surfaced as manual setup; wrap step or use Docker wrapper feature | | `triggers[]` (polling, cron, ...) | VCS / scheduled triggers | Manual; configure in TC UI | | `branches:` | VCS root branch filters | Manual; configure on the VCS root | | `dependencies:` (top-level plan deps) | Cross-pipeline `dependencies:` or snapshot dependencies | Manual | | `variables:` | Pipeline parameters | Lifted to top-level `parameters:` | | `${bamboo.foo}` references | `%foo%` (TC parameter) | Predefined names map to TC equivalents (see below) | | `plan-permissions:` | Project roles | Manual; configure in TC Administration → Roles | | `notifications:` | Notification rules | Manual; configure per project/user | ### Bamboo Task Mapping | Bamboo task | TeamCity step | Notes | |---|---|---| | `script` | `type: script` | Shorthand list and full form (`scripts:`, `interpreter:`) supported | | `checkout` | Remove -- TC VCS checkout is automatic | | | `clean` | Remove -- enable "Clean checkout" on VCS root | | | `maven` / `mvn2` / `mvn3` | `mvn -f <project> <goal>` | JDK and `tests:` flag surface as manual notes | | `ant` | `ant -f <buildfile> <target>` | | | `gradle` | `./gradlew <tasks>` | | | `npm` | `npm <command>` | | | `node` | `node <script> <args>` | | | `command` | Inline `<exe> <args>` | | | `docker` (build/push/run) | `docker <cmd> ...` | Registry login is not converted or flagged -- add `docker login` or a TC registry connection yourself | | `inject-variables` | `set -a; . file; set +a` | Manual: review whether to convert to TC parameters | | `dump-variables` | `env \| sort` | | | `artifact-download` | Manual artifact-dependency | Surfaced as manual setup | | `test-parser` / `j_unit` / `nunit-parser` / `mocha` | Remove -- TC has built-in test report import | Manual: confirm report path | | `ssh` / `scp` | Inline `ssh`/`scp` script | Manual: upload SSH key with `teamcity project ssh upload` | | `ms-build` / `ms-test` / `visual-studio` / `nunit-runner` | Inline equivalent commands | | | `fastlane` | `fastlane <lane>` | | | `unlock-keychain` | `security unlock-keychain ...` | Manual: store password as TC token | | `repository-tag` / `repository-branch` / `repository-commit` / `repository-push` | Inline `git` commands | Push credentials are not flagged -- ensure the agent has them | | `aws-code-deploy` | `aws deploy create-deployment ...` | Manual: store AWS credentials as TC tokens | | `grails` / `gulp` / `grunt` / `bower` | Inline runner invocation | | | Unknown task | Commented TODO stub with original fields | | ### Bamboo Variable Mapping `${bamboo.foo}` references in task fields map to TC parameter syntax: | Bamboo | TeamCity | |---|---| | `${bamboo.build.number}` | `%build.number%` | | `${bamboo.repository.revision.number}` | `%build.vcs.number%` | | `${bamboo.repository.branch.name}` | `%teamcity.build.branch%` | | `${bamboo.repository.git.repositoryUrl}` | `%vcsroot.url%` | | `${bamboo.working.directory}` | `%teamcity.build.checkoutDir%` | | `${bamboo.tmp.directory}` | `%system.teamcity.build.tempDir%` | | `${bamboo.buildPlanName}` | `%teamcity.buildConfName%` | | `${bamboo.planKey}` / `${bamboo.buildKey}` | `%system.teamcity.buildType.id%` | | `${bamboo.agentId}` | `%teamcity.agent.id%` | | `${bamboo.build.timeStamp}` | `%build.start.date.timestamp%` | | `${bamboo.<custom>}` | `%<custom>%` (define in TC project parameters) | | `${SHELL_VAR}` (no `bamboo.` prefix) | Left untouched (treated as shell expansion) | ### Bamboo Specs that aren't converted These constructs land in the bamboo-specs directory but the migrate command does not auto-convert them — handle manually: | Bamboo construct | TeamCity handling | |---|---| | `bamboo-specs/deployment.yml` (deployment plans) | Model as a separate pipeline triggered on the build pipeline's success; or use TC deployment build configuration | | Multi-document specs (`---`-separated) | The converter handles the first `plan:` document and flags the rest under Needs review -- split remaining documents into separate files and re-run `teamcity migrate` | | `repositories:` block (project-level VCS declarations) | Run `teamcity project vcs create` for each repo before pipeline creation | | `other:` block (`concurrent-build-plugin`, `clean-working-dir`, ...) | Configure cleanup/concurrency in TC build settings UI | | `linked-repositories:` | Manual: create TC VCS roots and reference by ID | | Stages/jobs whose names collide after sanitizing | The converter de-duplicates job IDs with `_2` suffixes, but `dependencies:` referencing the duplicated name resolve to the *first* job -- verify the generated `dependencies:` blocks | -
schema.md 3.8 KB
# TeamCity Pipeline YAML Quick Reference ## Contents - Structure (full annotated example) - Step Types (script, gradle, maven, node-js) - Agent Types (TeamCity Cloud + self-hosted) - Dependencies Between Jobs - Files / Artifacts - Validating (and what `validate` does NOT check) ## Structure ```yaml jobs: <job_id>: # Alphanumeric + underscores only name: "Display Name" runs-on: <agent> # See agent types below parameters: # Job-scoped env vars env.KEY: "value" enable-dependency-cache: true # Replaces manual caching dependencies: # Jobs that must complete first - other_job_id steps: - type: script # or: gradle, maven, node-js name: "Step Name" script-content: | echo "hello" files-publication: # Artifacts - path: "build/**" share-with-jobs: true # Downstream jobs can access publish-artifact: true # Visible in build results parameters: # Pipeline-scoped env vars env.GLOBAL_KEY: "value" secrets: # Sensitive values — value MUST start with "credentialsJSON:" API_KEY: "credentialsJSON:uuid-here" # referenced as %API_KEY% (matches converter output) # env.-prefixed keys become environment variables instead ``` ## Step Types ### `type: script` ```yaml - type: script name: "Run tests" script-content: npm test working-directory: "subdir" # Optional docker-image: "node:20" # Optional: run in container ``` ### `type: gradle` ```yaml - type: gradle name: "Build" gradle-params: clean build -x test ``` ### `type: maven` ```yaml - type: maven name: "Build" goals: clean package -DskipTests ``` ### `type: node-js` ```yaml - type: node-js name: "Build" shell-script: npm run build ``` ## Agent Types (TeamCity Cloud) Hosted agent names come from the server's pipeline schema — see the runner mapping in [mappings](mappings.md). For self-hosted agents: ```yaml runs-on: self-hosted: - os-family: Linux - arch: aarch64 ``` ## Dependencies Between Jobs ```yaml jobs: build: steps: [...] test: dependencies: - build # Simple: wait for build to finish steps: [...] deploy: dependencies: - build: reuse: successful # Reuse if nothing changed - test steps: [...] ``` ## Files / Artifacts ```yaml jobs: build: files-publication: - path: "dist/**" share-with-jobs: true # Other jobs can download publish-artifact: true # Show in UI deploy: dependencies: - build # Artifacts available automatically download-artifacts: # From external build configs (NOT in this pipeline) - ExternalConfig_ID: from: last-successful artifact-rules: "*.jar => lib/" ``` `download-artifacts:` is for pulling artifacts from a build configuration outside the current pipeline. For artifacts produced by an upstream job in the same pipeline, declare a `dependencies:` link and mark the artifact `share-with-jobs: true` on the producer — TC then makes them available automatically. ## Validating ```bash teamcity pipeline validate my-pipeline.tc.yml ``` ### What `validate` does NOT check The schema validates structure (jobs/steps shape, types, secret format, runner field types) but not the inner shape of each step type. That means: - A misspelled key like `script-conent:` will pass schema validation and fail at runtime. - `type: gradle` with no `gradle-params` may pass schema but produce an empty build. - Keys that don't exist (`if:`, `interruptible:`, `timeout:`) pass schema but are silently ignored at runtime. Treat `pipeline validate` as a fast structural check, not proof of correctness.
-
-
SKILL.md 5.1 KB
--- name: migrate-to-teamcity version: "0.3.0" description: Migrating CI/CD pipelines to TeamCity. Use when the user wants to migrate, convert, or switch to TeamCity from GitHub Actions (.github/workflows/) or Bamboo (bamboo-specs/*.yml), even if they only say "move our CI". Other CI systems (GitLab, Jenkins, CircleCI, Azure DevOps, Travis, Bitbucket) are not supported yet. --- # Migrate to TeamCity ## Quick Start ```bash teamcity migrate # detect + convert + write .tc.yml files teamcity migrate --dry-run --json # preview as structured JSON teamcity pipeline validate f.tc.yml # schema check teamcity project vcs create --url <repo-url> --auth anonymous -p ProjectId # create VCS root first teamcity pipeline create name -p ProjectId -f f.tc.yml --vcs-root <VcsRootId> teamcity run start PipelineId --watch ``` Run `teamcity migrate` from the repo root -- detection scans `.github/workflows/` and `bamboo-specs/` relative to the current directory. ## Reading the report - **Needs review** -- problems inside the generated YAML: TODO stubs, dropped steps, reusable-workflow placeholders. Fix these in the file before creating the pipeline. - **Manual setup needed** -- work the converter cannot do. Sort each item onto one of two sides: YAML edits (secrets, matrix expansion, expression `runs-on`, `container:`/`services:`) go before `pipeline create`; server-side configuration (connections, `if:`-derived branch filters, triggers, notifications) comes after. The checklist below orders them. - Exit code 1 means at least one source failed to convert *or* one generated file failed schema validation -- files that converted cleanly are still written. Read the per-file ✓/⚠/✗ lines instead of treating exit 1 as total failure. - `--json` prints `{"sources": [...], "results": [...]}` to stdout; each result carries `outputFile`, `yaml`, `needsReview`, `manualSetup`, and `validationError`. ## Gotchas - **Always `type: script` for `./gradlew` and `./mvnw`.** TC's `type: gradle`/`type: maven` runners use the agent's version, not the project's. This causes real build failures. - **Schema valid does not mean pipeline works.** Migration is not done until builds pass. - **Private repos: use a GitHub App connection, not a PAT.** Start with `teamcity project connection create github-app -p <project>` -- its output prints the authorize, App-install, and `vcs create` follow-up commands. That flow opens a browser; in headless runs pass existing App credentials (`--no-manifest --app-id <id> --client-id <id> --private-key-file <pem> --stdin`, client secret piped to stdin) or use SSH deploy keys (`teamcity project ssh upload` with a `git@github.com:` URL). Public repos: `--auth anonymous`. - **Secrets, triggers, and branch filters are always manual.** The converter flags them but cannot create them -- the checklist below covers each. - **VCS root must exist before pipeline create.** `teamcity pipeline create` takes `--vcs-root <id>`, not a URL. Create it first with `teamcity project vcs create`. - **Default branch defaults to `main`.** Pass `--branch refs/heads/master` to `teamcity project vcs create` if the repo uses `master`. - **Unknown actions/tasks become stubs.** Read the action's source, write an equivalent shell script. Most actions are thin CLI wrappers. See [mappings](references/mappings.md). ## Workflow Goal: get all pipeline jobs green on the TC server, not just generate valid YAML. Copy this checklist and check off items as you complete them: ``` Migration progress: - [ ] Convert: run `teamcity migrate` from the repo root - [ ] Fix every "Needs review" item, plus "Manual setup" items needing YAML edits (matrix expansion, expression `runs-on`, container/services) -- see mappings.md and gotchas.md - [ ] Wire up secrets in the YAML: the converter rewrites `${{ secrets.X }}` to `%X%` but does not define it -- store the value (`teamcity project token put <project> <value>`) and add `X: "credentialsJSON:<uuid>"` under the top-level `secrets:` block (see schema.md) - [ ] Validate: `teamcity pipeline validate <file>` -- only proceed when it passes - [ ] Create VCS root (`teamcity project vcs create`), then `teamcity pipeline create <name> -p <project> -f <file> --vcs-root <id>` - [ ] Set up the remaining runtime "Manual setup needed" items before running: registry/cloud connections the steps reference (the first run fails without them), and any `if:`-condition items -- gate converted deploy/release steps via branch filter, execution condition, or a guard in the script so the first run cannot deploy from the wrong branch - [ ] Run: `teamcity run start <id> --watch`; on failure read `teamcity run log <id> --failed --raw`, fix, `teamcity pipeline push`, re-run until green - [ ] Do the trigger-only "Manual setup needed" items: triggers, notifications - [ ] Report: what migrated and what remains manual ``` ## References - [Mappings](references/mappings.md) -- GitHub Actions and Bamboo to TeamCity translation tables - [Schema](references/schema.md) -- TC pipeline YAML quick reference - [Gotchas](references/gotchas.md) -- skip list, matrix expansion, troubleshooting, manual setup items
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.