Skip to content

Commit 1a373c3

Browse files
feat: release target eligible versions v1 endpoint (#1143)
1 parent 96a87ca commit 1a373c3

14 files changed

Lines changed: 1380 additions & 1 deletion

File tree

‎apps/api/openapi/openapi.json‎

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7492,6 +7492,130 @@
74927492
"summary": "Get the desired release for a release target"
74937493
}
74947494
},
7495+
"/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/eligible-versions": {
7496+
"post": {
7497+
"description": "Returns deployment versions that currently pass every policy rule for this release target. An optional CEL filter narrows the result; pagination is applied to the filtered set. Use the \"version\" variable in the CEL expression to access version properties.",
7498+
"operationId": "listEligibleVersionsForReleaseTarget",
7499+
"parameters": [
7500+
{
7501+
"description": "ID of the workspace",
7502+
"in": "path",
7503+
"name": "workspaceId",
7504+
"required": true,
7505+
"schema": {
7506+
"type": "string"
7507+
}
7508+
},
7509+
{
7510+
"description": "Key of the release target",
7511+
"in": "path",
7512+
"name": "releaseTargetKey",
7513+
"required": true,
7514+
"schema": {
7515+
"type": "string"
7516+
}
7517+
},
7518+
{
7519+
"description": "Maximum number of items to return",
7520+
"in": "query",
7521+
"name": "limit",
7522+
"required": false,
7523+
"schema": {
7524+
"default": 50,
7525+
"maximum": 1000,
7526+
"minimum": 1,
7527+
"type": "integer"
7528+
}
7529+
},
7530+
{
7531+
"description": "Number of items to skip",
7532+
"in": "query",
7533+
"name": "offset",
7534+
"required": false,
7535+
"schema": {
7536+
"default": 0,
7537+
"minimum": 0,
7538+
"type": "integer"
7539+
}
7540+
}
7541+
],
7542+
"requestBody": {
7543+
"content": {
7544+
"application/json": {
7545+
"schema": {
7546+
"properties": {
7547+
"filter": {
7548+
"description": "CEL expression to filter eligible versions. Defaults to \"true\" (all eligible versions).",
7549+
"type": "string"
7550+
}
7551+
},
7552+
"type": "object"
7553+
}
7554+
}
7555+
},
7556+
"required": true
7557+
},
7558+
"responses": {
7559+
"200": {
7560+
"content": {
7561+
"application/json": {
7562+
"schema": {
7563+
"properties": {
7564+
"items": {
7565+
"items": {
7566+
"$ref": "#/components/schemas/DeploymentVersion"
7567+
},
7568+
"type": "array"
7569+
},
7570+
"limit": {
7571+
"description": "Maximum number of items returned",
7572+
"type": "integer"
7573+
},
7574+
"offset": {
7575+
"description": "Number of items skipped",
7576+
"type": "integer"
7577+
},
7578+
"total": {
7579+
"description": "Total number of items available",
7580+
"type": "integer"
7581+
}
7582+
},
7583+
"required": [
7584+
"items",
7585+
"total",
7586+
"limit",
7587+
"offset"
7588+
],
7589+
"type": "object"
7590+
}
7591+
}
7592+
},
7593+
"description": "Eligible versions for the release target"
7594+
},
7595+
"400": {
7596+
"content": {
7597+
"application/json": {
7598+
"schema": {
7599+
"$ref": "#/components/schemas/ErrorResponse"
7600+
}
7601+
}
7602+
},
7603+
"description": "Invalid request"
7604+
},
7605+
"404": {
7606+
"content": {
7607+
"application/json": {
7608+
"schema": {
7609+
"$ref": "#/components/schemas/ErrorResponse"
7610+
}
7611+
}
7612+
},
7613+
"description": "Resource not found"
7614+
}
7615+
},
7616+
"summary": "List versions eligible for a release target"
7617+
}
7618+
},
74957619
"/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/jobs": {
74967620
"get": {
74977621
"description": "Returns a list of jobs for a release target {releaseTargetKey}.",

‎apps/api/openapi/paths/release-targets.jsonnet‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,39 @@ local openapi = import '../lib/openapi.libsonnet';
9090
},
9191
},
9292

93+
'/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/eligible-versions': {
94+
post: {
95+
summary: 'List versions eligible for a release target',
96+
operationId: 'listEligibleVersionsForReleaseTarget',
97+
description: 'Returns deployment versions that currently pass every policy rule for this release target. An optional CEL filter narrows the result; pagination is applied to the filtered set. Use the "version" variable in the CEL expression to access version properties.',
98+
parameters: [
99+
openapi.workspaceIdParam(),
100+
openapi.releaseTargetKeyParam(),
101+
openapi.limitParam(),
102+
openapi.offsetParam(),
103+
],
104+
requestBody: {
105+
required: true,
106+
content: {
107+
'application/json': {
108+
schema: {
109+
type: 'object',
110+
properties: {
111+
filter: {
112+
type: 'string',
113+
description: 'CEL expression to filter eligible versions. Defaults to "true" (all eligible versions).',
114+
},
115+
},
116+
},
117+
},
118+
},
119+
},
120+
responses: openapi.paginatedResponse(openapi.schemaRef('DeploymentVersion'), 'Eligible versions for the release target')
121+
+ openapi.notFoundResponse()
122+
+ openapi.badRequestResponse(),
123+
},
124+
},
125+
93126
'/v1/workspaces/{workspaceId}/release-targets/resource-preview': {
94127
post: {
95128
summary: 'Preview release targets for a resource',

‎apps/api/src/routes/v1/workspaces/release-targets.ts‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,34 @@ const getReleaseTargetState: AsyncTypedHandler<
236236
res.status(200).json(data);
237237
};
238238

239+
const listEligibleVersionsForReleaseTarget: AsyncTypedHandler<
240+
"/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/eligible-versions",
241+
"post"
242+
> = async (req, res) => {
243+
const { workspaceId, releaseTargetKey } = req.params;
244+
const { limit, offset } = req.query;
245+
const { filter } = req.body;
246+
247+
const { data, error, response } = await getClientFor(workspaceId).POST(
248+
"/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/eligible-versions",
249+
{
250+
params: {
251+
path: { workspaceId, releaseTargetKey },
252+
query: { limit, offset },
253+
},
254+
body: { filter },
255+
},
256+
);
257+
258+
if (error != null)
259+
throw new ApiError(
260+
error.error ?? "Failed to list eligible versions",
261+
response.status >= 400 && response.status < 500 ? response.status : 502,
262+
);
263+
264+
res.status(200).json(data);
265+
};
266+
239267
const getReleaseTargetStates: AsyncTypedHandler<
240268
"/v1/workspaces/{workspaceId}/release-targets/state",
241269
"post"
@@ -436,7 +464,11 @@ const previewReleaseTargetsForResource: AsyncTypedHandler<
436464
const releaseTargetKeyRouter = Router({ mergeParams: true })
437465
.get("/jobs", asyncHandler(getReleaseTargetJobs))
438466
.get("/desired-release", asyncHandler(getReleaseTargetDesiredRelease))
439-
.get("/state", asyncHandler(getReleaseTargetState));
467+
.get("/state", asyncHandler(getReleaseTargetState))
468+
.post(
469+
"/eligible-versions",
470+
asyncHandler(listEligibleVersionsForReleaseTarget),
471+
);
440472

441473
export const releaseTargetsRouter = Router({ mergeParams: true })
442474
.post("/state", asyncHandler(getReleaseTargetStates))

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

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,26 @@ export interface paths {
655655
patch?: never;
656656
trace?: never;
657657
};
658+
"/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/eligible-versions": {
659+
parameters: {
660+
query?: never;
661+
header?: never;
662+
path?: never;
663+
cookie?: never;
664+
};
665+
get?: never;
666+
put?: never;
667+
/**
668+
* List versions eligible for a release target
669+
* @description Returns deployment versions that currently pass every policy rule for this release target. An optional CEL filter narrows the result; pagination is applied to the filtered set. Use the "version" variable in the CEL expression to access version properties.
670+
*/
671+
post: operations["listEligibleVersionsForReleaseTarget"];
672+
delete?: never;
673+
options?: never;
674+
head?: never;
675+
patch?: never;
676+
trace?: never;
677+
};
658678
"/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/jobs": {
659679
parameters: {
660680
query?: never;
@@ -4984,6 +5004,69 @@ export interface operations {
49845004
};
49855005
};
49865006
};
5007+
listEligibleVersionsForReleaseTarget: {
5008+
parameters: {
5009+
query?: {
5010+
/** @description Maximum number of items to return */
5011+
limit?: number;
5012+
/** @description Number of items to skip */
5013+
offset?: number;
5014+
};
5015+
header?: never;
5016+
path: {
5017+
/** @description ID of the workspace */
5018+
workspaceId: string;
5019+
/** @description Key of the release target */
5020+
releaseTargetKey: string;
5021+
};
5022+
cookie?: never;
5023+
};
5024+
requestBody: {
5025+
content: {
5026+
"application/json": {
5027+
/** @description CEL expression to filter eligible versions. Defaults to "true" (all eligible versions). */
5028+
filter?: string;
5029+
};
5030+
};
5031+
};
5032+
responses: {
5033+
/** @description Eligible versions for the release target */
5034+
200: {
5035+
headers: {
5036+
[name: string]: unknown;
5037+
};
5038+
content: {
5039+
"application/json": {
5040+
items: components["schemas"]["DeploymentVersion"][];
5041+
/** @description Maximum number of items returned */
5042+
limit: number;
5043+
/** @description Number of items skipped */
5044+
offset: number;
5045+
/** @description Total number of items available */
5046+
total: number;
5047+
};
5048+
};
5049+
};
5050+
/** @description Invalid request */
5051+
400: {
5052+
headers: {
5053+
[name: string]: unknown;
5054+
};
5055+
content: {
5056+
"application/json": components["schemas"]["ErrorResponse"];
5057+
};
5058+
};
5059+
/** @description Resource not found */
5060+
404: {
5061+
headers: {
5062+
[name: string]: unknown;
5063+
};
5064+
content: {
5065+
"application/json": components["schemas"]["ErrorResponse"];
5066+
};
5067+
};
5068+
};
5069+
};
49875070
getJobsForReleaseTarget: {
49885071
parameters: {
49895072
query?: {

0 commit comments

Comments
 (0)