> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ctrlplane.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Releases and Jobs

> How Ctrlplane turns deployment versions into actual deployments

This guide explains how Ctrlplane turns deployment versions into actual
deployments through **releases** and **jobs**.

## Overview

The flow from version to execution:

```
Deployment Version (what to deploy)
    ↓
Release (intent to deploy to a specific target)
    ↓
Job (actual deployment task)
    ↓
Job Agent (executes the deployment)
```

## Release

A **Release** represents the intent to deploy a
specific version to a specific release target
(Deployment × Environment × Resource).

Ctrlplane creates one release per target. A target is a single resource that
matches the deployment's resource selector and is also included in an
environment (via the environment's selector). When a release is approved,
Ctrlplane creates a job for that same target.

### Release Properties

```yaml theme={null}
id: rel_abc123
deploymentId: dep_xyz
environmentId: env_prod
resourceId: res_cluster1
versionId: ver_v123
createdAt: "2024-01-15T12:00:00Z"
```

Releases do not carry their own status field. Instead, the state of a release
is determined by the **Release Target State**, which tracks:

* **Desired release** — the release that policies have selected for deployment
* **Current release** — the release whose job completed successfully (with passing verifications)
* **Latest job** — the most recent job created for this target, along with its status and verifications

### How Releases are Created

Releases are created automatically by Ctrlplane when:

1. A new deployment version is created with status `ready`
2. Ctrlplane evaluates which release targets should receive this version
3. For each target, a release is created
4. Policies are evaluated to determine if the release can proceed

**Example Flow**:

```
1. CI creates version: API Service v1.2.3 (status: ready)
   ↓
2. Ctrlplane finds release targets for "API Service":
   - API Service → Production → cluster-1
   - API Service → Production → cluster-2
   - API Service → Staging → staging-cluster
   ↓
3. Ctrlplane creates 3 releases, one for each target
   ↓
4. Ctrlplane evaluates policies:
   - Production requires approval → Releases pending
   - Staging auto-deploys → Release approved
   ↓
5. Jobs created for approved releases
```

### Release Lifecycle

```
          [Version Created]
                 ↓
       [Policy Evaluation]
         ↓               ↓
    [Blocked]      [Passes] ←→ [User Action]
                        ↓
              [Release Created]
                        ↓
                 [Job Created]
                        ↓
               [Job Executes]
         ↓                        ↓
    [Completed]              [Failed]
```

### Viewing Releases

**Via Web UI**:

1. Navigate to deployment
2. Click "Releases" tab
3. See all releases with their current and desired state

**Via CLI**:

```bash theme={null}
# List releases for a deployment
ctrlc api get releases --deployment {deploymentId}

# Get release details
ctrlc api get release {releaseId}
```

### Release Variables

Releases have resolved variables from:

* Deployment variables (with environment-specific values)
* Resource variables
* Version config

These are passed to the job for execution.

### Cancelling Releases

Cancel a pending or active release:

```bash theme={null}
ctrlc api cancel release {releaseId}
```

Active releases will have their jobs cancelled.

## Job

A **Job** is the actual deployment task that gets executed by a job agent. Jobs are created from approved releases.

### Job Properties

```yaml theme={null}
id: job_abc123
releaseId: rel_xyz789
jobAgentId: agent_123
status: in_progress
externalId: "12345"
message: Deploying version v1.2.3
createdAt: "2024-01-15T12:00:00Z"
startedAt: "2024-01-15T12:01:00Z"
completedAt: null
```

### Job Status

* **`pending`** - Job created, waiting for agent to pick up
* **`triggered`** - Job dispatched to external system (e.g., GitHub Actions)
* **`in_progress`** - Job is currently executing
* **`completed`** - Job finished successfully
* **`failed`** - Job failed
* **`cancelled`** - Job was cancelled
* **`skipped`** - Job was skipped
* **`invalid_job_agent`** - Job agent configuration invalid

### Job Lifecycle

```
     [Release Approved]
             ↓
      [Job Created]
             ↓
       [Pending] ──────→ Agent polls /queue/next
             ↓
      [Agent Gets Job]
             ↓
   [Agent Acknowledges] ──→ Job status: in_progress
             ↓
  [Agent Executes Deployment]
             ↓
    [Agent Reports Status]
             ↓
    [Completed / Failed]
```

### Job Configuration

Jobs receive configuration from multiple sources (in priority order):

1. **Version's jobAgentConfig** (highest priority)
2. **Deployment's jobAgentConfig**
3. **Resolved variables**
4. **Release context** (environment, resource info)

**Example merged config**:

```yaml theme={null}
# From deployment
workflow: deploy.yml
owner: my-org
repo: api-service

# From version (overrides)
imageTag: my-org/api-service:v1.2.3

# From variables
replicaCount: "5"

# From release context
environmentName: Production
resourceIdentifier: k8s-prod-use1
```

### Job Agents

Job agents are responsible for:

1. Polling for new jobs (`GET /job-agents/{agentId}/queue/next`)
2. Acknowledging jobs
3. Executing the deployment
4. Reporting status updates
5. Marking job as completed or failed

**Built-in Agent Types**:

* **GitHub Actions** - Triggers GitHub workflow
* **Kubernetes** - Creates Kubernetes Job
* **ArgoCD** - Syncs ArgoCD Application

### Job Execution Flow

#### 1. Job Agent Polls

```bash theme={null}
GET /api/v1/job-agents/{agentId}/queue/next
```

**Response**:

```yaml theme={null}
jobs:
  - id: job_abc123
    release:
      id: rel_xyz
      version:
        tag: v1.2.3
        config: {}
      environment:
        name: Production
      resource:
        identifier: k8s-prod-use1
        config: {}
      variables:
        REPLICA_COUNT: "5"
    jobAgentConfig:
      imageTag: my-org/api-service:v1.2.3
```

#### 2. Agent Acknowledges Job

```bash theme={null}
PATCH /api/v1/jobs/{jobId}
```

```yaml theme={null}
status: in_progress
message: Starting deployment
```

#### 3. Agent Executes Deployment

The agent uses the job configuration to perform the deployment:

**Kubernetes Agent Example**:

```typescript theme={null}
const manifest = renderManifest(job.jobAgentConfig.manifest, {
  version: job.release.version.tag,
  replicas: job.release.variables.REPLICA_COUNT,
  image: job.jobAgentConfig.imageTag
});

await kubectl.apply(manifest, job.release.resource.config.namespace);
```

**GitHub Actions Example**:

```typescript theme={null}
await github.actions.createWorkflowDispatch({
  owner: job.jobAgentConfig.owner,
  repo: job.jobAgentConfig.repo,
  workflow_id: job.jobAgentConfig.workflow,
  ref: job.jobAgentConfig.ref || 'main',
  inputs: {
    job_id: job.id,
    deployment_version: job.release.version.tag,
    environment: job.release.environment.name,
    resource_identifier: job.release.resource.identifier
  }
});
```

#### 4. Agent Updates Status

As the deployment progresses:

```bash theme={null}
# Update with progress message
PATCH /api/v1/jobs/{jobId}
# Body: { "message": "Applying Kubernetes manifests" }

# Mark as completed
PATCH /api/v1/jobs/{jobId}
# Body: { "status": "completed", "message": "Deployment successful" }

# Or mark as failed
PATCH /api/v1/jobs/{jobId}
# Body: { "status": "failed", "message": "Deployment failed: connection timeout" }
```

### External Job IDs

When job agents trigger external systems (like GitHub Actions), they can store the external job ID:

```bash theme={null}
PATCH /api/v1/jobs/{jobId}
# Body: { "externalId": "github-workflow-run-12345" }
```

This allows linking to the external system's UI for detailed logs.

### Job Retry

If a job fails, you can create a new job for the same release:

```bash theme={null}
ctrlc api redeploy release {releaseId}
```

This creates a new job for the release.

### Viewing Jobs

**Via Web UI**:

1. Navigate to deployment
2. Click "Jobs" tab
3. See execution history with status

**Via CLI**:

```bash theme={null}
# List jobs for a deployment
ctrlc api get jobs --deployment {deploymentId}

# Get job details
ctrlc api get job {jobId}
```

## Version → Release → Job Example

Let's walk through a complete example:

### 1. CI Creates Version

```bash theme={null}
ctrlc api upsert version \
  --workspace my-workspace \
  --deployment dep_api \
  --tag v1.2.3 \
  --metadata image/tag=my-org/api:v1.2.3
```

### 2. Ctrlplane Creates Releases

Ctrlplane finds release targets:

* API Service → Production → cluster-1
* API Service → Production → cluster-2

Creates 2 releases. Production releases are blocked by the approval policy.

### 3. User Approves

```bash theme={null}
ctrlc api approve release rel_123
```

Both releases are now eligible for job creation.

### 4. Ctrlplane Creates Jobs

Two jobs created:

* `job_1` for cluster-1
* `job_2` for cluster-2

Both jobs start with status: `pending`

### 5. Job Agent Polls

```bash theme={null}
GET /api/v1/job-agents/agent_k8s/queue/next
```

Receives both jobs.

### 6. Agent Processes Jobs

For each job:

```typescript theme={null}
// Acknowledge
await job.acknowledge();

// Execute
await kubectl.apply(manifest);

// Complete
await job.update({ status: 'completed' });
```

### 7. Jobs Complete

Both jobs complete successfully. The release target state updates: the release
becomes the **current release** for each target.

## Release Sequencing

By default, when a new version is created for a deployment:

* **Existing jobs** for older versions may be cancelled
* **New jobs** are created for the new version

This behavior is controlled by policies and can be configured.

### Sequential Releases

Ensure releases happen one at a time:

```yaml theme={null}
releaseSequencing:
  mode: sequential
```

### Parallel Releases

Allow multiple versions to deploy concurrently:

```yaml theme={null}
releaseSequencing:
  mode: parallel
```

## Deployment Tracing

For detailed observability, use the trace API to report execution steps:

```bash theme={null}
# In your deployment script
ctrlplane trace start "Deploy to Kubernetes"
ctrlplane trace step "Pull image" "completed"
ctrlplane trace step "Apply manifests" "completed"
ctrlplane trace end "completed" "Deployment successful"
```

Traces are linked to jobs and provide fine-grained visibility into deployment execution.

## Best Practices

### Job Status Updates

**Do**:

* ✅ Acknowledge jobs immediately when picked up
* ✅ Update status regularly during execution
* ✅ Provide descriptive messages
* ✅ Mark as completed or failed explicitly

**Don't**:

* ❌ Leave jobs in pending state indefinitely
* ❌ Skip acknowledging jobs
* ❌ Provide generic error messages

### Error Handling

When jobs fail:

1. Set status to `failed`
2. Include detailed error message
3. Store external job ID for log access
4. Consider automatic retry logic in agent

### Release Management

* Monitor pending releases (awaiting approval)
* Set up notifications for failed jobs
* Regularly review release history
* Clean up old completed releases (retention policy)

## Troubleshooting

### Releases not progressing

* Check if policies require approval
* Review policy evaluation results
* Verify environment progression requirements met
* Check for blocking policy rules

### Jobs not being picked up by agent

* Verify agent is running and polling
* Check agent ID matches deployment configuration
* Review job agent logs for errors
* Confirm agent has network access to API

### Jobs fail immediately

* Review job agent configuration
* Check external system (GitHub, Kubernetes) availability
* Verify credentials/permissions
* Review job logs and error messages

### Multiple jobs created for same release

* Check release sequencing configuration
* Review job creation logic
* May be intentional for retry scenarios

## Next Steps

* [Job Agents](../integrations/job-agents/github) - Set up and configure job agents
* [Policies](../policies/overview) - Control release approval and progression
* [CI/CD Integration](../integrations/cicd) - Integrate version creation into your CI
* [Verification](../policies/verification/overview) - Validate deployment health
