Skip to content

Commit 8f556d2

Browse files
refactor: strictly type job agent configs and use oapi discriminator (ctrlplanedev#730)
1 parent bf0f59c commit 8f556d2

File tree

78 files changed

+14941
-10856
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+14941
-10856
lines changed

apps/api/openapi/openapi.json

Lines changed: 6459 additions & 5807 deletions
Large diffs are not rendered by default.

apps/api/openapi/schemas/deployments.jsonnet

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ local openapi = import '../lib/openapi.libsonnet';
1010
slug: { type: 'string' },
1111
description: { type: 'string' },
1212
jobAgentId: { type: 'string' },
13-
jobAgentConfig: {
14-
type: 'object',
15-
additionalProperties: true,
16-
},
13+
jobAgentConfig: openapi.schemaRef('DeploymentJobAgentConfig'),
1714
resourceSelector: openapi.schemaRef('Selector'),
1815
},
1916
},
@@ -26,10 +23,7 @@ local openapi = import '../lib/openapi.libsonnet';
2623
slug: { type: 'string' },
2724
description: { type: 'string' },
2825
jobAgentId: { type: 'string' },
29-
jobAgentConfig: {
30-
type: 'object',
31-
additionalProperties: true,
32-
},
26+
jobAgentConfig: openapi.schemaRef('DeploymentJobAgentConfig'),
3327
resourceSelector: openapi.schemaRef('Selector'),
3428
},
3529
},
@@ -43,13 +37,82 @@ local openapi = import '../lib/openapi.libsonnet';
4337
description: { type: 'string' },
4438
systemId: { type: 'string' },
4539
jobAgentId: { type: 'string' },
46-
jobAgentConfig: {
47-
type: 'object',
48-
additionalProperties: true,
49-
},
40+
jobAgentConfig: openapi.schemaRef('DeploymentJobAgentConfig'),
5041
resourceSelector: openapi.schemaRef('Selector'),
5142
},
5243
},
44+
45+
DeploymentJobAgentConfig: {
46+
oneOf: [
47+
openapi.schemaRef('DeploymentGithubJobAgentConfig'),
48+
openapi.schemaRef('DeploymentArgoCDJobAgentConfig'),
49+
openapi.schemaRef('DeploymentTerraformCloudJobAgentConfig'),
50+
openapi.schemaRef('DeploymentCustomJobAgentConfig'),
51+
],
52+
discriminator: {
53+
propertyName: 'type',
54+
mapping: {
55+
'github-app': '#/components/schemas/DeploymentGithubJobAgentConfig',
56+
'argo-cd': '#/components/schemas/DeploymentArgoCDJobAgentConfig',
57+
tfe: '#/components/schemas/DeploymentTerraformCloudJobAgentConfig',
58+
custom: '#/components/schemas/DeploymentCustomJobAgentConfig',
59+
},
60+
},
61+
},
62+
63+
DeploymentGithubJobAgentConfig: {
64+
type: 'object',
65+
required: ['type', 'repo', 'workflowId'],
66+
properties: {
67+
type: {
68+
type: 'string',
69+
enum: ['github-app'],
70+
description: 'Deployment job agent type discriminator.',
71+
},
72+
repo: { type: 'string', description: 'GitHub repository name.' },
73+
workflowId: { type: 'integer', format: 'int64', description: 'GitHub Actions workflow ID.' },
74+
ref: { type: 'string', description: 'Git ref to run the workflow on (defaults to "main" if omitted).' },
75+
},
76+
},
77+
78+
DeploymentArgoCDJobAgentConfig: {
79+
type: 'object',
80+
required: ['type', 'template'],
81+
properties: {
82+
type: {
83+
type: 'string',
84+
enum: ['argo-cd'],
85+
description: 'Deployment job agent type discriminator.',
86+
},
87+
template: { type: 'string', description: 'ArgoCD Application YAML/JSON template (supports Go templates).' },
88+
},
89+
},
90+
91+
DeploymentTerraformCloudJobAgentConfig: {
92+
type: 'object',
93+
required: ['type', 'template'],
94+
properties: {
95+
type: {
96+
type: 'string',
97+
enum: ['tfe'],
98+
description: 'Deployment job agent type discriminator.',
99+
},
100+
template: { type: 'string', description: 'Terraform Cloud workspace template (YAML/JSON; supports Go templates).' },
101+
},
102+
},
103+
104+
DeploymentCustomJobAgentConfig: {
105+
type: 'object',
106+
required: ['type'],
107+
properties: {
108+
type: {
109+
type: 'string',
110+
enum: ['custom'],
111+
description: 'Deployment job agent type discriminator.',
112+
},
113+
},
114+
additionalProperties: true,
115+
},
53116
DeploymentAndSystem: {
54117
type: 'object',
55118
required: ['deployment', 'system'],

apps/api/openapi/schemas/job-agents.jsonnet

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ local openapi = import '../lib/openapi.libsonnet';
33
{
44
UpsertJobAgentRequest: {
55
type: 'object',
6-
required: ['name', 'type'],
6+
required: ['name', 'type', 'config'],
77
properties: {
88
name: { type: 'string' },
99
type: { type: 'string' },
1010
metadata: {
1111
type: 'object',
1212
additionalProperties: { type: 'string' }
1313
},
14-
config: { type: 'object', additionalProperties: true },
14+
config: openapi.schemaRef('JobAgentConfig'),
1515
},
1616
},
1717
JobAgent: {
@@ -21,11 +21,104 @@ local openapi = import '../lib/openapi.libsonnet';
2121
id: { type: 'string' },
2222
name: { type: 'string' },
2323
type: { type: 'string' },
24-
config: { type: 'object', additionalProperties: true },
24+
config: openapi.schemaRef('JobAgentConfig'),
2525
metadata: {
2626
type: 'object',
2727
additionalProperties: { type: 'string' }
2828
},
2929
},
3030
},
31+
32+
JobAgentConfig: {
33+
oneOf: [
34+
openapi.schemaRef('GithubJobAgentConfig'),
35+
openapi.schemaRef('ArgoCDJobAgentConfig'),
36+
openapi.schemaRef('TerraformCloudJobAgentConfig'),
37+
openapi.schemaRef('TestRunnerJobAgentConfig'),
38+
openapi.schemaRef('CustomJobAgentConfig'),
39+
],
40+
discriminator: {
41+
propertyName: 'type',
42+
mapping: {
43+
'github-app': '#/components/schemas/GithubJobAgentConfig',
44+
'argo-cd': '#/components/schemas/ArgoCDJobAgentConfig',
45+
tfe: '#/components/schemas/TerraformCloudJobAgentConfig',
46+
'test-runner': '#/components/schemas/TestRunnerJobAgentConfig',
47+
custom: '#/components/schemas/CustomJobAgentConfig',
48+
},
49+
},
50+
},
51+
52+
GithubJobAgentConfig: {
53+
type: 'object',
54+
required: ['type', 'installationId', 'owner'],
55+
properties: {
56+
type: {
57+
type: 'string',
58+
enum: ['github-app'],
59+
description: 'Job agent type discriminator.',
60+
},
61+
installationId: { type: 'integer', format: 'int' },
62+
owner: { type: 'string' },
63+
},
64+
},
65+
66+
ArgoCDJobAgentConfig: {
67+
type: 'object',
68+
required: ['type', 'serverUrl', 'apiKey'],
69+
properties: {
70+
type: {
71+
type: 'string',
72+
enum: ['argo-cd'],
73+
description: 'Job agent type discriminator.',
74+
},
75+
serverUrl: { type: 'string', description: 'ArgoCD server address (host[:port] or URL).' },
76+
apiKey: { type: 'string', description: 'ArgoCD API token.' },
77+
},
78+
},
79+
80+
TerraformCloudJobAgentConfig: {
81+
type: 'object',
82+
required: ['type', 'address', 'token', 'organization'],
83+
properties: {
84+
type: {
85+
type: 'string',
86+
enum: ['tfe'],
87+
description: 'Job agent type discriminator.',
88+
},
89+
organization: { type: 'string', description: 'Terraform Cloud organization name.' },
90+
address: { type: 'string', description: 'Terraform Cloud address (e.g. https://app.terraform.io).' },
91+
token: { type: 'string', description: 'Terraform Cloud API token.' },
92+
template: { type: 'string', description: 'Terraform Cloud workspace template (YAML/JSON; supports Go templates).' },
93+
},
94+
additionalProperties: true,
95+
},
96+
97+
TestRunnerJobAgentConfig: {
98+
type: 'object',
99+
required: ['type'],
100+
properties: {
101+
type: {
102+
type: 'string',
103+
enum: ['test-runner'],
104+
description: 'Job agent type discriminator.',
105+
},
106+
delaySeconds: { type: 'integer', format: 'int', description: 'Delay before resolving the job.' },
107+
status: { type: 'string', enum: ['completed', 'failure'], description: 'Final status to set.' },
108+
message: { type: 'string', description: 'Optional message to include in the job output.' },
109+
},
110+
},
111+
112+
CustomJobAgentConfig: {
113+
type: 'object',
114+
required: ['type'],
115+
properties: {
116+
type: {
117+
type: 'string',
118+
enum: ['custom'],
119+
description: 'Job agent type discriminator.',
120+
},
121+
},
122+
additionalProperties: true,
123+
},
31124
}

apps/api/openapi/schemas/jobs.jsonnet

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ local Job = {
1616
id: { type: 'string' },
1717
releaseId: { type: 'string' },
1818
jobAgentId: { type: 'string' },
19-
jobAgentConfig: {
20-
type: 'object',
21-
additionalProperties: true,
22-
},
19+
jobAgentConfig: openapi.schemaRef('FullJobAgentConfig'),
2320
externalId: { type: 'string' },
2421
status: openapi.schemaRef('JobStatus'),
2522
createdAt: { type: 'string', format: 'date-time' },
@@ -81,4 +78,57 @@ local JobPropertyKeys = std.objectFields(Job.properties);
8178
{ required: ['agentId', 'externalId'] },
8279
],
8380
},
81+
82+
FullJobAgentConfig: {
83+
oneOf: [
84+
openapi.schemaRef('FullGithubJobAgentConfig'),
85+
openapi.schemaRef('FullArgoCDJobAgentConfig'),
86+
openapi.schemaRef('FullTerraformCloudJobAgentConfig'),
87+
openapi.schemaRef('FullTestRunnerJobAgentConfig'),
88+
openapi.schemaRef('FullCustomJobAgentConfig'),
89+
],
90+
discriminator: {
91+
propertyName: 'type',
92+
mapping: {
93+
'github-app': '#/components/schemas/FullGithubJobAgentConfig',
94+
'argo-cd': '#/components/schemas/FullArgoCDJobAgentConfig',
95+
tfe: '#/components/schemas/FullTerraformCloudJobAgentConfig',
96+
'test-runner': '#/components/schemas/FullTestRunnerJobAgentConfig',
97+
custom: '#/components/schemas/FullCustomJobAgentConfig',
98+
},
99+
},
100+
},
101+
102+
FullGithubJobAgentConfig: {
103+
allOf: [
104+
openapi.schemaRef('GithubJobAgentConfig'),
105+
openapi.schemaRef('DeploymentGithubJobAgentConfig'),
106+
],
107+
},
108+
109+
FullArgoCDJobAgentConfig: {
110+
allOf: [
111+
openapi.schemaRef('ArgoCDJobAgentConfig'),
112+
openapi.schemaRef('DeploymentArgoCDJobAgentConfig'),
113+
],
114+
},
115+
116+
FullTerraformCloudJobAgentConfig: {
117+
allOf: [
118+
openapi.schemaRef('TerraformCloudJobAgentConfig'),
119+
openapi.schemaRef('DeploymentTerraformCloudJobAgentConfig'),
120+
],
121+
},
122+
123+
FullTestRunnerJobAgentConfig: {
124+
allOf: [
125+
openapi.schemaRef('TestRunnerJobAgentConfig'),
126+
],
127+
},
128+
129+
FullCustomJobAgentConfig: {
130+
allOf: [
131+
openapi.schemaRef('CustomJobAgentConfig'),
132+
],
133+
},
84134
}

apps/api/src/routes/v1/workspaces/deployments.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const deleteDeployment: AsyncTypedHandler<
8080
name: "",
8181
systemId: "",
8282
slug: "",
83-
jobAgentConfig: {},
83+
jobAgentConfig: { type: "custom" },
8484
},
8585
});
8686

@@ -98,7 +98,7 @@ const postDeployment: AsyncTypedHandler<
9898
const deployment: WorkspaceEngine["schemas"]["Deployment"] = {
9999
id: uuidv4(),
100100
...body,
101-
jobAgentConfig: body.jobAgentConfig ?? {},
101+
jobAgentConfig: body.jobAgentConfig ?? { type: "custom" },
102102
};
103103

104104
const isValid = await validResourceSelector(body.resourceSelector);

apps/api/src/routes/v1/workspaces/job-agents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const upsertJobAgent: AsyncTypedHandler<
3333
name: body.name,
3434
type: body.type,
3535
workspaceId,
36-
config: body.config ?? {},
36+
config: body.config,
3737
metadata: body.metadata ?? {},
3838
};
3939

0 commit comments

Comments
 (0)