Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 35 additions & 15 deletions apps/workspace-engine/oapi/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1725,26 +1725,46 @@
"$ref": "#/components/schemas/Environment"
},
"latestJob": {
"allOf": [
{
"$ref": "#/components/schemas/Job"
"nullable": true,
"properties": {
"completedAt": {
"format": "date-time",
"type": "string"
},
{
"properties": {
"verifications": {
"items": {
"$ref": "#/components/schemas/JobVerification"
},
"type": "array"
}
"createdAt": {
"format": "date-time",
"type": "string"
},
"id": {
"type": "string"
},
"message": {
"type": "string"
},
"metadata": {
"additionalProperties": {
"type": "string"
},
"required": [
"verifications"
],
"type": "object"
},
"status": {
"$ref": "#/components/schemas/JobStatus"
},
"verifications": {
"items": {
"$ref": "#/components/schemas/JobVerification"
},
"type": "array"
}
},
"required": [
"id",
"status",
"createdAt",
"metadata",
"verifications"
],
"nullable": true
"type": "object"
},
"releaseTarget": {
"properties": {
Expand Down
26 changes: 15 additions & 11 deletions apps/workspace-engine/oapi/spec/schemas/release_targets.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,23 @@ local openapi = import '../lib/openapi.libsonnet';
currentVersion: openapi.schemaRef('DeploymentVersion', nullable=true),
latestJob: {
nullable: true,
allOf: [
openapi.schemaRef('Job'),
{
type: 'object',
required: ['id', 'status', 'createdAt', 'metadata', 'verifications'],
properties: {
id: { type: 'string' },
status: openapi.schemaRef('JobStatus'),
message: { type: 'string' },
createdAt: { type: 'string', format: 'date-time' },
completedAt: { type: 'string', format: 'date-time' },
metadata: {
type: 'object',
required: ['verifications'],
properties: {
verifications: {
type: 'array',
items: openapi.schemaRef('JobVerification'),
},
},
additionalProperties: { type: 'string' },
},
],
verifications: {
type: 'array',
items: openapi.schemaRef('JobVerification'),
},
},
Comment on lines 21 to +39
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's verify the file exists and check its structure
git ls-files | grep -E "(release_targets|Job)" | head -20

Repository: ctrlplanedev/ctrlplane

Length of output: 897


🏁 Script executed:

# Check the file at the specified location
cat -n "apps/workspace-engine/oapi/spec/schemas/release_targets.jsonnet" | head -50

Repository: ctrlplanedev/ctrlplane

Length of output: 1702


🏁 Script executed:

# Search for Job schema definition
fd -t f "\.jsonnet$" apps/workspace-engine/oapi/spec/schemas/ -x grep -l "Job" {}

Repository: ctrlplanedev/ctrlplane

Length of output: 527


🏁 Script executed:

# Let's examine the Job schema to see what fields it has
cat -n "apps/workspace-engine/oapi/spec/schemas/jobs.jsonnet"

Repository: ctrlplanedev/ctrlplane

Length of output: 6790


🏁 Script executed:

# Check git history to see what latestJob was before this change
cd apps/workspace-engine/oapi/spec/schemas && git log --oneline -20 release_targets.jsonnet

Repository: ctrlplanedev/ctrlplane

Length of output: 78


🏁 Script executed:

# Get the diff for this specific file to see what changed
cd apps/workspace-engine/oapi/spec/schemas && git show HEAD:release_targets.jsonnet 2>/dev/null | head -50 || echo "Cannot get previous version"

Repository: ctrlplanedev/ctrlplane

Length of output: 48


🏁 Script executed:

# Search for references to latestJob in the codebase
rg "latestJob" --type ts --type go --type jsonnet -B2 -A2

Repository: ctrlplanedev/ctrlplane

Length of output: 97


🏁 Script executed:

# Let's search for latestJob references more broadly
rg "latestJob" -A3 -B3

Repository: ctrlplanedev/ctrlplane

Length of output: 49409


🏁 Script executed:

# Check the git diff to see what changed in this file
cd apps/workspace-engine/oapi/spec/schemas && git diff HEAD~1 release_targets.jsonnet 2>/dev/null || git log --all --oneline release_targets.jsonnet | head -10

Repository: ctrlplanedev/ctrlplane

Length of output: 157


🏁 Script executed:

# Let's look at the generated Go types to see if they match
find apps/workspace-engine -name "*.go" -type f | xargs grep -l "ReleaseTargetItem" | head -3

Repository: ctrlplanedev/ctrlplane

Length of output: 108


🏁 Script executed:

# Check if there are TypeScript SDK files generated from these schemas
find apps -name "*.ts" -type f | xargs grep -l "ReleaseTargetItem\|latestJob" | head -5

Repository: ctrlplanedev/ctrlplane

Length of output: 313


🏁 Script executed:

# Let's verify that DeploymentSummaries.tsx actually uses completedAt and would break
grep -n "completedAt" "apps/web/app/routes/ws/environments/_components/DeploymentSummaries.tsx"

Repository: ctrlplanedev/ctrlplane

Length of output: 177


🏁 Script executed:

# Check the git diff for the specific commit to see if this is intentional
cd apps/workspace-engine/oapi/spec/schemas && git show af5f8f12:release_targets.jsonnet | head -50

Repository: ctrlplanedev/ctrlplane

Length of output: 321


🏁 Script executed:

# Check the previous version of the file
cd apps/workspace-engine/oapi/spec/schemas && git show af5f8f12:apps/workspace-engine/oapi/spec/schemas/release_targets.jsonnet | head -50

Repository: ctrlplanedev/ctrlplane

Length of output: 1186


🏁 Script executed:

# Check the current HEAD against the previous commit to see what changed
git diff af5f8f12 HEAD -- apps/workspace-engine/oapi/spec/schemas/release_targets.jsonnet | head -100

Repository: ctrlplanedev/ctrlplane

Length of output: 1484


This narrows a published contract.

latestJob is being changed from a full Job reference to an inline partial object. Previously it used allOf: [openapi.schemaRef('Job'), {...}], but now it explicitly defines only id, status, message, createdAt, metadata, and verifications. This removes access to fields like startedAt, completedAt, updatedAt, jobAgentId, jobAgentConfig, releaseId, workflowJobId, and others.

Existing code already uses removed fields (e.g., DeploymentSummaries.tsx accesses latestJob?.completedAt on line 96), which will break with this schema change. Treat this as an explicit breaking change and verify all consumers are updated, or revert to the allOf approach that preserves the full Job contract.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/workspace-engine/oapi/spec/schemas/release_targets.jsonnet` around lines
21 - 38, The change narrows the published contract by replacing the full Job
reference with an inline partial object for latestJob, removing fields consumers
rely on (e.g., startedAt, completedAt); restore the original contract shape by
using allOf with openapi.schemaRef('Job') combined with any additional
constraints instead of redefining properties inline, ensuring latestJob still
exposes the full Job schema (so callers like DeploymentSummaries.tsx that read
latestJob?.completedAt keep working) or explicitly add back every removed Job
field if you truly intend a breaking change and update all consumers
accordingly.

},
},
},
Expand Down
7 changes: 0 additions & 7 deletions apps/workspace-engine/pkg/db/queries/release_targets.sql
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,8 @@ SELECT DISTINCT ON (rel.resource_id, rel.environment_id, rel.deployment_id)
j.id AS job_id,
j.status AS job_status,
j.message AS job_message,
j.reason AS job_reason,
j.created_at AS job_created_at,
j.started_at AS job_started_at,
j.completed_at AS job_completed_at,
j.updated_at AS job_updated_at,
j.external_id AS job_external_id,
j.job_agent_id AS job_agent_id,
j.job_agent_config AS job_agent_config,
j.dispatch_context AS job_dispatch_context,
COALESCE(
(SELECT json_object_agg(m.key, m.value)
FROM job_metadata m WHERE m.job_id = j.id),
Expand Down
39 changes: 9 additions & 30 deletions apps/workspace-engine/pkg/db/release_targets.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 7 additions & 16 deletions apps/workspace-engine/pkg/oapi/oapi.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ func (g *PostgresGetter) ListReleaseTargets(
latestJobMap := make(map[string]db.ListLatestJobsByDeploymentIDRow, len(latestJobs))
var jobIDs []uuid.UUID
for _, lj := range latestJobs {
key := fmt.Sprintf("%s-%s-%s", lj.ResourceID.String(), lj.EnvironmentID.String(), lj.DeploymentID.String())
key := fmt.Sprintf(
"%s-%s-%s",
lj.ResourceID.String(),
lj.EnvironmentID.String(),
lj.DeploymentID.String(),
)
latestJobMap[key] = lj
jobIDs = append(jobIDs, lj.JobID)
}
Expand Down Expand Up @@ -150,19 +155,11 @@ func (g *PostgresGetter) ListReleaseTargets(

if lj, ok := latestJobMap[key]; ok {
jobH := gin.H{
"id": lj.JobID.String(),
"status": lj.JobStatus,
"message": lj.JobMessage.String,
"reason": lj.JobReason,
"createdAt": lj.JobCreatedAt.Time,
"startedAt": lj.JobStartedAt.Time,
"completedAt": lj.JobCompletedAt.Time,
"updatedAt": lj.JobUpdatedAt.Time,
"externalId": lj.JobExternalID.String,
"jobAgentId": lj.JobAgentID,
"jobAgentConfig": json.RawMessage(lj.JobAgentConfig),
"dispatchContext": json.RawMessage(lj.JobDispatchContext),
"metadata": json.RawMessage(lj.JobMetadata),
"id": lj.JobID.String(),
"status": lj.JobStatus,
"message": lj.JobMessage.String,
"metadata": json.RawMessage(lj.JobMetadata),
"createdAt": lj.JobCreatedAt.Time,
}
if v, ok := verificationsMap[lj.JobID.String()]; ok {
jobH["verifications"] = v
Expand Down
18 changes: 13 additions & 5 deletions packages/workspace-engine-sdk/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -757,11 +757,19 @@ export interface components {
currentVersion?: components["schemas"]["DeploymentVersion"];
desiredVersion?: components["schemas"]["DeploymentVersion"];
environment: components["schemas"]["Environment"];
latestJob?:
| (components["schemas"]["Job"] & {
verifications: components["schemas"]["JobVerification"][];
})
| null;
latestJob?: {
/** Format: date-time */
completedAt?: string;
/** Format: date-time */
createdAt: string;
id: string;
message?: string;
metadata: {
[key: string]: string;
};
status: components["schemas"]["JobStatus"];
verifications: components["schemas"]["JobVerification"][];
} | null;
releaseTarget: {
deploymentId: string;
environmentId: string;
Expand Down
Loading