Skip to content

Commit 9741cad

Browse files
chore: db migration for adding slug to workflow (#1136)
1 parent cbd36ee commit 9741cad

18 files changed

Lines changed: 7321 additions & 26 deletions

File tree

‎apps/api/openapi/openapi.json‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@
326326
},
327327
"name": {
328328
"type": "string"
329+
},
330+
"slug": {
331+
"description": "URL-safe identifier unique within the workspace. Derived from name if omitted.",
332+
"type": "string"
329333
}
330334
},
331335
"required": [
@@ -2679,6 +2683,10 @@
26792683
},
26802684
"name": {
26812685
"type": "string"
2686+
},
2687+
"slug": {
2688+
"description": "URL-safe identifier unique within the workspace.",
2689+
"type": "string"
26822690
}
26832691
},
26842692
"required": [
@@ -3417,11 +3425,15 @@
34173425
},
34183426
"name": {
34193427
"type": "string"
3428+
},
3429+
"slug": {
3430+
"type": "string"
34203431
}
34213432
},
34223433
"required": [
34233434
"id",
34243435
"name",
3436+
"slug",
34253437
"inputs",
34263438
"jobAgents"
34273439
],

‎apps/api/openapi/schemas/workflows.jsonnet‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ local openapi = import '../lib/openapi.libsonnet';
115115
required: ['name', 'inputs', 'jobAgents'],
116116
properties: {
117117
name: { type: 'string' },
118+
slug: { type: 'string', description: 'URL-safe identifier unique within the workspace. Derived from name if omitted.' },
118119
inputs: {
119120
type: 'array',
120121
items: openapi.schemaRef('WorkflowInput'),
@@ -131,6 +132,7 @@ local openapi = import '../lib/openapi.libsonnet';
131132
required: ['name', 'inputs', 'jobAgents'],
132133
properties: {
133134
name: { type: 'string' },
135+
slug: { type: 'string', description: 'URL-safe identifier unique within the workspace.' },
134136
inputs: {
135137
type: 'array',
136138
items: openapi.schemaRef('WorkflowInput'),
@@ -144,10 +146,11 @@ local openapi = import '../lib/openapi.libsonnet';
144146

145147
Workflow: {
146148
type: 'object',
147-
required: ['id', 'name', 'inputs', 'jobAgents'],
149+
required: ['id', 'name', 'slug', 'inputs', 'jobAgents'],
148150
properties: {
149151
id: { type: 'string' },
150152
name: { type: 'string' },
153+
slug: { type: 'string' },
151154
inputs: {
152155
type: 'array',
153156
items: openapi.schemaRef('WorkflowInput'),

‎apps/api/src/routes/v1/workspaces/workflows.ts‎

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ import { db } from "@ctrlplane/db/client";
77
import * as schema from "@ctrlplane/db/schema";
88
import { getClientFor } from "@ctrlplane/workspace-engine-sdk";
99

10+
const slugifyWorkflowName = (name: string) =>
11+
name
12+
.toLowerCase()
13+
.replace(/[^a-z0-9]+/g, "-")
14+
.replace(/^-+|-+$/g, "");
15+
1016
const listWorkflows: AsyncTypedHandler<
1117
"/v1/workspaces/{workspaceId}/workflows",
1218
"get"
@@ -29,9 +35,10 @@ const listWorkflows: AsyncTypedHandler<
2935
.limit(limit)
3036
.offset(offset);
3137

32-
const items = rows.map(({ id, name, inputs, jobAgents }) => ({
38+
const items = rows.map(({ id, name, slug, inputs, jobAgents }) => ({
3339
id,
3440
name,
41+
slug,
3542
inputs,
3643
jobAgents,
3744
}));
@@ -44,14 +51,15 @@ const createWorkflow: AsyncTypedHandler<
4451
"post"
4552
> = async (req, res) => {
4653
const { workspaceId } = req.params;
54+
const slug = req.body.slug ?? slugifyWorkflowName(req.body.name);
4755
const created = await db
4856
.insert(schema.workflow)
49-
.values({ ...req.body, workspaceId })
57+
.values({ ...req.body, slug, workspaceId })
5058
.returning()
5159
.then(takeFirst);
5260

5361
const { id, name, inputs, jobAgents } = created;
54-
res.status(201).json({ id, name, inputs, jobAgents });
62+
res.status(201).json({ id, name, slug, inputs, jobAgents });
5563
};
5664

5765
const getWorkflow: AsyncTypedHandler<
@@ -72,8 +80,8 @@ const getWorkflow: AsyncTypedHandler<
7280

7381
if (workflow == null) throw new NotFoundError("Workflow not found");
7482

75-
const { id, name, inputs, jobAgents } = workflow;
76-
res.json({ id, name, inputs, jobAgents });
83+
const { id, name, slug, inputs, jobAgents } = workflow;
84+
res.json({ id, name, slug, inputs, jobAgents });
7785
};
7886

7987
const updateWorkflow: AsyncTypedHandler<
@@ -95,8 +103,8 @@ const updateWorkflow: AsyncTypedHandler<
95103

96104
if (updated == null) throw new NotFoundError("Workflow not found");
97105

98-
const { id, name, inputs, jobAgents } = updated;
99-
res.status(202).json({ id, name, inputs, jobAgents });
106+
const { id, name, slug, inputs, jobAgents } = updated;
107+
res.status(202).json({ id, name, slug, inputs, jobAgents });
100108
};
101109

102110
const deleteWorkflow: AsyncTypedHandler<
@@ -117,8 +125,8 @@ const deleteWorkflow: AsyncTypedHandler<
117125

118126
if (deleted == null) throw new NotFoundError("Workflow not found");
119127

120-
const { id, name, inputs, jobAgents } = deleted;
121-
res.status(202).json({ id, name, inputs, jobAgents });
128+
const { id, name, slug, inputs, jobAgents } = deleted;
129+
res.status(202).json({ id, name, slug, inputs, jobAgents });
122130
};
123131

124132
const createWorkflowRun: AsyncTypedHandler<

‎apps/api/src/types/openapi.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,8 @@ export interface components {
12361236
inputs: components["schemas"]["WorkflowInput"][];
12371237
jobAgents: components["schemas"]["CreateWorkflowJobAgent"][];
12381238
name: string;
1239+
/** @description URL-safe identifier unique within the workspace. Derived from name if omitted. */
1240+
slug?: string;
12391241
};
12401242
CreateWorkflowJobAgent: {
12411243
/** @description Configuration for the job agent */
@@ -2069,6 +2071,8 @@ export interface components {
20692071
inputs: components["schemas"]["WorkflowInput"][];
20702072
jobAgents: components["schemas"]["CreateWorkflowJobAgent"][];
20712073
name: string;
2074+
/** @description URL-safe identifier unique within the workspace. */
2075+
slug?: string;
20722076
};
20732077
UpdateWorkspaceRequest: {
20742078
/** @description Display name of the workspace */
@@ -2334,6 +2338,7 @@ export interface components {
23342338
inputs: components["schemas"]["WorkflowInput"][];
23352339
jobAgents: components["schemas"]["WorkflowJobAgent"][];
23362340
name: string;
2341+
slug: string;
23372342
};
23382343
WorkflowArrayInput: components["schemas"]["WorkflowManualArrayInput"] | components["schemas"]["WorkflowSelectorArrayInput"];
23392344
WorkflowBooleanInput: {

‎apps/workspace-engine/oapi/openapi.json‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,11 +3035,15 @@
30353035
},
30363036
"name": {
30373037
"type": "string"
3038+
},
3039+
"slug": {
3040+
"type": "string"
30383041
}
30393042
},
30403043
"required": [
30413044
"id",
30423045
"name",
3046+
"slug",
30433047
"inputs",
30443048
"jobs"
30453049
],

‎apps/workspace-engine/oapi/spec/schemas/workflows.jsonnet‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ local openapi = import '../lib/openapi.libsonnet';
1414

1515
Workflow: {
1616
type: 'object',
17-
required: ['id', 'name', 'inputs', 'jobs'],
17+
required: ['id', 'name', 'slug', 'inputs', 'jobs'],
1818
properties: {
1919
id: { type: 'string' },
2020
name: { type: 'string' },
21+
slug: { type: 'string' },
2122
inputs: {
2223
type: 'array',
2324
items: openapi.schemaRef('WorkflowInput'),

‎apps/workspace-engine/pkg/db/models.go‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎apps/workspace-engine/pkg/db/queries/schema.sql‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,11 @@ CREATE TABLE user_approval_record (
264264
CREATE TABLE workflow (
265265
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
266266
name TEXT NOT NULL,
267+
slug TEXT NOT NULL,
267268
inputs JSONB NOT NULL DEFAULT '[]',
268269
job_agents JSONB NOT NULL DEFAULT '[]',
269-
workspace_id UUID NOT NULL REFERENCES workspace(id) ON DELETE CASCADE
270+
workspace_id UUID NOT NULL REFERENCES workspace(id) ON DELETE CASCADE,
271+
UNIQUE (workspace_id, slug)
270272
);
271273

272274
CREATE TABLE workflow_run (

‎apps/workspace-engine/pkg/db/workflows.sql.go‎

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎apps/workspace-engine/pkg/oapi/oapi.gen.go‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)