Skip to main content
A Deployment represents a service or application that you want to deploy across your infrastructure. Deployments have versions (created by your CI), which get released to environments and resources.

What is a Deployment?

A deployment is a logical unit of software that you want to orchestrate:
  • API Service - Your backend API
  • Frontend Application - Web or mobile frontend
  • Background Worker - Async job processor
  • Database Migration - Schema changes
  • Configuration Update - Infrastructure configuration
Each deployment can have multiple versions (builds, releases) that get deployed to different environments and resources.

Deployment Properties

id: dep_abc123
systemId: sys_xyz789
name: API Service
slug: api-service
description: Main backend API service
jobAgentId: agent_123
jobAgentConfig:
  workflow: deploy.yml
  owner: my-org
  repo: api-service
resourceSelector:
  type: kind
  operator: equals
  value: kubernetes-cluster
createdAt: "2024-01-15T10:00:00Z"
metadata:
  team: backend
  language: nodejs

name

Human-readable display name for the deployment. Examples:
  • “API Service”
  • “Frontend Application”
  • “Payment Processor”
  • “User Service”

slug

URL-friendly identifier, unique within the system. Examples:
  • api-service
  • frontend-app
  • payment-processor

systemId

The system this deployment belongs to. Deployments are scoped to systems.

jobAgentId

The ID of the job agent that will execute deployment jobs. Required: Every deployment must have a job agent configured.

jobAgentConfig

Configuration passed to the job agent when executing deployments. The structure depends on the agent type. GitHub Actions Agent:
workflow: deploy.yml
owner: my-github-org
repo: my-repo
ref: main
Kubernetes Agent:
manifest: |
  apiVersion: batch/v1
  kind: Job
  ...
ArgoCD Agent:
application: my-app
server: https://argocd.example.com

resourceSelector (Optional)

Limits which resources this deployment can target. If specified, only resources matching this selector can receive this deployment. Use Cases:
  • Kubernetes-only deployments: Match kind: kubernetes-cluster
  • Region-specific: Match metadata.region: us-east-1
  • Team-specific: Match metadata.team: platform
Example - Kubernetes only:
type: kind
operator: equals
value: kubernetes-cluster
If not specified, the deployment can target any resource.

description

Optional description of what this deployment does.

metadata

Optional key-value pairs for classification. Common Metadata:
team: backend
language: nodejs
repository: github.com/org/api-service

Creating a Deployment

Via Web UI

  1. Navigate to your system
  2. Click “Deployments” tab
  3. Click “Create Deployment”
  4. Fill in:
    • Name: “API Service”
    • Slug: “api-service”
    • Description: “Main backend API”
    • Job Agent: Select from dropdown
    • Job Agent Config: JSON configuration
    • Resource Selector: (optional)
  5. Click “Create”

Via CLI (YAML)

# deployment.yaml
type: Deployment
name: API Service
slug: api-service
description: Main backend API service
jobAgent:
  ref: github-actions-agent
jobAgentConfig:
  workflow: deploy.yml
  owner: my-org
  repo: api-service
resourceSelector: resource.kind == "KubernetesCluster"
ctrlc apply -f deployment.yaml

Multiple Deployments

# deployments.yaml
---
type: Deployment
name: API Service
slug: api-service
description: Main backend API service
jobAgent:
  ref: github-actions-agent
jobAgentConfig:
  workflow: deploy.yml
  owner: my-org
  repo: api-service
---
type: Deployment
name: Frontend App
slug: frontend-app
description: Customer-facing web application
jobAgent:
  ref: kubernetes-agent
jobAgentConfig:
  namespace: default
ctrlc apply -f deployments.yaml

Deployment Versions

Versions represent specific builds or releases of your deployment. They are typically created by your CI system after building.

Version Properties

id: ver_abc123
deploymentId: dep_abc123
tag: v1.2.3
name: Release 1.2.3
status: ready
config:
  imageTag: v1.2.3
  buildNumber: "456"
jobAgentConfig:
  imageTag: my-org/api-service:v1.2.3
metadata:
  git_commit: abc123def
  git_branch: main
  build_number: "456"
dependencies: []
createdAt: "2024-01-15T12:00:00Z"

Creating Versions (from CI)

After your CI builds an artifact, create a version in Ctrlplane:
# GitHub Actions example
- name: Create Ctrlplane version
  env:
    CTRLPLANE_API_KEY: ${{ secrets.CTRLPLANE_API_KEY }}
  run: |
    ctrlc api upsert version \
      --workspace ${{ vars.CTRLPLANE_WORKSPACE }} \
      --deployment ${{ vars.CTRLPLANE_DEPLOYMENT_ID }} \
      --tag ${{ github.sha }} \
      --name "Build #${{ github.run_number }}" \
      --metadata git/commit=${{ github.sha }} \
      --metadata git/branch=${{ github.ref_name }} \
      --metadata build/number=${{ github.run_number }}

Version Status

Versions have a status field:
  • building - Version is being built (won’t be deployed yet)
  • ready - Version is ready for deployment (default for policies)
  • failed - Build failed (won’t be deployed)
Workflow:
  1. CI starts building → Create version with status building
  2. Build succeeds → Update status to ready
  3. Ctrlplane creates releases/jobs for ready versions
Or simpler:
  1. Build completes → Create version with status ready immediately

Version Config vs Job Agent Config

config: General version configuration, visible in UI
config:
  buildNumber: "456"
  gitCommit: abc123
jobAgentConfig: Specific configuration for job execution (overrides deployment’s jobAgentConfig)
jobAgentConfig:
  imageTag: my-org/api-service:v1.2.3
  helmValues:
    replicas: 3

Version Dependencies

Versions can declare dependencies on other deployment versions. Use the API for versions with dependencies:
curl -X POST "https://app.ctrlplane.dev/api/v1/deployments/{deploymentId}/versions" \
  -H "Authorization: Bearer $CTRLPLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tag": "v1.2.3",
    "status": "ready",
    "dependencies": [
      {
        "deploymentId": "dep_database",
        "versionId": "ver_db_v2"
      }
    ]
  }'
Ctrlplane can enforce that dependencies are deployed first before deploying this version.

Deployment Variables

Variables allow environment-specific or version-specific configuration.

Creating Deployment Variables

Variables can be configured via the Web UI or API:
curl -X POST "https://app.ctrlplane.dev/api/v1/deployments/{deploymentId}/variables" \
  -H "Authorization: Bearer $CTRLPLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "REPLICA_COUNT",
    "description": "Number of replicas to run"
  }'

Setting Environment-Specific Values

# Value for development
curl -X POST "https://app.ctrlplane.dev/api/v1/deployments/{deploymentId}/variables/{variableId}/values" \
  -H "Authorization: Bearer $CTRLPLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "environmentId": "env_dev",
    "value": "1"
  }'

# Value for production
curl -X POST "https://app.ctrlplane.dev/api/v1/deployments/{deploymentId}/variables/{variableId}/values" \
  -H "Authorization: Bearer $CTRLPLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "environmentId": "env_prod",
    "value": "5"
  }'

Using Variables in Jobs

Variables are resolved during job creation and passed to the job agent:
# In GitHub Actions workflow
- name: Get job inputs
  uses: ctrlplanedev/get-job-inputs@v1
  id: job
  with:
    job_id: ${{ inputs.job_id }}

- name: Deploy with variables
  run: |
    echo "Replicas: ${{ steps.job.outputs.variable_REPLICA_COUNT }}"
    helm upgrade my-app ./chart \
      --set replicaCount=${{ steps.job.outputs.variable_REPLICA_COUNT }}

Release Targets

When you create a deployment, Ctrlplane automatically creates release targets by crossing the deployment with environments and resources. Formula: Deployment × Environment × Resource = Release Targets Example: Given:
  • Deployment: “API Service”
  • Environments: Development, Staging, Production
  • Resources in Production: 3 clusters
Release Targets Created:
  1. API Service → Development → dev-cluster
  2. API Service → Staging → staging-cluster
  3. API Service → Production → prod-cluster-1
  4. API Service → Production → prod-cluster-2
  5. API Service → Production → prod-cluster-3
Each release target can receive deployment versions independently.

Filtering Release Targets

Use deployment’s resourceSelector to limit which targets are created:
resourceSelector:
  type: kind
  operator: equals
  value: kubernetes-cluster
Now only Kubernetes resources will have release targets for this deployment.

Deployment Lifecycle

1. Create Deployment

Define the deployment in Ctrlplane with job agent configuration.

2. CI Builds and Creates Version

Your CI pipeline builds the artifact and creates a deployment version.

3. Ctrlplane Evaluates Policies

Ctrlplane checks policies (approvals, environment progression, etc.).

4. Jobs Created

For each release target that should receive the version, a job is created.

5. Job Agent Executes

The configured job agent picks up the job and executes the deployment.

6. Status Updated

The job reports status back to Ctrlplane.

Viewing Deployment Status

Via Web UI

  1. Navigate to the deployment
  2. See tabs:
    • Versions: All versions created
    • Releases: Active releases across targets
    • Jobs: Execution history
    • Variables: Configured variables

Via API

Get deployment details:
curl https://app.ctrlplane.dev/api/v1/deployments/{deploymentId} \
  -H "Authorization: Bearer $CTRLPLANE_API_KEY"
List versions:
curl https://app.ctrlplane.dev/api/v1/deployments/{deploymentId}/versions \
  -H "Authorization: Bearer $CTRLPLANE_API_KEY"
List releases:
curl https://app.ctrlplane.dev/api/v1/deployments/{deploymentId}/releases \
  -H "Authorization: Bearer $CTRLPLANE_API_KEY"

Common Patterns

Microservices

# microservices.yaml
---
type: Deployment
name: User Service
slug: user-service
jobAgent:
  ref: kubernetes-agent
---
type: Deployment
name: Order Service
slug: order-service
jobAgent:
  ref: kubernetes-agent
---
type: Deployment
name: Payment Service
slug: payment-service
jobAgent:
  ref: kubernetes-agent
ctrlc apply -f microservices.yaml

Frontend + Backend

# fullstack.yaml
---
type: Deployment
name: API Service
slug: api-service
jobAgent:
  ref: kubernetes-agent
resourceSelector: resource.kind == "KubernetesCluster"
---
type: Deployment
name: Frontend App
slug: frontend-app
jobAgent:
  ref: github-actions-agent
ctrlc apply -f fullstack.yaml

Database + Application

# app-with-migrations.yaml
---
type: Deployment
name: Database Migration
slug: database-migration
description: Run database migrations before API deployment
jobAgent:
  ref: kubernetes-agent
---
type: Deployment
name: API Service
slug: api-service
description: API depends on migrations completing first
jobAgent:
  ref: kubernetes-agent
ctrlc apply -f app-with-migrations.yaml

Multi-Platform

# multi-platform.yaml
---
type: Deployment
name: Web Service
slug: web-service
jobAgent:
  ref: kubernetes-agent
resourceSelector: resource.kind == "KubernetesCluster"
---
type: Deployment
name: Lambda Function
slug: lambda-function
jobAgent:
  ref: github-actions-agent
resourceSelector: resource.kind == "AWSLambda"
ctrlc apply -f multi-platform.yaml

Best Practices

Naming

Good Names:
  • ✅ “API Service”
  • ✅ “Frontend Application”
  • ✅ “Payment Processor”
Good Slugs:
  • api-service
  • frontend-app
  • payment-processor
Avoid:
  • ❌ “Service” (too generic)
  • ❌ “api_service” (use hyphens)
  • ❌ “API-SERVICE” (use lowercase)

Job Agent Configuration

Do:
  • ✅ Use version’s jobAgentConfig for version-specific values (like image tags)
  • ✅ Use deployment’s jobAgentConfig for stable configuration
  • ✅ Keep sensitive data in secrets (not in config)
Example:
# Deployment jobAgentConfig (stable)
jobAgentConfig:
  workflow: deploy.yml
  owner: my-org
  repo: api-service
# Version jobAgentConfig (version-specific)
jobAgentConfig:
  imageTag: my-org/api-service:v1.2.3

Version Tags

Good Tags:
  • v1.2.3 (semantic version)
  • 2024-01-15-prod (date-based)
  • abc123def (git commit)
Avoid:
  • latest (not specific)
  • prod (not a version)
  • test (too vague)

Resource Selectors

Use resource selectors to:
  • Limit Kubernetes deployments to Kubernetes resources
  • Separate platform-specific deployments
  • Control which resources can receive a deployment

Troubleshooting

No release targets created

  • Check resource selector matches some resources
  • Verify environments have matching resources
  • Ensure deployment and environments are in same system

Jobs not being created for new versions

  • Check version status is ready
  • Review policies for denials/pending approvals
  • Verify job agent is configured
  • Check release target exists

Job agent config not working

  • Verify jobAgentConfig structure matches agent type
  • Check version’s jobAgentConfig overrides correctly
  • Review job agent logs for configuration errors

Next Steps