diff --git a/apps/event-worker/src/utils/dispatch-evaluate-jobs.ts b/apps/event-worker/src/utils/dispatch-evaluate-jobs.ts index e494ec53f..3e57a0a57 100644 --- a/apps/event-worker/src/utils/dispatch-evaluate-jobs.ts +++ b/apps/event-worker/src/utils/dispatch-evaluate-jobs.ts @@ -1,8 +1,8 @@ -import type * as schema from "@ctrlplane/db/schema"; +import type { ReleaseTargetIdentifier } from "@ctrlplane/rule-engine"; import { Channel, getQueue } from "@ctrlplane/events"; -export const dispatchEvaluateJobs = async (rts: schema.ReleaseTarget[]) => { +export const dispatchEvaluateJobs = async (rts: ReleaseTargetIdentifier[]) => { const jobs = rts.map((rt) => ({ name: `${rt.resourceId}-${rt.environmentId}-${rt.deploymentId}`, data: rt, diff --git a/apps/event-worker/src/workers/compute-deployment-resource-selector.ts b/apps/event-worker/src/workers/compute-deployment-resource-selector.ts index 641a49b14..d6b477b31 100644 --- a/apps/event-worker/src/workers/compute-deployment-resource-selector.ts +++ b/apps/event-worker/src/workers/compute-deployment-resource-selector.ts @@ -20,8 +20,8 @@ export const computeDeploymentResourceSelectorWorkerEvent = createWorker( await db.transaction(async (tx) => { await tx.execute( sql` - SELECT * from ${schema.deployment} - WHERE ${schema.deployment.id} = ${id} + SELECT * from ${schema.computedDeploymentResource} + WHERE ${eq(schema.computedDeploymentResource.deploymentId, deployment.id)} FOR UPDATE NOWAIT `, ); @@ -58,7 +58,7 @@ export const computeDeploymentResourceSelectorWorkerEvent = createWorker( .onConflictDoNothing(); }); - getQueue(Channel.ComputeSystemsReleaseTargets).add( + await getQueue(Channel.ComputeSystemsReleaseTargets).add( deployment.system.id, deployment.system, ); diff --git a/apps/event-worker/src/workers/compute-environment-resource-selector.ts b/apps/event-worker/src/workers/compute-environment-resource-selector.ts index 287a46bdb..fce58b15e 100644 --- a/apps/event-worker/src/workers/compute-environment-resource-selector.ts +++ b/apps/event-worker/src/workers/compute-environment-resource-selector.ts @@ -38,8 +38,8 @@ export const computeEnvironmentResourceSelectorWorkerEvent = createWorker( // acquire a lock on the environment await tx.execute( sql` - SELECT * from ${schema.environment} - WHERE ${schema.environment.id} = ${id} + SELECT * from ${schema.computedEnvironmentResource} + WHERE ${eq(schema.computedEnvironmentResource.environmentId, environment.id)} FOR UPDATE NOWAIT `, ); @@ -79,7 +79,7 @@ export const computeEnvironmentResourceSelectorWorkerEvent = createWorker( .onConflictDoNothing(); }); - getQueue(Channel.ComputeSystemsReleaseTargets).add( + await getQueue(Channel.ComputeSystemsReleaseTargets).add( environment.system.id, environment.system, ); diff --git a/apps/event-worker/src/workers/compute-policy-target-release-target-selector.ts b/apps/event-worker/src/workers/compute-policy-target-release-target-selector.ts index 2b53793c2..db2d19704 100644 --- a/apps/event-worker/src/workers/compute-policy-target-release-target-selector.ts +++ b/apps/event-worker/src/workers/compute-policy-target-release-target-selector.ts @@ -1,6 +1,6 @@ import type { Tx } from "@ctrlplane/db"; -import { and, eq, inArray, isNull, selector, sql } from "@ctrlplane/db"; +import { and, eq, isNull, selector, sql } from "@ctrlplane/db"; import { db } from "@ctrlplane/db/client"; import * as schema from "@ctrlplane/db/schema"; import { Channel, createWorker, getQueue } from "@ctrlplane/events"; @@ -67,14 +67,12 @@ export const computePolicyTargetReleaseTargetSelectorWorkerEvent = createWorker( const { workspaceId } = policy; try { - const rts = await db.transaction(async (tx) => { + await db.transaction(async (tx) => { await tx.execute( sql` - SELECT * FROM ${schema.system} - INNER JOIN ${schema.environment} ON ${eq(schema.environment.systemId, schema.system.id)} - INNER JOIN ${schema.deployment} ON ${eq(schema.deployment.systemId, schema.system.id)} - INNER JOIN ${schema.releaseTarget} ON ${eq(schema.releaseTarget.environmentId, schema.environment.id)} - WHERE ${eq(schema.system.workspaceId, workspaceId)} + SELECT * from ${schema.computedPolicyTargetReleaseTarget} + INNER JOIN ${schema.releaseTarget} ON ${eq(schema.releaseTarget.id, schema.computedPolicyTargetReleaseTarget.releaseTargetId)} + WHERE ${eq(schema.computedPolicyTargetReleaseTarget.policyTargetId, policyTarget.id)} FOR UPDATE NOWAIT `, ); @@ -93,28 +91,41 @@ export const computePolicyTargetReleaseTargetSelectorWorkerEvent = createWorker( policyTarget, ); - if (releaseTargets.length === 0) return []; - return tx + if (releaseTargets.length === 0) return; + await tx .insert(schema.computedPolicyTargetReleaseTarget) .values(releaseTargets) - .onConflictDoNothing() - .returning(); + .onConflictDoNothing(); }); - if (rts.length === 0) return; + const releaseTargets = await db + .select() + .from(schema.releaseTarget) + .innerJoin( + schema.resource, + eq(schema.releaseTarget.resourceId, schema.resource.id), + ) + .where( + and( + isNull(schema.resource.deletedAt), + eq(schema.resource.workspaceId, workspaceId), + ), + ) + .then((rows) => rows.map((row) => row.release_target)); - const releaseTargets = await db.query.releaseTarget.findMany({ - where: inArray( - schema.releaseTarget.id, - rts.map((rt) => rt.releaseTargetId), + const queueInsertionPromises = releaseTargets.map((rt) => + getQueue(Channel.EvaluateReleaseTarget).add( + `${rt.resourceId}-${rt.environmentId}-${rt.deploymentId}`, + rt, + { + deduplication: { + id: `${rt.resourceId}-${rt.environmentId}-${rt.deploymentId}`, + ttl: 500, + }, + }, ), - }); - - const jobs = releaseTargets.map((rt) => ({ - name: `${rt.resourceId}-${rt.environmentId}-${rt.deploymentId}`, - data: rt, - })); - await getQueue(Channel.EvaluateReleaseTarget).addBulk(jobs); + ); + await Promise.all(queueInsertionPromises); } catch (e: any) { const isRowLocked = e.code === "55P03"; if (isRowLocked) { diff --git a/apps/event-worker/src/workers/compute-systems-release-targets.ts b/apps/event-worker/src/workers/compute-systems-release-targets.ts index 347bf05bf..92df2606d 100644 --- a/apps/event-worker/src/workers/compute-systems-release-targets.ts +++ b/apps/event-worker/src/workers/compute-systems-release-targets.ts @@ -5,6 +5,8 @@ import { db } from "@ctrlplane/db/client"; import * as schema from "@ctrlplane/db/schema"; import { Channel, createWorker, getQueue } from "@ctrlplane/events"; +import { dispatchEvaluateJobs } from "../utils/dispatch-evaluate-jobs.js"; + const findMatchingEnvironmentDeploymentPairs = ( tx: Tx, system: { id: string; workspaceId: string }, @@ -75,50 +77,60 @@ export const computeSystemsReleaseTargetsWorker = createWorker( const environmentIds = environments.map((e) => e.id); const { workspaceId } = system; + if (deploymentIds.length === 0 || environmentIds.length === 0) return; + try { const createdReleaseTargets = await db.transaction(async (tx) => { await tx.execute( sql` - SELECT * FROM ${schema.system} - INNER JOIN ${schema.environment} ON ${eq(schema.environment.systemId, schema.system.id)} - INNER JOIN ${schema.deployment} ON ${eq(schema.deployment.systemId, schema.system.id)} - INNER JOIN ${schema.releaseTarget} ON ${eq(schema.releaseTarget.environmentId, schema.environment.id)} - WHERE ${eq(schema.system.id, systemId)} + SELECT ${schema.releaseTarget.id} FROM ${schema.releaseTarget} + WHERE ${or( + inArray(schema.releaseTarget.deploymentId, deploymentIds), + inArray(schema.releaseTarget.environmentId, environmentIds), + )} FOR UPDATE NOWAIT `, ); - const previousReleaseTargets = await tx - .delete(schema.releaseTarget) - .where( - or( - inArray(schema.releaseTarget.deploymentId, deploymentIds), - inArray(schema.releaseTarget.environmentId, environmentIds), - ), - ) - .returning(); + await tx.execute( + sql` + SELECT * FROM ${schema.computedEnvironmentResource} + WHERE ${inArray(schema.computedEnvironmentResource.environmentId, environmentIds)} + FOR UPDATE NOWAIT + `, + ); + + await tx.execute( + sql` + SELECT * FROM ${schema.computedDeploymentResource} + WHERE ${inArray(schema.computedDeploymentResource.deploymentId, deploymentIds)} + FOR UPDATE NOWAIT + `, + ); + + const previousReleaseTargets = await tx.query.releaseTarget.findMany({ + where: or( + inArray(schema.releaseTarget.deploymentId, deploymentIds), + inArray(schema.releaseTarget.environmentId, environmentIds), + ), + }); const releaseTargets = await findMatchingEnvironmentDeploymentPairs( tx, system, ); - if (releaseTargets.length > 0) - await tx - .insert(schema.releaseTarget) - .values(releaseTargets) - .onConflictDoNothing(); - const created = releaseTargets.filter( (rt) => !previousReleaseTargets.some( (prevRt) => prevRt.deploymentId === rt.deploymentId && - prevRt.resourceId === rt.resourceId, + prevRt.resourceId === rt.resourceId && + prevRt.environmentId === rt.environmentId, ), ); - - return created; + if (created.length === 0) return []; + return tx.insert(schema.releaseTarget).values(created).returning(); }); if (createdReleaseTargets.length === 0) return; @@ -132,18 +144,24 @@ export const computeSystemsReleaseTargetsWorker = createWorker( ) .where(eq(schema.policy.workspaceId, workspaceId)); - for (const { policy_target: policyTarget } of policyTargets) { - getQueue(Channel.ComputePolicyTargetReleaseTargetSelector).add( - policyTarget.id, - policyTarget, - ); + if (policyTargets.length > 0) { + for (const { policy_target: policyTarget } of policyTargets) { + getQueue(Channel.ComputePolicyTargetReleaseTargetSelector).add( + policyTarget.id, + policyTarget, + ); + } + return; } + + await dispatchEvaluateJobs(createdReleaseTargets); } catch (e: any) { const isRowLocked = e.code === "55P03"; if (isRowLocked) { await getQueue(Channel.ComputeSystemsReleaseTargets).add( job.name, job.data, + { delay: 500 }, ); return; } diff --git a/apps/event-worker/src/workers/evaluate-release-target.ts b/apps/event-worker/src/workers/evaluate-release-target.ts index c6e0654a4..2523998d0 100644 --- a/apps/event-worker/src/workers/evaluate-release-target.ts +++ b/apps/event-worker/src/workers/evaluate-release-target.ts @@ -11,8 +11,6 @@ import { VersionReleaseManager, } from "@ctrlplane/rule-engine"; -import { createAndAcquireMutex } from "../releases/mutex.js"; - const log = logger.child({ worker: "evaluate-release-target" }); const tracer = trace.getTracer("evaluate-release-target"); const withSpan = makeWithSpan(tracer); @@ -104,13 +102,13 @@ const createRelease = withSpan( */ const handleVersionRelease = withSpan( "handleVersionRelease", - async (span, releaseTarget: any) => { + async (span, tx: Tx, releaseTarget: any) => { const workspaceId = releaseTarget.resource.workspaceId; span.setAttribute("releaseTarget.id", String(releaseTarget.id)); span.setAttribute("workspace.id", workspaceId); - const vrm = new VersionReleaseManager(db, { + const vrm = new VersionReleaseManager(tx, { ...releaseTarget, workspaceId, }); @@ -140,13 +138,13 @@ const handleVersionRelease = withSpan( */ const handleVariableRelease = withSpan( "handleVariableRelease", - async (span, releaseTarget: any) => { + async (span, tx: Tx, releaseTarget: any) => { const workspaceId = releaseTarget.resource.workspaceId; span.setAttribute("releaseTarget.id", String(releaseTarget.id)); span.setAttribute("workspace.id", workspaceId); - const varrm = new VariableReleaseManager(db, { + const varrm = new VariableReleaseManager(tx, { ...releaseTarget, workspaceId, }); @@ -172,91 +170,84 @@ export const evaluateReleaseTargetWorker = createWorker( span.setAttribute("environment.id", job.data.environmentId); span.setAttribute("deployment.id", job.data.deploymentId); - const [mutex, isAcquired] = await createAndAcquireMutex(job.data, { - tryLock: true, - }); - - if (!isAcquired) { - log.info("Failed to acquire mutex for release target", { - releaseTarget: job.data, - }); - - await getQueue(Channel.EvaluateReleaseTarget).add(job.name, job.data, { - jobId: job.id, - delay: 1000, - }); - - throw new Error("Failed to acquire mutex for release target"); - } - try { - // Get release target - const releaseTarget = await db.query.releaseTarget.findFirst({ - where: and( - eq(schema.releaseTarget.resourceId, job.data.resourceId), - eq(schema.releaseTarget.environmentId, job.data.environmentId), - eq(schema.releaseTarget.deploymentId, job.data.deploymentId), - ), - with: { - resource: true, - environment: true, - deployment: true, - }, - }); - if (!releaseTarget) throw new Error("Failed to get release target"); - - const existingVersionRelease = await db.query.versionRelease.findFirst({ - where: eq(schema.versionRelease.releaseTargetId, releaseTarget.id), - orderBy: desc(schema.versionRelease.createdAt), - }); - - const existingVariableRelease = - await db.query.variableSetRelease.findFirst({ - where: eq( - schema.variableSetRelease.releaseTargetId, - releaseTarget.id, + const release = await db.transaction(async (tx) => { + const releaseTarget = await tx.query.releaseTarget.findFirst({ + where: and( + eq(schema.releaseTarget.resourceId, job.data.resourceId), + eq(schema.releaseTarget.environmentId, job.data.environmentId), + eq(schema.releaseTarget.deploymentId, job.data.deploymentId), ), - orderBy: desc(schema.variableSetRelease.createdAt), + with: { + resource: true, + environment: true, + deployment: true, + }, }); + if (!releaseTarget) throw new Error("Failed to get release target"); - const [versionRelease, variableRelease] = await Promise.all([ - handleVersionRelease(releaseTarget), - handleVariableRelease(releaseTarget), - ]); + const existingVersionRelease = await tx.query.versionRelease.findFirst({ + where: eq(schema.versionRelease.releaseTargetId, releaseTarget.id), + orderBy: desc(schema.versionRelease.createdAt), + }); - if (versionRelease == null) { - return; - } + const existingVariableRelease = + await tx.query.variableSetRelease.findFirst({ + where: eq( + schema.variableSetRelease.releaseTargetId, + releaseTarget.id, + ), + orderBy: desc(schema.variableSetRelease.createdAt), + }); + + const [versionRelease, variableRelease] = await Promise.all([ + handleVersionRelease(tx, releaseTarget), + handleVariableRelease(tx, releaseTarget), + ]); + + if (versionRelease == null) return; + + const isSameVersionRelease = + existingVersionRelease?.id === versionRelease.id; + const isSameVariableRelease = + existingVariableRelease?.id === variableRelease.id; + if (isSameVersionRelease && isSameVariableRelease) return; + + log.info("Creating new release for target", { + releaseTarget, + existingVersionRelease, + versionRelease, + existingVariableRelease, + variableRelease, + }); - const isSameVersionRelease = - existingVersionRelease?.id === versionRelease.id; - const isSameVariableRelease = - existingVariableRelease?.id === variableRelease.id; - if (isSameVersionRelease && isSameVariableRelease) return; - - log.info("Creating new release for target", { - releaseTarget, - existingVersionRelease, - versionRelease, - existingVariableRelease, - variableRelease, + return tx + .insert(schema.release) + .values({ + versionReleaseId: versionRelease.id, + variableReleaseId: variableRelease.id, + }) + .returning() + .then(takeFirst); }); - const release = await db - .insert(schema.release) - .values({ - versionReleaseId: versionRelease.id, - variableReleaseId: variableRelease.id, - }) - .returning() - .then(takeFirst); - - if (process.env.ENABLE_NEW_POLICY_ENGINE === "true") { - const job = await db.transaction((tx) => createRelease(tx, release)); + if (process.env.ENABLE_NEW_POLICY_ENGINE === "true" && release != null) { + const job = await db.transaction(async (tx) => + createRelease(tx, release), + ); getQueue(Channel.DispatchJob).add(job.id, { jobId: job.id }); } - } finally { - await mutex.unlock(); + } catch (e: any) { + const isRowLocked = e.code === "55P03"; + const isReleaseTargetNotCommittedYet = e.code === "23503"; + if (isRowLocked || isReleaseTargetNotCommittedYet) { + await getQueue(Channel.EvaluateReleaseTarget).add(job.name, job.data, { + delay: 500, + }); + return; + } + log.error("Error in evaluateReleaseTarget", { error: e }); + throw e; } }), // Member intensive work, attemp to reduce crashing diff --git a/apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/openapi.ts b/apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/openapi.ts new file mode 100644 index 000000000..73d03fb9d --- /dev/null +++ b/apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/openapi.ts @@ -0,0 +1,86 @@ +import type { Swagger } from "atlassian-openapi"; + +export const openapi: Swagger.SwaggerV3 = { + openapi: "3.0.0", + info: { + title: "Ctrlplane API", + version: "1.0.0", + }, + paths: { + "/v1/release-targets/{releaseTargetId}/releases": { + get: { + summary: "Get the latest 100 releases for a release target", + operationId: "getReleaseTargetReleases", + parameters: [ + { + name: "releaseTargetId", + in: "path", + required: true, + schema: { type: "string", format: "uuid" }, + }, + ], + responses: { + 200: { + description: "The latest 100 releases for the release target", + content: { + "application/json": { + schema: { + type: "array", + items: { + type: "object", + properties: { + deployment: { $ref: "#/components/schemas/Deployment" }, + version: { + $ref: "#/components/schemas/DeploymentVersion", + }, + variables: { + type: "array", + items: { + type: "object", + properties: { + key: { type: "string" }, + value: { type: "string" }, + }, + required: ["key", "value"], + }, + }, + }, + required: ["deployment", "version", "variables"], + }, + }, + }, + }, + }, + 404: { + description: "The release target was not found", + content: { + "application/json": { + schema: { + type: "object", + properties: { + error: { type: "string" }, + }, + required: ["error"], + }, + }, + }, + }, + 500: { + description: "An internal server error occurred", + content: { + "application/json": { + schema: { + type: "object", + properties: { + error: { type: "string" }, + }, + required: ["error"], + }, + }, + }, + }, + }, + }, + }, + }, +}; diff --git a/apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts b/apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts new file mode 100644 index 000000000..b48457f9d --- /dev/null +++ b/apps/webservice/src/app/api/v1/release-targets/[releaseTargetId]/releases/route.ts @@ -0,0 +1,119 @@ +import { NextResponse } from "next/server"; +import { INTERNAL_SERVER_ERROR, NOT_FOUND } from "http-status"; + +import { desc, eq, sql, takeFirstOrNull } from "@ctrlplane/db"; +import * as schema from "@ctrlplane/db/schema"; +import { logger } from "@ctrlplane/logger"; +import { variablesAES256 } from "@ctrlplane/secrets"; +import { Permission } from "@ctrlplane/validators/auth"; + +import { authn, authz } from "~/app/api/v1/auth"; +import { request } from "~/app/api/v1/middleware"; + +const log = logger.child({ + route: "v1/release-targets/[releaseTargetId]/releases", +}); + +export const GET = request() + .use(authn) + .use( + authz(({ can, params }) => + can + .perform(Permission.ReleaseTargetGet) + .on({ type: "releaseTarget", id: params.releaseTargetId ?? "" }), + ), + ) + .handle }>( + async ({ db }, { params }) => { + try { + const { releaseTargetId } = await params; + + const releaseTarget = await db + .select() + .from(schema.releaseTarget) + .where(eq(schema.releaseTarget.id, releaseTargetId)) + .then(takeFirstOrNull); + + if (releaseTarget == null) + return NextResponse.json( + { error: "Release target not found" }, + { status: NOT_FOUND }, + ); + + const variableSetReleaseSubquery = db + .select({ + id: schema.variableSetRelease.id, + values: sql< + { key: string; value: unknown; sensitive: boolean }[] + >`COALESCE(json_agg(json_build_object('key', ${schema.variableValueSnapshot.key}, 'value', ${schema.variableValueSnapshot.value}, 'sensitive', ${schema.variableValueSnapshot.sensitive})), '[]'::json)`.as( + "values", + ), + }) + .from(schema.variableSetRelease) + .leftJoin( + schema.variableSetReleaseValue, + eq( + schema.variableSetRelease.id, + schema.variableSetReleaseValue.variableSetReleaseId, + ), + ) + .leftJoin( + schema.variableValueSnapshot, + eq( + schema.variableSetReleaseValue.variableValueSnapshotId, + schema.variableValueSnapshot.id, + ), + ) + .groupBy(schema.variableSetRelease.id) + .as("variableSetReleaseSubquery"); + + const releaseResult = await db + .select() + .from(schema.release) + .innerJoin( + schema.versionRelease, + eq(schema.release.versionReleaseId, schema.versionRelease.id), + ) + .innerJoin( + schema.deploymentVersion, + eq(schema.versionRelease.versionId, schema.deploymentVersion.id), + ) + .innerJoin( + variableSetReleaseSubquery, + eq(schema.release.variableReleaseId, variableSetReleaseSubquery.id), + ) + .innerJoin( + schema.deployment, + eq(schema.deploymentVersion.deploymentId, schema.deployment.id), + ) + .where(eq(schema.versionRelease.releaseTargetId, releaseTargetId)) + .orderBy(desc(schema.release.createdAt)) + .limit(100); + + const releases = releaseResult.map((release) => { + const { values } = release.variableSetReleaseSubquery; + const variables = values.map(({ key, value, sensitive }) => { + const strval = String(value); + const resolvedValue = sensitive + ? variablesAES256().decrypt(strval) + : strval; + return { key, value: resolvedValue }; + }); + + return { + deployment: release.deployment, + version: release.deployment_version, + variables, + }; + }); + + return NextResponse.json(releases); + } catch (error) { + log.error(error); + return NextResponse.json( + { error: "Error fetching releases" }, + { status: INTERNAL_SERVER_ERROR }, + ); + } + }, + ); diff --git a/e2e/api/schema.ts b/e2e/api/schema.ts index 4eb769bc3..abc229d55 100644 --- a/e2e/api/schema.ts +++ b/e2e/api/schema.ts @@ -4,3962 +4,4056 @@ */ export interface paths { - "/api/v1/cloud-locations/{provider}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get all regions for a specific cloud provider - * @description Returns geographic data for all regions of a specific cloud provider - */ - get: operations["getCloudProviderRegions"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/deployment-version-channels": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a deployment version channel */ - post: operations["createDeploymentVersionChannel"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/deployment-versions/{deploymentVersionId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** Updates a deployment version */ - patch: operations["updateDeploymentVersion"]; - trace?: never; - }; - "/v1/deployment-versions": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Upserts a deployment version */ - post: operations["upsertDeploymentVersion"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/deployments/{deploymentId}/deployment-version-channels/name/{name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - /** Delete a deployment version channel */ - delete: operations["deleteDeploymentVersionChannel"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/deployments/{deploymentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a deployment */ - get: operations["getDeployment"]; - put?: never; - post?: never; - /** Delete a deployment */ - delete: operations["deleteDeployment"]; - options?: never; - head?: never; - /** Update a deployment */ - patch: operations["updateDeployment"]; - trace?: never; - }; - "/v1/deployments/{deploymentId}/release-channels/name/{name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - /** Delete a release channel */ - delete: operations["deleteReleaseChannel"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/deployments/{deploymentId}/resources": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get resources for a deployment */ - get: operations["getResourcesForDeployment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/deployments": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a deployment */ - post: operations["createDeployment"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/environments/{environmentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get an environment */ - get: operations["getEnvironment"]; - put?: never; - post?: never; - /** Delete an environment */ - delete: operations["deleteEnvironment"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/environments/{environmentId}/resources": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get resources for an environment */ - get: operations["getResourcesForEnvironment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/environments": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create an environment */ - post: operations["createEnvironment"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/job-agents/{agentId}/jobs/running": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a agents running jobs */ - get: operations["getAgentRunningJobs"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/job-agents/{agentId}/queue/acknowledge": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Acknowledge a job for an agent - * @description Marks a job as acknowledged by the agent - */ - post: operations["acknowledgeAgentJob"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/job-agents/{agentId}/queue/next": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get the next jobs */ - get: operations["getNextJobs"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/job-agents/name": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** Upserts the agent */ - patch: operations["upsertJobAgent"]; - trace?: never; - }; - "/v1/jobs/{jobId}/acknowledge": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Acknowledge a job */ - post: operations["acknowledgeJob"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/jobs/{jobId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a Job */ - get: operations["getJob"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** Update a job */ - patch: operations["updateJob"]; - trace?: never; - }; - "/v1/policies/{policyId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - /** Delete a policy */ - delete: operations["deletePolicy"]; - options?: never; - head?: never; - /** Update a policy */ - patch: operations["updatePolicy"]; - trace?: never; - }; - "/v1/policies/{policyId}/release-targets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get release targets for a policy */ - get: operations["getReleaseTargetsForPolicy"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/policies": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Upsert a policy */ - post: operations["upsertPolicy"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/relationship/job-to-resource": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a relationship between a job and a resource */ - post: operations["createJobToResourceRelationship"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/relationship/resource-to-resource": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a relationship between two resources */ - post: operations["createResourceToResourceRelationship"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/release-channels": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a release channel */ - post: operations["createReleaseChannel"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/releases/{releaseId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** Updates a release */ - patch: operations["updateRelease"]; - trace?: never; - }; - "/v1/releases": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Upserts a release */ - post: operations["upsertRelease"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/resource-providers/{providerId}/set": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** Sets the resource for a provider. */ - patch: operations["setResourceProvidersResources"]; - trace?: never; - }; - "/v1/resource-relationship-rules": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a resource relationship rule */ - post: operations["upsertResourceRelationshipRule"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/resource-schemas": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a resource schema */ - post: operations["createResourceSchema"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/resource-schemas/{schemaId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - /** Delete a resource schema */ - delete: operations["deleteResourceSchema"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/resources/{resourceId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a resource */ - get: operations["getResource"]; - put?: never; - post?: never; - /** Delete a resource */ - delete: operations["deleteResource"]; - options?: never; - head?: never; - /** Update a resource */ - patch: operations["updateResource"]; - trace?: never; - }; - "/v1/resources/{resourceId}/release-targets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get release targets for a resource */ - get: operations["getReleaseTargets"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/resources": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create or update a resource */ - post: operations["upsertResource"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/systems/{systemId}/environments/{name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - /** Delete an environment */ - delete: operations["deleteEnvironmentByName"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/systems/{systemId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a system */ - get: operations["getSystem"]; - put?: never; - post?: never; - /** Delete a system */ - delete: operations["deleteSystem"]; - options?: never; - head?: never; - /** Update a system */ - patch: operations["updateSystem"]; - trace?: never; - }; - "/v1/systems": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Create a system */ - post: operations["createSystem"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployments": { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - /** List all deployments */ - get: operations["listDeployments"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/environments": { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - /** List all environments */ - get: operations["listEnvironments"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a workspace */ - get: operations["getWorkspace"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policies/{name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - /** Delete a policy by name */ - delete: operations["deletePolicyByName"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resource-providers/name/{name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Upserts a resource provider. */ - get: operations["upsertResourceProvider"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/identifier/{identifier}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a resource by identifier */ - get: operations["getResourceByIdentifier"]; - put?: never; - post?: never; - /** Delete a resource by identifier */ - delete: operations["deleteResourceByIdentifier"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/metadata-grouped-counts": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Get grouped counts of resources */ - post: operations["getGroupedCounts"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources": { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - /** List all resources */ - get: operations["listResources"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/systems": { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - /** List all systems */ - get: operations["listSystems"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/slug/{workspaceSlug}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a workspace by slug */ - get: operations["getWorkspaceBySlug"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; + "/api/v1/cloud-locations/{provider}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get all regions for a specific cloud provider + * @description Returns geographic data for all regions of a specific cloud provider + */ + get: operations["getCloudProviderRegions"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/deployment-version-channels": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a deployment version channel */ + post: operations["createDeploymentVersionChannel"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/deployment-versions/{deploymentVersionId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Updates a deployment version */ + patch: operations["updateDeploymentVersion"]; + trace?: never; + }; + "/v1/deployment-versions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Upserts a deployment version */ + post: operations["upsertDeploymentVersion"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/deployments/{deploymentId}/deployment-version-channels/name/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** Delete a deployment version channel */ + delete: operations["deleteDeploymentVersionChannel"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/deployments/{deploymentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a deployment */ + get: operations["getDeployment"]; + put?: never; + post?: never; + /** Delete a deployment */ + delete: operations["deleteDeployment"]; + options?: never; + head?: never; + /** Update a deployment */ + patch: operations["updateDeployment"]; + trace?: never; + }; + "/v1/deployments/{deploymentId}/release-channels/name/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** Delete a release channel */ + delete: operations["deleteReleaseChannel"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/deployments/{deploymentId}/resources": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get resources for a deployment */ + get: operations["getResourcesForDeployment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/deployments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a deployment */ + post: operations["createDeployment"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/environments/{environmentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get an environment */ + get: operations["getEnvironment"]; + put?: never; + post?: never; + /** Delete an environment */ + delete: operations["deleteEnvironment"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/environments/{environmentId}/resources": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get resources for an environment */ + get: operations["getResourcesForEnvironment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/environments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create an environment */ + post: operations["createEnvironment"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/job-agents/{agentId}/jobs/running": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a agents running jobs */ + get: operations["getAgentRunningJobs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/job-agents/{agentId}/queue/acknowledge": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Acknowledge a job for an agent + * @description Marks a job as acknowledged by the agent + */ + post: operations["acknowledgeAgentJob"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/job-agents/{agentId}/queue/next": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get the next jobs */ + get: operations["getNextJobs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/job-agents/name": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Upserts the agent */ + patch: operations["upsertJobAgent"]; + trace?: never; + }; + "/v1/jobs/{jobId}/acknowledge": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Acknowledge a job */ + post: operations["acknowledgeJob"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/jobs/{jobId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a Job */ + get: operations["getJob"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Update a job */ + patch: operations["updateJob"]; + trace?: never; + }; + "/v1/policies/{policyId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** Delete a policy */ + delete: operations["deletePolicy"]; + options?: never; + head?: never; + /** Update a policy */ + patch: operations["updatePolicy"]; + trace?: never; + }; + "/v1/policies/{policyId}/release-targets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get release targets for a policy */ + get: operations["getReleaseTargetsForPolicy"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/policies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Upsert a policy */ + post: operations["upsertPolicy"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/relationship/job-to-resource": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a relationship between a job and a resource */ + post: operations["createJobToResourceRelationship"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/relationship/resource-to-resource": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a relationship between two resources */ + post: operations["createResourceToResourceRelationship"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/release-channels": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a release channel */ + post: operations["createReleaseChannel"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/release-targets/{releaseTargetId}/releases": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get the latest 100 releases for a release target */ + get: operations["getReleaseTargetReleases"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/releases/{releaseId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Updates a release */ + patch: operations["updateRelease"]; + trace?: never; + }; + "/v1/releases": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Upserts a release */ + post: operations["upsertRelease"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/resource-providers/{providerId}/set": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Sets the resource for a provider. */ + patch: operations["setResourceProvidersResources"]; + trace?: never; + }; + "/v1/resource-relationship-rules": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a resource relationship rule */ + post: operations["upsertResourceRelationshipRule"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/resource-schemas": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a resource schema */ + post: operations["createResourceSchema"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/resource-schemas/{schemaId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** Delete a resource schema */ + delete: operations["deleteResourceSchema"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/resources/{resourceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a resource */ + get: operations["getResource"]; + put?: never; + post?: never; + /** Delete a resource */ + delete: operations["deleteResource"]; + options?: never; + head?: never; + /** Update a resource */ + patch: operations["updateResource"]; + trace?: never; + }; + "/v1/resources/{resourceId}/release-targets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get release targets for a resource */ + get: operations["getReleaseTargets"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/resources": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create or update a resource */ + post: operations["upsertResource"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/systems/{systemId}/environments/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** Delete an environment */ + delete: operations["deleteEnvironmentByName"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/systems/{systemId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a system */ + get: operations["getSystem"]; + put?: never; + post?: never; + /** Delete a system */ + delete: operations["deleteSystem"]; + options?: never; + head?: never; + /** Update a system */ + patch: operations["updateSystem"]; + trace?: never; + }; + "/v1/systems": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Create a system */ + post: operations["createSystem"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployments": { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + /** List all deployments */ + get: operations["listDeployments"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/environments": { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + /** List all environments */ + get: operations["listEnvironments"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a workspace */ + get: operations["getWorkspace"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policies/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** Delete a policy by name */ + delete: operations["deletePolicyByName"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resource-providers/name/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Upserts a resource provider. */ + get: operations["upsertResourceProvider"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/identifier/{identifier}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a resource by identifier */ + get: operations["getResourceByIdentifier"]; + put?: never; + post?: never; + /** Delete a resource by identifier */ + delete: operations["deleteResourceByIdentifier"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/metadata-grouped-counts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Get grouped counts of resources */ + post: operations["getGroupedCounts"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources": { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + /** List all resources */ + get: operations["listResources"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/systems": { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + /** List all systems */ + get: operations["listSystems"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/slug/{workspaceSlug}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a workspace by slug */ + get: operations["getWorkspaceBySlug"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; } export type webhooks = Record; export interface components { - schemas: { - CloudRegionGeoData: { - /** - * @description Timezone of the region in UTC format - * @example UTC+1 - */ - timezone: string; - /** - * Format: float - * @description Latitude coordinate for the region - * @example 50.1109 - */ - latitude: number; - /** - * Format: float - * @description Longitude coordinate for the region - * @example 8.6821 - */ - longitude: number; - }; - JobWithTrigger: components["schemas"]["Job"] & { - release?: components["schemas"]["Release"]; - deploymentVersion?: components["schemas"]["DeploymentVersion"]; - deployment?: components["schemas"]["Deployment"]; - runbook?: components["schemas"]["Runbook"]; - resource?: components["schemas"]["Resource"]; - environment?: components["schemas"]["Environment"]; - variables: components["schemas"]["VariableMap"]; - approval?: { - id: string; - /** @enum {string} */ - status: "pending" | "approved" | "rejected"; - /** @description Null when status is pending, contains approver details when approved or rejected */ - approver?: { - id: string; - name: string; - } | null; - } | null; - }; - Workspace: { - /** - * Format: uuid - * @description The workspace ID - */ + schemas: { + CloudRegionGeoData: { + /** + * @description Timezone of the region in UTC format + * @example UTC+1 + */ + timezone: string; + /** + * Format: float + * @description Latitude coordinate for the region + * @example 50.1109 + */ + latitude: number; + /** + * Format: float + * @description Longitude coordinate for the region + * @example 8.6821 + */ + longitude: number; + }; + JobWithTrigger: components["schemas"]["Job"] & { + release?: components["schemas"]["Release"]; + deploymentVersion?: components["schemas"]["DeploymentVersion"]; + deployment?: components["schemas"]["Deployment"]; + runbook?: components["schemas"]["Runbook"]; + resource?: components["schemas"]["Resource"]; + environment?: components["schemas"]["Environment"]; + variables: components["schemas"]["VariableMap"]; + approval?: { + id: string; + /** @enum {string} */ + status: "pending" | "approved" | "rejected"; + /** @description Null when status is pending, contains approver details when approved or rejected */ + approver?: { + id: string; + name: string; + } | null; + } | null; + }; + Workspace: { + /** + * Format: uuid + * @description The workspace ID + */ + id: string; + /** @description The name of the workspace */ + name: string; + /** @description The slug of the workspace */ + slug: string; + /** + * @description The email of the Google service account attached to the workspace + * @example ctrlplane@ctrlplane-workspace.iam.gserviceaccount.com + */ + googleServiceAccountEmail?: string | null; + /** + * @description The ARN of the AWS role attached to the workspace + * @example arn:aws:iam::123456789012:role/ctrlplane-workspace-role + */ + awsRoleArn?: string | null; + }; + System: { + /** + * Format: uuid + * @description The system ID + */ + id: string; + /** + * Format: uuid + * @description The workspace ID of the system + */ + workspaceId: string; + /** @description The name of the system */ + name: string; + /** @description The slug of the system */ + slug: string; + /** @description The description of the system */ + description?: string; + }; + Deployment: { + /** Format: uuid */ + id: string; + name: string; + slug: string; + description: string; + /** Format: uuid */ + systemId: string; + /** Format: uuid */ + jobAgentId?: string | null; + jobAgentConfig: { + [key: string]: unknown; + }; + retryCount?: number; + timeout?: number | null; + }; + /** @description Schema for updating a deployment (all fields optional) */ + UpdateDeployment: { + [key: string]: unknown; + } & (WithRequired & { + [key: string]: unknown; + }); + Release: { + /** Format: uuid */ + id: string; + name: string; + version: string; + config: { + [key: string]: unknown; + }; + jobAgentConfig: { + [key: string]: unknown; + }; + /** Format: uuid */ + deploymentId: string; + /** Format: date-time */ + createdAt: string; + metadata?: { + [key: string]: unknown; + }; + }; + DeploymentVersion: { + /** Format: uuid */ + id: string; + name: string; + tag: string; + config: { + [key: string]: unknown; + }; + jobAgentConfig: { + [key: string]: unknown; + }; + /** Format: uuid */ + deploymentId: string; + /** Format: date-time */ + createdAt: string; + metadata?: { + [key: string]: string; + }; + /** @enum {string} */ + status?: "building" | "ready" | "failed"; + }; + Policy: { + /** + * Format: uuid + * @description The policy ID + */ + id: string; + /** + * Format: uuid + * @description The system ID + */ + systemId: string; + /** @description The name of the policy */ + name: string; + /** @description The description of the policy */ + description?: string | null; + /** + * @description The approval requirement of the policy + * @enum {string} + */ + approvalRequirement: "manual" | "automatic"; + /** + * @description If a policy depends on an environment, whether or not the policy requires all, some, or optional successful releases in the environment + * @enum {string} + */ + successType: "some" | "all" | "optional"; + /** @description If a policy depends on an environment, the minimum number of successful releases in the environment */ + successMinimum: number; + /** @description The maximum number of concurrent releases in the environment */ + concurrencyLimit?: number | null; + /** @description The duration of the rollout in milliseconds */ + rolloutDuration: number; + /** @description The minimum interval between releases in milliseconds */ + minimumReleaseInterval: number; + /** + * @description If a new release is created, whether it will wait for the current release to finish before starting, or cancel the current release + * @enum {string} + */ + releaseSequencing: "wait" | "cancel"; + }; + Environment: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + systemId: string; + name: string; + description?: string; + /** Format: uuid */ + policyId?: string | null; + resourceSelector?: { + [key: string]: unknown; + } | null; + /** + * @description The directory path of the environment + * @default + * @example my/env/path + */ + directory: string; + /** Format: date-time */ + createdAt: string; + metadata?: { + [key: string]: string; + }; + policy?: components["schemas"]["Policy"]; + }; + Runbook: { + /** Format: uuid */ + id: string; + name: string; + /** Format: uuid */ + systemId: string; + /** Format: uuid */ + jobAgentId: string; + }; + Resource: { + /** Format: uuid */ + id: string; + name: string; + version: string; + kind: string; + identifier: string; + config: { + [key: string]: unknown; + }; + metadata: { + [key: string]: unknown; + }; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + /** Format: uuid */ + workspaceId: string; + }; + ResourceWithVariables: components["schemas"]["Resource"] & { + variables?: components["schemas"]["VariableMap"]; + }; + ResourceWithMetadata: components["schemas"]["Resource"] & { + metadata?: components["schemas"]["MetadataMap"]; + }; + ResourceWithVariablesAndMetadata: components["schemas"]["ResourceWithVariables"] & + components["schemas"]["ResourceWithMetadata"]; + /** @enum {string} */ + JobStatus: + | "successful" + | "cancelled" + | "skipped" + | "in_progress" + | "action_required" + | "pending" + | "failure" + | "invalid_job_agent" + | "invalid_integration" + | "external_run_not_found"; + Job: { + /** Format: uuid */ + id: string; + status: components["schemas"]["JobStatus"]; + /** @description External job identifier (e.g. GitHub workflow run ID) */ + externalId?: string | null; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + /** Format: date-time */ + startedAt?: string | null; + /** Format: date-time */ + completedAt?: string | null; + /** Format: uuid */ + jobAgentId?: string; + /** @description Configuration for the Job Agent */ + jobAgentConfig: { + [key: string]: unknown; + }; + message?: string; + reason?: string; + }; + MetadataMap: { + [key: string]: string; + }; + VariableMap: { + [key: string]: + | (string | boolean | number | Record | unknown[]) + | null; + }; + ReferenceVariable: { + key: string; + reference: string; + path: string[]; + defaultValue?: + | string + | number + | boolean + | Record + | unknown[]; + }; + DirectVariable: { + key: string; + value: string | number | boolean | Record | unknown[]; + sensitive?: boolean; + }; + Variable: + | components["schemas"]["DirectVariable"] + | components["schemas"]["ReferenceVariable"]; + PolicyTarget: { + deploymentSelector?: { + [key: string]: unknown; + } | null; + environmentSelector?: { + [key: string]: unknown; + } | null; + resourceSelector?: { + [key: string]: unknown; + } | null; + }; + DenyWindow: { + timeZone: string; + rrule: { + [key: string]: unknown; + }; + /** Format: date-time */ + dtend?: string; + }; + DeploymentVersionSelector: { + name: string; + deploymentVersionSelector: { + [key: string]: unknown; + }; + description?: string; + }; + VersionAnyApproval: { + requiredApprovalsCount: number; + }; + VersionUserApproval: { + userId: string; + }; + VersionRoleApproval: { + roleId: string; + requiredApprovalsCount: number; + }; + Policy1: { + /** Format: uuid */ + id: string; + name: string; + description?: string; + priority: number; + /** Format: date-time */ + createdAt: string; + enabled: boolean; + /** Format: uuid */ + workspaceId: string; + targets: components["schemas"]["PolicyTarget"][]; + denyWindows: components["schemas"]["DenyWindow"][]; + deploymentVersionSelector?: components["schemas"]["DeploymentVersionSelector"]; + versionAnyApprovals?: components["schemas"]["VersionAnyApproval"][]; + versionUserApprovals: components["schemas"]["VersionUserApproval"][]; + versionRoleApprovals: components["schemas"]["VersionRoleApproval"][]; + }; + /** @enum {string} */ + ResourceRelationshipRuleDependencyType: + | "depends_on" + | "depends_indirectly_on" + | "uses_at_runtime" + | "created_after" + | "provisioned_in" + | "inherits_from"; + ResourceRelationshipRule: { + id: string; + workspaceId: string; + name: string; + reference: string; + dependencyType: components["schemas"]["ResourceRelationshipRuleDependencyType"]; + dependencyDescription?: string; + description?: string; + sourceKind: string; + sourceVersion: string; + targetKind: string; + targetVersion: string; + }; + CreateResourceRelationshipRule: { + workspaceId: string; + name: string; + reference: string; + dependencyType: components["schemas"]["ResourceRelationshipRuleDependencyType"]; + dependencyDescription?: string; + description?: string; + sourceKind: string; + sourceVersion: string; + targetKind: string; + targetVersion: string; + metadataKeysMatch: string[]; + }; + ReleaseTarget: { + /** Format: uuid */ + id: string; + resource: components["schemas"]["Resource"]; + environment: components["schemas"]["Environment"]; + deployment: components["schemas"]["Deployment"]; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + getCloudProviderRegions: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Cloud provider (aws, gcp, azure) */ + provider: "aws" | "gcp" | "azure"; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully returned geographic data for cloud provider regions */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + [key: string]: components["schemas"]["CloudRegionGeoData"]; + }; + }; + }; + /** @description Cloud provider not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Cloud provider 'unknown' not found */ + error?: string; + }; + }; + }; + }; + }; + createDeploymentVersionChannel: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + deploymentId: string; + name: string; + description?: string | null; + versionSelector: { + [key: string]: unknown; + }; + }; + }; + }; + responses: { + /** @description Deployment version channel created successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { id: string; - /** @description The name of the workspace */ + deploymentId: string; name: string; - /** @description The slug of the workspace */ - slug: string; - /** - * @description The email of the Google service account attached to the workspace - * @example ctrlplane@ctrlplane-workspace.iam.gserviceaccount.com - */ - googleServiceAccountEmail?: string | null; - /** - * @description The ARN of the AWS role attached to the workspace - * @example arn:aws:iam::123456789012:role/ctrlplane-workspace-role - */ - awsRoleArn?: string | null; - }; - System: { - /** - * Format: uuid - * @description The system ID - */ + description?: string | null; + /** Format: date-time */ + createdAt: string; + versionSelector?: { + [key: string]: unknown; + }; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Deployment version channel already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; id: string; - /** - * Format: uuid - * @description The workspace ID of the system - */ - workspaceId: string; - /** @description The name of the system */ - name: string; - /** @description The slug of the system */ - slug: string; - /** @description The description of the system */ - description?: string; + }; + }; + }; + /** @description Failed to create deployment version channel */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + updateDeploymentVersion: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The deployment version ID */ + deploymentVersionId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + tag?: string; + deploymentId?: string; + /** Format: date-time */ + createdAt?: string; + name?: string; + config?: { + [key: string]: unknown; + }; + jobAgentConfig?: { + [key: string]: unknown; + }; + /** @enum {string} */ + status?: "ready" | "building" | "failed"; + message?: string; + metadata?: { + [key: string]: string; + }; + }; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeploymentVersion"]; + }; + }; + /** @description Deployment version not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + upsertDeploymentVersion: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + tag: string; + deploymentId: string; + /** Format: date-time */ + createdAt?: string; + name?: string; + config?: { + [key: string]: unknown; + }; + jobAgentConfig?: { + [key: string]: unknown; + }; + /** @enum {string} */ + status?: "ready" | "building" | "failed"; + message?: string; + metadata?: { + [key: string]: string; + }; + }; + }; + }; + responses: { + /** @description OK */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeploymentVersion"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + deleteDeploymentVersionChannel: { + parameters: { + query?: never; + header?: never; + path: { + deploymentId: string; + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Deployment version channel deleted */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message: string; + }; + }; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Deployment version channel not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Failed to delete deployment version channel */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + getDeployment: { + parameters: { + query?: never; + header?: never; + path: { + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Deployment found */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Deployment"]; + }; + }; + /** @description Deployment not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + deleteDeployment: { + parameters: { + query?: never; + header?: never; + path: { + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Deployment deleted */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Deployment"]; + }; + }; + /** @description Deployment not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Failed to delete deployment */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + updateDeployment: { + parameters: { + query?: never; + header?: never; + path: { + deploymentId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + name?: string; + slug?: string; + description?: string; + /** Format: uuid */ + systemId?: string; + /** Format: uuid */ + jobAgentId?: string | null; + jobAgentConfig?: { + [key: string]: unknown; + }; + retryCount?: number; + timeout?: number | null; + resourceSelector?: { + [key: string]: unknown; + } | null; + }; + }; + }; + responses: { + /** @description Deployment updated */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Deployment"]; + }; + }; + /** @description Deployment not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Failed to update deployment */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + deleteReleaseChannel: { + parameters: { + query?: never; + header?: never; + path: { + deploymentId: string; + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Release channel deleted */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message: string; + }; + }; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Release channel not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Failed to delete release channel */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + getResourcesForDeployment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the deployment */ + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + resources?: components["schemas"]["Resource"][]; + count?: number; + }; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + createDeployment: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: { + content: { + "application/json": { + /** + * Format: uuid + * @description The ID of the system to create the deployment for + * @example 123e4567-e89b-12d3-a456-426614174000 + */ + systemId: string; + /** + * @description The name of the deployment + * @example My Deployment + */ + name: string; + /** + * @description The slug of the deployment + * @example my-deployment + */ + slug: string; + /** + * @description The description of the deployment + * @example This is a deployment for my system + */ + description?: string; + /** + * Format: uuid + * @description The ID of the job agent to use for the deployment + * @example 123e4567-e89b-12d3-a456-426614174000 + */ + jobAgentId?: string; + /** + * @description The configuration for the job agent + * @example { + * "key": "value" + * } + */ + jobAgentConfig?: Record; + /** + * @description The number of times to retry the deployment + * @example 3 + */ + retryCount?: number; + /** + * @description The timeout for the deployment + * @example 60 + */ + timeout?: number; + /** + * @description The resource selector for the deployment + * @example { + * "key": "value" + * } + */ + resourceSelector?: { + [key: string]: unknown; + }; + }; + }; + }; + responses: { + /** @description Deployment created */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Deployment"]; + }; + }; + /** @description Deployment already exists */ + 409: { + headers: { + [name: string]: unknown; }; - Deployment: { + content: { + "application/json": { + error: string; /** Format: uuid */ id: string; - name: string; - slug: string; - description: string; - /** Format: uuid */ - systemId: string; - /** Format: uuid */ - jobAgentId?: string | null; - jobAgentConfig: { - [key: string]: unknown; - }; - retryCount?: number; - timeout?: number | null; - }; - /** @description Schema for updating a deployment (all fields optional) */ - UpdateDeployment: { - [key: string]: unknown; - } & (WithRequired & { + }; + }; + }; + /** @description Failed to create deployment */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + getEnvironment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the environment */ + environmentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Environment"]; + }; + }; + /** @description Environment not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Environment not found */ + error: string; + }; + }; + }; + }; + }; + deleteEnvironment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the environment */ + environmentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Environment deleted successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getResourcesForEnvironment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the environment */ + environmentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + resources?: components["schemas"]["Resource"][]; + count?: number; + }; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + createEnvironment: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** + * @description The directory path of the environment + * @default + * @example my/env/path + */ + directory?: string; + systemId: string; + name: string; + description?: string; + resourceSelector?: { [key: string]: unknown; - }); - Release: { - /** Format: uuid */ + }; + policyId?: string; + releaseChannels?: string[]; + deploymentVersionChannels?: string[]; + metadata?: { + [key: string]: string; + }; + }; + }; + }; + responses: { + /** @description Environment created successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Environment"]; + }; + }; + /** @description Environment already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + id?: string; + }; + }; + }; + /** @description Failed to create environment */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + getAgentRunningJobs: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The execution ID */ + agentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Job"][]; + }; + }; + }; + }; + acknowledgeAgentJob: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the job agent */ + agentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully acknowledged job */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + job?: components["schemas"]["Job"]; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Workspace not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + getNextJobs: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The agent ID */ + agentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + jobs?: components["schemas"]["Job"][]; + }; + }; + }; + }; + }; + upsertJobAgent: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + workspaceId: string; + name: string; + type: string; + }; + }; + }; + responses: { + /** @description Successfully retrieved or created the agent */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { id: string; name: string; - version: string; - config: { - [key: string]: unknown; - }; - jobAgentConfig: { - [key: string]: unknown; + workspaceId: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + acknowledgeJob: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The job ID */ + jobId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + sucess: boolean; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + getJob: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The job ID */ + jobId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JobWithTrigger"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Job not found. */ + error?: string; + }; + }; + }; + }; + }; + updateJob: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The execution ID */ + jobId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + status?: components["schemas"]["JobStatus"]; + message?: string | null; + externalId?: string | null; + }; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + id: string; + }; + }; + }; + }; + }; + deletePolicy: { + parameters: { + query?: never; + header?: never; + path: { + policyId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + count?: number; + }; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + updatePolicy: { + parameters: { + query?: never; + header?: never; + path: { + policyId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + name?: string; + description?: string; + priority?: number; + enabled?: boolean; + workspaceId?: string; + targets?: components["schemas"]["PolicyTarget"][]; + denyWindows?: { + timeZone: string; + rrule?: { + [key: string]: unknown; }; - /** Format: uuid */ - deploymentId: string; /** Format: date-time */ - createdAt: string; - metadata?: { - [key: string]: unknown; + dtend?: string; + }[]; + deploymentVersionSelector?: components["schemas"]["DeploymentVersionSelector"]; + versionAnyApprovals?: { + requiredApprovalsCount?: number; + }[]; + versionUserApprovals?: components["schemas"]["VersionUserApproval"][]; + versionRoleApprovals?: { + roleId: string; + requiredApprovalsCount?: number; + }[]; + }; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Policy"]; + }; + }; + /** @description Policy not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + getReleaseTargetsForPolicy: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the policy */ + policyId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + releaseTargets?: components["schemas"]["ReleaseTarget"][]; + count?: number; + }; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + upsertPolicy: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + name: string; + description?: string; + priority?: number; + enabled?: boolean; + workspaceId: string; + targets: components["schemas"]["PolicyTarget"][]; + denyWindows?: { + timeZone: string; + rrule?: { + [key: string]: unknown; }; + /** Format: date-time */ + dtend?: string; + }[]; + deploymentVersionSelector?: components["schemas"]["DeploymentVersionSelector"]; + versionAnyApprovals?: { + requiredApprovalsCount?: number; + }[]; + versionUserApprovals?: components["schemas"]["VersionUserApproval"][]; + versionRoleApprovals?: { + roleId: string; + requiredApprovalsCount?: number; + }[]; + }; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Policy1"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + createJobToResourceRelationship: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** + * Format: uuid + * @description Unique identifier of the job + * @example 123e4567-e89b-12d3-a456-426614174000 + */ + jobId: string; + /** + * @description Unique identifier of the resource + * @example resource-123 + */ + resourceIdentifier: string; + }; + }; + }; + responses: { + /** @description Relationship created successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Relationship created successfully */ + message?: string; + }; + }; + }; + /** @description Invalid request body */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Invalid jobId format */ + error?: string; + }; + }; + }; + /** @description Job or resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Job with specified ID not found */ + error?: string; + }; + }; + }; + /** @description Relationship already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Relationship between job and resource already exists */ + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Internal server error occurred */ + error?: string; + }; + }; + }; + }; + }; + createResourceToResourceRelationship: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** + * Format: uuid + * @description The workspace ID + * @example 123e4567-e89b-12d3-a456-426614174000 + */ + workspaceId: string; + /** + * @description The identifier of the resource to connect + * @example my-resource + */ + fromIdentifier: string; + /** + * @description The identifier of the resource to connect to + * @example my-resource + */ + toIdentifier: string; + /** + * @description The type of relationship + * @example depends_on + */ + type: string; + }; + }; + }; + responses: { + /** @description Relationship created */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Relationship created successfully */ + message?: string; + }; + }; + }; + /** @description Invalid request body */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Relationship already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + createReleaseChannel: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + deploymentId: string; + name: string; + description?: string | null; + releaseSelector: { + [key: string]: unknown; + }; }; - DeploymentVersion: { - /** Format: uuid */ + }; + }; + responses: { + /** @description Release channel created successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { id: string; - name: string; - tag: string; - config: { - [key: string]: unknown; - }; - jobAgentConfig: { - [key: string]: unknown; - }; - /** Format: uuid */ deploymentId: string; - /** Format: date-time */ - createdAt: string; - metadata?: { - [key: string]: string; - }; - /** @enum {string} */ - status?: "building" | "ready" | "failed"; - }; - Policy: { - /** - * Format: uuid - * @description The policy ID - */ - id: string; - /** - * Format: uuid - * @description The system ID - */ - systemId: string; - /** @description The name of the policy */ name: string; - /** @description The description of the policy */ description?: string | null; - /** - * @description The approval requirement of the policy - * @enum {string} - */ - approvalRequirement: "manual" | "automatic"; - /** - * @description If a policy depends on an environment, whether or not the policy requires all, some, or optional successful releases in the environment - * @enum {string} - */ - successType: "some" | "all" | "optional"; - /** @description If a policy depends on an environment, the minimum number of successful releases in the environment */ - successMinimum: number; - /** @description The maximum number of concurrent releases in the environment */ - concurrencyLimit?: number | null; - /** @description The duration of the rollout in milliseconds */ - rolloutDuration: number; - /** @description The minimum interval between releases in milliseconds */ - minimumReleaseInterval: number; - /** - * @description If a new release is created, whether it will wait for the current release to finish before starting, or cancel the current release - * @enum {string} - */ - releaseSequencing: "wait" | "cancel"; - }; - Environment: { - /** Format: uuid */ - id: string; - /** Format: uuid */ - systemId: string; - name: string; - description?: string; - /** Format: uuid */ - policyId?: string | null; - resourceSelector?: { - [key: string]: unknown; - } | null; - /** - * @description The directory path of the environment - * @default - * @example my/env/path - */ - directory: string; /** Format: date-time */ createdAt: string; - metadata?: { - [key: string]: string; - }; - policy?: components["schemas"]["Policy"]; - }; - Runbook: { - /** Format: uuid */ - id: string; - name: string; - /** Format: uuid */ - systemId: string; - /** Format: uuid */ - jobAgentId: string; - }; - Resource: { - /** Format: uuid */ + releaseSelector?: { + [key: string]: unknown; + }; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description Release channel already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; id: string; + }; + }; + }; + /** @description Failed to create release channel */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + getReleaseTargetReleases: { + parameters: { + query?: never; + header?: never; + path: { + releaseTargetId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The latest 100 releases for the release target */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + deployment: components["schemas"]["Deployment"]; + version: components["schemas"]["DeploymentVersion"]; + variables: { + key: string; + value: string; + }[]; + }[]; + }; + }; + /** @description The release target was not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + /** @description An internal server error occurred */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + updateRelease: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The release ID */ + releaseId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + version?: string; + deploymentId?: string; + /** Format: date-time */ + createdAt?: string; + name?: string; + config?: { + [key: string]: unknown; + }; + jobAgentConfig?: { + [key: string]: unknown; + }; + /** @enum {string} */ + status?: "ready" | "building" | "failed"; + message?: string; + metadata?: { + [key: string]: string; + }; + }; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Release"]; + }; + }; + }; + }; + upsertRelease: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + version: string; + deploymentId: string; + /** Format: date-time */ + createdAt?: string; + name?: string; + config?: { + [key: string]: unknown; + }; + jobAgentConfig?: { + [key: string]: unknown; + }; + /** @enum {string} */ + status?: "ready" | "building" | "failed"; + message?: string; + metadata?: { + [key: string]: string; + }; + }; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Release"]; + }; + }; + /** @description Release already exists */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + id?: string; + }; + }; + }; + }; + }; + setResourceProvidersResources: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the scanner */ + providerId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + resources: { + identifier: string; name: string; version: string; kind: string; - identifier: string; config: { - [key: string]: unknown; + [key: string]: unknown; }; metadata: { - [key: string]: unknown; - }; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - /** Format: uuid */ - workspaceId: string; - }; - ResourceWithVariables: components["schemas"]["Resource"] & { - variables?: components["schemas"]["VariableMap"]; - }; - ResourceWithMetadata: components["schemas"]["Resource"] & { - metadata?: components["schemas"]["MetadataMap"]; - }; - ResourceWithVariablesAndMetadata: components["schemas"]["ResourceWithVariables"] & components["schemas"]["ResourceWithMetadata"]; - /** @enum {string} */ - JobStatus: "successful" | "cancelled" | "skipped" | "in_progress" | "action_required" | "pending" | "failure" | "invalid_job_agent" | "invalid_integration" | "external_run_not_found"; - Job: { + [key: string]: string; + }; + }[]; + }; + }; + }; + responses: { + /** @description Successfully updated the deployment resources */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + resources?: { + ignored?: { + identifier?: string; + name?: string; + version?: string; + kind?: string; + workspaceId?: string; + }[]; + inserted?: { + id?: string; + name?: string; + version?: string; + kind?: string; + config?: { + [key: string]: unknown; + }; + }[]; + updated?: { + id?: string; + name?: string; + version?: string; + kind?: string; + config?: { + [key: string]: unknown; + }; + }[]; + deleted?: { + id?: string; + name?: string; + version?: string; + kind?: string; + config?: { + [key: string]: unknown; + }; + }[]; + }; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Deployment resources not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + upsertResourceRelationshipRule: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateResourceRelationshipRule"]; + }; + }; + responses: { + /** @description Resource relationship rule created successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceRelationshipRule"]; + }; + }; + /** @description Failed to create resource relationship rule */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + createResourceSchema: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** + * Format: uuid + * @description The ID of the workspace + */ + workspaceId: string; + /** @description Version of the schema */ + version: string; + /** @description Kind of resource this schema is for */ + kind: string; + /** @description The JSON schema definition */ + jsonSchema: Record; + }; + }; + }; + responses: { + /** @description Resource schema created successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { /** Format: uuid */ - id: string; - status: components["schemas"]["JobStatus"]; - /** @description External job identifier (e.g. GitHub workflow run ID) */ - externalId?: string | null; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string; - /** Format: date-time */ - startedAt?: string | null; - /** Format: date-time */ - completedAt?: string | null; + id?: string; /** Format: uuid */ - jobAgentId?: string; - /** @description Configuration for the Job Agent */ - jobAgentConfig: { - [key: string]: unknown; - }; - message?: string; - reason?: string; - }; - MetadataMap: { - [key: string]: string; - }; - VariableMap: { - [key: string]: (string | boolean | number | Record | unknown[]) | null; - }; - ReferenceVariable: { - key: string; - reference: string; - path: string[]; - defaultValue?: string | number | boolean | Record | unknown[]; - }; - DirectVariable: { - key: string; - value: string | number | boolean | Record | unknown[]; - sensitive?: boolean; - }; - Variable: components["schemas"]["DirectVariable"] | components["schemas"]["ReferenceVariable"]; - PolicyTarget: { - deploymentSelector?: { - [key: string]: unknown; - } | null; - environmentSelector?: { - [key: string]: unknown; - } | null; - resourceSelector?: { - [key: string]: unknown; - } | null; - }; - DenyWindow: { - timeZone: string; - rrule: { - [key: string]: unknown; - }; - /** Format: date-time */ - dtend?: string; - }; - DeploymentVersionSelector: { - name: string; - deploymentVersionSelector: { - [key: string]: unknown; - }; - description?: string; - }; - VersionAnyApproval: { - requiredApprovalsCount: number; - }; - VersionUserApproval: { - userId: string; - }; - VersionRoleApproval: { - roleId: string; - requiredApprovalsCount: number; - }; - Policy1: { + workspaceId?: string; + version?: string; + kind?: string; + jsonSchema?: Record; + }; + }; + }; + /** @description Invalid request body */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Schema already exists for this version and kind */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; /** Format: uuid */ - id: string; - name: string; - description?: string; - priority: number; - /** Format: date-time */ - createdAt: string; - enabled: boolean; + id?: string; + }; + }; + }; + }; + }; + deleteResourceSchema: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the schema to delete */ + schemaId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Schema deleted successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { /** Format: uuid */ - workspaceId: string; - targets: components["schemas"]["PolicyTarget"][]; - denyWindows: components["schemas"]["DenyWindow"][]; - deploymentVersionSelector?: components["schemas"]["DeploymentVersionSelector"]; - versionAnyApprovals?: components["schemas"]["VersionAnyApproval"][]; - versionUserApprovals: components["schemas"]["VersionUserApproval"][]; - versionRoleApprovals: components["schemas"]["VersionRoleApproval"][]; - }; - /** @enum {string} */ - ResourceRelationshipRuleDependencyType: "depends_on" | "depends_indirectly_on" | "uses_at_runtime" | "created_after" | "provisioned_in" | "inherits_from"; - ResourceRelationshipRule: { + id?: string; + }; + }; + }; + /** @description Schema not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Schema not found */ + error?: string; + }; + }; + }; + }; + }; + getResource: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The resource ID */ + resourceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceWithVariablesAndMetadata"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Resource not found */ + error: string; + }; + }; + }; + }; + }; + deleteResource: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The resource ID */ + resourceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Resource deleted successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + success: boolean; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + updateResource: { + parameters: { + query?: never; + header?: never; + path: { + resourceId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + name?: string; + version?: string; + kind?: string; + identifier?: string; + workspaceId?: string; + metadata?: components["schemas"]["MetadataMap"]; + variables?: components["schemas"]["DirectVariable"][]; + }; + }; + }; + responses: { + /** @description Resource updated successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceWithVariablesAndMetadata"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: string; + }; + }; + }; + }; + }; + getReleaseTargets: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The resource ID */ + resourceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReleaseTarget"][]; + }; + }; + }; + }; + upsertResource: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** Format: uuid */ + workspaceId: string; + name: string; + kind: string; + identifier: string; + version: string; + config: Record; + metadata?: { + [key: string]: string; + }; + variables?: components["schemas"]["Variable"][]; + }; + }; + }; + responses: { + /** @description The created or updated resource */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Resource"]; + }; + }; + }; + }; + deleteEnvironmentByName: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the system */ + systemId: string; + /** @description Name of the environment */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Environment deleted successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getSystem: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the system */ + systemId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description System retrieved successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["System"] & { + environments?: components["schemas"]["Environment"][]; + deployments?: components["schemas"]["Deployment"][]; + }; + }; + }; + }; + }; + deleteSystem: { + parameters: { + query?: never; + header?: never; + path: { + systemId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description System deleted successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example System deleted */ + message?: string; + }; + }; + }; + /** @description System not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example System not found */ + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Internal server error */ + error?: string; + }; + }; + }; + }; + }; + updateSystem: { + parameters: { + query?: never; + header?: never; + path: { + /** @description UUID of the system */ + systemId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** @description Name of the system */ + name?: string; + /** @description Slug of the system */ + slug?: string; + /** @description Description of the system */ + description?: string; + /** + * Format: uuid + * @description UUID of the workspace + */ + workspaceId?: string; + }; + }; + }; + responses: { + /** @description System updated successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["System"]; + }; + }; + /** @description System not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example System not found */ + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Internal server error */ + error?: string; + }; + }; + }; + }; + }; + createSystem: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: { + content: { + "application/json": { + /** + * Format: uuid + * @description The workspace ID of the system + */ + workspaceId: string; + /** @description The name of the system */ + name: string; + /** @description The slug of the system */ + slug: string; + /** @description The description of the system */ + description?: string; + }; + }; + }; + responses: { + /** @description System created successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["System"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: { + /** @enum {string} */ + code: "invalid_type" | "invalid_literal" | "custom"; + message: string; + path: (string | number)[]; + }[]; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Internal Server Error */ + error?: string; + }; + }; + }; + }; + }; + listDeployments: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description All deployments */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + data?: components["schemas"]["Deployment"][]; + }; + }; + }; + }; + }; + listEnvironments: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description All environments */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + data?: components["schemas"]["Environment"][]; + }; + }; + }; + }; + }; + getWorkspace: { + parameters: { + query?: never; + header?: never; + path: { + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Workspace found */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Workspace"]; + }; + }; + /** @description Workspace not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; + deletePolicyByName: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Name of the policy */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully deleted the policy */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example true */ + success?: boolean; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Policy not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Policy not found */ + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + upsertResourceProvider: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Name of the workspace */ + workspaceId: string; + /** @description Name of the resource provider */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully retrieved or created the resource provider */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { id: string; - workspaceId: string; name: string; - reference: string; - dependencyType: components["schemas"]["ResourceRelationshipRuleDependencyType"]; - dependencyDescription?: string; - description?: string; - sourceKind: string; - sourceVersion: string; - targetKind: string; - targetVersion: string; - }; - CreateResourceRelationshipRule: { workspaceId: string; - name: string; - reference: string; - dependencyType: components["schemas"]["ResourceRelationshipRuleDependencyType"]; - dependencyDescription?: string; - description?: string; - sourceKind: string; - sourceVersion: string; - targetKind: string; - targetVersion: string; - metadataKeysMatch: string[]; - }; - ReleaseTarget: { - /** Format: uuid */ - id: string; - resource: components["schemas"]["Resource"]; - environment: components["schemas"]["Environment"]; - deployment: components["schemas"]["Deployment"]; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} -export type $defs = Record; -export interface operations { - getCloudProviderRegions: { - parameters: { - query?: never; - header?: never; - path: { - /** @description Cloud provider (aws, gcp, azure) */ - provider: "aws" | "gcp" | "azure"; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully returned geographic data for cloud provider regions */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - [key: string]: components["schemas"]["CloudRegionGeoData"]; - }; - }; - }; - /** @description Cloud provider not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Cloud provider 'unknown' not found */ - error?: string; - }; - }; - }; - }; - }; - createDeploymentVersionChannel: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - deploymentId: string; - name: string; - description?: string | null; - versionSelector: { - [key: string]: unknown; - }; - }; - }; - }; - responses: { - /** @description Deployment version channel created successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - id: string; - deploymentId: string; - name: string; - description?: string | null; - /** Format: date-time */ - createdAt: string; - versionSelector?: { - [key: string]: unknown; - }; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Forbidden */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Deployment version channel already exists */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - id: string; - }; - }; - }; - /** @description Failed to create deployment version channel */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - updateDeploymentVersion: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The deployment version ID */ - deploymentVersionId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - tag?: string; - deploymentId?: string; - /** Format: date-time */ - createdAt?: string; - name?: string; - config?: { - [key: string]: unknown; - }; - jobAgentConfig?: { - [key: string]: unknown; - }; - /** @enum {string} */ - status?: "ready" | "building" | "failed"; - message?: string; - metadata?: { - [key: string]: string; - }; - }; - }; - }; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeploymentVersion"]; - }; - }; - /** @description Deployment version not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - upsertDeploymentVersion: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - tag: string; - deploymentId: string; - /** Format: date-time */ - createdAt?: string; - name?: string; - config?: { - [key: string]: unknown; - }; - jobAgentConfig?: { - [key: string]: unknown; - }; - /** @enum {string} */ - status?: "ready" | "building" | "failed"; - message?: string; - metadata?: { - [key: string]: string; - }; - }; - }; - }; - responses: { - /** @description OK */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeploymentVersion"]; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - deleteDeploymentVersionChannel: { - parameters: { - query?: never; - header?: never; - path: { - deploymentId: string; - name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Deployment version channel deleted */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - message: string; - }; - }; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Deployment version channel not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Failed to delete deployment version channel */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - getDeployment: { - parameters: { - query?: never; - header?: never; - path: { - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Deployment found */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Deployment"]; - }; - }; - /** @description Deployment not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - deleteDeployment: { - parameters: { - query?: never; - header?: never; - path: { - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Deployment deleted */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Deployment"]; - }; - }; - /** @description Deployment not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Failed to delete deployment */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - updateDeployment: { - parameters: { - query?: never; - header?: never; - path: { - deploymentId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name?: string; - slug?: string; - description?: string; - /** Format: uuid */ - systemId?: string; - /** Format: uuid */ - jobAgentId?: string | null; - jobAgentConfig?: { - [key: string]: unknown; - }; - retryCount?: number; - timeout?: number | null; - resourceSelector?: { - [key: string]: unknown; - } | null; - }; - }; - }; - responses: { - /** @description Deployment updated */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Deployment"]; - }; - }; - /** @description Deployment not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Failed to update deployment */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - deleteReleaseChannel: { - parameters: { - query?: never; - header?: never; - path: { - deploymentId: string; - name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Release channel deleted */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - message: string; - }; - }; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Release channel not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Failed to delete release channel */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - getResourcesForDeployment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - resources?: components["schemas"]["Resource"][]; - count?: number; - }; - }; - }; - /** @description Internal Server Error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - createDeployment: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: { - content: { - "application/json": { - /** - * Format: uuid - * @description The ID of the system to create the deployment for - * @example 123e4567-e89b-12d3-a456-426614174000 - */ - systemId: string; - /** - * @description The name of the deployment - * @example My Deployment - */ - name: string; - /** - * @description The slug of the deployment - * @example my-deployment - */ - slug: string; - /** - * @description The description of the deployment - * @example This is a deployment for my system - */ - description?: string; - /** - * Format: uuid - * @description The ID of the job agent to use for the deployment - * @example 123e4567-e89b-12d3-a456-426614174000 - */ - jobAgentId?: string; - /** - * @description The configuration for the job agent - * @example { - * "key": "value" - * } - */ - jobAgentConfig?: Record; - /** - * @description The number of times to retry the deployment - * @example 3 - */ - retryCount?: number; - /** - * @description The timeout for the deployment - * @example 60 - */ - timeout?: number; - /** - * @description The resource selector for the deployment - * @example { - * "key": "value" - * } - */ - resourceSelector?: { - [key: string]: unknown; - }; - }; - }; - }; - responses: { - /** @description Deployment created */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Deployment"]; - }; - }; - /** @description Deployment already exists */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - /** Format: uuid */ - id: string; - }; - }; - }; - /** @description Failed to create deployment */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - getEnvironment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the environment */ - environmentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successful response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Environment"]; - }; - }; - /** @description Environment not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Environment not found */ - error: string; - }; - }; - }; - }; - }; - deleteEnvironment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the environment */ - environmentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Environment deleted successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - getResourcesForEnvironment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the environment */ - environmentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - resources?: components["schemas"]["Resource"][]; - count?: number; - }; - }; - }; - /** @description Internal Server Error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - createEnvironment: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** - * @description The directory path of the environment - * @default - * @example my/env/path - */ - directory?: string; - systemId: string; - name: string; - description?: string; - resourceSelector?: { - [key: string]: unknown; - }; - policyId?: string; - releaseChannels?: string[]; - deploymentVersionChannels?: string[]; - metadata?: { - [key: string]: string; - }; - }; - }; - }; - responses: { - /** @description Environment created successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Environment"]; - }; - }; - /** @description Environment already exists */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - id?: string; - }; - }; - }; - /** @description Failed to create environment */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - getAgentRunningJobs: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The execution ID */ - agentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Job"][]; - }; - }; - }; - }; - acknowledgeAgentJob: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the job agent */ - agentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully acknowledged job */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - job?: components["schemas"]["Job"]; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Workspace not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - getNextJobs: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The agent ID */ - agentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - jobs?: components["schemas"]["Job"][]; - }; - }; - }; - }; - }; - upsertJobAgent: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - workspaceId: string; - name: string; - type: string; - }; - }; - }; - responses: { - /** @description Successfully retrieved or created the agent */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - id: string; - name: string; - workspaceId: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - acknowledgeJob: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The job ID */ - jobId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - sucess: boolean; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - getJob: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The job ID */ - jobId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["JobWithTrigger"]; - }; - }; - /** @description Not Found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Job not found. */ - error?: string; - }; - }; - }; - }; - }; - updateJob: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The execution ID */ - jobId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - status?: components["schemas"]["JobStatus"]; - message?: string | null; - externalId?: string | null; - }; - }; - }; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - id: string; - }; - }; - }; - }; - }; - deletePolicy: { - parameters: { - query?: never; - header?: never; - path: { - policyId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - count?: number; - }; - }; - }; - /** @description Internal Server Error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - updatePolicy: { - parameters: { - query?: never; - header?: never; - path: { - policyId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name?: string; - description?: string; - priority?: number; - enabled?: boolean; - workspaceId?: string; - targets?: components["schemas"]["PolicyTarget"][]; - denyWindows?: { - timeZone: string; - rrule?: { - [key: string]: unknown; - }; - /** Format: date-time */ - dtend?: string; - }[]; - deploymentVersionSelector?: components["schemas"]["DeploymentVersionSelector"]; - versionAnyApprovals?: { - requiredApprovalsCount?: number; - }[]; - versionUserApprovals?: components["schemas"]["VersionUserApproval"][]; - versionRoleApprovals?: { - roleId: string; - requiredApprovalsCount?: number; - }[]; - }; - }; - }; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Policy"]; - }; - }; - /** @description Policy not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Internal Server Error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - getReleaseTargetsForPolicy: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the policy */ - policyId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - releaseTargets?: components["schemas"]["ReleaseTarget"][]; - count?: number; - }; - }; - }; - /** @description Internal Server Error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - upsertPolicy: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name: string; - description?: string; - priority?: number; - enabled?: boolean; - workspaceId: string; - targets: components["schemas"]["PolicyTarget"][]; - denyWindows?: { - timeZone: string; - rrule?: { - [key: string]: unknown; - }; - /** Format: date-time */ - dtend?: string; - }[]; - deploymentVersionSelector?: components["schemas"]["DeploymentVersionSelector"]; - versionAnyApprovals?: { - requiredApprovalsCount?: number; - }[]; - versionUserApprovals?: components["schemas"]["VersionUserApproval"][]; - versionRoleApprovals?: { - roleId: string; - requiredApprovalsCount?: number; - }[]; - }; - }; - }; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Policy1"]; - }; - }; - /** @description Internal Server Error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - createJobToResourceRelationship: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** - * Format: uuid - * @description Unique identifier of the job - * @example 123e4567-e89b-12d3-a456-426614174000 - */ - jobId: string; - /** - * @description Unique identifier of the resource - * @example resource-123 - */ - resourceIdentifier: string; - }; - }; - }; - responses: { - /** @description Relationship created successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Relationship created successfully */ - message?: string; - }; - }; - }; - /** @description Invalid request body */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Invalid jobId format */ - error?: string; - }; - }; - }; - /** @description Job or resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Job with specified ID not found */ - error?: string; - }; - }; - }; - /** @description Relationship already exists */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Relationship between job and resource already exists */ - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Internal server error occurred */ - error?: string; - }; - }; - }; - }; - }; - createResourceToResourceRelationship: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** - * Format: uuid - * @description The workspace ID - * @example 123e4567-e89b-12d3-a456-426614174000 - */ - workspaceId: string; - /** - * @description The identifier of the resource to connect - * @example my-resource - */ - fromIdentifier: string; - /** - * @description The identifier of the resource to connect to - * @example my-resource - */ - toIdentifier: string; - /** - * @description The type of relationship - * @example depends_on - */ - type: string; - }; - }; - }; - responses: { - /** @description Relationship created */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Relationship created successfully */ - message?: string; - }; - }; - }; - /** @description Invalid request body */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Relationship already exists */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - createReleaseChannel: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - deploymentId: string; - name: string; - description?: string | null; - releaseSelector: { - [key: string]: unknown; - }; - }; - }; - }; - responses: { - /** @description Release channel created successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - id: string; - deploymentId: string; - name: string; - description?: string | null; - /** Format: date-time */ - createdAt: string; - releaseSelector?: { - [key: string]: unknown; - }; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Forbidden */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - /** @description Release channel already exists */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - id: string; - }; - }; - }; - /** @description Failed to create release channel */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - updateRelease: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The release ID */ - releaseId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - version?: string; - deploymentId?: string; - /** Format: date-time */ - createdAt?: string; - name?: string; - config?: { - [key: string]: unknown; - }; - jobAgentConfig?: { - [key: string]: unknown; - }; - /** @enum {string} */ - status?: "ready" | "building" | "failed"; - message?: string; - metadata?: { - [key: string]: string; - }; - }; - }; - }; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Release"]; - }; - }; - }; - }; - upsertRelease: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - version: string; - deploymentId: string; - /** Format: date-time */ - createdAt?: string; - name?: string; - config?: { - [key: string]: unknown; - }; - jobAgentConfig?: { - [key: string]: unknown; - }; - /** @enum {string} */ - status?: "ready" | "building" | "failed"; - message?: string; - metadata?: { - [key: string]: string; - }; - }; - }; - }; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Release"]; - }; - }; - /** @description Release already exists */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - id?: string; - }; - }; - }; - }; - }; - setResourceProvidersResources: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the scanner */ - providerId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - resources: { - identifier: string; - name: string; - version: string; - kind: string; - config: { - [key: string]: unknown; - }; - metadata: { - [key: string]: string; - }; - }[]; - }; - }; - }; - responses: { - /** @description Successfully updated the deployment resources */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - resources?: { - ignored?: { - identifier?: string; - name?: string; - version?: string; - kind?: string; - workspaceId?: string; - }[]; - inserted?: { - id?: string; - name?: string; - version?: string; - kind?: string; - config?: { - [key: string]: unknown; - }; - }[]; - updated?: { - id?: string; - name?: string; - version?: string; - kind?: string; - config?: { - [key: string]: unknown; - }; - }[]; - deleted?: { - id?: string; - name?: string; - version?: string; - kind?: string; - config?: { - [key: string]: unknown; - }; - }[]; - }; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Deployment resources not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - upsertResourceRelationshipRule: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["CreateResourceRelationshipRule"]; - }; - }; - responses: { - /** @description Resource relationship rule created successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ResourceRelationshipRule"]; - }; - }; - /** @description Failed to create resource relationship rule */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - createResourceSchema: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** - * Format: uuid - * @description The ID of the workspace - */ - workspaceId: string; - /** @description Version of the schema */ - version: string; - /** @description Kind of resource this schema is for */ - kind: string; - /** @description The JSON schema definition */ - jsonSchema: Record; - }; - }; - }; - responses: { - /** @description Resource schema created successfully */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** Format: uuid */ - id?: string; - /** Format: uuid */ - workspaceId?: string; - version?: string; - kind?: string; - jsonSchema?: Record; - }; - }; - }; - /** @description Invalid request body */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Schema already exists for this version and kind */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - /** Format: uuid */ - id?: string; - }; - }; - }; - }; - }; - deleteResourceSchema: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the schema to delete */ - schemaId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Schema deleted successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** Format: uuid */ - id?: string; - }; - }; - }; - /** @description Schema not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Schema not found */ - error?: string; - }; - }; - }; - }; - }; - getResource: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The resource ID */ - resourceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ResourceWithVariablesAndMetadata"]; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Resource not found */ - error: string; - }; - }; - }; - }; - }; - deleteResource: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The resource ID */ - resourceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Resource deleted successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - success: boolean; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - updateResource: { - parameters: { - query?: never; - header?: never; - path: { - resourceId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - name?: string; - version?: string; - kind?: string; - identifier?: string; - workspaceId?: string; - metadata?: components["schemas"]["MetadataMap"]; - variables?: components["schemas"]["DirectVariable"][]; - }; - }; - }; - responses: { - /** @description Resource updated successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ResourceWithVariablesAndMetadata"]; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error: string; - }; - }; - }; - }; - }; - getReleaseTargets: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The resource ID */ - resourceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ReleaseTarget"][]; - }; - }; - }; - }; - upsertResource: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** Format: uuid */ - workspaceId: string; - name: string; - kind: string; - identifier: string; - version: string; - config: Record; - metadata?: { - [key: string]: string; - }; - variables?: components["schemas"]["Variable"][]; - }; - }; - }; - responses: { - /** @description The created or updated resource */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Resource"]; - }; - }; - }; - }; - deleteEnvironmentByName: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the system */ - systemId: string; - /** @description Name of the environment */ - name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Environment deleted successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - getSystem: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the system */ - systemId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description System retrieved successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["System"] & { - environments?: components["schemas"]["Environment"][]; - deployments?: components["schemas"]["Deployment"][]; - }; - }; - }; - }; - }; - deleteSystem: { - parameters: { - query?: never; - header?: never; - path: { - systemId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description System deleted successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example System deleted */ - message?: string; - }; - }; - }; - /** @description System not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example System not found */ - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Internal server error */ - error?: string; - }; - }; - }; - }; - }; - updateSystem: { - parameters: { - query?: never; - header?: never; - path: { - /** @description UUID of the system */ - systemId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** @description Name of the system */ - name?: string; - /** @description Slug of the system */ - slug?: string; - /** @description Description of the system */ - description?: string; - /** - * Format: uuid - * @description UUID of the workspace - */ - workspaceId?: string; - }; - }; - }; - responses: { - /** @description System updated successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["System"]; - }; - }; - /** @description System not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example System not found */ - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Internal server error */ - error?: string; - }; - }; - }; - }; - }; - createSystem: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: { - content: { - "application/json": { - /** - * Format: uuid - * @description The workspace ID of the system - */ - workspaceId: string; - /** @description The name of the system */ - name: string; - /** @description The slug of the system */ - slug: string; - /** @description The description of the system */ - description?: string; - }; - }; - }; - responses: { - /** @description System created successfully */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["System"]; - }; - }; - /** @description Bad request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: { - /** @enum {string} */ - code: "invalid_type" | "invalid_literal" | "custom"; - message: string; - path: (string | number)[]; - }[]; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Internal Server Error */ - error?: string; - }; - }; - }; - }; - }; - listDeployments: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description All deployments */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - data?: components["schemas"]["Deployment"][]; - }; - }; - }; - }; - }; - listEnvironments: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description All environments */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - data?: components["schemas"]["Environment"][]; - }; - }; - }; - }; - }; - getWorkspace: { - parameters: { - query?: never; - header?: never; - path: { - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Workspace found */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Workspace"]; - }; - }; - /** @description Workspace not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; - deletePolicyByName: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Name of the policy */ - name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully deleted the policy */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example true */ - success?: boolean; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Policy not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Policy not found */ - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - upsertResourceProvider: { - parameters: { - query?: never; - header?: never; - path: { - /** @description Name of the workspace */ - workspaceId: string; - /** @description Name of the resource provider */ - name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully retrieved or created the resource provider */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - id: string; - name: string; - workspaceId: string; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Workspace not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - getResourceByIdentifier: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - identifier: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully retrieved the resource */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ResourceWithVariablesAndMetadata"] & { - relationships?: { - [key: string]: { - ruleId: string; - type: string; - reference: string; - target: components["schemas"]["Resource"]; - }; - }; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Resource not found */ - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - deleteResourceByIdentifier: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - identifier: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully deleted the resource */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example true */ - success?: boolean; - }; - }; - }; - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Permission denied */ - 403: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @example Resource not found */ - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; - getGroupedCounts: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - metadataKeys: string[]; - allowNullCombinations: boolean; - }; - }; - }; - responses: { - /** @description Success */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - keys: string[]; - combinations: { - metadata: { - [key: string]: string; - }; - resources: number; - }[]; - }; - }; - }; - }; - }; - listResources: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description All resources */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - resources?: components["schemas"]["Resource"][]; - }; - }; - }; - }; - }; - listSystems: { - parameters: { - query?: never; - header?: never; - path: { - /** @description The ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description All systems */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - data?: components["schemas"]["System"][]; - }; - }; - }; - }; - }; - getWorkspaceBySlug: { - parameters: { - query?: never; - header?: never; - path: { - workspaceSlug: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Workspace found */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Workspace"]; - }; - }; - /** @description Workspace not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - error?: string; - }; - }; - }; - }; - }; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Workspace not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getResourceByIdentifier: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + identifier: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully retrieved the resource */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceWithVariablesAndMetadata"] & { + relationships?: { + [key: string]: { + ruleId: string; + type: string; + reference: string; + target: components["schemas"]["Resource"]; + }; + }; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Resource not found */ + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + deleteResourceByIdentifier: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + identifier: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully deleted the resource */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example true */ + success?: boolean; + }; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Permission denied */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example Resource not found */ + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getGroupedCounts: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + metadataKeys: string[]; + allowNullCombinations: boolean; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + keys: string[]; + combinations: { + metadata: { + [key: string]: string; + }; + resources: number; + }[]; + }; + }; + }; + }; + }; + listResources: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description All resources */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + resources?: components["schemas"]["Resource"][]; + }; + }; + }; + }; + }; + listSystems: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description All systems */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + data?: components["schemas"]["System"][]; + }; + }; + }; + }; + }; + getWorkspaceBySlug: { + parameters: { + query?: never; + header?: never; + path: { + workspaceSlug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Workspace found */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Workspace"]; + }; + }; + /** @description Workspace not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; + }; + }; + }; + }; } type WithRequired = T & { - [P in K]-?: T[P]; + [P in K]-?: T[P]; }; diff --git a/e2e/api/yaml-loader.ts b/e2e/api/yaml-loader.ts index 63df1e624..c78df4a78 100644 --- a/e2e/api/yaml-loader.ts +++ b/e2e/api/yaml-loader.ts @@ -32,6 +32,14 @@ export interface TestYamlFile { slug: string; description?: string; resourceSelector?: any; + versions?: Array<{ + tag: string; + name?: string; + config?: Record; + metadata?: Record; + status?: "building" | "ready" | "failed"; + message?: string; + }>; }>; policies?: Array<{ name: string; @@ -76,6 +84,12 @@ export interface ImportedEntities { name: string; slug: string; originalName?: string; + versions?: Array<{ + id: string; + name: string; + tag: string; + status: "building" | "ready" | "failed"; + }>; }>; policies: Array<{ id: string; @@ -214,11 +228,44 @@ export async function importEntitiesFromYaml( ); } + const versions: Array<{ + id: string; + name: string; + tag: string; + status: "building" | "ready" | "failed"; + }> = []; + + if (deployment.versions && deployment.versions.length > 0) { + for (const version of deployment.versions) { + const versionResponse = await api.POST("/v1/deployment-versions", { + body: { + ...version, + deploymentId: deploymentResponse.data!.id, + }, + }); + + if (versionResponse.response.status !== 201) { + throw new Error( + `Failed to create deployment version: ${JSON.stringify(versionResponse.error)}`, + ); + } + + const versionData = versionResponse.data!; + versions.push({ + id: versionData.id, + name: versionData.name, + tag: versionData.tag, + status: versionData.status ?? "ready", + }); + } + } + result.deployments.push({ id: deploymentResponse.data!.id, name: deploymentResponse.data!.name, slug: deploymentResponse.data!.slug, originalName: deployment.name, + versions, }); } } diff --git a/e2e/tests/api/release.spec.ts b/e2e/tests/api/release.spec.ts new file mode 100644 index 000000000..2638039ae --- /dev/null +++ b/e2e/tests/api/release.spec.ts @@ -0,0 +1,270 @@ +import path from "path"; +import { faker } from "@faker-js/faker"; +import { expect } from "@playwright/test"; + +import { + cleanupImportedEntities, + ImportedEntities, + importEntitiesFromYaml, +} from "../../api"; +import { test } from "../fixtures"; + +const yamlPath = path.join(__dirname, "release.spec.yaml"); + +test.describe("Release Creation", () => { + let importedEntities: ImportedEntities; + + test.beforeAll(async ({ api, workspace }) => { + importedEntities = await importEntitiesFromYaml( + api, + workspace.id, + yamlPath, + ); + await new Promise((resolve) => setTimeout(resolve, 5_000)); + }); + + test.afterAll(async ({ api, workspace }) => { + await cleanupImportedEntities(api, importedEntities, workspace.id); + }); + + test("should create a release when a new version is created", async ({ + api, + page, + workspace, + }) => { + const importedResource = importedEntities.resources.at(0)!; + const resourceResponse = await api.GET( + "/v1/workspaces/{workspaceId}/resources/identifier/{identifier}", + { + params: { + path: { + workspaceId: workspace.id, + identifier: importedResource.identifier, + }, + }, + }, + ); + expect(resourceResponse.response.status).toBe(200); + const resource = resourceResponse.data; + expect(resource).toBeDefined(); + const resourceId = resource?.id ?? ""; + + const releaseTargetResponse = await api.GET( + "/v1/resources/{resourceId}/release-targets", + { + params: { + path: { + resourceId, + }, + }, + }, + ); + expect(releaseTargetResponse.response.status).toBe(200); + const releaseTargets = releaseTargetResponse.data ?? []; + expect(releaseTargets.length).toBe(1); + const releaseTarget = releaseTargets[0]!; + + const importedDeployment = importedEntities.deployments[0]!; + const importedEnvironment = importedEntities.environments[0]!; + + expect(releaseTarget.resource.id).toBe(resourceId); + expect(releaseTarget.environment.id).toBe(importedEnvironment.id); + expect(releaseTarget.deployment.id).toBe(importedDeployment.id); + + const versionTag = faker.string.alphanumeric(10); + + const versionResponse = await api.POST("/v1/deployment-versions", { + body: { + deploymentId: importedDeployment.id, + tag: versionTag, + }, + }); + expect(versionResponse.response.status).toBe(201); + + await page.waitForTimeout(10_000); + + const releaseResponse = await api.GET( + "/v1/release-targets/{releaseTargetId}/releases", + { + params: { + path: { + releaseTargetId: releaseTarget.id, + }, + }, + }, + ); + + expect(releaseResponse.response.status).toBe(200); + const releases = releaseResponse.data ?? []; + const matchedRelease = releases.find( + (release) => release.version.tag === versionTag, + ); + expect(matchedRelease).toBeDefined(); + }); + + test("should create a release when a new resource is created", async ({ + api, + workspace, + }) => { + const systemPrefix = importedEntities.system.slug.split("-")[0]!; + const resourceName = `${systemPrefix}-resource-2`; + const resourceResponse = await api.POST("/v1/resources", { + body: { + name: resourceName, + kind: "service", + identifier: resourceName, + version: "1.0.0", + config: {}, + metadata: {}, + variables: [], + workspaceId: workspace.id, + }, + }); + expect(resourceResponse.response.status).toBe(200); + const resource = resourceResponse.data; + expect(resource).toBeDefined(); + const resourceId = resource?.id ?? ""; + + await new Promise((resolve) => setTimeout(resolve, 10_000)); + + const releaseTargetResponse = await api.GET( + "/v1/resources/{resourceId}/release-targets", + { + params: { + path: { + resourceId, + }, + }, + }, + ); + expect(releaseTargetResponse.response.status).toBe(200); + const releaseTargets = releaseTargetResponse.data ?? []; + expect(releaseTargets.length).toBe(1); + const releaseTarget = releaseTargets[0]!; + + expect(releaseTarget.resource.id).toBe(resourceId); + + const releaseResponse = await api.GET( + "/v1/release-targets/{releaseTargetId}/releases", + { + params: { + path: { + releaseTargetId: releaseTarget.id, + }, + }, + }, + ); + expect(releaseResponse.response.status).toBe(200); + const releases = releaseResponse.data ?? []; + console.log(releases); + const versionTag = importedEntities.deployments.at(0)!.versions!.at(0)!.tag; + const matchedRelease = releases.find( + (release) => release.version.tag === versionTag, + ); + expect(matchedRelease).toBeDefined(); + }); + + test("should not create a release when an existing resource is updated", async ({ + api, + workspace, + }) => { + const systemPrefix = importedEntities.system.slug.split("-")[0]!; + const resourceName = `${systemPrefix}-resource-2`; + const resourceResponse = await api.POST("/v1/resources", { + body: { + name: resourceName, + kind: "service", + identifier: resourceName, + version: "1.0.0", + config: {}, + metadata: {}, + variables: [], + workspaceId: workspace.id, + }, + }); + expect(resourceResponse.response.status).toBe(200); + const resource = resourceResponse.data; + expect(resource).toBeDefined(); + const resourceId = resource?.id ?? ""; + + await new Promise((resolve) => setTimeout(resolve, 5_000)); + + const releaseTargetResponse = await api.GET( + "/v1/resources/{resourceId}/release-targets", + { + params: { + path: { + resourceId, + }, + }, + }, + ); + expect(releaseTargetResponse.response.status).toBe(200); + const releaseTargets = releaseTargetResponse.data ?? []; + expect(releaseTargets.length).toBe(1); + const releaseTarget = releaseTargets[0]!; + + expect(releaseTarget.resource.id).toBe(resourceId); + + const releaseResponse = await api.GET( + "/v1/release-targets/{releaseTargetId}/releases", + { + params: { + path: { + releaseTargetId: releaseTarget.id, + }, + }, + }, + ); + expect(releaseResponse.response.status).toBe(200); + const releases = releaseResponse.data ?? []; + console.log(releases); + const versionTag = importedEntities.deployments.at(0)!.versions!.at(0)!.tag; + const matchedRelease = releases.find( + (release) => release.version.tag === versionTag, + ); + expect(matchedRelease).toBeDefined(); + + const updatedResourceResponse = await api.PATCH( + "/v1/resources/{resourceId}", + { + params: { + path: { + resourceId, + }, + }, + body: { + version: "1.0.1", + }, + }, + ); + expect(updatedResourceResponse.response.status).toBe(200); + + const releaseTargetResponseAfterUpdate = await api.GET( + "/v1/resources/{resourceId}/release-targets", + { + params: { path: { resourceId } }, + }, + ); + expect(releaseTargetResponseAfterUpdate.response.status).toBe(200); + const releaseTargetsAfterUpdate = + releaseTargetResponseAfterUpdate.data ?? []; + expect(releaseTargetsAfterUpdate.length).toBe(1); + const releaseTargetAfterUpdate = releaseTargetsAfterUpdate[0]!; + expect(releaseTargetAfterUpdate.resource.id).toBe(resourceId); + + const releaseResponseAfterUpdate = await api.GET( + "/v1/release-targets/{releaseTargetId}/releases", + { + params: { path: { releaseTargetId: releaseTargetAfterUpdate.id } }, + }, + ); + expect(releaseResponseAfterUpdate.response.status).toBe(200); + const releasesAfterUpdate = releaseResponseAfterUpdate.data ?? []; + expect(releasesAfterUpdate.length).toBe(1); + const matchedReleaseAfterUpdate = releasesAfterUpdate.find( + (release) => release.version.tag === versionTag, + ); + expect(matchedReleaseAfterUpdate).toBeDefined(); + }); +}); diff --git a/e2e/tests/api/release.spec.yaml b/e2e/tests/api/release.spec.yaml new file mode 100644 index 000000000..88997ac9e --- /dev/null +++ b/e2e/tests/api/release.spec.yaml @@ -0,0 +1,31 @@ +system: + name: "{{ prefix }}-releases" + slug: "{{ prefix }}-releases" + description: System for testing releases + +resources: + - name: "{{ prefix }}-resource" + kind: service + identifier: "{{ prefix }}-resource" + version: 1.0.0 + config: + enabled: true + metadata: + env: qa + +environments: + - name: "{{ prefix }}-environment" + slug: "{{ prefix }}-environment" + description: Environment for testing releases + systemId: "{{ prefix }}-releases" + resourceSelector: + type: identifier + operator: "contains" + value: "{{ prefix }}" + +deployments: + - name: "{{ prefix }}-deployment" + slug: "{{ prefix }}-deployment" + description: Deployment for testing releases + versions: + - tag: "1.0.0" diff --git a/openapi.v1.json b/openapi.v1.json index c38eb7014..51e6c8c00 100644 --- a/openapi.v1.json +++ b/openapi.v1.json @@ -2393,6 +2393,105 @@ ] } }, + "/v1/release-targets/{releaseTargetId}/releases": { + "get": { + "summary": "Get the latest 100 releases for a release target", + "operationId": "getReleaseTargetReleases", + "parameters": [ + { + "name": "releaseTargetId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "The latest 100 releases for the release target", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "deployment": { + "$ref": "#/components/schemas/Deployment" + }, + "version": { + "$ref": "#/components/schemas/DeploymentVersion" + }, + "variables": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "key", + "value" + ] + } + } + }, + "required": [ + "deployment", + "version", + "variables" + ] + } + } + } + } + }, + "404": { + "description": "The release target was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + }, + "required": [ + "error" + ] + } + } + } + }, + "500": { + "description": "An internal server error occurred", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + }, + "required": [ + "error" + ] + } + } + } + } + } + } + }, "/v1/releases/{releaseId}": { "patch": { "summary": "Updates a release", diff --git a/packages/auth/src/utils/rbac.ts b/packages/auth/src/utils/rbac.ts index 4e2c241c7..171ea63c4 100644 --- a/packages/auth/src/utils/rbac.ts +++ b/packages/auth/src/utils/rbac.ts @@ -431,6 +431,28 @@ const getPolicyScopes = async (id: string) => { ]; }; +const getReleaseTargetScopes = async (id: string) => { + const result = await db + .select() + .from(releaseTarget) + .innerJoin(resource, eq(releaseTarget.resourceId, resource.id)) + .innerJoin(deployment, eq(releaseTarget.deploymentId, deployment.id)) + .innerJoin(environment, eq(releaseTarget.environmentId, environment.id)) + .innerJoin(system, eq(deployment.systemId, system.id)) + .innerJoin(workspace, eq(system.workspaceId, workspace.id)) + .where(eq(releaseTarget.id, id)) + .then(takeFirst); + + return [ + { type: "releaseTarget" as const, id: result.release_target.id }, + { type: "resource" as const, id: result.resource.id }, + { type: "environment" as const, id: result.environment.id }, + { type: "deployment" as const, id: result.deployment.id }, + { type: "system" as const, id: result.system.id }, + { type: "workspace" as const, id: result.workspace.id }, + ]; +}; + type Scope = { type: ScopeType; id: string }; export const scopeHandlers: Record< ScopeType, @@ -453,6 +475,7 @@ export const scopeHandlers: Record< jobAgent: getJobAgentScopes, job: getJobScopes, policy: getPolicyScopes, + releaseTarget: getReleaseTargetScopes, }; const fetchScopeHierarchyForResource = async (resource: { diff --git a/packages/db/src/schema/rbac.ts b/packages/db/src/schema/rbac.ts index f8079ce85..c0cbe383a 100644 --- a/packages/db/src/schema/rbac.ts +++ b/packages/db/src/schema/rbac.ts @@ -50,6 +50,7 @@ export const scopeType = pgEnum("scope_type", [ "runbook", "policy", "resourceView", + "releaseTarget", ]); export const scopeTypeSchema = z.enum(scopeType.enumValues); export type ScopeType = z.infer; diff --git a/packages/validators/src/auth/index.ts b/packages/validators/src/auth/index.ts index 698ba47a5..1a3573bc2 100644 --- a/packages/validators/src/auth/index.ts +++ b/packages/validators/src/auth/index.ts @@ -111,6 +111,8 @@ export enum Permission { PolicyCreate = "policy.create", PolicyUpdate = "policy.update", PolicyDelete = "policy.delete", + + ReleaseTargetGet = "releaseTarget.get", } export const permission = z.nativeEnum(Permission);