diff --git a/apps/api/openapi/openapi.json b/apps/api/openapi/openapi.json index b428d6f43..1b5c4ff41 100644 --- a/apps/api/openapi/openapi.json +++ b/apps/api/openapi/openapi.json @@ -1117,6 +1117,7 @@ "mapping": { "datadog": "#/components/schemas/DatadogMetricProvider", "http": "#/components/schemas/HTTPMetricProvider", + "prometheus": "#/components/schemas/PrometheusMetricProvider", "sleep": "#/components/schemas/SleepMetricProvider", "terraformCloudRun": "#/components/schemas/TerraformCloudRunMetricProvider" }, @@ -1132,6 +1133,9 @@ { "$ref": "#/components/schemas/DatadogMetricProvider" }, + { + "$ref": "#/components/schemas/PrometheusMetricProvider" + }, { "$ref": "#/components/schemas/TerraformCloudRunMetricProvider" } @@ -1270,6 +1274,130 @@ ], "type": "object" }, + "PrometheusMetricProvider": { + "properties": { + "address": { + "description": "Prometheus server address (supports Go templates)", + "example": "http://prometheus.example.com:9090", + "type": "string" + }, + "authentication": { + "description": "Authentication configuration for Prometheus", + "properties": { + "bearerToken": { + "description": "Bearer token for authentication (supports Go templates for variable references)", + "example": "{{.variables.prometheus_token}}", + "type": "string" + }, + "oauth2": { + "description": "OAuth2 client credentials flow", + "properties": { + "clientId": { + "description": "OAuth2 client ID (supports Go templates)", + "type": "string" + }, + "clientSecret": { + "description": "OAuth2 client secret (supports Go templates)", + "type": "string" + }, + "scopes": { + "description": "OAuth2 scopes", + "items": { + "type": "string" + }, + "type": "array" + }, + "tokenUrl": { + "description": "Token endpoint URL", + "type": "string" + } + }, + "required": [ + "tokenUrl", + "clientId", + "clientSecret" + ], + "type": "object" + } + }, + "type": "object" + }, + "headers": { + "description": "Additional HTTP headers for the Prometheus request (values support Go templates)", + "items": { + "properties": { + "key": { + "example": "X-Scope-OrgID", + "type": "string" + }, + "value": { + "example": "tenant_a", + "type": "string" + } + }, + "required": [ + "key", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "insecure": { + "default": false, + "description": "Skip TLS certificate verification", + "type": "boolean" + }, + "query": { + "description": "PromQL query expression (supports Go templates)", + "example": "sum(irate(istio_requests_total{reporter=\"source\",destination_service=~\"{{.resource.name}}\",response_code!~\"5.*\"}[5m]))", + "type": "string" + }, + "rangeQuery": { + "description": "If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query)", + "properties": { + "end": { + "description": "How far back from now for the query end, as a Prometheus duration (e.g., \"0s\" for now, \"1m\" for 1 minute ago). Defaults to \"0s\" (now) if unset.", + "example": "0s", + "type": "string" + }, + "start": { + "description": "How far back from now to start the query, as a Prometheus duration (e.g., \"5m\", \"1h\"). Defaults to 10 * step if unset.", + "example": "5m", + "type": "string" + }, + "step": { + "description": "Query resolution step width as a Prometheus duration (e.g., \"15s\", \"1m\", \"500ms\")", + "example": "1m", + "type": "string" + } + }, + "required": [ + "step" + ], + "type": "object" + }, + "timeout": { + "description": "Query timeout in seconds", + "example": 30, + "format": "int64", + "type": "integer" + }, + "type": { + "description": "Provider type", + "enum": [ + "prometheus" + ], + "type": "string" + } + }, + "required": [ + "type", + "address", + "query" + ], + "type": "object" + }, "PropertyMatcher": { "properties": { "fromProperty": { diff --git a/apps/api/openapi/schemas/verifications.jsonnet b/apps/api/openapi/schemas/verifications.jsonnet index d824befd9..2d35abfd8 100644 --- a/apps/api/openapi/schemas/verifications.jsonnet +++ b/apps/api/openapi/schemas/verifications.jsonnet @@ -118,6 +118,7 @@ local openapi = import '../lib/openapi.libsonnet'; openapi.schemaRef('HTTPMetricProvider'), openapi.schemaRef('SleepMetricProvider'), openapi.schemaRef('DatadogMetricProvider'), + openapi.schemaRef('PrometheusMetricProvider'), openapi.schemaRef('TerraformCloudRunMetricProvider'), ], discriminator: { @@ -126,6 +127,7 @@ local openapi = import '../lib/openapi.libsonnet'; http: '#/components/schemas/HTTPMetricProvider', sleep: '#/components/schemas/SleepMetricProvider', datadog: '#/components/schemas/DatadogMetricProvider', + prometheus: '#/components/schemas/PrometheusMetricProvider', terraformCloudRun: '#/components/schemas/TerraformCloudRunMetricProvider', }, }, @@ -239,6 +241,95 @@ local openapi = import '../lib/openapi.libsonnet'; }, }, + PrometheusMetricProvider: { + type: 'object', + required: ['type', 'address', 'query'], + properties: { + type: { + type: 'string', + enum: ['prometheus'], + description: 'Provider type', + }, + address: { + type: 'string', + description: 'Prometheus server address (supports Go templates)', + example: 'http://prometheus.example.com:9090', + }, + query: { + type: 'string', + description: 'PromQL query expression (supports Go templates)', + example: 'sum(irate(istio_requests_total{reporter="source",destination_service=~"{{.resource.name}}",response_code!~"5.*"}[5m]))', + }, + timeout: { + type: 'integer', + format: 'int64', + description: 'Query timeout in seconds', + example: 30, + }, + insecure: { + type: 'boolean', + description: 'Skip TLS certificate verification', + default: false, + }, + headers: { + type: 'array', + description: 'Additional HTTP headers for the Prometheus request (values support Go templates)', + items: { + type: 'object', + required: ['key', 'value'], + properties: { + key: { type: 'string', example: 'X-Scope-OrgID' }, + value: { type: 'string', example: 'tenant_a' }, + }, + }, + }, + authentication: { + type: 'object', + description: 'Authentication configuration for Prometheus', + properties: { + bearerToken: { + type: 'string', + description: 'Bearer token for authentication (supports Go templates for variable references)', + example: '{{.variables.prometheus_token}}', + }, + oauth2: { + type: 'object', + description: 'OAuth2 client credentials flow', + required: ['tokenUrl', 'clientId', 'clientSecret'], + properties: { + tokenUrl: { type: 'string', description: 'Token endpoint URL' }, + clientId: { type: 'string', description: 'OAuth2 client ID (supports Go templates)' }, + clientSecret: { type: 'string', description: 'OAuth2 client secret (supports Go templates)' }, + scopes: { type: 'array', items: { type: 'string' }, description: 'OAuth2 scopes' }, + }, + }, + }, + }, + rangeQuery: { + type: 'object', + description: 'If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query)', + required: ['step'], + properties: { + start: { + type: 'string', + description: 'How far back from now to start the query, as a Prometheus duration (e.g., "5m", "1h"). Defaults to 10 * step if unset.', + example: '5m', + }, + end: { + type: 'string', + description: 'How far back from now for the query end, as a Prometheus duration (e.g., "0s" for now, "1m" for 1 minute ago). Defaults to "0s" (now) if unset.', + example: '0s', + }, + step: { + type: 'string', + description: 'Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms")', + example: '1m', + }, + }, + }, + }, + }, + TerraformCloudRunMetricProvider: { type: 'object', required: ['type', 'address', 'token', 'runId'], diff --git a/apps/api/src/types/openapi.ts b/apps/api/src/types/openapi.ts index 04604319c..3a37de9a4 100644 --- a/apps/api/src/types/openapi.ts +++ b/apps/api/src/types/openapi.ts @@ -1192,7 +1192,7 @@ export interface components { }; }; LiteralValue: components["schemas"]["BooleanValue"] | components["schemas"]["NumberValue"] | components["schemas"]["IntegerValue"] | components["schemas"]["StringValue"] | components["schemas"]["ObjectValue"] | components["schemas"]["NullValue"]; - MetricProvider: components["schemas"]["HTTPMetricProvider"] | components["schemas"]["SleepMetricProvider"] | components["schemas"]["DatadogMetricProvider"] | components["schemas"]["TerraformCloudRunMetricProvider"]; + MetricProvider: components["schemas"]["HTTPMetricProvider"] | components["schemas"]["SleepMetricProvider"] | components["schemas"]["DatadogMetricProvider"] | components["schemas"]["PrometheusMetricProvider"] | components["schemas"]["TerraformCloudRunMetricProvider"]; /** @enum {boolean} */ NullValue: true; NumberValue: number; @@ -1234,6 +1234,78 @@ export interface components { verification?: components["schemas"]["VerificationRule"]; versionCooldown?: components["schemas"]["VersionCooldownRule"]; }; + PrometheusMetricProvider: { + /** + * @description Prometheus server address (supports Go templates) + * @example http://prometheus.example.com:9090 + */ + address: string; + /** @description Authentication configuration for Prometheus */ + authentication?: { + /** + * @description Bearer token for authentication (supports Go templates for variable references) + * @example {{.variables.prometheus_token}} + */ + bearerToken?: string; + /** @description OAuth2 client credentials flow */ + oauth2?: { + /** @description OAuth2 client ID (supports Go templates) */ + clientId: string; + /** @description OAuth2 client secret (supports Go templates) */ + clientSecret: string; + /** @description OAuth2 scopes */ + scopes?: string[]; + /** @description Token endpoint URL */ + tokenUrl: string; + }; + }; + /** @description Additional HTTP headers for the Prometheus request (values support Go templates) */ + headers?: { + /** @example X-Scope-OrgID */ + key: string; + /** @example tenant_a */ + value: string; + }[]; + /** + * @description Skip TLS certificate verification + * @default false + */ + insecure: boolean; + /** + * @description PromQL query expression (supports Go templates) + * @example sum(irate(istio_requests_total{reporter="source",destination_service=~"{{.resource.name}}",response_code!~"5.*"}[5m])) + */ + query: string; + /** @description If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query) */ + rangeQuery?: { + /** + * @description How far back from now for the query end, as a Prometheus duration (e.g., "0s" for now, "1m" for 1 minute ago). Defaults to "0s" (now) if unset. + * @example 0s + */ + end?: string; + /** + * @description How far back from now to start the query, as a Prometheus duration (e.g., "5m", "1h"). Defaults to 10 * step if unset. + * @example 5m + */ + start?: string; + /** + * @description Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms") + * @example 1m + */ + step: string; + }; + /** + * Format: int64 + * @description Query timeout in seconds + * @example 30 + */ + timeout?: number; + /** + * @description Provider type (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: "prometheus"; + }; PropertyMatcher: { fromProperty: string[]; /** @enum {string} */ diff --git a/apps/web/app/routes/ws/deployments/_components/release-targets/Verifications.tsx b/apps/web/app/routes/ws/deployments/_components/release-targets/Verifications.tsx index 074330021..f75410e2b 100644 --- a/apps/web/app/routes/ws/deployments/_components/release-targets/Verifications.tsx +++ b/apps/web/app/routes/ws/deployments/_components/release-targets/Verifications.tsx @@ -19,6 +19,9 @@ import { import { cn } from "~/lib/utils"; import { ArgoCDVerificationDisplay } from "./argocd/ArgoCD"; import { isArgoCDMeasurement } from "./argocd/argocd-metric"; +import { PrometheusVerificationDisplay } from "./prometheus/Prometheus"; +import { PrometheusIcon } from "./prometheus/PrometheusIcon"; +import { isPrometheusProvider } from "./prometheus/prometheus-metric"; import { VerificationMetricStatus } from "./VerificationMetricStatus"; type JobVerification = WorkspaceEngine["schemas"]["JobVerification"]; @@ -152,6 +155,7 @@ function MetricDisplay({ metric }: { metric: VerificationMetricStatus }) { const isArgoCD = latestMeasurement != null && isArgoCDMeasurement(latestMeasurement.data); + const isPrometheus = isPrometheusProvider(metric.provider); return ( @@ -163,6 +167,9 @@ function MetricDisplay({ metric }: { metric: VerificationMetricStatus }) { open ? "rotate-90" : "", )} /> + {isPrometheus && ( + + )} {metric.name}
@@ -171,7 +178,8 @@ function MetricDisplay({ metric }: { metric: VerificationMetricStatus }) { {isArgoCD && } - {!isArgoCD && ( + {isPrometheus && } + {!isArgoCD && !isPrometheus && ( <> {sortedMeasurements.map((measurement, idx) => ( diff --git a/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/Prometheus.tsx b/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/Prometheus.tsx new file mode 100644 index 000000000..b1bbc6e1a --- /dev/null +++ b/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/Prometheus.tsx @@ -0,0 +1,119 @@ +import type { WorkspaceEngine } from "@ctrlplane/workspace-engine-sdk"; +import { formatDistanceToNowStrict } from "date-fns"; + +import { cn } from "~/lib/utils"; +import { + parsePrometheusMeasurement, + parsePrometheusProvider, +} from "./prometheus-metric"; + +type VerificationMetricStatus = + WorkspaceEngine["schemas"]["VerificationMetricStatus"]; +type MetricMeasurement = VerificationMetricStatus["measurements"][number]; + +export function PrometheusVerificationDisplay({ + metric, +}: { + metric: VerificationMetricStatus; +}) { + const provider = parsePrometheusProvider(metric.provider); + const sortedMeasurements = [...metric.measurements].sort( + (a, b) => + new Date(b.measuredAt).getTime() - new Date(a.measuredAt).getTime(), + ); + + return ( +
+ + {sortedMeasurements.length > 0 && ( + + )} +
+ ); +} + +function ProviderInfo({ + query, + address, + successCondition, +}: { + query?: string; + address?: string; + successCondition: string; +}) { + return ( +
+ {query != null && ( +
+ Query + + {query} + +
+ )} +
+ Condition + + {successCondition} + +
+ {address != null && ( +
+ Server + {address} +
+ )} +
+ ); +} + +function MeasurementTrend({ + measurements, +}: { + measurements: MetricMeasurement[]; +}) { + return ( +
+ Measurements +
+ {measurements.map((m, i) => ( + + ))} +
+
+ ); +} + +function MeasurementRow({ measurement }: { measurement: MetricMeasurement }) { + const parsed = parsePrometheusMeasurement(measurement.data); + const isPassed = measurement.status === "passed"; + const isFailed = measurement.status === "failed"; + + const timeAgo = formatDistanceToNowStrict( + new Date(measurement.measuredAt), + { addSuffix: true }, + ); + + return ( +
+
+ + {timeAgo} +
+ + {parsed?.value != null ? parsed.value : "—"} + +
+ ); +} diff --git a/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/PrometheusIcon.tsx b/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/PrometheusIcon.tsx new file mode 100644 index 000000000..453644831 --- /dev/null +++ b/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/PrometheusIcon.tsx @@ -0,0 +1,12 @@ +export function PrometheusIcon({ className }: { className?: string }) { + return ( + + + + ); +} diff --git a/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/prometheus-metric.ts b/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/prometheus-metric.ts new file mode 100644 index 000000000..ae72cf6ee --- /dev/null +++ b/apps/web/app/routes/ws/deployments/_components/release-targets/prometheus/prometheus-metric.ts @@ -0,0 +1,57 @@ +import { z } from "zod"; + +export const prometheusProviderConfig = z.object({ + type: z.literal("prometheus"), + address: z.string(), + query: z.string(), + timeout: z.number().optional(), +}); + +export type PrometheusProviderConfig = z.infer; + +const prometheusTimeSeriesPoint = z.object({ + timestamp: z.number(), + value: z.number(), +}); + +const prometheusResultEntry = z.object({ + metric: z.record(z.string()).optional(), + value: z.number(), + values: z.array(prometheusTimeSeriesPoint).optional(), +}); + +export const prometheusMeasurementData = z.object({ + ok: z.boolean(), + statusCode: z.number(), + duration: z.number().optional(), + value: z.number().nullable().optional(), + results: z.array(prometheusResultEntry).nullable().optional(), + error: z.string().optional(), + errorType: z.string().optional(), +}); + +export type PrometheusMeasurementData = z.infer< + typeof prometheusMeasurementData +>; + +export function parsePrometheusProvider( + provider: unknown, +): PrometheusProviderConfig | null { + const result = prometheusProviderConfig.safeParse(provider); + return result.success ? result.data : null; +} + +export function parsePrometheusMeasurement( + data: unknown, +): PrometheusMeasurementData | null { + const result = prometheusMeasurementData.safeParse(data); + return result.success ? result.data : null; +} + +export function isPrometheusMeasurement(data: unknown): boolean { + return prometheusMeasurementData.safeParse(data).success; +} + +export function isPrometheusProvider(provider: unknown): boolean { + return prometheusProviderConfig.safeParse(provider).success; +} diff --git a/apps/workspace-engine/oapi/openapi.json b/apps/workspace-engine/oapi/openapi.json index 766e00004..34f9ec8ca 100644 --- a/apps/workspace-engine/oapi/openapi.json +++ b/apps/workspace-engine/oapi/openapi.json @@ -970,6 +970,7 @@ "mapping": { "datadog": "#/components/schemas/DatadogMetricProvider", "http": "#/components/schemas/HTTPMetricProvider", + "prometheus": "#/components/schemas/PrometheusMetricProvider", "sleep": "#/components/schemas/SleepMetricProvider", "terraformCloudRun": "#/components/schemas/TerraformCloudRunMetricProvider" }, @@ -985,6 +986,9 @@ { "$ref": "#/components/schemas/DatadogMetricProvider" }, + { + "$ref": "#/components/schemas/PrometheusMetricProvider" + }, { "$ref": "#/components/schemas/TerraformCloudRunMetricProvider" } @@ -1191,6 +1195,130 @@ ], "type": "object" }, + "PrometheusMetricProvider": { + "properties": { + "address": { + "description": "Prometheus server address (supports Go templates)", + "example": "http://prometheus.example.com:9090", + "type": "string" + }, + "authentication": { + "description": "Authentication configuration for Prometheus", + "properties": { + "bearerToken": { + "description": "Bearer token for authentication (supports Go templates for variable references)", + "example": "{{.variables.prometheus_token}}", + "type": "string" + }, + "oauth2": { + "description": "OAuth2 client credentials flow", + "properties": { + "clientId": { + "description": "OAuth2 client ID (supports Go templates)", + "type": "string" + }, + "clientSecret": { + "description": "OAuth2 client secret (supports Go templates)", + "type": "string" + }, + "scopes": { + "description": "OAuth2 scopes", + "items": { + "type": "string" + }, + "type": "array" + }, + "tokenUrl": { + "description": "Token endpoint URL", + "type": "string" + } + }, + "required": [ + "tokenUrl", + "clientId", + "clientSecret" + ], + "type": "object" + } + }, + "type": "object" + }, + "headers": { + "description": "Additional HTTP headers for the Prometheus request (values support Go templates)", + "items": { + "properties": { + "key": { + "example": "X-Scope-OrgID", + "type": "string" + }, + "value": { + "example": "tenant_a", + "type": "string" + } + }, + "required": [ + "key", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "insecure": { + "default": false, + "description": "Skip TLS certificate verification", + "type": "boolean" + }, + "query": { + "description": "PromQL query expression (supports Go templates)", + "example": "sum(irate(istio_requests_total{reporter=\"source\",destination_service=~\"{{.resource.name}}\",response_code!~\"5.*\"}[5m]))", + "type": "string" + }, + "rangeQuery": { + "description": "If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query)", + "properties": { + "end": { + "description": "How far back from now for the query end, as a Prometheus duration (e.g., \"0s\" for now, \"1m\" for 1 minute ago). Defaults to \"0s\" (now) if unset.", + "example": "0s", + "type": "string" + }, + "start": { + "description": "How far back from now to start the query, as a Prometheus duration (e.g., \"5m\", \"1h\"). Defaults to 10 * step if unset.", + "example": "5m", + "type": "string" + }, + "step": { + "description": "Query resolution step width as a Prometheus duration (e.g., \"15s\", \"1m\", \"500ms\")", + "example": "1m", + "type": "string" + } + }, + "required": [ + "step" + ], + "type": "object" + }, + "timeout": { + "description": "Query timeout in seconds", + "example": 30, + "format": "int64", + "type": "integer" + }, + "type": { + "description": "Provider type", + "enum": [ + "prometheus" + ], + "type": "string" + } + }, + "required": [ + "type", + "address", + "query" + ], + "type": "object" + }, "PropertiesMatcher": { "properties": { "properties": { diff --git a/apps/workspace-engine/oapi/spec/schemas/verification.jsonnet b/apps/workspace-engine/oapi/spec/schemas/verification.jsonnet index 7c2ec18cb..a82ab3a74 100644 --- a/apps/workspace-engine/oapi/spec/schemas/verification.jsonnet +++ b/apps/workspace-engine/oapi/spec/schemas/verification.jsonnet @@ -118,6 +118,7 @@ local openapi = import '../lib/openapi.libsonnet'; openapi.schemaRef('HTTPMetricProvider'), openapi.schemaRef('SleepMetricProvider'), openapi.schemaRef('DatadogMetricProvider'), + openapi.schemaRef('PrometheusMetricProvider'), openapi.schemaRef('TerraformCloudRunMetricProvider'), ], discriminator: { @@ -126,6 +127,7 @@ local openapi = import '../lib/openapi.libsonnet'; http: '#/components/schemas/HTTPMetricProvider', sleep: '#/components/schemas/SleepMetricProvider', datadog: '#/components/schemas/DatadogMetricProvider', + prometheus: '#/components/schemas/PrometheusMetricProvider', terraformCloudRun: '#/components/schemas/TerraformCloudRunMetricProvider', }, }, @@ -239,6 +241,95 @@ local openapi = import '../lib/openapi.libsonnet'; }, }, + PrometheusMetricProvider: { + type: 'object', + required: ['type', 'address', 'query'], + properties: { + type: { + type: 'string', + enum: ['prometheus'], + description: 'Provider type', + }, + address: { + type: 'string', + description: 'Prometheus server address (supports Go templates)', + example: 'http://prometheus.example.com:9090', + }, + query: { + type: 'string', + description: 'PromQL query expression (supports Go templates)', + example: 'sum(irate(istio_requests_total{reporter="source",destination_service=~"{{.resource.name}}",response_code!~"5.*"}[5m]))', + }, + timeout: { + type: 'integer', + format: 'int64', + description: 'Query timeout in seconds', + example: 30, + }, + insecure: { + type: 'boolean', + description: 'Skip TLS certificate verification', + default: false, + }, + headers: { + type: 'array', + description: 'Additional HTTP headers for the Prometheus request (values support Go templates)', + items: { + type: 'object', + required: ['key', 'value'], + properties: { + key: { type: 'string', example: 'X-Scope-OrgID' }, + value: { type: 'string', example: 'tenant_a' }, + }, + }, + }, + authentication: { + type: 'object', + description: 'Authentication configuration for Prometheus', + properties: { + bearerToken: { + type: 'string', + description: 'Bearer token for authentication (supports Go templates for variable references)', + example: '{{.variables.prometheus_token}}', + }, + oauth2: { + type: 'object', + description: 'OAuth2 client credentials flow', + required: ['tokenUrl', 'clientId', 'clientSecret'], + properties: { + tokenUrl: { type: 'string', description: 'Token endpoint URL' }, + clientId: { type: 'string', description: 'OAuth2 client ID (supports Go templates)' }, + clientSecret: { type: 'string', description: 'OAuth2 client secret (supports Go templates)' }, + scopes: { type: 'array', items: { type: 'string' }, description: 'OAuth2 scopes' }, + }, + }, + }, + }, + rangeQuery: { + type: 'object', + description: 'If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query)', + required: ['step'], + properties: { + start: { + type: 'string', + description: 'How far back from now to start the query, as a Prometheus duration (e.g., "5m", "1h"). Defaults to 10 * step if unset.', + example: '5m', + }, + end: { + type: 'string', + description: 'How far back from now for the query end, as a Prometheus duration (e.g., "0s" for now, "1m" for 1 minute ago). Defaults to "0s" (now) if unset.', + example: '0s', + }, + step: { + type: 'string', + description: 'Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms")', + example: '1m', + }, + }, + }, + }, + }, + TerraformCloudRunMetricProvider: { type: 'object', required: ['type', 'address', 'token', 'runId'], diff --git a/apps/workspace-engine/pkg/oapi/oapi.gen.go b/apps/workspace-engine/pkg/oapi/oapi.gen.go index dca78d380..5c01aaaa9 100644 --- a/apps/workspace-engine/pkg/oapi/oapi.gen.go +++ b/apps/workspace-engine/pkg/oapi/oapi.gen.go @@ -116,6 +116,11 @@ const ( True NullValue = true ) +// Defines values for PrometheusMetricProviderType. +const ( + Prometheus PrometheusMetricProviderType = "prometheus" +) + // Defines values for PropertyMatcherOperator. const ( Contains PropertyMatcherOperator = "contains" @@ -670,6 +675,66 @@ type PolicySkip struct { WorkspaceId string `json:"workspaceId"` } +// PrometheusMetricProvider defines model for PrometheusMetricProvider. +type PrometheusMetricProvider struct { + // Address Prometheus server address (supports Go templates) + Address string `json:"address"` + + // Authentication Authentication configuration for Prometheus + Authentication *struct { + // BearerToken Bearer token for authentication (supports Go templates for variable references) + BearerToken *string `json:"bearerToken,omitempty"` + + // Oauth2 OAuth2 client credentials flow + Oauth2 *struct { + // ClientId OAuth2 client ID (supports Go templates) + ClientId string `json:"clientId"` + + // ClientSecret OAuth2 client secret (supports Go templates) + ClientSecret string `json:"clientSecret"` + + // Scopes OAuth2 scopes + Scopes *[]string `json:"scopes,omitempty"` + + // TokenUrl Token endpoint URL + TokenUrl string `json:"tokenUrl"` + } `json:"oauth2,omitempty"` + } `json:"authentication,omitempty"` + + // Headers Additional HTTP headers for the Prometheus request (values support Go templates) + Headers *[]struct { + Key string `json:"key"` + Value string `json:"value"` + } `json:"headers,omitempty"` + + // Insecure Skip TLS certificate verification + Insecure *bool `json:"insecure,omitempty"` + + // Query PromQL query expression (supports Go templates) + Query string `json:"query"` + + // RangeQuery If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query) + RangeQuery *struct { + // End How far back from now for the query end, as a Prometheus duration (e.g., "0s" for now, "1m" for 1 minute ago). Defaults to "0s" (now) if unset. + End *string `json:"end,omitempty"` + + // Start How far back from now to start the query, as a Prometheus duration (e.g., "5m", "1h"). Defaults to 10 * step if unset. + Start *string `json:"start,omitempty"` + + // Step Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms") + Step string `json:"step"` + } `json:"rangeQuery,omitempty"` + + // Timeout Query timeout in seconds + Timeout *int64 `json:"timeout,omitempty"` + + // Type Provider type + Type PrometheusMetricProviderType `json:"type"` +} + +// PrometheusMetricProviderType Provider type +type PrometheusMetricProviderType string + // PropertiesMatcher defines model for PropertiesMatcher. type PropertiesMatcher struct { Properties []PropertyMatcher `json:"properties"` @@ -1832,6 +1897,34 @@ func (t *MetricProvider) MergeDatadogMetricProvider(v DatadogMetricProvider) err return err } +// AsPrometheusMetricProvider returns the union data inside the MetricProvider as a PrometheusMetricProvider +func (t MetricProvider) AsPrometheusMetricProvider() (PrometheusMetricProvider, error) { + var body PrometheusMetricProvider + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPrometheusMetricProvider overwrites any union data inside the MetricProvider as the provided PrometheusMetricProvider +func (t *MetricProvider) FromPrometheusMetricProvider(v PrometheusMetricProvider) error { + v.Type = "prometheus" + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePrometheusMetricProvider performs a merge with any union data inside the MetricProvider, using the provided PrometheusMetricProvider +func (t *MetricProvider) MergePrometheusMetricProvider(v PrometheusMetricProvider) error { + v.Type = "prometheus" + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + // AsTerraformCloudRunMetricProvider returns the union data inside the MetricProvider as a TerraformCloudRunMetricProvider func (t MetricProvider) AsTerraformCloudRunMetricProvider() (TerraformCloudRunMetricProvider, error) { var body TerraformCloudRunMetricProvider @@ -1878,6 +1971,8 @@ func (t MetricProvider) ValueByDiscriminator() (interface{}, error) { return t.AsDatadogMetricProvider() case "http": return t.AsHTTPMetricProvider() + case "prometheus": + return t.AsPrometheusMetricProvider() case "sleep": return t.AsSleepMetricProvider() case "terraformCloudRun": diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/metric.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/metric.go index 9b8d566ed..1303a1f0e 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/metric.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/metric.go @@ -7,6 +7,7 @@ import ( "workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider" "workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/datadog" "workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/http" + "workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/prometheus" "workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/sleep" "github.com/charmbracelet/log" @@ -41,6 +42,13 @@ func CreateProvider(providerCfg oapi.MetricProvider) (provider.Provider, error) } return datadog.NewFromOAPI(datadogProvider) + case "prometheus": + prometheusProvider, err := providerCfg.AsPrometheusMetricProvider() + if err != nil { + return nil, fmt.Errorf("failed to parse Prometheus provider: %w", err) + } + return prometheus.NewFromOAPI(prometheusProvider) + // case "terraformCloudRun": // terraformCloudRunProvider, err := providerCfg.AsTerraformCloudRunMetricProvider() // if err != nil { diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/prometheus/prometheus.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/prometheus/prometheus.go new file mode 100644 index 000000000..7dedac402 --- /dev/null +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/prometheus/prometheus.go @@ -0,0 +1,484 @@ +package prometheus + +import ( + "context" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "strings" + "time" + "workspace-engine/pkg/oapi" + "workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider" + + "github.com/charmbracelet/log" + "github.com/prometheus/common/model" +) + +var _ provider.Provider = (*PrometheusProvider)(nil) + +type prometheusResponse struct { + Status string `json:"status"` + Data struct { + ResultType string `json:"resultType"` + Result json.RawMessage `json:"result"` + } `json:"data"` + Error string `json:"error,omitempty"` + ErrorType string `json:"errorType,omitempty"` +} + +type vectorResult struct { + Metric map[string]string `json:"metric"` + Value [2]json.RawMessage `json:"value"` +} + +type matrixResult struct { + Metric map[string]string `json:"metric"` + Values [][2]json.RawMessage `json:"values"` +} + +type prometheusHeader = struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type prometheusOAuth2 = struct { + ClientId string `json:"clientId"` + ClientSecret string `json:"clientSecret"` + Scopes *[]string `json:"scopes,omitempty"` + TokenUrl string `json:"tokenUrl"` +} + +type prometheusAuth = struct { + BearerToken *string `json:"bearerToken,omitempty"` + Oauth2 *prometheusOAuth2 `json:"oauth2,omitempty"` +} + +type PrometheusProvider struct { + config *oapi.PrometheusMetricProvider +} + +func NewPrometheusProvider(config *oapi.PrometheusMetricProvider) (*PrometheusProvider, error) { + if config.Address == "" { + return nil, fmt.Errorf("address is required") + } + if config.Query == "" { + return nil, fmt.Errorf("query is required") + } + return &PrometheusProvider{config: config}, nil +} + +func NewFromOAPI(config oapi.PrometheusMetricProvider) (*PrometheusProvider, error) { + return NewPrometheusProvider(&config) +} + +func (p *PrometheusProvider) Type() string { + return "prometheus" +} + +func (p *PrometheusProvider) Measure(ctx context.Context, providerCtx *provider.ProviderContext) (time.Time, map[string]any, error) { + startTime := time.Now() + + resolvedProvider := resolveProviderTemplates(p.config, providerCtx) + + reqURL, err := buildQueryURL(resolvedProvider, startTime) + if err != nil { + return time.Time{}, nil, fmt.Errorf("failed to build query URL: %w", err) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil) + if err != nil { + return time.Time{}, nil, fmt.Errorf("failed to create request: %w", err) + } + client := buildHTTPClient(resolvedProvider) + + if err := setHeaders(req, resolvedProvider, client); err != nil { + return time.Time{}, nil, err + } + resp, err := client.Do(req) + duration := time.Since(startTime) + if err != nil { + log.Error("Prometheus metric request failed", "address", resolvedProvider.Address, "error", err) + return time.Time{}, nil, fmt.Errorf("prometheus request failed: %w", err) + } + defer resp.Body.Close() + + respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1024*1024)) + if err != nil { + return time.Time{}, nil, fmt.Errorf("failed to read response: %w", err) + } + + data, err := buildResultData(resp.StatusCode, respBody, duration) + if err != nil { + return time.Time{}, nil, err + } + + log.Debug("Prometheus metric measurement", + "address", resolvedProvider.Address, + "query", resolvedProvider.Query, + "status", resp.StatusCode, + "duration", duration) + + return startTime, data, nil +} + +func resolveProviderTemplates(config *oapi.PrometheusMetricProvider, providerCtx *provider.ProviderContext) *oapi.PrometheusMetricProvider { + resolved := &oapi.PrometheusMetricProvider{ + Address: providerCtx.Template(config.Address), + Query: providerCtx.Template(config.Query), + Type: config.Type, + Timeout: config.Timeout, + Insecure: config.Insecure, + RangeQuery: config.RangeQuery, + } + + resolved.Headers = resolveHeaders(config.Headers, providerCtx) + resolved.Authentication = resolveAuthentication(config.Authentication, providerCtx) + + return resolved +} + +func resolveHeaders(headers *[]prometheusHeader, providerCtx *provider.ProviderContext) *[]prometheusHeader { + if headers == nil { + return nil + } + + resolved := make([]prometheusHeader, len(*headers)) + for i, h := range *headers { + resolved[i] = prometheusHeader{Key: h.Key, Value: providerCtx.Template(h.Value)} + } + return &resolved +} + +func resolveAuthentication(auth *prometheusAuth, providerCtx *provider.ProviderContext) *prometheusAuth { + if auth == nil { + return nil + } + + resolved := *auth + if resolved.BearerToken != nil { + token := providerCtx.Template(*resolved.BearerToken) + resolved.BearerToken = &token + } + if resolved.Oauth2 != nil { + oauth2 := *resolved.Oauth2 + oauth2.ClientId = providerCtx.Template(oauth2.ClientId) + oauth2.ClientSecret = providerCtx.Template(oauth2.ClientSecret) + oauth2.TokenUrl = providerCtx.Template(oauth2.TokenUrl) + resolved.Oauth2 = &oauth2 + } + return &resolved +} + +func buildQueryURL(config *oapi.PrometheusMetricProvider, now time.Time) (string, error) { + address := strings.TrimRight(config.Address, "/") + params := url.Values{} + params.Set("query", config.Query) + + if config.Timeout != nil { + params.Set("timeout", fmt.Sprintf("%ds", *config.Timeout)) + } + + if config.RangeQuery != nil { + step := config.RangeQuery.Step + params.Set("step", step) + + stepDuration, err := parsePrometheusDuration(step) + if err != nil { + return "", fmt.Errorf("invalid step duration %q: %w", step, err) + } + + end := now + if config.RangeQuery.End != nil && *config.RangeQuery.End != "" { + d, err := parsePrometheusDuration(*config.RangeQuery.End) + if err != nil { + return "", fmt.Errorf("invalid end duration %q: %w", *config.RangeQuery.End, err) + } + end = now.Add(-d) + } + + start := end.Add(-stepDuration * 10) + if config.RangeQuery.Start != nil && *config.RangeQuery.Start != "" { + d, err := parsePrometheusDuration(*config.RangeQuery.Start) + if err != nil { + return "", fmt.Errorf("invalid start duration %q: %w", *config.RangeQuery.Start, err) + } + start = now.Add(-d) + } + + params.Set("start", formatTimestamp(start)) + params.Set("end", formatTimestamp(end)) + + return address + "/api/v1/query_range?" + params.Encode(), nil + } + + return address + "/api/v1/query?" + params.Encode(), nil +} + +func setHeaders(req *http.Request, config *oapi.PrometheusMetricProvider, client *http.Client) error { + if err := setAuthHeader(req, config.Authentication, client); err != nil { + return err + } + + if config.Headers == nil { + return nil + } + + for _, h := range *config.Headers { + req.Header.Set(h.Key, h.Value) + } + return nil +} + +func setAuthHeader(req *http.Request, auth *prometheusAuth, client *http.Client) error { + if auth == nil { + return nil + } + + if auth.Oauth2 != nil { + token, err := fetchOAuth2Token(req.Context(), auth.Oauth2, client) + if err != nil { + return fmt.Errorf("oauth2 token fetch failed: %w", err) + } + req.Header.Set("Authorization", "Bearer "+token) + return nil + } + + if auth.BearerToken != nil && *auth.BearerToken != "" { + req.Header.Set("Authorization", "Bearer "+*auth.BearerToken) + } + return nil +} + +func fetchOAuth2Token(ctx context.Context, oauth2 *prometheusOAuth2, client *http.Client) (string, error) { + data := url.Values{ + "grant_type": {"client_credentials"}, + "client_id": {oauth2.ClientId}, + "client_secret": {oauth2.ClientSecret}, + } + if oauth2.Scopes != nil && len(*oauth2.Scopes) > 0 { + data.Set("scope", strings.Join(*oauth2.Scopes, " ")) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, oauth2.TokenUrl, strings.NewReader(data.Encode())) + if err != nil { + return "", fmt.Errorf("failed to create token request: %w", err) + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + resp, err := client.Do(req) + if err != nil { + return "", fmt.Errorf("token request failed: %w", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(io.LimitReader(resp.Body, 1024*1024)) + if err != nil { + return "", fmt.Errorf("failed to read token response: %w", err) + } + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return "", fmt.Errorf("token endpoint returned %d: %s", resp.StatusCode, string(body)) + } + + var tokenResp struct { + AccessToken string `json:"access_token"` + } + if err := json.Unmarshal(body, &tokenResp); err != nil { + return "", fmt.Errorf("failed to parse token response: %w", err) + } + if tokenResp.AccessToken == "" { + return "", fmt.Errorf("token response missing access_token") + } + + return tokenResp.AccessToken, nil +} + +func buildHTTPClient(config *oapi.PrometheusMetricProvider) *http.Client { + timeout := 30 * time.Second + if config.Timeout != nil { + timeout = time.Duration(*config.Timeout) * time.Second + } + + client := &http.Client{Timeout: timeout} + + if config.Insecure != nil && *config.Insecure { + client.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec + } + } + + return client +} + +func buildResultData(statusCode int, respBody []byte, duration time.Duration) (map[string]any, error) { + var rawJSON any + if err := json.Unmarshal(respBody, &rawJSON); err != nil { + return nil, fmt.Errorf("failed to parse Prometheus response: %w", err) + } + + var promResp prometheusResponse + if err := json.Unmarshal(respBody, &promResp); err != nil { + return nil, fmt.Errorf("failed to parse Prometheus response structure: %w", err) + } + + data := map[string]any{ + "ok": statusCode >= 200 && statusCode < 300 && promResp.Status == "success", + "statusCode": statusCode, + "body": string(respBody), + "json": rawJSON, + "duration": duration.Milliseconds(), + } + + if promResp.Status != "success" { + data["error"] = promResp.Error + data["errorType"] = promResp.ErrorType + return data, nil + } + + value, results, err := extractResults(promResp) + if err != nil { + log.Warn("Could not extract Prometheus result values", "error", err) + } + + data["value"] = value + data["results"] = results + + return data, nil +} + +func extractResults(resp prometheusResponse) (*float64, []map[string]any, error) { + switch resp.Data.ResultType { + case "vector": + return extractVectorResults(resp.Data.Result) + case "matrix": + return extractMatrixResults(resp.Data.Result) + case "scalar": + return extractScalarResult(resp.Data.Result) + default: + return nil, nil, fmt.Errorf("unsupported result type: %s", resp.Data.ResultType) + } +} + +func extractVectorResults(raw json.RawMessage) (*float64, []map[string]any, error) { + var vectors []vectorResult + if err := json.Unmarshal(raw, &vectors); err != nil { + return nil, nil, fmt.Errorf("failed to parse vector result: %w", err) + } + + if len(vectors) == 0 { + return nil, nil, nil + } + + var primary *float64 + results := make([]map[string]any, 0, len(vectors)) + + for i, v := range vectors { + val, err := parseScalarValue(v.Value[1]) + if err != nil { + log.Warn("Could not parse vector value", "index", i, "error", err) + continue + } + if primary == nil { + primary = &val + } + results = append(results, map[string]any{ + "metric": v.Metric, + "value": val, + }) + } + + return primary, results, nil +} + +func extractMatrixResults(raw json.RawMessage) (*float64, []map[string]any, error) { + var matrices []matrixResult + if err := json.Unmarshal(raw, &matrices); err != nil { + return nil, nil, fmt.Errorf("failed to parse matrix result: %w", err) + } + + if len(matrices) == 0 { + return nil, nil, nil + } + + var primary *float64 + results := make([]map[string]any, 0, len(matrices)) + + for i, m := range matrices { + if len(m.Values) == 0 { + continue + } + lastPair := m.Values[len(m.Values)-1] + val, err := parseScalarValue(lastPair[1]) + if err != nil { + log.Warn("Could not parse matrix value", "index", i, "error", err) + continue + } + if primary == nil { + primary = &val + } + + values := make([]map[string]any, 0, len(m.Values)) + for _, pair := range m.Values { + ts, _ := parseScalarValue(pair[0]) + v, err := parseScalarValue(pair[1]) + if err != nil { + continue + } + values = append(values, map[string]any{ + "timestamp": ts, + "value": v, + }) + } + + results = append(results, map[string]any{ + "metric": m.Metric, + "value": val, + "values": values, + }) + } + + return primary, results, nil +} + +func extractScalarResult(raw json.RawMessage) (*float64, []map[string]any, error) { + var pair [2]json.RawMessage + if err := json.Unmarshal(raw, &pair); err != nil { + return nil, nil, fmt.Errorf("failed to parse scalar result: %w", err) + } + + val, err := parseScalarValue(pair[1]) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse scalar value: %w", err) + } + + return &val, []map[string]any{{"value": val}}, nil +} + +func parseScalarValue(raw json.RawMessage) (float64, error) { + var s string + if err := json.Unmarshal(raw, &s); err == nil { + return strconv.ParseFloat(s, 64) + } + + var f float64 + if err := json.Unmarshal(raw, &f); err != nil { + return 0, fmt.Errorf("cannot parse value %q", string(raw)) + } + return f, nil +} + +func parsePrometheusDuration(s string) (time.Duration, error) { + d, err := model.ParseDuration(s) + if err != nil { + return 0, fmt.Errorf("invalid prometheus duration %q: %w", s, err) + } + return time.Duration(d), nil +} + +func formatTimestamp(t time.Time) string { + return strconv.FormatFloat(float64(t.UnixNano())/1e9, 'f', 3, 64) +} diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/prometheus/prometheus_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/prometheus/prometheus_test.go new file mode 100644 index 000000000..1438f9b05 --- /dev/null +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider/prometheus/prometheus_test.go @@ -0,0 +1,1016 @@ +package prometheus + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + "workspace-engine/pkg/oapi" + "workspace-engine/pkg/workspace/releasemanager/verification/metrics/provider" +) + +func ptr[T any](v T) *T { return &v } + +func TestNewPrometheusProvider(t *testing.T) { + tests := []struct { + name string + config *oapi.PrometheusMetricProvider + wantErr bool + errSubstr string + }{ + { + name: "valid config", + config: &oapi.PrometheusMetricProvider{Address: "http://localhost:9090", Query: "up"}, + wantErr: false, + }, + { + name: "missing address", + config: &oapi.PrometheusMetricProvider{Query: "up"}, + wantErr: true, + errSubstr: "address is required", + }, + { + name: "missing query", + config: &oapi.PrometheusMetricProvider{Address: "http://localhost:9090"}, + wantErr: true, + errSubstr: "query is required", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p, err := NewPrometheusProvider(tt.config) + if tt.wantErr { + if err == nil { + t.Fatal("expected error but got none") + } + if !strings.Contains(err.Error(), tt.errSubstr) { + t.Errorf("expected error containing %q, got %q", tt.errSubstr, err.Error()) + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if p.Type() != "prometheus" { + t.Errorf("expected type prometheus, got %s", p.Type()) + } + }) + } +} + +func TestBuildQueryURL_InstantQuery(t *testing.T) { + now := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC) + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: `up{job="test"}`, + } + + u, err := buildQueryURL(config, now) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !strings.Contains(u, "/api/v1/query?") { + t.Errorf("expected instant query path, got %s", u) + } + if !strings.Contains(u, "query=up") { + t.Errorf("expected query param, got %s", u) + } + if strings.Contains(u, "step=") { + t.Error("instant query should not have step param") + } +} + +func TestBuildQueryURL_InstantQueryWithTimeout(t *testing.T) { + now := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC) + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: "up", + Timeout: ptr(int64(45)), + } + + u, err := buildQueryURL(config, now) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !strings.Contains(u, "timeout=45s") { + t.Errorf("expected timeout=45s in URL, got %s", u) + } +} + +func TestBuildQueryURL_RangeQueryDefaults(t *testing.T) { + now := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC) + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: "rate(http_requests_total[5m])", + RangeQuery: &struct { + End *string `json:"end,omitempty"` + Start *string `json:"start,omitempty"` + Step string `json:"step"` + }{ + Step: "1m", + }, + } + + u, err := buildQueryURL(config, now) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !strings.Contains(u, "/api/v1/query_range?") { + t.Errorf("expected range query path, got %s", u) + } + if !strings.Contains(u, "step=1m") { + t.Errorf("expected step=1m, got %s", u) + } + + expectedEnd := formatTimestamp(now) + if !strings.Contains(u, "end="+expectedEnd) { + t.Errorf("expected end=now, got URL %s", u) + } + + expectedStart := formatTimestamp(now.Add(-10 * time.Minute)) + if !strings.Contains(u, "start="+expectedStart) { + t.Errorf("expected default start of 10*step (10m) before now, got URL %s", u) + } +} + +func TestBuildQueryURL_RangeQueryWithExplicitStart(t *testing.T) { + now := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC) + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: "up", + RangeQuery: &struct { + End *string `json:"end,omitempty"` + Start *string `json:"start,omitempty"` + Step string `json:"step"` + }{ + Step: "15s", + Start: ptr("5m"), + }, + } + + u, err := buildQueryURL(config, now) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedStart := formatTimestamp(now.Add(-5 * time.Minute)) + if !strings.Contains(u, "start="+expectedStart) { + t.Errorf("expected start=5m ago, got URL %s", u) + } +} + +func TestBuildQueryURL_RangeQueryWithExplicitEnd(t *testing.T) { + now := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC) + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: "up", + RangeQuery: &struct { + End *string `json:"end,omitempty"` + Start *string `json:"start,omitempty"` + Step string `json:"step"` + }{ + Step: "15s", + End: ptr("1m"), + }, + } + + u, err := buildQueryURL(config, now) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedEnd := formatTimestamp(now.Add(-1 * time.Minute)) + if !strings.Contains(u, "end="+expectedEnd) { + t.Errorf("expected end=1m ago, got URL %s", u) + } +} + +func TestBuildQueryURL_InvalidStep(t *testing.T) { + now := time.Now() + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: "up", + RangeQuery: &struct { + End *string `json:"end,omitempty"` + Start *string `json:"start,omitempty"` + Step string `json:"step"` + }{ + Step: "invalid", + }, + } + + _, err := buildQueryURL(config, now) + if err == nil { + t.Fatal("expected error for invalid step duration") + } + if !strings.Contains(err.Error(), "invalid step duration") { + t.Errorf("expected 'invalid step duration' error, got %q", err.Error()) + } +} + +func TestBuildQueryURL_InvalidStart(t *testing.T) { + now := time.Now() + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: "up", + RangeQuery: &struct { + End *string `json:"end,omitempty"` + Start *string `json:"start,omitempty"` + Step string `json:"step"` + }{ + Step: "15s", + Start: ptr("invalid"), + }, + } + + _, err := buildQueryURL(config, now) + if err == nil { + t.Fatal("expected error for invalid start duration") + } + if !strings.Contains(err.Error(), "invalid start duration") { + t.Errorf("expected 'invalid start duration' error, got %q", err.Error()) + } +} + +func TestBuildQueryURL_InvalidEnd(t *testing.T) { + now := time.Now() + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090", + Query: "up", + RangeQuery: &struct { + End *string `json:"end,omitempty"` + Start *string `json:"start,omitempty"` + Step string `json:"step"` + }{ + Step: "15s", + End: ptr("invalid"), + }, + } + + _, err := buildQueryURL(config, now) + if err == nil { + t.Fatal("expected error for invalid end duration") + } + if !strings.Contains(err.Error(), "invalid end duration") { + t.Errorf("expected 'invalid end duration' error, got %q", err.Error()) + } +} + +func TestBuildQueryURL_TrailingSlash(t *testing.T) { + now := time.Now() + + config := &oapi.PrometheusMetricProvider{ + Address: "http://prometheus:9090/", + Query: "up", + } + + u, err := buildQueryURL(config, now) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if strings.Contains(u, "//api") { + t.Errorf("address trailing slash should be trimmed, got %s", u) + } +} + +func TestParsePrometheusDuration(t *testing.T) { + tests := []struct { + input string + want time.Duration + wantErr bool + }{ + {"15s", 15 * time.Second, false}, + {"1m", 1 * time.Minute, false}, + {"2h", 2 * time.Hour, false}, + {"1d", 24 * time.Hour, false}, + {"1w", 7 * 24 * time.Hour, false}, + {"500ms", 500 * time.Millisecond, false}, + {"1y", 365 * 24 * time.Hour, false}, + {"", 0, true}, + {"abc", 0, true}, + {"10x", 0, true}, + } + + for _, tt := range tests { + t.Run(tt.input, func(t *testing.T) { + got, err := parsePrometheusDuration(tt.input) + if tt.wantErr { + if err == nil { + t.Error("expected error but got none") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got != tt.want { + t.Errorf("parsePrometheusDuration(%q) = %v, want %v", tt.input, got, tt.want) + } + }) + } +} + +func TestSetHeaders_BearerToken(t *testing.T) { + config := &oapi.PrometheusMetricProvider{ + Authentication: &prometheusAuth{ + BearerToken: ptr("my-secret-token"), + }, + } + + req, _ := http.NewRequest("GET", "http://example.com", nil) + setHeaders(req, config, http.DefaultClient) + + got := req.Header.Get("Authorization") + want := "Bearer my-secret-token" + if got != want { + t.Errorf("expected Authorization %q, got %q", want, got) + } +} + +func TestSetHeaders_CustomHeaders(t *testing.T) { + headers := []prometheusHeader{ + {Key: "X-Scope-OrgID", Value: "tenant_a"}, + {Key: "X-Custom", Value: "value"}, + } + config := &oapi.PrometheusMetricProvider{ + Headers: &headers, + } + + req, _ := http.NewRequest("GET", "http://example.com", nil) + setHeaders(req, config, http.DefaultClient) + + if got := req.Header.Get("X-Scope-OrgID"); got != "tenant_a" { + t.Errorf("expected X-Scope-OrgID=tenant_a, got %q", got) + } + if got := req.Header.Get("X-Custom"); got != "value" { + t.Errorf("expected X-Custom=value, got %q", got) + } +} + +func TestSetHeaders_NoAuth(t *testing.T) { + config := &oapi.PrometheusMetricProvider{} + + req, _ := http.NewRequest("GET", "http://example.com", nil) + setHeaders(req, config, http.DefaultClient) + + if got := req.Header.Get("Authorization"); got != "" { + t.Errorf("expected no Authorization header, got %q", got) + } +} + +func TestBuildHTTPClient_DefaultTimeout(t *testing.T) { + config := &oapi.PrometheusMetricProvider{} + client := buildHTTPClient(config) + + if client.Timeout != 30*time.Second { + t.Errorf("expected default 30s timeout, got %v", client.Timeout) + } + if client.Transport != nil { + t.Error("expected nil transport for non-insecure config") + } +} + +func TestBuildHTTPClient_CustomTimeout(t *testing.T) { + config := &oapi.PrometheusMetricProvider{ + Timeout: ptr(int64(60)), + } + client := buildHTTPClient(config) + + if client.Timeout != 60*time.Second { + t.Errorf("expected 60s timeout, got %v", client.Timeout) + } +} + +func TestBuildHTTPClient_Insecure(t *testing.T) { + config := &oapi.PrometheusMetricProvider{ + Insecure: ptr(true), + } + client := buildHTTPClient(config) + + if client.Transport == nil { + t.Fatal("expected transport to be set for insecure config") + } +} + +func TestBuildResultData_VectorSuccess(t *testing.T) { + body := `{ + "status": "success", + "data": { + "resultType": "vector", + "result": [ + {"metric": {"__name__": "up", "job": "prometheus"}, "value": [1700000000, "1"]} + ] + } + }` + + data, err := buildResultData(200, []byte(body), 50*time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if ok, _ := data["ok"].(bool); !ok { + t.Error("expected ok=true") + } + if sc, _ := data["statusCode"].(int); sc != 200 { + t.Errorf("expected statusCode=200, got %v", sc) + } + if dur, _ := data["duration"].(int64); dur != 50 { + t.Errorf("expected duration=50, got %v", dur) + } + if val, ok := data["value"].(*float64); !ok || val == nil || *val != 1.0 { + t.Errorf("expected value=1.0, got %v", data["value"]) + } + + results, ok := data["results"].([]map[string]any) + if !ok || len(results) != 1 { + t.Fatalf("expected 1 result, got %v", data["results"]) + } + if results[0]["value"] != 1.0 { + t.Errorf("expected result value=1.0, got %v", results[0]["value"]) + } + metric, ok := results[0]["metric"].(map[string]string) + if !ok { + t.Fatalf("expected metric to be map[string]string, got %T", results[0]["metric"]) + } + if metric["job"] != "prometheus" { + t.Errorf("expected job=prometheus, got %s", metric["job"]) + } +} + +func TestBuildResultData_VectorMultipleResults(t *testing.T) { + body := `{ + "status": "success", + "data": { + "resultType": "vector", + "result": [ + {"metric": {"instance": "a"}, "value": [1700000000, "0.5"]}, + {"metric": {"instance": "b"}, "value": [1700000000, "0.8"]} + ] + } + }` + + data, err := buildResultData(200, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + val := data["value"].(*float64) + if *val != 0.5 { + t.Errorf("expected primary value=0.5 (first element), got %v", *val) + } + + results := data["results"].([]map[string]any) + if len(results) != 2 { + t.Fatalf("expected 2 results, got %d", len(results)) + } +} + +func TestBuildResultData_VectorEmpty(t *testing.T) { + body := `{ + "status": "success", + "data": { + "resultType": "vector", + "result": [] + } + }` + + data, err := buildResultData(200, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if val, ok := data["value"].(*float64); ok && val != nil { + t.Errorf("expected nil value for empty vector, got %v", *val) + } +} + +func TestBuildResultData_VectorFirstElementUnparseable(t *testing.T) { + body := `{ + "status": "success", + "data": { + "resultType": "vector", + "result": [ + {"metric": {"instance": "a"}, "value": [1700000000, "not_a_number"]}, + {"metric": {"instance": "b"}, "value": [1700000000, "0.5"]} + ] + } + }` + + data, err := buildResultData(200, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + val, ok := data["value"].(*float64) + if !ok || val == nil { + t.Fatal("expected non-nil primary value from second element") + } + if *val != 0.5 { + t.Errorf("expected primary value=0.5 (first valid element), got %v", *val) + } +} + +func TestBuildResultData_MatrixSuccess(t *testing.T) { + body := `{ + "status": "success", + "data": { + "resultType": "matrix", + "result": [ + { + "metric": {"job": "prometheus"}, + "values": [ + [1700000000, "0.1"], + [1700000015, "0.2"], + [1700000030, "0.3"] + ] + } + ] + } + }` + + data, err := buildResultData(200, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + val := data["value"].(*float64) + if *val != 0.3 { + t.Errorf("expected primary value=0.3 (last in series), got %v", *val) + } + + results := data["results"].([]map[string]any) + if len(results) != 1 { + t.Fatalf("expected 1 result series, got %d", len(results)) + } + if results[0]["value"] != 0.3 { + t.Errorf("expected series value=0.3, got %v", results[0]["value"]) + } + values, ok := results[0]["values"].([]map[string]any) + if !ok { + t.Fatalf("expected values to be []map[string]any, got %T", results[0]["values"]) + } + if len(values) != 3 { + t.Errorf("expected 3 data points, got %d", len(values)) + } +} + +func TestBuildResultData_MatrixFirstSeriesEmpty(t *testing.T) { + body := `{ + "status": "success", + "data": { + "resultType": "matrix", + "result": [ + { + "metric": {"instance": "a"}, + "values": [] + }, + { + "metric": {"instance": "b"}, + "values": [[1700000000, "0.7"]] + } + ] + } + }` + + data, err := buildResultData(200, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + val, ok := data["value"].(*float64) + if !ok || val == nil { + t.Fatal("expected non-nil primary value from second series") + } + if *val != 0.7 { + t.Errorf("expected primary value=0.7 (first valid series), got %v", *val) + } +} + +func TestBuildResultData_ScalarSuccess(t *testing.T) { + body := `{ + "status": "success", + "data": { + "resultType": "scalar", + "result": [1700000000, "42.5"] + } + }` + + data, err := buildResultData(200, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + val := data["value"].(*float64) + if *val != 42.5 { + t.Errorf("expected value=42.5, got %v", *val) + } +} + +func TestBuildResultData_ErrorResponse(t *testing.T) { + body := `{ + "status": "error", + "errorType": "bad_data", + "error": "invalid expression" + }` + + data, err := buildResultData(400, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if ok, _ := data["ok"].(bool); ok { + t.Error("expected ok=false for error response") + } + if data["error"] != "invalid expression" { + t.Errorf("expected error message, got %v", data["error"]) + } + if data["errorType"] != "bad_data" { + t.Errorf("expected errorType=bad_data, got %v", data["errorType"]) + } +} + +func TestBuildResultData_Non2xxStatus(t *testing.T) { + body := `{"status": "success", "data": {"resultType": "vector", "result": []}}` + + data, err := buildResultData(503, []byte(body), time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if ok, _ := data["ok"].(bool); ok { + t.Error("expected ok=false for 503 even with status=success") + } + if sc, _ := data["statusCode"].(int); sc != 503 { + t.Errorf("expected statusCode=503, got %v", sc) + } +} + +func TestBuildResultData_InvalidJSON(t *testing.T) { + _, err := buildResultData(200, []byte("not json"), time.Millisecond) + if err == nil { + t.Fatal("expected error for invalid JSON") + } +} + +func TestBuildResultData_DataContract(t *testing.T) { + body := `{ + "status": "success", + "data": {"resultType": "vector", "result": [{"metric": {}, "value": [1700000000, "1"]}]} + }` + + data, err := buildResultData(200, []byte(body), 123*time.Millisecond) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + requiredKeys := []string{"ok", "statusCode", "body", "json", "duration", "value", "results"} + for _, key := range requiredKeys { + if _, exists := data[key]; !exists { + t.Errorf("missing required key %q in data map", key) + } + } + + if _, ok := data["ok"].(bool); !ok { + t.Errorf("ok should be bool, got %T", data["ok"]) + } + if _, ok := data["statusCode"].(int); !ok { + t.Errorf("statusCode should be int, got %T", data["statusCode"]) + } + if _, ok := data["body"].(string); !ok { + t.Errorf("body should be string, got %T", data["body"]) + } + if _, ok := data["duration"].(int64); !ok { + t.Errorf("duration should be int64, got %T", data["duration"]) + } + if data["duration"].(int64) != 123 { + t.Errorf("expected duration=123, got %v", data["duration"]) + } +} + +func TestResolveProviderTemplates(t *testing.T) { + token := "{{.variables.token}}" + config := &oapi.PrometheusMetricProvider{ + Address: "http://{{.variables.host}}:9090", + Query: `up{job="{{.deployment.name}}"}`, + Timeout: ptr(int64(30)), + Authentication: &prometheusAuth{ + BearerToken: &token, + }, + Headers: &[]prometheusHeader{ + {Key: "X-Tenant", Value: "{{.variables.tenant}}"}, + }, + } + + providerCtx := &provider.ProviderContext{ + Deployment: &oapi.Deployment{ + Id: "d1", + Name: "api", + Slug: "api", + SystemId: "s1", + }, + Variables: map[string]any{ + "host": "prometheus.internal", + "token": "secret123", + "tenant": "org-a", + }, + } + + resolved := resolveProviderTemplates(config, providerCtx) + + if resolved.Address != "http://prometheus.internal:9090" { + t.Errorf("expected resolved address, got %s", resolved.Address) + } + if resolved.Query != `up{job="api"}` { + t.Errorf("expected resolved query, got %s", resolved.Query) + } + if *resolved.Authentication.BearerToken != "secret123" { + t.Errorf("expected resolved bearer token, got %s", *resolved.Authentication.BearerToken) + } + if (*resolved.Headers)[0].Value != "org-a" { + t.Errorf("expected resolved header value, got %s", (*resolved.Headers)[0].Value) + } + if *resolved.Timeout != 30 { + t.Errorf("expected timeout preserved, got %d", *resolved.Timeout) + } +} + +func TestResolveProviderTemplates_NilOptionals(t *testing.T) { + config := &oapi.PrometheusMetricProvider{ + Address: "http://localhost:9090", + Query: "up", + } + + resolved := resolveProviderTemplates(config, &provider.ProviderContext{}) + + if resolved.Headers != nil { + t.Error("expected nil headers when input is nil") + } + if resolved.Authentication != nil { + t.Error("expected nil authentication when input is nil") + } +} + +func TestMeasure_InstantQueryE2E(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.Contains(r.URL.Path, "/api/v1/query") { + t.Errorf("expected /api/v1/query path, got %s", r.URL.Path) + } + if strings.Contains(r.URL.Path, "query_range") { + t.Error("expected instant query, got range query") + } + if r.URL.Query().Get("query") != `up{job="prometheus"}` { + t.Errorf("unexpected query param: %s", r.URL.Query().Get("query")) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{ + "status": "success", + "data": map[string]any{ + "resultType": "vector", + "result": []map[string]any{ + { + "metric": map[string]string{"__name__": "up", "job": "prometheus"}, + "value": []any{1700000000, "1"}, + }, + }, + }, + }) + })) + defer server.Close() + + p, err := NewPrometheusProvider(&oapi.PrometheusMetricProvider{ + Address: server.URL, + Query: `up{job="prometheus"}`, + Type: "prometheus", + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + measuredAt, data, err := p.Measure(context.Background(), &provider.ProviderContext{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if measuredAt.IsZero() { + t.Error("expected non-zero measuredAt") + } + if ok, _ := data["ok"].(bool); !ok { + t.Error("expected ok=true") + } + if val, ok := data["value"].(*float64); !ok || *val != 1.0 { + t.Errorf("expected value=1.0, got %v", data["value"]) + } +} + +func TestMeasure_RangeQueryE2E(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.Contains(r.URL.Path, "/api/v1/query_range") { + t.Errorf("expected /api/v1/query_range path, got %s", r.URL.Path) + } + if r.URL.Query().Get("step") != "15s" { + t.Errorf("expected step=15s, got %s", r.URL.Query().Get("step")) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]any{ + "status": "success", + "data": map[string]any{ + "resultType": "matrix", + "result": []map[string]any{ + { + "metric": map[string]string{"job": "test"}, + "values": [][]any{ + {1700000000, "0.1"}, + {1700000015, "0.2"}, + }, + }, + }, + }, + }) + })) + defer server.Close() + + p, err := NewPrometheusProvider(&oapi.PrometheusMetricProvider{ + Address: server.URL, + Query: "rate(requests[5m])", + Type: "prometheus", + RangeQuery: &struct { + End *string `json:"end,omitempty"` + Start *string `json:"start,omitempty"` + Step string `json:"step"` + }{ + Step: "15s", + }, + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + _, data, err := p.Measure(context.Background(), &provider.ProviderContext{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + val := data["value"].(*float64) + if *val != 0.2 { + t.Errorf("expected last matrix value=0.2, got %v", *val) + } +} + +func TestMeasure_BearerTokenSent(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if auth := r.Header.Get("Authorization"); auth != "Bearer test-token" { + t.Errorf("expected Bearer test-token, got %q", auth) + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"status":"success","data":{"resultType":"vector","result":[]}}`)) + })) + defer server.Close() + + token := "test-token" + p, _ := NewPrometheusProvider(&oapi.PrometheusMetricProvider{ + Address: server.URL, + Query: "up", + Type: "prometheus", + Authentication: &prometheusAuth{ + BearerToken: &token, + }, + }) + + _, _, err := p.Measure(context.Background(), &provider.ProviderContext{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestMeasure_CustomHeadersSent(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if got := r.Header.Get("X-Scope-OrgID"); got != "tenant_a" { + t.Errorf("expected X-Scope-OrgID=tenant_a, got %q", got) + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"status":"success","data":{"resultType":"vector","result":[]}}`)) + })) + defer server.Close() + + headers := []prometheusHeader{{Key: "X-Scope-OrgID", Value: "tenant_a"}} + p, _ := NewPrometheusProvider(&oapi.PrometheusMetricProvider{ + Address: server.URL, + Query: "up", + Type: "prometheus", + Headers: &headers, + }) + + _, _, err := p.Measure(context.Background(), &provider.ProviderContext{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestMeasure_PrometheusError(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(422) + _, _ = w.Write([]byte(`{"status":"error","errorType":"bad_data","error":"invalid query"}`)) + })) + defer server.Close() + + p, _ := NewPrometheusProvider(&oapi.PrometheusMetricProvider{ + Address: server.URL, + Query: "invalid{", + Type: "prometheus", + }) + + _, data, err := p.Measure(context.Background(), &provider.ProviderContext{}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if ok, _ := data["ok"].(bool); ok { + t.Error("expected ok=false for error response") + } + if data["error"] != "invalid query" { + t.Errorf("expected error field, got %v", data["error"]) + } +} + +func TestMeasure_ConnectionRefused(t *testing.T) { + p, _ := NewPrometheusProvider(&oapi.PrometheusMetricProvider{ + Address: "http://localhost:1", + Query: "up", + Type: "prometheus", + Timeout: ptr(int64(1)), + }) + + _, _, err := p.Measure(context.Background(), &provider.ProviderContext{}) + if err == nil { + t.Fatal("expected error for connection refused") + } +} + +func TestParseScalarValue(t *testing.T) { + tests := []struct { + name string + input json.RawMessage + want float64 + wantErr bool + }{ + {"quoted string", json.RawMessage(`"1.5"`), 1.5, false}, + {"quoted integer", json.RawMessage(`"42"`), 42.0, false}, + {"raw number", json.RawMessage(`1700000000`), 1700000000, false}, + {"quoted zero", json.RawMessage(`"0"`), 0, false}, + {"invalid", json.RawMessage(`"not_a_number"`), 0, true}, + {"null", json.RawMessage(`null`), 0, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseScalarValue(tt.input) + if tt.wantErr { + if err == nil { + t.Error("expected error but got none") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got != tt.want { + t.Errorf("parseScalarValue() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestFormatTimestamp(t *testing.T) { + ts := time.Date(2026, 2, 9, 12, 0, 0, 500000000, time.UTC) + got := formatTimestamp(ts) + + if !strings.Contains(got, ".") { + t.Errorf("expected sub-second precision, got %s", got) + } + + val, err := parseScalarValue(json.RawMessage(got)) + if err != nil { + t.Fatalf("formatTimestamp output should be parseable: %v", err) + } + if val < 1e9 { + t.Errorf("expected unix timestamp, got %v", val) + } +} diff --git a/packages/workspace-engine-sdk/src/schema.ts b/packages/workspace-engine-sdk/src/schema.ts index ffbd8571b..635b015c3 100644 --- a/packages/workspace-engine-sdk/src/schema.ts +++ b/packages/workspace-engine-sdk/src/schema.ts @@ -4,4567 +4,4714 @@ */ export interface paths { - "/v1/validate/resource-selector": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** Validate a resource selector */ - post: operations["validateResourceSelector"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List workspace IDs - * @description Returns a list of workspace that are in memory. These could be inactive. - */ - get: operations["listWorkspaceIds"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployment-versions/{versionId}/jobs-list": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployment version jobs list - * @description Returns jobs grouped by environment and release target for a deployment version. - */ - get: operations["getDeploymentVersionJobsList"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployments": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List deployments - * @description Returns a paginated list of deployments for a workspace. - */ - get: operations["listDeployments"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployment - * @description Returns a specific deployment by ID. - */ - get: operations["getDeployment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/policies": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get policies for a deployment - * @description Returns a list of resolved policies for a deployment. - */ - get: operations["getPoliciesForDeployment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/release-targets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get release targets for a deployment - * @description Returns a list of release targets for a deployment. - */ - get: operations["getReleaseTargetsForDeployment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/resources": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get resources for a deployment - * @description Returns a paginated list of resources for deployment {deploymentId}. - */ - get: operations["getDeploymentResources"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/versions": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get versions for a deployment - * @description Returns a list of releases for a deployment. - */ - get: operations["getVersionsForDeployment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deploymentversions/{deploymentVersionId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployment version - * @description Returns a deployment version by ID. - */ - get: operations["getDeploymentVersion"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/entities/{relatableEntityType}/{entityId}/relations": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get related entities for a given entity - * @description Returns all entities related to the specified entity (deployment, environment, or resource) based on relationship rules. Relationships are grouped by relationship reference. - */ - get: operations["getRelatedEntities"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/environments": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List environments - * @description Returns a list of environments for a workspace. - */ - get: operations["listEnvironments"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/environments/{environmentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get environment - * @description Returns a specific environment by ID. - */ - get: operations["getEnvironment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/environments/{environmentId}/release-targets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get release targets for an environment - * @description Returns a list of release targets for an environment. - */ - get: operations["getReleaseTargetsForEnvironment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/environments/{environmentId}/resources": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get resources for an environment - * @description Returns a paginated list of resources for environment {environmentId}. - */ - get: operations["getEnvironmentResources"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/github-entities/{installationId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get GitHub entity by installation ID - * @description Returns a GitHub entity by installation ID. - */ - get: operations["getGitHubEntityByInstallationId"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/job-agents": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get job agents - * @description Returns a list of job agents. - */ - get: operations["getJobAgents"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/job-agents/{jobAgentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get job agent - * @description Returns a specific job agent by ID. - */ - get: operations["getJobAgent"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/job-agents/{jobAgentId}/deployments": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployments for a job agent - * @description Returns a list of deployments for a job agent. - */ - get: operations["getDeploymentsForJobAgent"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/job-agents/{jobAgentId}/jobs": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get jobs for a job agent - * @description Returns a list of jobs for a job agent. - */ - get: operations["getJobsForJobAgent"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/jobs": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List jobs - * @description Returns a list of jobs. - */ - get: operations["getJobs"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/jobs/{jobId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get job - * @description Returns a specific job by ID. - */ - get: operations["getJob"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/jobs/{jobId}/with-release": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get job with release - * @description Returns a specific job by ID with its release. - */ - get: operations["getJobWithRelease"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policies": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List policies - * @description Returns a list of policies for workspace {workspaceId}. - */ - get: operations["listPolicies"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policies/evaluate": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Evaluate policies - * @description Evaluates all policies for a workspace. - */ - post: operations["evaluatePolicies"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policies/{policyId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get policy - * @description Returns a specific policy by ID. - */ - get: operations["getPolicy"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policies/{policyId}/release-targets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get release targets for a policy - * @description Returns a list of release targets for a policy {policyId}. - */ - get: operations["getReleaseTargetsForPolicy"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policies/{policyId}/rules/{ruleId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get rule - * @description Returns a specific rule by ID. - */ - get: operations["getRule"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policy-skips": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List policy skips for a workspace - * @description Returns a list of policy skips for workspace {workspaceId}. - */ - get: operations["listPolicySkips"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policy-skips/environment/{environmentId}/version/{deploymentVersionId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get policy skips for an environment and version - * @description Returns a list of policy skips for an environment and version. - */ - get: operations["getPolicySkipsForEnvironmentAndVersion"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/policy-skips/{policySkipId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get policy skip by ID - * @description Returns a specific policy skip by ID. - */ - get: operations["getPolicySkip"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/relationship-rules": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get relationship rules for a given workspace - * @description Returns all relationship rules for the specified workspace. - */ - get: operations["getRelationshipRules"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/relationship-rules/{relationshipRuleId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get relationship rule */ - get: operations["getRelationshipRule"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/release-targets/evaluate": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Evaluate policies for a release target - * @description Evaluates all policies and rules that apply to a given release target and returns the evaluation results. - */ - post: operations["evaluateReleaseTarget"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/desired-release": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get the desired release for a release target - * @description Returns the desired release for a release target {releaseTargetKey}. - */ - get: operations["getReleaseTargetDesiredRelease"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/jobs": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get jobs for a release target - * @description Returns a list of jobs for a release target {releaseTargetKey}. - */ - get: operations["getJobsForReleaseTarget"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/policies": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get policies for a release target - * @description Returns a list of policies for a release target {releaseTargetId}. - */ - get: operations["getPoliciesForReleaseTarget"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/state": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get the state for a release target - * @description Returns the state for a release target {releaseTargetKey}. - */ - get: operations["getReleaseTargetState"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/releases/{releaseId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get release - * @description Returns a specific release by ID. - */ - get: operations["getRelease"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/releases/{releaseId}/verifications": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get release verifications - * @description Returns all verifications for jobs belonging to this release. - */ - get: operations["getReleaseVerifications"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resource-providers": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get all resource providers */ - get: operations["getResourceProviders"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resource-providers/cache-batch": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Cache a large resource batch for deferred processing - * @description Stores resources in memory and returns a batch ID. The batch is processed when a corresponding Kafka event is received. Uses Ristretto cache with 5-minute TTL. - */ - post: operations["cacheBatch"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resource-providers/name/{name}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** Get a resource provider by name */ - get: operations["getResourceProviderByName"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/kinds": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get kinds for a workspace - * @description Returns a list of all resource kinds in a workspace. - */ - get: operations["getKindsForWorkspace"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/query": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Query resources with CEL expression - * @description Returns paginated resources that match the provided CEL expression. Use the "resource" variable in your expression to access resource properties. - */ - post: operations["queryResources"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get resource by identifier - * @description Returns a specific resource by its identifier. - */ - get: operations["getResourceByIdentifier"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/deployments": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployments for a resource - * @description Returns a paginated list of deployments that match the given resource. - */ - get: operations["getDeploymentsForResource"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/relationships": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get relationships for a resource - * @description Returns all relationships for the specified resource. - */ - get: operations["getRelationshipsForResource"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/release-targets": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get release targets for a resource - * @description Returns a list of release targets for a resource. - */ - get: operations["getReleaseTargetsForResource"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/release-targets/deployment/{deploymentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get release target for a resource in a deployment - * @description Returns a release target for a resource in a deployment. - */ - get: operations["getReleaseTargetForResourceInDeployment"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/variables": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get variables for a resource - * @description Returns a list of variables for a resource - */ - get: operations["getVariablesForResource"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/status": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get engine status - * @description Returns the status of the engine. - */ - get: operations["getEngineStatus"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/systems": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List systems - * @description Returns a list of systems for a workspace. - */ - get: operations["listSystems"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/systems/{systemId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; + "/v1/validate/resource-selector": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Validate a resource selector */ + post: operations["validateResourceSelector"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List workspace IDs + * @description Returns a list of workspace that are in memory. These could be inactive. + */ + get: operations["listWorkspaceIds"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployment-versions/{versionId}/jobs-list": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployment version jobs list + * @description Returns jobs grouped by environment and release target for a deployment version. + */ + get: operations["getDeploymentVersionJobsList"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List deployments + * @description Returns a paginated list of deployments for a workspace. + */ + get: operations["listDeployments"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployments/{deploymentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployment + * @description Returns a specific deployment by ID. + */ + get: operations["getDeployment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/policies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get policies for a deployment + * @description Returns a list of resolved policies for a deployment. + */ + get: operations["getPoliciesForDeployment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/release-targets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get release targets for a deployment + * @description Returns a list of release targets for a deployment. + */ + get: operations["getReleaseTargetsForDeployment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/resources": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get resources for a deployment + * @description Returns a paginated list of resources for deployment {deploymentId}. + */ + get: operations["getDeploymentResources"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/versions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get versions for a deployment + * @description Returns a list of releases for a deployment. + */ + get: operations["getVersionsForDeployment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deploymentversions/{deploymentVersionId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployment version + * @description Returns a deployment version by ID. + */ + get: operations["getDeploymentVersion"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/entities/{relatableEntityType}/{entityId}/relations": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get related entities for a given entity + * @description Returns all entities related to the specified entity (deployment, environment, or resource) based on relationship rules. Relationships are grouped by relationship reference. + */ + get: operations["getRelatedEntities"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/environments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List environments + * @description Returns a list of environments for a workspace. + */ + get: operations["listEnvironments"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/environments/{environmentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get environment + * @description Returns a specific environment by ID. + */ + get: operations["getEnvironment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/environments/{environmentId}/release-targets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get release targets for an environment + * @description Returns a list of release targets for an environment. + */ + get: operations["getReleaseTargetsForEnvironment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/environments/{environmentId}/resources": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get resources for an environment + * @description Returns a paginated list of resources for environment {environmentId}. + */ + get: operations["getEnvironmentResources"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/github-entities/{installationId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get GitHub entity by installation ID + * @description Returns a GitHub entity by installation ID. + */ + get: operations["getGitHubEntityByInstallationId"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/job-agents": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get job agents + * @description Returns a list of job agents. + */ + get: operations["getJobAgents"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/job-agents/{jobAgentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get job agent + * @description Returns a specific job agent by ID. + */ + get: operations["getJobAgent"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/job-agents/{jobAgentId}/deployments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployments for a job agent + * @description Returns a list of deployments for a job agent. + */ + get: operations["getDeploymentsForJobAgent"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/job-agents/{jobAgentId}/jobs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get jobs for a job agent + * @description Returns a list of jobs for a job agent. + */ + get: operations["getJobsForJobAgent"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/jobs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List jobs + * @description Returns a list of jobs. + */ + get: operations["getJobs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/jobs/{jobId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get job + * @description Returns a specific job by ID. + */ + get: operations["getJob"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/jobs/{jobId}/with-release": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get job with release + * @description Returns a specific job by ID with its release. + */ + get: operations["getJobWithRelease"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List policies + * @description Returns a list of policies for workspace {workspaceId}. + */ + get: operations["listPolicies"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policies/evaluate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Evaluate policies + * @description Evaluates all policies for a workspace. + */ + post: operations["evaluatePolicies"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policies/{policyId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get policy + * @description Returns a specific policy by ID. + */ + get: operations["getPolicy"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policies/{policyId}/release-targets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get release targets for a policy + * @description Returns a list of release targets for a policy {policyId}. + */ + get: operations["getReleaseTargetsForPolicy"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policies/{policyId}/rules/{ruleId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get rule + * @description Returns a specific rule by ID. + */ + get: operations["getRule"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policy-skips": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List policy skips for a workspace + * @description Returns a list of policy skips for workspace {workspaceId}. + */ + get: operations["listPolicySkips"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policy-skips/environment/{environmentId}/version/{deploymentVersionId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get policy skips for an environment and version + * @description Returns a list of policy skips for an environment and version. + */ + get: operations["getPolicySkipsForEnvironmentAndVersion"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/policy-skips/{policySkipId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get policy skip by ID + * @description Returns a specific policy skip by ID. + */ + get: operations["getPolicySkip"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/relationship-rules": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get relationship rules for a given workspace + * @description Returns all relationship rules for the specified workspace. + */ + get: operations["getRelationshipRules"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/relationship-rules/{relationshipRuleId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get relationship rule */ + get: operations["getRelationshipRule"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/release-targets/evaluate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Evaluate policies for a release target + * @description Evaluates all policies and rules that apply to a given release target and returns the evaluation results. + */ + post: operations["evaluateReleaseTarget"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/desired-release": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get the desired release for a release target + * @description Returns the desired release for a release target {releaseTargetKey}. + */ + get: operations["getReleaseTargetDesiredRelease"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/jobs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get jobs for a release target + * @description Returns a list of jobs for a release target {releaseTargetKey}. + */ + get: operations["getJobsForReleaseTarget"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/policies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get policies for a release target + * @description Returns a list of policies for a release target {releaseTargetId}. + */ + get: operations["getPoliciesForReleaseTarget"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/state": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get the state for a release target + * @description Returns the state for a release target {releaseTargetKey}. + */ + get: operations["getReleaseTargetState"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/releases/{releaseId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get release + * @description Returns a specific release by ID. + */ + get: operations["getRelease"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/releases/{releaseId}/verifications": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get release verifications + * @description Returns all verifications for jobs belonging to this release. + */ + get: operations["getReleaseVerifications"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resource-providers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get all resource providers */ + get: operations["getResourceProviders"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resource-providers/cache-batch": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Cache a large resource batch for deferred processing + * @description Stores resources in memory and returns a batch ID. The batch is processed when a corresponding Kafka event is received. Uses Ristretto cache with 5-minute TTL. + */ + post: operations["cacheBatch"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resource-providers/name/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get a resource provider by name */ + get: operations["getResourceProviderByName"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/kinds": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get kinds for a workspace + * @description Returns a list of all resource kinds in a workspace. + */ + get: operations["getKindsForWorkspace"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/query": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Query resources with CEL expression + * @description Returns paginated resources that match the provided CEL expression. Use the "resource" variable in your expression to access resource properties. + */ + post: operations["queryResources"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get resource by identifier + * @description Returns a specific resource by its identifier. + */ + get: operations["getResourceByIdentifier"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/deployments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployments for a resource + * @description Returns a paginated list of deployments that match the given resource. + */ + get: operations["getDeploymentsForResource"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/relationships": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get relationships for a resource + * @description Returns all relationships for the specified resource. + */ + get: operations["getRelationshipsForResource"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/release-targets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get release targets for a resource + * @description Returns a list of release targets for a resource. + */ + get: operations["getReleaseTargetsForResource"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/release-targets/deployment/{deploymentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get release target for a resource in a deployment + * @description Returns a release target for a resource in a deployment. + */ + get: operations["getReleaseTargetForResourceInDeployment"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/variables": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get variables for a resource + * @description Returns a list of variables for a resource + */ + get: operations["getVariablesForResource"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get engine status + * @description Returns the status of the engine. + */ + get: operations["getEngineStatus"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/systems": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List systems + * @description Returns a list of systems for a workspace. + */ + get: operations["listSystems"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/systems/{systemId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get system + * @description Returns a specific system by ID. + */ + get: operations["getSystem"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/workflow-templates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get all workflow templates + * @description Gets all workflow templates for a workspace. + */ + get: operations["getWorkflowTemplates"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/workflow-templates/{workflowTemplateId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get a workflow template + * @description Gets a workflow template. + */ + get: operations["getWorkflowTemplate"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/workflow-templates/{workflowTemplateId}/workflows": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get all workflows for a workflow template + * @description Gets all workflows for a workflow template. + */ + get: operations["getWorkflowsByTemplate"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + AnyApprovalRule: { + /** Format: int32 */ + minApprovals: number; + }; + /** @enum {string} */ + ApprovalStatus: "approved" | "rejected"; + ArgoCDJobAgentConfig: { + /** @description ArgoCD API token. */ + apiKey: string; + /** @description ArgoCD server address (host[:port] or URL). */ + serverUrl: string; + /** @description ArgoCD application template. */ + template: string; + }; + BooleanValue: boolean; + CelMatcher: { + cel: string; + }; + CelSelector: { + cel: string; + }; + DatadogMetricProvider: { + /** + * @description Datadog aggregator + * @default last + * @enum {string} + */ + aggregator: + | "avg" + | "min" + | "max" + | "sum" + | "last" + | "percentile" + | "mean" + | "l2norm" + | "area"; + /** + * @description Datadog API key (supports Go templates for variable references) + * @example {{.variables.dd_api_key}} + */ + apiKey: string; + /** + * @description Datadog Application key (supports Go templates for variable references) + * @example {{.variables.dd_app_key}} + */ + appKey: string; + /** @description Datadog formula (supports Go templates) */ + formula?: string; + /** + * Format: int64 + * @example 30 + */ + intervalSeconds?: number; + /** + * @description Datadog metrics queries (supports Go templates) + * @example { + * "q": "sum:requests.error.rate{service:{{.resource.name}}}" + * } + */ + queries: { + [key: string]: string; + }; + /** + * @description Datadog site URL (e.g., datadoghq.com, datadoghq.eu, us3.datadoghq.com) + * @default datadoghq.com + */ + site: string; + /** + * @description Provider type (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: "datadog"; + }; + DeployDecision: { + policyResults: components["schemas"]["PolicyEvaluation"][]; + }; + Deployment: { + description?: string; + id: string; + jobAgentConfig: components["schemas"]["JobAgentConfig"]; + jobAgentId?: string; + metadata: { + [key: string]: string; + }; + name: string; + resourceSelector?: components["schemas"]["Selector"]; + slug: string; + systemId: string; + }; + DeploymentAndSystem: { + deployment: components["schemas"]["Deployment"]; + system: components["schemas"]["System"]; + }; + DeploymentDependencyRule: { + dependsOnDeploymentSelector: components["schemas"]["Selector"]; + /** @description Reference to the entity that this rule depends on */ + reference?: string; + }; + DeploymentVariable: { + defaultValue?: components["schemas"]["LiteralValue"]; + deploymentId: string; + description?: string; + id: string; + key: string; + }; + DeploymentVariableValue: { + deploymentVariableId: string; + id: string; + /** Format: int64 */ + priority: number; + resourceSelector?: components["schemas"]["Selector"]; + value: components["schemas"]["Value"]; + }; + DeploymentVariableWithValues: { + values: components["schemas"]["DeploymentVariableValue"][]; + variable: components["schemas"]["DeploymentVariable"]; + }; + DeploymentVersion: { + config: { + [key: string]: unknown; + }; + /** Format: date-time */ + createdAt: string; + deploymentId: string; + id: string; + jobAgentConfig: components["schemas"]["JobAgentConfig"]; + message?: string; + metadata: { + [key: string]: string; + }; + name: string; + status: components["schemas"]["DeploymentVersionStatus"]; + tag: string; + }; + /** @enum {string} */ + DeploymentVersionStatus: + | "unspecified" + | "building" + | "ready" + | "failed" + | "rejected" + | "paused"; + DeploymentWindowRule: { + /** + * @description If true, deployments are only allowed during the window. If false, deployments are blocked during the window (deny window) + * @default true + */ + allowWindow: boolean; + /** + * Format: int32 + * @description Duration of each deployment window in minutes + */ + durationMinutes: number; + /** @description RFC 5545 recurrence rule defining when deployment windows start (e.g., FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9) */ + rrule: string; + /** @description IANA timezone for the rrule (e.g., America/New_York). Defaults to UTC if not specified */ + timezone?: string; + }; + DeploymentWithVariables: { + deployment: components["schemas"]["Deployment"]; + variables: components["schemas"]["DeploymentVariableWithValues"][]; + }; + EntityRelation: { + direction: components["schemas"]["RelationDirection"]; + entity: components["schemas"]["RelatableEntity"]; + /** @description ID of the related entity */ + entityId: string; + entityType: components["schemas"]["RelatableEntityType"]; + rule: components["schemas"]["RelationshipRule"]; + }; + Environment: { + /** Format: date-time */ + createdAt: string; + description?: string; + id: string; + metadata: { + [key: string]: string; + }; + name: string; + resourceSelector?: components["schemas"]["Selector"]; + systemId: string; + }; + EnvironmentProgressionRule: { + dependsOnEnvironmentSelector: components["schemas"]["Selector"]; + /** + * Format: int32 + * @description Maximum age of dependency deployment before blocking progression (prevents stale promotions) + */ + maximumAgeHours?: number; + /** + * Format: int32 + * @description Minimum time to wait after the depends on environment is in a success state before the current environment can be deployed + * @default 0 + */ + minimumSockTimeMinutes: number; + /** + * Format: float + * @default 100 + */ + minimumSuccessPercentage: number; + successStatuses?: components["schemas"]["JobStatus"][]; + }; + ErrorResponse: { + /** @example Workspace not found */ + error?: string; + }; + EvaluateReleaseTargetRequest: { + releaseTarget: components["schemas"]["ReleaseTarget"]; + version: components["schemas"]["DeploymentVersion"]; + }; + EvaluationScope: { + environmentId?: string; + versionId?: string; + }; + GithubEntity: { + installationId: number; + slug: string; + }; + GithubJobAgentConfig: { + /** + * Format: int + * @description GitHub app installation ID. + */ + installationId: number; + /** @description GitHub repository owner. */ + owner: string; + /** @description Git ref to run the workflow on (defaults to "main" if omitted). */ + ref?: string; + /** @description GitHub repository name. */ + repo: string; + /** + * Format: int64 + * @description GitHub Actions workflow ID. + */ + workflowId: number; + }; + GradualRolloutRule: { + /** + * @description Strategy for scheduling deployments to release targets. "linear": Each target is deployed at a fixed interval of timeScaleInterval seconds. "linear-normalized": Deployments are spaced evenly so that the last target is scheduled at or before timeScaleInterval seconds. See rolloutType algorithm documentation for details. + * @enum {string} + */ + rolloutType: "linear" | "linear-normalized"; + /** + * Format: int32 + * @description Base time interval in seconds used to compute the delay between deployments to release targets. + */ + timeScaleInterval: number; + }; + HTTPMetricProvider: { + /** @description Request body (supports Go templates) */ + body?: string; + /** @description HTTP headers (values support Go templates) */ + headers?: { + [key: string]: string; + }; + /** + * @description HTTP method + * @default GET + * @enum {string} + */ + method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS"; + /** + * @description Request timeout (duration string, e.g., "30s") + * @default 30s + */ + timeout: string; + /** + * @description Provider type (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: "http"; + /** + * @description HTTP endpoint URL (supports Go templates) + * @example http://{{ .resource.name }}.{{ .environment.name }}/health + */ + url: string; + }; + IntegerValue: number; + Job: { + /** Format: date-time */ + completedAt?: string; + /** Format: date-time */ + createdAt: string; + externalId?: string; + id: string; + jobAgentConfig: components["schemas"]["JobAgentConfig"]; + jobAgentId: string; + message?: string; + metadata: { + [key: string]: string; + }; + releaseId: string; + /** Format: date-time */ + startedAt?: string; + status: components["schemas"]["JobStatus"]; + traceToken?: string; + /** Format: date-time */ + updatedAt: string; + workflowJobId: string; + }; + JobAgent: { + config: components["schemas"]["JobAgentConfig"]; + id: string; + metadata?: { + [key: string]: string; + }; + name: string; + type: string; + workspaceId: string; + }; + JobAgentConfig: { + [key: string]: unknown; + }; + /** @enum {string} */ + JobStatus: + | "cancelled" + | "skipped" + | "inProgress" + | "actionRequired" + | "pending" + | "failure" + | "invalidJobAgent" + | "invalidIntegration" + | "externalRunNotFound" + | "successful"; + JobUpdateEvent: { + agentId?: string; + externalId?: string; + fieldsToUpdate?: ( + | "completedAt" + | "createdAt" + | "externalId" + | "id" + | "jobAgentConfig" + | "jobAgentId" + | "message" + | "metadata" + | "releaseId" + | "startedAt" + | "status" + | "traceToken" + | "updatedAt" + | "workflowJobId" + )[]; + id?: string; + job: components["schemas"]["Job"]; + } & (unknown | unknown); + JobVerification: { + /** + * Format: date-time + * @description When verification was created + */ + createdAt: string; + id: string; + jobId: string; + /** @description Summary message of verification result */ + message?: string; + /** @description Metrics associated with this verification */ + metrics: components["schemas"]["VerificationMetricStatus"][]; + }; + /** @enum {string} */ + JobVerificationStatus: "running" | "passed" | "failed" | "cancelled"; + JobWithRelease: { + deployment?: components["schemas"]["Deployment"]; + environment?: components["schemas"]["Environment"]; + job: components["schemas"]["Job"]; + release: components["schemas"]["Release"]; + resource?: components["schemas"]["Resource"]; + }; + JobWithVerifications: { + job: components["schemas"]["Job"]; + verifications: components["schemas"]["JobVerification"][]; + }; + JsonSelector: { + json: { + [key: string]: unknown; + }; + }; + LiteralValue: + | components["schemas"]["BooleanValue"] + | components["schemas"]["NumberValue"] + | components["schemas"]["IntegerValue"] + | components["schemas"]["StringValue"] + | components["schemas"]["ObjectValue"] + | components["schemas"]["NullValue"]; + MetricProvider: + | components["schemas"]["HTTPMetricProvider"] + | components["schemas"]["SleepMetricProvider"] + | components["schemas"]["DatadogMetricProvider"] + | components["schemas"]["PrometheusMetricProvider"] + | components["schemas"]["TerraformCloudRunMetricProvider"]; + /** @enum {boolean} */ + NullValue: true; + NumberValue: number; + ObjectValue: { + object: { + [key: string]: unknown; + }; + }; + Policy: { + createdAt: string; + description?: string; + enabled: boolean; + id: string; + /** @description Arbitrary metadata for the policy (record) */ + metadata: { + [key: string]: string; + }; + name: string; + priority: number; + rules: components["schemas"]["PolicyRule"][]; + /** @description CEL expression for matching release targets. Use "true" to match all targets. */ + selector: string; + workspaceId: string; + }; + PolicyEvaluation: { + policy?: components["schemas"]["Policy"]; + ruleResults: components["schemas"]["RuleEvaluation"][]; + summary?: string; + }; + PolicyRule: { + anyApproval?: components["schemas"]["AnyApprovalRule"]; + createdAt: string; + deploymentDependency?: components["schemas"]["DeploymentDependencyRule"]; + deploymentWindow?: components["schemas"]["DeploymentWindowRule"]; + environmentProgression?: components["schemas"]["EnvironmentProgressionRule"]; + gradualRollout?: components["schemas"]["GradualRolloutRule"]; + id: string; + policyId: string; + retry?: components["schemas"]["RetryRule"]; + rollback?: components["schemas"]["RollbackRule"]; + verification?: components["schemas"]["VerificationRule"]; + versionCooldown?: components["schemas"]["VersionCooldownRule"]; + versionSelector?: components["schemas"]["VersionSelectorRule"]; + }; + PolicySkip: { + /** + * Format: date-time + * @description When this skip was created + */ + createdAt: string; + /** @description User ID who created this skip */ + createdBy: string; + /** @description Environment this skip applies to. If null, applies to all environments. */ + environmentId?: string; + /** + * Format: date-time + * @description When this skip expires. If null, skip never expires. + */ + expiresAt?: string; + /** @description Unique identifier for the skip */ + id: string; + /** @description Required reason for why this skip is needed (e.g., incident ticket, emergency situation) */ + reason: string; + /** @description Resource this skip applies to. If null, applies to all resources (in the environment if specified, or globally). */ + resourceId?: string; + /** @description Rule ID this skip applies to */ + ruleId: string; + /** @description Deployment version this skip applies to */ + versionId: string; + /** @description Workspace this skip belongs to */ + workspaceId: string; + }; + PrometheusMetricProvider: { + /** + * @description Prometheus server address (supports Go templates) + * @example http://prometheus.example.com:9090 + */ + address: string; + /** @description Authentication configuration for Prometheus */ + authentication?: { /** - * Get system - * @description Returns a specific system by ID. + * @description Bearer token for authentication (supports Go templates for variable references) + * @example {{.variables.prometheus_token}} */ - get: operations["getSystem"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/workflow-templates": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; + bearerToken?: string; + /** @description OAuth2 client credentials flow */ + oauth2?: { + /** @description OAuth2 client ID (supports Go templates) */ + clientId: string; + /** @description OAuth2 client secret (supports Go templates) */ + clientSecret: string; + /** @description OAuth2 scopes */ + scopes?: string[]; + /** @description Token endpoint URL */ + tokenUrl: string; + }; + }; + /** @description Additional HTTP headers for the Prometheus request (values support Go templates) */ + headers?: { + /** @example X-Scope-OrgID */ + key: string; + /** @example tenant_a */ + value: string; + }[]; + /** + * @description Skip TLS certificate verification + * @default false + */ + insecure: boolean; + /** + * @description PromQL query expression (supports Go templates) + * @example sum(irate(istio_requests_total{reporter="source",destination_service=~"{{.resource.name}}",response_code!~"5.*"}[5m])) + */ + query: string; + /** @description If provided, a range query (/api/v1/query_range) is used instead of an instant query (/api/v1/query) */ + rangeQuery?: { /** - * Get all workflow templates - * @description Gets all workflow templates for a workspace. + * @description How far back from now for the query end, as a Prometheus duration (e.g., "0s" for now, "1m" for 1 minute ago). Defaults to "0s" (now) if unset. + * @example 0s */ - get: operations["getWorkflowTemplates"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/workflow-templates/{workflowTemplateId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; + end?: string; /** - * Get a workflow template - * @description Gets a workflow template. + * @description How far back from now to start the query, as a Prometheus duration (e.g., "5m", "1h"). Defaults to 10 * step if unset. + * @example 5m */ - get: operations["getWorkflowTemplate"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/workflow-templates/{workflowTemplateId}/workflows": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; + start?: string; /** - * Get all workflows for a workflow template - * @description Gets all workflows for a workflow template. + * @description Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms") + * @example 1m */ - get: operations["getWorkflowsByTemplate"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; + step: string; + }; + /** + * Format: int64 + * @description Query timeout in seconds + * @example 30 + */ + timeout?: number; + /** + * @description Provider type (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: "prometheus"; }; -} -export type webhooks = Record; -export interface components { - schemas: { - AnyApprovalRule: { - /** Format: int32 */ - minApprovals: number; - }; - /** @enum {string} */ - ApprovalStatus: "approved" | "rejected"; - ArgoCDJobAgentConfig: { - /** @description ArgoCD API token. */ - apiKey: string; - /** @description ArgoCD server address (host[:port] or URL). */ - serverUrl: string; - /** @description ArgoCD application template. */ - template: string; - }; - BooleanValue: boolean; - CelMatcher: { - cel: string; - }; - CelSelector: { - cel: string; - }; - DatadogMetricProvider: { - /** - * @description Datadog aggregator - * @default last - * @enum {string} - */ - aggregator: "avg" | "min" | "max" | "sum" | "last" | "percentile" | "mean" | "l2norm" | "area"; - /** - * @description Datadog API key (supports Go templates for variable references) - * @example {{.variables.dd_api_key}} - */ - apiKey: string; - /** - * @description Datadog Application key (supports Go templates for variable references) - * @example {{.variables.dd_app_key}} - */ - appKey: string; - /** @description Datadog formula (supports Go templates) */ - formula?: string; - /** - * Format: int64 - * @example 30 - */ - intervalSeconds?: number; - /** - * @description Datadog metrics queries (supports Go templates) - * @example { - * "q": "sum:requests.error.rate{service:{{.resource.name}}}" - * } - */ - queries: { - [key: string]: string; - }; - /** - * @description Datadog site URL (e.g., datadoghq.com, datadoghq.eu, us3.datadoghq.com) - * @default datadoghq.com - */ - site: string; - /** - * @description Provider type (enum property replaced by openapi-typescript) - * @enum {string} - */ - type: "datadog"; - }; - DeployDecision: { - policyResults: components["schemas"]["PolicyEvaluation"][]; - }; - Deployment: { - description?: string; - id: string; - jobAgentConfig: components["schemas"]["JobAgentConfig"]; - jobAgentId?: string; - metadata: { - [key: string]: string; - }; - name: string; - resourceSelector?: components["schemas"]["Selector"]; - slug: string; - systemId: string; - }; - DeploymentAndSystem: { - deployment: components["schemas"]["Deployment"]; - system: components["schemas"]["System"]; - }; - DeploymentDependencyRule: { - dependsOnDeploymentSelector: components["schemas"]["Selector"]; - /** @description Reference to the entity that this rule depends on */ - reference?: string; - }; - DeploymentVariable: { - defaultValue?: components["schemas"]["LiteralValue"]; - deploymentId: string; - description?: string; - id: string; - key: string; - }; - DeploymentVariableValue: { - deploymentVariableId: string; - id: string; - /** Format: int64 */ - priority: number; - resourceSelector?: components["schemas"]["Selector"]; - value: components["schemas"]["Value"]; - }; - DeploymentVariableWithValues: { - values: components["schemas"]["DeploymentVariableValue"][]; - variable: components["schemas"]["DeploymentVariable"]; - }; - DeploymentVersion: { - config: { - [key: string]: unknown; - }; - /** Format: date-time */ - createdAt: string; - deploymentId: string; - id: string; - jobAgentConfig: components["schemas"]["JobAgentConfig"]; - message?: string; - metadata: { - [key: string]: string; - }; - name: string; - status: components["schemas"]["DeploymentVersionStatus"]; - tag: string; - }; - /** @enum {string} */ - DeploymentVersionStatus: "unspecified" | "building" | "ready" | "failed" | "rejected" | "paused"; - DeploymentWindowRule: { - /** - * @description If true, deployments are only allowed during the window. If false, deployments are blocked during the window (deny window) - * @default true - */ - allowWindow: boolean; - /** - * Format: int32 - * @description Duration of each deployment window in minutes - */ - durationMinutes: number; - /** @description RFC 5545 recurrence rule defining when deployment windows start (e.g., FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9) */ - rrule: string; - /** @description IANA timezone for the rrule (e.g., America/New_York). Defaults to UTC if not specified */ - timezone?: string; - }; - DeploymentWithVariables: { - deployment: components["schemas"]["Deployment"]; - variables: components["schemas"]["DeploymentVariableWithValues"][]; - }; - EntityRelation: { - direction: components["schemas"]["RelationDirection"]; - entity: components["schemas"]["RelatableEntity"]; - /** @description ID of the related entity */ - entityId: string; - entityType: components["schemas"]["RelatableEntityType"]; - rule: components["schemas"]["RelationshipRule"]; - }; - Environment: { - /** Format: date-time */ - createdAt: string; - description?: string; - id: string; - metadata: { - [key: string]: string; - }; - name: string; - resourceSelector?: components["schemas"]["Selector"]; - systemId: string; - }; - EnvironmentProgressionRule: { - dependsOnEnvironmentSelector: components["schemas"]["Selector"]; - /** - * Format: int32 - * @description Maximum age of dependency deployment before blocking progression (prevents stale promotions) - */ - maximumAgeHours?: number; - /** - * Format: int32 - * @description Minimum time to wait after the depends on environment is in a success state before the current environment can be deployed - * @default 0 - */ - minimumSockTimeMinutes: number; - /** - * Format: float - * @default 100 - */ - minimumSuccessPercentage: number; - successStatuses?: components["schemas"]["JobStatus"][]; - }; - ErrorResponse: { - /** @example Workspace not found */ - error?: string; - }; - EvaluateReleaseTargetRequest: { - releaseTarget: components["schemas"]["ReleaseTarget"]; - version: components["schemas"]["DeploymentVersion"]; - }; - EvaluationScope: { - environmentId?: string; - versionId?: string; - }; - GithubEntity: { - installationId: number; - slug: string; - }; - GithubJobAgentConfig: { - /** - * Format: int - * @description GitHub app installation ID. - */ - installationId: number; - /** @description GitHub repository owner. */ - owner: string; - /** @description Git ref to run the workflow on (defaults to "main" if omitted). */ - ref?: string; - /** @description GitHub repository name. */ - repo: string; - /** - * Format: int64 - * @description GitHub Actions workflow ID. - */ - workflowId: number; - }; - GradualRolloutRule: { - /** - * @description Strategy for scheduling deployments to release targets. "linear": Each target is deployed at a fixed interval of timeScaleInterval seconds. "linear-normalized": Deployments are spaced evenly so that the last target is scheduled at or before timeScaleInterval seconds. See rolloutType algorithm documentation for details. - * @enum {string} - */ - rolloutType: "linear" | "linear-normalized"; - /** - * Format: int32 - * @description Base time interval in seconds used to compute the delay between deployments to release targets. - */ - timeScaleInterval: number; - }; - HTTPMetricProvider: { - /** @description Request body (supports Go templates) */ - body?: string; - /** @description HTTP headers (values support Go templates) */ - headers?: { - [key: string]: string; - }; - /** - * @description HTTP method - * @default GET - * @enum {string} - */ - method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS"; - /** - * @description Request timeout (duration string, e.g., "30s") - * @default 30s - */ - timeout: string; - /** - * @description Provider type (enum property replaced by openapi-typescript) - * @enum {string} - */ - type: "http"; - /** - * @description HTTP endpoint URL (supports Go templates) - * @example http://{{ .resource.name }}.{{ .environment.name }}/health - */ - url: string; - }; - IntegerValue: number; - Job: { - /** Format: date-time */ - completedAt?: string; - /** Format: date-time */ - createdAt: string; - externalId?: string; - id: string; - jobAgentConfig: components["schemas"]["JobAgentConfig"]; - jobAgentId: string; - message?: string; - metadata: { - [key: string]: string; - }; - releaseId: string; - /** Format: date-time */ - startedAt?: string; - status: components["schemas"]["JobStatus"]; - traceToken?: string; - /** Format: date-time */ - updatedAt: string; - workflowJobId: string; - }; - JobAgent: { - config: components["schemas"]["JobAgentConfig"]; - id: string; - metadata?: { - [key: string]: string; - }; - name: string; - type: string; - workspaceId: string; - }; - JobAgentConfig: { + PropertiesMatcher: { + properties: components["schemas"]["PropertyMatcher"][]; + }; + PropertyMatcher: { + fromProperty: string[]; + /** @enum {string} */ + operator: + | "equals" + | "notEquals" + | "contains" + | "startsWith" + | "endsWith" + | "regex"; + toProperty: string[]; + }; + ReferenceValue: { + path: string[]; + reference: string; + }; + RelatableEntity: + | components["schemas"]["Deployment"] + | components["schemas"]["Environment"] + | components["schemas"]["Resource"]; + /** @enum {string} */ + RelatableEntityType: "deployment" | "environment" | "resource"; + /** @enum {string} */ + RelationDirection: "from" | "to"; + RelationshipRule: { + description?: string; + fromSelector?: components["schemas"]["Selector"]; + fromType: components["schemas"]["RelatableEntityType"]; + id: string; + matcher: + | components["schemas"]["CelMatcher"] + | components["schemas"]["PropertiesMatcher"]; + metadata: { + [key: string]: string; + }; + name: string; + reference: string; + relationshipType: string; + toSelector?: components["schemas"]["Selector"]; + toType: components["schemas"]["RelatableEntityType"]; + workspaceId: string; + }; + Release: { + createdAt: string; + encryptedVariables: string[]; + releaseTarget: components["schemas"]["ReleaseTarget"]; + variables: { + [key: string]: components["schemas"]["LiteralValue"]; + }; + version: components["schemas"]["DeploymentVersion"]; + }; + ReleaseTarget: { + deploymentId: string; + environmentId: string; + resourceId: string; + }; + ReleaseTargetState: { + currentRelease?: components["schemas"]["Release"]; + desiredRelease?: components["schemas"]["Release"]; + latestJob?: components["schemas"]["JobWithVerifications"]; + }; + ReleaseTargetWithState: { + deployment: components["schemas"]["Deployment"]; + environment: components["schemas"]["Environment"]; + releaseTarget: components["schemas"]["ReleaseTarget"]; + resource: components["schemas"]["Resource"]; + state: components["schemas"]["ReleaseTargetState"]; + }; + ResolvedPolicy: { + environmentIds: string[]; + policy: components["schemas"]["Policy"]; + releaseTargets: components["schemas"]["ReleaseTarget"][]; + }; + Resource: { + config: { + [key: string]: unknown; + }; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + deletedAt?: string; + id: string; + identifier: string; + kind: string; + /** Format: date-time */ + lockedAt?: string; + metadata: { + [key: string]: string; + }; + name: string; + providerId?: string; + /** Format: date-time */ + updatedAt?: string; + version: string; + workspaceId: string; + }; + ResourceProvider: { + /** Format: date-time */ + createdAt: string; + id: string; + metadata: { + [key: string]: string; + }; + name: string; + /** Format: uuid */ + workspaceId: string; + }; + ResourceVariable: { + key: string; + resourceId: string; + value: components["schemas"]["Value"]; + }; + ResourceVariablesBulkUpdateEvent: { + resourceId: string; + variables: { + [key: string]: unknown; + }; + }; + RetryRule: { + /** + * Format: int32 + * @description Minimum seconds to wait between retry attempts. If null, retries are allowed immediately after job completion. + */ + backoffSeconds?: number; + /** + * @description Backoff strategy: "linear" uses constant backoffSeconds delay, "exponential" doubles the delay with each retry (backoffSeconds * 2^(attempt-1)). + * @default linear + * @enum {string} + */ + backoffStrategy: "linear" | "exponential"; + /** + * Format: int32 + * @description Maximum backoff time in seconds (cap for exponential backoff). If null, no maximum is enforced. + */ + maxBackoffSeconds?: number; + /** + * Format: int32 + * @description Maximum number of retries allowed. 0 means no retries (1 attempt total), 3 means up to 4 attempts (1 initial + 3 retries). + */ + maxRetries: number; + /** @description Job statuses that count toward the retry limit. If null or empty, defaults to ["failure", "invalidIntegration", "invalidJobAgent"] for maxRetries > 0, or ["failure", "invalidIntegration", "invalidJobAgent", "successful"] for maxRetries = 0. Cancelled and skipped jobs never count by default (allows redeployment after cancellation). Example: ["failure", "cancelled"] will only count failed/cancelled jobs. */ + retryOnStatuses?: components["schemas"]["JobStatus"][]; + }; + RollbackRule: { + /** @description Job statuses that will trigger a rollback */ + onJobStatuses?: components["schemas"]["JobStatus"][]; + /** + * @description If true, a release target will be rolled back if the verification fails + * @default false + */ + onVerificationFailure: boolean; + }; + RuleEvaluation: { + /** @description Whether the rule requires an action (e.g., approval, wait) */ + actionRequired: boolean; + /** + * @description Type of action required + * @enum {string} + */ + actionType?: "approval" | "wait"; + /** @description Whether the rule allows the deployment */ + allowed: boolean; + /** @description Additional details about the rule evaluation */ + details: { + [key: string]: unknown; + }; + /** @description Human-readable explanation of the rule result */ + message: string; + /** + * Format: date-time + * @description The time when this rule should be re-evaluated (e.g., when soak time will be complete, when gradual rollout schedule is due) + */ + nextEvaluationTime?: string; + /** @description The ID of the rule that was evaluated */ + ruleId: string; + /** + * Format: date-time + * @description The time when the rule requirement was satisfied (e.g., when approvals were met, soak time completed) + */ + satisfiedAt?: string; + }; + Selector: + | components["schemas"]["JsonSelector"] + | components["schemas"]["CelSelector"]; + SensitiveValue: { + valueHash: string; + }; + SleepMetricProvider: { + /** + * Format: int32 + * @example 30 + */ + durationSeconds: number; + /** + * @description Provider type (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: "sleep"; + }; + StringValue: string; + System: { + description?: string; + id: string; + metadata?: { + [key: string]: string; + }; + name: string; + workspaceId: string; + }; + TerraformCloudJobAgentConfig: { + /** @description Terraform Cloud address (e.g. https://app.terraform.io). */ + address: string; + /** @description Terraform Cloud organization name. */ + organization: string; + /** @description Terraform Cloud workspace template. */ + template: string; + /** @description Terraform Cloud API token. */ + token: string; + }; + TerraformCloudRunMetricProvider: { + /** + * @description Terraform Cloud address + * @example https://app.terraform.io + */ + address: string; + /** + * @description Terraform Cloud run ID + * @example run-1234567890 + */ + runId: string; + /** + * @description Terraform Cloud token + * @example {{.variables.terraform_cloud_token}} + */ + token: string; + /** + * @description Provider type (enum property replaced by openapi-typescript) + * @enum {string} + */ + type: "terraformCloudRun"; + }; + TestRunnerJobAgentConfig: { + /** + * Format: int + * @description Delay in seconds before resolving the job. + */ + delaySeconds?: number; + /** @description Optional message to include in the job output. */ + message?: string; + /** @description Final status to set (e.g. "successful", "failure"). */ + status?: string; + }; + UserApprovalRecord: { + createdAt: string; + environmentId: string; + reason?: string; + status: components["schemas"]["ApprovalStatus"]; + userId: string; + versionId: string; + }; + Value: + | components["schemas"]["LiteralValue"] + | components["schemas"]["ReferenceValue"] + | components["schemas"]["SensitiveValue"]; + VerificationMeasurement: { + /** @description Raw measurement data */ + data?: { + [key: string]: unknown; + }; + /** + * Format: date-time + * @description When measurement was taken + */ + measuredAt: string; + /** @description Measurement result message */ + message?: string; + status: components["schemas"]["VerificationMeasurementStatus"]; + }; + /** + * @description Status of a verification measurement + * @enum {string} + */ + VerificationMeasurementStatus: "passed" | "failed" | "inconclusive"; + VerificationMetricSpec: { + /** @description Number of measurements to take */ + count: number; + /** + * @description CEL expression to evaluate measurement failure (e.g., "result.statusCode == 500"), if not provided, a failure is just the opposite of the success condition + * @example result.statusCode == 500 + */ + failureCondition?: string; + /** + * @description Stop after this many consecutive failures (0 = no limit) + * @default 0 + */ + failureThreshold: number; + /** + * Format: int32 + * @description Interval between measurements in seconds + * @example 30 + */ + intervalSeconds: number; + /** @description Name of the verification metric */ + name: string; + provider: components["schemas"]["MetricProvider"]; + /** + * @description CEL expression to evaluate measurement success (e.g., "result.statusCode == 200") + * @example result.statusCode == 200 + */ + successCondition: string; + /** + * @description Minimum number of consecutive successful measurements required to consider the metric successful + * @example 0 + */ + successThreshold?: number; + }; + VerificationMetricStatus: components["schemas"]["VerificationMetricSpec"] & { + /** @description Individual verification measurements taken for this metric */ + measurements: components["schemas"]["VerificationMeasurement"][]; + }; + VerificationRule: { + /** @description Metrics to verify */ + metrics: components["schemas"]["VerificationMetricSpec"][]; + /** + * @description When to trigger verification + * @default jobSuccess + * @enum {string} + */ + triggerOn: "jobCreated" | "jobStarted" | "jobSuccess" | "jobFailure"; + }; + VersionCooldownRule: { + /** + * Format: int32 + * @description Minimum time in seconds that must pass since the currently deployed (or in-progress) version was created before allowing another deployment. This enables batching of frequent upstream releases into periodic deployments. + */ + intervalSeconds: number; + }; + VersionSelectorRule: { + /** @description Human-readable description of what this version selector does. Example: "Only deploy v2.x versions to staging environments" */ + description?: string; + selector: components["schemas"]["Selector"]; + }; + Workflow: { + id: string; + inputs: { + [key: string]: unknown; + }; + workflowTemplateId: string; + }; + WorkflowArrayInput: + | components["schemas"]["WorkflowManualArrayInput"] + | components["schemas"]["WorkflowSelectorArrayInput"]; + WorkflowBooleanInput: { + default?: boolean; + name: string; + /** @enum {string} */ + type: "boolean"; + }; + WorkflowInput: + | components["schemas"]["WorkflowStringInput"] + | components["schemas"]["WorkflowNumberInput"] + | components["schemas"]["WorkflowBooleanInput"] + | components["schemas"]["WorkflowArrayInput"]; + WorkflowJob: { + /** @description Configuration for the job agent */ + config: { + [key: string]: unknown; + }; + id: string; + index: number; + /** @description Reference to the job agent */ + ref: string; + workflowId: string; + }; + WorkflowJobAgentConfig: { + config: { + [key: string]: unknown; + }; + id: string; + }; + WorkflowJobMatrix: { + [key: string]: + | { [key: string]: unknown; - }; - /** @enum {string} */ - JobStatus: "cancelled" | "skipped" | "inProgress" | "actionRequired" | "pending" | "failure" | "invalidJobAgent" | "invalidIntegration" | "externalRunNotFound" | "successful"; - JobUpdateEvent: { - agentId?: string; - externalId?: string; - fieldsToUpdate?: ("completedAt" | "createdAt" | "externalId" | "id" | "jobAgentConfig" | "jobAgentId" | "message" | "metadata" | "releaseId" | "startedAt" | "status" | "traceToken" | "updatedAt" | "workflowJobId")[]; - id?: string; - job: components["schemas"]["Job"]; - } & (unknown | unknown); - JobVerification: { - /** - * Format: date-time - * @description When verification was created - */ - createdAt: string; - id: string; - jobId: string; - /** @description Summary message of verification result */ - message?: string; - /** @description Metrics associated with this verification */ - metrics: components["schemas"]["VerificationMetricStatus"][]; - }; - /** @enum {string} */ - JobVerificationStatus: "running" | "passed" | "failed" | "cancelled"; - JobWithRelease: { - deployment?: components["schemas"]["Deployment"]; - environment?: components["schemas"]["Environment"]; - job: components["schemas"]["Job"]; - release: components["schemas"]["Release"]; - resource?: components["schemas"]["Resource"]; - }; - JobWithVerifications: { - job: components["schemas"]["Job"]; - verifications: components["schemas"]["JobVerification"][]; - }; - JsonSelector: { - json: { - [key: string]: unknown; - }; - }; - LiteralValue: components["schemas"]["BooleanValue"] | components["schemas"]["NumberValue"] | components["schemas"]["IntegerValue"] | components["schemas"]["StringValue"] | components["schemas"]["ObjectValue"] | components["schemas"]["NullValue"]; - MetricProvider: components["schemas"]["HTTPMetricProvider"] | components["schemas"]["SleepMetricProvider"] | components["schemas"]["DatadogMetricProvider"] | components["schemas"]["TerraformCloudRunMetricProvider"]; - /** @enum {boolean} */ - NullValue: true; - NumberValue: number; - ObjectValue: { - object: { - [key: string]: unknown; - }; - }; - Policy: { - createdAt: string; - description?: string; - enabled: boolean; - id: string; - /** @description Arbitrary metadata for the policy (record) */ - metadata: { - [key: string]: string; - }; - name: string; - priority: number; - rules: components["schemas"]["PolicyRule"][]; - /** @description CEL expression for matching release targets. Use "true" to match all targets. */ - selector: string; - workspaceId: string; - }; - PolicyEvaluation: { - policy?: components["schemas"]["Policy"]; - ruleResults: components["schemas"]["RuleEvaluation"][]; - summary?: string; - }; - PolicyRule: { - anyApproval?: components["schemas"]["AnyApprovalRule"]; - createdAt: string; - deploymentDependency?: components["schemas"]["DeploymentDependencyRule"]; - deploymentWindow?: components["schemas"]["DeploymentWindowRule"]; - environmentProgression?: components["schemas"]["EnvironmentProgressionRule"]; - gradualRollout?: components["schemas"]["GradualRolloutRule"]; - id: string; - policyId: string; - retry?: components["schemas"]["RetryRule"]; - rollback?: components["schemas"]["RollbackRule"]; - verification?: components["schemas"]["VerificationRule"]; - versionCooldown?: components["schemas"]["VersionCooldownRule"]; - versionSelector?: components["schemas"]["VersionSelectorRule"]; - }; - PolicySkip: { - /** - * Format: date-time - * @description When this skip was created - */ - createdAt: string; - /** @description User ID who created this skip */ - createdBy: string; - /** @description Environment this skip applies to. If null, applies to all environments. */ - environmentId?: string; - /** - * Format: date-time - * @description When this skip expires. If null, skip never expires. - */ - expiresAt?: string; - /** @description Unique identifier for the skip */ - id: string; - /** @description Required reason for why this skip is needed (e.g., incident ticket, emergency situation) */ - reason: string; - /** @description Resource this skip applies to. If null, applies to all resources (in the environment if specified, or globally). */ - resourceId?: string; - /** @description Rule ID this skip applies to */ - ruleId: string; - /** @description Deployment version this skip applies to */ - versionId: string; - /** @description Workspace this skip belongs to */ - workspaceId: string; - }; - PropertiesMatcher: { - properties: components["schemas"]["PropertyMatcher"][]; - }; - PropertyMatcher: { - fromProperty: string[]; - /** @enum {string} */ - operator: "equals" | "notEquals" | "contains" | "startsWith" | "endsWith" | "regex"; - toProperty: string[]; - }; - ReferenceValue: { - path: string[]; - reference: string; - }; - RelatableEntity: components["schemas"]["Deployment"] | components["schemas"]["Environment"] | components["schemas"]["Resource"]; - /** @enum {string} */ - RelatableEntityType: "deployment" | "environment" | "resource"; + }[] + | string; + }; + WorkflowJobTemplate: { + /** @description Configuration for the job agent */ + config: { + [key: string]: unknown; + }; + id: string; + matrix?: components["schemas"]["WorkflowJobMatrix"]; + name: string; + /** @description Reference to the job agent */ + ref: string; + }; + WorkflowJobWithJobs: components["schemas"]["WorkflowJob"] & { + jobs: components["schemas"]["Job"][]; + }; + WorkflowManualArrayInput: { + default?: { + [key: string]: unknown; + }[]; + name: string; + /** @enum {string} */ + type: "array"; + }; + WorkflowNumberInput: { + default?: number; + name: string; + /** @enum {string} */ + type: "number"; + }; + WorkflowSelectorArrayInput: { + name: string; + selector: { + default?: components["schemas"]["Selector"]; /** @enum {string} */ - RelationDirection: "from" | "to"; - RelationshipRule: { - description?: string; - fromSelector?: components["schemas"]["Selector"]; - fromType: components["schemas"]["RelatableEntityType"]; - id: string; - matcher: components["schemas"]["CelMatcher"] | components["schemas"]["PropertiesMatcher"]; - metadata: { - [key: string]: string; - }; - name: string; - reference: string; - relationshipType: string; - toSelector?: components["schemas"]["Selector"]; - toType: components["schemas"]["RelatableEntityType"]; - workspaceId: string; - }; - Release: { - createdAt: string; - encryptedVariables: string[]; - releaseTarget: components["schemas"]["ReleaseTarget"]; - variables: { - [key: string]: components["schemas"]["LiteralValue"]; - }; - version: components["schemas"]["DeploymentVersion"]; - }; - ReleaseTarget: { - deploymentId: string; - environmentId: string; - resourceId: string; - }; - ReleaseTargetState: { - currentRelease?: components["schemas"]["Release"]; - desiredRelease?: components["schemas"]["Release"]; - latestJob?: components["schemas"]["JobWithVerifications"]; + entityType: "resource" | "environment" | "deployment"; + }; + /** @enum {string} */ + type: "array"; + }; + WorkflowStringInput: { + default?: string; + name: string; + /** @enum {string} */ + type: "string"; + }; + WorkflowTemplate: { + id: string; + inputs: components["schemas"]["WorkflowInput"][]; + jobs: components["schemas"]["WorkflowJobTemplate"][]; + name: string; + }; + WorkflowWithJobs: components["schemas"]["Workflow"] & { + jobs: components["schemas"]["WorkflowJobWithJobs"][]; + }; + }; + responses: never; + parameters: { + /** @description Type of the entity (deployment, environment, or resource) */ + relatableEntityType: components["schemas"]["RelatableEntityType"]; + }; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + validateResourceSelector: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: { + content: { + "application/json": { + resourceSelector?: components["schemas"]["Selector"]; }; - ReleaseTargetWithState: { - deployment: components["schemas"]["Deployment"]; + }; + }; + responses: { + /** @description The validated resource selector */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + errors: string[]; + valid: boolean; + }; + }; + }; + }; + }; + listWorkspaceIds: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description A list of workspace IDs */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + workspaceIds?: string[]; + }; + }; + }; + }; + }; + getDeploymentVersionJobsList: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment version */ + versionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Jobs list grouped by environment and release target */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { environment: components["schemas"]["Environment"]; - releaseTarget: components["schemas"]["ReleaseTarget"]; - resource: components["schemas"]["Resource"]; - state: components["schemas"]["ReleaseTargetState"]; - }; - ResolvedPolicy: { - environmentIds: string[]; - policy: components["schemas"]["Policy"]; - releaseTargets: components["schemas"]["ReleaseTarget"][]; - }; - Resource: { - config: { - [key: string]: unknown; - }; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - deletedAt?: string; - id: string; - identifier: string; - kind: string; - /** Format: date-time */ - lockedAt?: string; - metadata: { - [key: string]: string; - }; - name: string; - providerId?: string; - /** Format: date-time */ - updatedAt?: string; - version: string; - workspaceId: string; - }; - ResourceProvider: { - /** Format: date-time */ - createdAt: string; - id: string; - metadata: { - [key: string]: string; - }; - name: string; - /** Format: uuid */ - workspaceId: string; - }; - ResourceVariable: { - key: string; - resourceId: string; - value: components["schemas"]["Value"]; - }; - ResourceVariablesBulkUpdateEvent: { - resourceId: string; - variables: { - [key: string]: unknown; - }; - }; - RetryRule: { - /** - * Format: int32 - * @description Minimum seconds to wait between retry attempts. If null, retries are allowed immediately after job completion. - */ - backoffSeconds?: number; - /** - * @description Backoff strategy: "linear" uses constant backoffSeconds delay, "exponential" doubles the delay with each retry (backoffSeconds * 2^(attempt-1)). - * @default linear - * @enum {string} - */ - backoffStrategy: "linear" | "exponential"; - /** - * Format: int32 - * @description Maximum backoff time in seconds (cap for exponential backoff). If null, no maximum is enforced. - */ - maxBackoffSeconds?: number; - /** - * Format: int32 - * @description Maximum number of retries allowed. 0 means no retries (1 attempt total), 3 means up to 4 attempts (1 initial + 3 retries). - */ - maxRetries: number; - /** @description Job statuses that count toward the retry limit. If null or empty, defaults to ["failure", "invalidIntegration", "invalidJobAgent"] for maxRetries > 0, or ["failure", "invalidIntegration", "invalidJobAgent", "successful"] for maxRetries = 0. Cancelled and skipped jobs never count by default (allows redeployment after cancellation). Example: ["failure", "cancelled"] will only count failed/cancelled jobs. */ - retryOnStatuses?: components["schemas"]["JobStatus"][]; - }; - RollbackRule: { - /** @description Job statuses that will trigger a rollback */ - onJobStatuses?: components["schemas"]["JobStatus"][]; - /** - * @description If true, a release target will be rolled back if the verification fails - * @default false - */ - onVerificationFailure: boolean; - }; - RuleEvaluation: { - /** @description Whether the rule requires an action (e.g., approval, wait) */ - actionRequired: boolean; - /** - * @description Type of action required - * @enum {string} - */ - actionType?: "approval" | "wait"; - /** @description Whether the rule allows the deployment */ - allowed: boolean; - /** @description Additional details about the rule evaluation */ - details: { - [key: string]: unknown; - }; - /** @description Human-readable explanation of the rule result */ - message: string; - /** - * Format: date-time - * @description The time when this rule should be re-evaluated (e.g., when soak time will be complete, when gradual rollout schedule is due) - */ - nextEvaluationTime?: string; - /** @description The ID of the rule that was evaluated */ - ruleId: string; - /** - * Format: date-time - * @description The time when the rule requirement was satisfied (e.g., when approvals were met, soak time completed) - */ - satisfiedAt?: string; - }; - Selector: components["schemas"]["JsonSelector"] | components["schemas"]["CelSelector"]; - SensitiveValue: { - valueHash: string; - }; - SleepMetricProvider: { - /** - * Format: int32 - * @example 30 - */ - durationSeconds: number; - /** - * @description Provider type (enum property replaced by openapi-typescript) - * @enum {string} - */ - type: "sleep"; - }; - StringValue: string; - System: { - description?: string; - id: string; - metadata?: { - [key: string]: string; - }; - name: string; - workspaceId: string; - }; - TerraformCloudJobAgentConfig: { - /** @description Terraform Cloud address (e.g. https://app.terraform.io). */ - address: string; - /** @description Terraform Cloud organization name. */ - organization: string; - /** @description Terraform Cloud workspace template. */ - template: string; - /** @description Terraform Cloud API token. */ - token: string; - }; - TerraformCloudRunMetricProvider: { - /** - * @description Terraform Cloud address - * @example https://app.terraform.io - */ - address: string; - /** - * @description Terraform Cloud run ID - * @example run-1234567890 - */ - runId: string; - /** - * @description Terraform Cloud token - * @example {{.variables.terraform_cloud_token}} - */ - token: string; - /** - * @description Provider type (enum property replaced by openapi-typescript) - * @enum {string} - */ - type: "terraformCloudRun"; - }; - TestRunnerJobAgentConfig: { - /** - * Format: int - * @description Delay in seconds before resolving the job. - */ - delaySeconds?: number; - /** @description Optional message to include in the job output. */ - message?: string; - /** @description Final status to set (e.g. "successful", "failure"). */ - status?: string; - }; - UserApprovalRecord: { - createdAt: string; - environmentId: string; - reason?: string; - status: components["schemas"]["ApprovalStatus"]; - userId: string; - versionId: string; - }; - Value: components["schemas"]["LiteralValue"] | components["schemas"]["ReferenceValue"] | components["schemas"]["SensitiveValue"]; - VerificationMeasurement: { - /** @description Raw measurement data */ - data?: { - [key: string]: unknown; - }; - /** - * Format: date-time - * @description When measurement was taken - */ - measuredAt: string; - /** @description Measurement result message */ - message?: string; - status: components["schemas"]["VerificationMeasurementStatus"]; - }; - /** - * @description Status of a verification measurement - * @enum {string} - */ - VerificationMeasurementStatus: "passed" | "failed" | "inconclusive"; - VerificationMetricSpec: { - /** @description Number of measurements to take */ - count: number; - /** - * @description CEL expression to evaluate measurement failure (e.g., "result.statusCode == 500"), if not provided, a failure is just the opposite of the success condition - * @example result.statusCode == 500 - */ - failureCondition?: string; - /** - * @description Stop after this many consecutive failures (0 = no limit) - * @default 0 - */ - failureThreshold: number; - /** - * Format: int32 - * @description Interval between measurements in seconds - * @example 30 - */ - intervalSeconds: number; - /** @description Name of the verification metric */ - name: string; - provider: components["schemas"]["MetricProvider"]; - /** - * @description CEL expression to evaluate measurement success (e.g., "result.statusCode == 200") - * @example result.statusCode == 200 - */ - successCondition: string; - /** - * @description Minimum number of consecutive successful measurements required to consider the metric successful - * @example 0 - */ - successThreshold?: number; - }; - VerificationMetricStatus: components["schemas"]["VerificationMetricSpec"] & { - /** @description Individual verification measurements taken for this metric */ - measurements: components["schemas"]["VerificationMeasurement"][]; - }; - VerificationRule: { - /** @description Metrics to verify */ - metrics: components["schemas"]["VerificationMetricSpec"][]; - /** - * @description When to trigger verification - * @default jobSuccess - * @enum {string} - */ - triggerOn: "jobCreated" | "jobStarted" | "jobSuccess" | "jobFailure"; - }; - VersionCooldownRule: { - /** - * Format: int32 - * @description Minimum time in seconds that must pass since the currently deployed (or in-progress) version was created before allowing another deployment. This enables batching of frequent upstream releases into periodic deployments. - */ - intervalSeconds: number; - }; - VersionSelectorRule: { - /** @description Human-readable description of what this version selector does. Example: "Only deploy v2.x versions to staging environments" */ - description?: string; - selector: components["schemas"]["Selector"]; - }; - Workflow: { - id: string; - inputs: { - [key: string]: unknown; - }; - workflowTemplateId: string; - }; - WorkflowArrayInput: components["schemas"]["WorkflowManualArrayInput"] | components["schemas"]["WorkflowSelectorArrayInput"]; - WorkflowBooleanInput: { - default?: boolean; - name: string; - /** @enum {string} */ - type: "boolean"; - }; - WorkflowInput: components["schemas"]["WorkflowStringInput"] | components["schemas"]["WorkflowNumberInput"] | components["schemas"]["WorkflowBooleanInput"] | components["schemas"]["WorkflowArrayInput"]; - WorkflowJob: { - /** @description Configuration for the job agent */ - config: { - [key: string]: unknown; - }; - id: string; - index: number; - /** @description Reference to the job agent */ - ref: string; - workflowId: string; - }; - WorkflowJobAgentConfig: { - config: { - [key: string]: unknown; - }; - id: string; - }; - WorkflowJobMatrix: { - [key: string]: { - [key: string]: unknown; - }[] | string; - }; - WorkflowJobTemplate: { - /** @description Configuration for the job agent */ - config: { - [key: string]: unknown; - }; - id: string; - matrix?: components["schemas"]["WorkflowJobMatrix"]; - name: string; - /** @description Reference to the job agent */ - ref: string; - }; - WorkflowJobWithJobs: components["schemas"]["WorkflowJob"] & { - jobs: components["schemas"]["Job"][]; - }; - WorkflowManualArrayInput: { - default?: { - [key: string]: unknown; + releaseTargets: { + deployment: components["schemas"]["Deployment"]; + deploymentId: string; + environment: components["schemas"]["Environment"]; + environmentId: string; + id: string; + jobs: { + /** Format: date-time */ + createdAt: string; + externalId?: string; + id: string; + metadata: { + [key: string]: string; + }; + status: components["schemas"]["JobStatus"]; + }[]; + resource: components["schemas"]["Resource"]; + resourceId: string; }[]; - name: string; - /** @enum {string} */ - type: "array"; - }; - WorkflowNumberInput: { - default?: number; - name: string; - /** @enum {string} */ - type: "number"; - }; - WorkflowSelectorArrayInput: { - name: string; - selector: { - default?: components["schemas"]["Selector"]; - /** @enum {string} */ - entityType: "resource" | "environment" | "deployment"; - }; - /** @enum {string} */ - type: "array"; + }[]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; }; - WorkflowStringInput: { - default?: string; - name: string; - /** @enum {string} */ - type: "string"; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; - WorkflowTemplate: { - id: string; - inputs: components["schemas"]["WorkflowInput"][]; - jobs: components["schemas"]["WorkflowJobTemplate"][]; - name: string; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; }; - WorkflowWithJobs: components["schemas"]["Workflow"] & { - jobs: components["schemas"]["WorkflowJobWithJobs"][]; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; + }; + }; + }; + listDeployments: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["DeploymentAndSystem"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getDeployment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment */ + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested deployment */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeploymentWithVariables"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getPoliciesForDeployment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment */ + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description A list of resolved policies */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["ResolvedPolicy"][]; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getReleaseTargetsForDeployment: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + /** @description Filter by resource name */ + query?: string; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment */ + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["ReleaseTargetWithState"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getDeploymentResources: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment */ + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Resource"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getVersionsForDeployment: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment */ + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["DeploymentVersion"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getDeploymentVersion: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment version */ + deploymentVersionId: string; + }; + cookie?: never; }; - responses: never; + requestBody?: never; + responses: { + /** @description OK response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeploymentVersion"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getRelatedEntities: { parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; /** @description Type of the entity (deployment, environment, or resource) */ - relatableEntityType: components["schemas"]["RelatableEntityType"]; + relatableEntityType: components["parameters"]["relatableEntityType"]; + /** @description ID of the entity */ + entityId: string; + }; + cookie?: never; }; - requestBodies: never; - headers: never; - pathItems: never; -} -export type $defs = Record; -export interface operations { - validateResourceSelector: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: { - content: { - "application/json": { - resourceSelector?: components["schemas"]["Selector"]; - }; - }; - }; - responses: { - /** @description The validated resource selector */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - errors: string[]; - valid: boolean; - }; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Related entities grouped by relationship reference */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + relations?: { + [key: string]: components["schemas"]["EntityRelation"][]; + }; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - listWorkspaceIds: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of workspace IDs */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - workspaceIds?: string[]; - }; - }; - }; - }; + }; + listEnvironments: { + parameters: { + query?: { + /** @description Number of items to skip */ + offset?: number; + /** @description Maximum number of items to return */ + limit?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getDeploymentVersionJobsList: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment version */ - versionId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Jobs list grouped by environment and release target */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - environment: components["schemas"]["Environment"]; - releaseTargets: { - deployment: components["schemas"]["Deployment"]; - deploymentId: string; - environment: components["schemas"]["Environment"]; - environmentId: string; - id: string; - jobs: { - /** Format: date-time */ - createdAt: string; - externalId?: string; - id: string; - metadata: { - [key: string]: string; - }; - status: components["schemas"]["JobStatus"]; - }[]; - resource: components["schemas"]["Resource"]; - resourceId: string; - }[]; - }[]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description A list of environments */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Environment"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - listDeployments: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["DeploymentAndSystem"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getEnvironment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the environment */ + environmentId: string; + }; + cookie?: never; }; - getDeployment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested deployment */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeploymentWithVariables"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested environment */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Environment"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getPoliciesForDeployment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of resolved policies */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["ResolvedPolicy"][]; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getReleaseTargetsForEnvironment: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the environment */ + environmentId: string; + }; + cookie?: never; }; - getReleaseTargetsForDeployment: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - /** @description Filter by resource name */ - query?: string; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["ReleaseTargetWithState"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["ReleaseTargetWithState"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getDeploymentResources: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Resource"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getEnvironmentResources: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the environment */ + environmentId: string; + }; + cookie?: never; }; - getVersionsForDeployment: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["DeploymentVersion"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Resource"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getDeploymentVersion: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment version */ - deploymentVersionId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeploymentVersion"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getGitHubEntityByInstallationId: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Installation ID of the GitHub entity */ + installationId: number; + }; + cookie?: never; }; - getRelatedEntities: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Type of the entity (deployment, environment, or resource) */ - relatableEntityType: components["parameters"]["relatableEntityType"]; - /** @description ID of the entity */ - entityId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Related entities grouped by relationship reference */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - relations?: { - [key: string]: components["schemas"]["EntityRelation"][]; - }; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description OK response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GithubEntity"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - listEnvironments: { - parameters: { - query?: { - /** @description Number of items to skip */ - offset?: number; - /** @description Maximum number of items to return */ - limit?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of environments */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Environment"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getJobAgents: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getEnvironment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the environment */ - environmentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested environment */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Environment"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["JobAgent"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getJobAgent: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the job agent */ + jobAgentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested job agent */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JobAgent"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getDeploymentsForJobAgent: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the job agent */ + jobAgentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Deployment"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getJobsForJobAgent: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the job agent */ + jobAgentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Job"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getJobs: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + /** @description ID of the resource */ + resourceId?: string; + /** @description ID of the environment */ + environmentId?: string; + /** @description ID of the deployment */ + deploymentId?: string; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["JobWithRelease"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getJob: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the job */ + jobId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Get job */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Job"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getJobWithRelease: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the job */ + jobId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Get job with release */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JobWithRelease"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + listPolicies: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description A list of policies */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + policies?: components["schemas"]["Policy"][]; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + evaluatePolicies: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["EvaluationScope"]; + }; + }; + responses: { + /** @description OK response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + decision?: components["schemas"]["DeployDecision"]; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getPolicy: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the policy */ + policyId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested policy */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Policy"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getReleaseTargetsForPolicy: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the policy */ + policyId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description A list of release targets */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + releaseTargets?: components["schemas"]["ReleaseTarget"][]; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getReleaseTargetsForEnvironment: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the environment */ - environmentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["ReleaseTargetWithState"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getRule: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the policy */ + policyId: string; + /** @description ID of the rule */ + ruleId: string; + }; + cookie?: never; }; - getEnvironmentResources: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the environment */ - environmentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Resource"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description OK response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PolicyRule"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getGitHubEntityByInstallationId: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Installation ID of the GitHub entity */ - installationId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["GithubEntity"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + listPolicySkips: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getJobAgents: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["JobAgent"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description A list of policy skips */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + skips?: components["schemas"]["PolicySkip"][]; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getJobAgent: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the job agent */ - jobAgentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested job agent */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["JobAgent"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getPolicySkipsForEnvironmentAndVersion: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the environment */ + environmentId: string; + /** @description ID of the deployment version */ + deploymentVersionId: string; + }; + cookie?: never; }; - getDeploymentsForJobAgent: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the job agent */ - jobAgentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Deployment"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description A list of policy skips */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items?: components["schemas"]["PolicySkip"][]; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getJobsForJobAgent: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the job agent */ - jobAgentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Job"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getPolicySkip: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Policy skip ID */ + policySkipId: string; + }; + cookie?: never; }; - getJobs: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - /** @description ID of the resource */ - resourceId?: string; - /** @description ID of the environment */ - environmentId?: string; - /** @description ID of the deployment */ - deploymentId?: string; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["JobWithRelease"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested policy skip */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PolicySkip"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getJob: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the job */ - jobId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Get job */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Job"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getRelationshipRules: { + parameters: { + query?: { + /** @description Number of items to skip */ + offset?: number; + /** @description Maximum number of items to return */ + limit?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getJobWithRelease: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the job */ - jobId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Get job with release */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["JobWithRelease"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["RelationshipRule"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - listPolicies: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of policies */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - policies?: components["schemas"]["Policy"][]; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getRelationshipRule: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the relationship rule */ + relationshipRuleId: string; + }; + cookie?: never; }; - evaluatePolicies: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; + requestBody?: never; + responses: { + /** @description OK response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["RelationshipRule"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + evaluateReleaseTarget: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["EvaluateReleaseTargetRequest"]; + }; + }; + responses: { + /** @description Policy evaluation results for the release target */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + decision?: components["schemas"]["DeployDecision"]; + /** @description The number of policies evaluated */ + policiesEvaluated?: number; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getReleaseTargetDesiredRelease: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Key of the release target */ + releaseTargetKey: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The desired release for the release target */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + desiredRelease?: components["schemas"]["Release"]; + }; }; - requestBody: { - content: { - "application/json": components["schemas"]["EvaluationScope"]; - }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; }; - responses: { - /** @description OK response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - decision?: components["schemas"]["DeployDecision"]; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; + }; }; - getPolicy: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the policy */ - policyId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested policy */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Policy"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getJobsForReleaseTarget: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + /** @description CEL expression to filter the results */ + cel?: string; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Key of the release target */ + releaseTargetKey: string; + }; + cookie?: never; }; - getReleaseTargetsForPolicy: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the policy */ - policyId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of release targets */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - releaseTargets?: components["schemas"]["ReleaseTarget"][]; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Job"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getRule: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the policy */ - policyId: string; - /** @description ID of the rule */ - ruleId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["PolicyRule"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getPoliciesForReleaseTarget: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Key of the release target */ + releaseTargetKey: string; + }; + cookie?: never; }; - listPolicySkips: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of policy skips */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - skips?: components["schemas"]["PolicySkip"][]; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description A list of policies */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + policies?: components["schemas"]["Policy"][]; + }; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getPolicySkipsForEnvironmentAndVersion: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the environment */ - environmentId: string; - /** @description ID of the deployment version */ - deploymentVersionId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of policy skips */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items?: components["schemas"]["PolicySkip"][]; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getReleaseTargetState: { + parameters: { + query?: { + /** @description Whether to bypass the cache */ + bypassCache?: boolean; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Key of the release target */ + releaseTargetKey: string; + }; + cookie?: never; }; - getPolicySkip: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Policy skip ID */ - policySkipId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested policy skip */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["PolicySkip"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The state for the release target */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReleaseTargetState"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getRelationshipRules: { - parameters: { - query?: { - /** @description Number of items to skip */ - offset?: number; - /** @description Maximum number of items to return */ - limit?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["RelationshipRule"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getRelease: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the release */ + releaseId: string; + }; + cookie?: never; }; - getRelationshipRule: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the relationship rule */ - relationshipRuleId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["RelationshipRule"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested release */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Release"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - evaluateReleaseTarget: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["EvaluateReleaseTargetRequest"]; - }; - }; - responses: { - /** @description Policy evaluation results for the release target */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - decision?: components["schemas"]["DeployDecision"]; - /** @description The number of policies evaluated */ - policiesEvaluated?: number; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getReleaseVerifications: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the release */ + releaseId: string; + }; + cookie?: never; }; - getReleaseTargetDesiredRelease: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Key of the release target */ - releaseTargetKey: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The desired release for the release target */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - desiredRelease?: components["schemas"]["Release"]; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description List of verifications for the release */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["JobVerification"][]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getResourceProviders: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["ResourceProvider"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + }; + }; + cacheBatch: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** @description The ID of the resource provider */ + providerId: string; + /** @description Array of resources to cache */ + resources: components["schemas"]["Resource"][]; + }; + }; + }; + responses: { + /** @description Batch cached successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @description Unique ID for this cached batch */ + batchId?: string; + /** @description Number of resources cached */ + resourceCount?: number; + }; + }; + }; + }; + }; + getResourceProviderByName: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Name of the resource provider */ + name: string; + }; + cookie?: never; }; - getJobsForReleaseTarget: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - /** @description CEL expression to filter the results */ - cel?: string; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Key of the release target */ - releaseTargetKey: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Job"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description OK response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceProvider"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getPoliciesForReleaseTarget: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Key of the release target */ - releaseTargetKey: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of policies */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - policies?: components["schemas"]["Policy"][]; - }; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getKindsForWorkspace: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getReleaseTargetState: { - parameters: { - query?: { - /** @description Whether to bypass the cache */ - bypassCache?: boolean; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Key of the release target */ - releaseTargetKey: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The state for the release target */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ReleaseTargetState"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested kinds */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string[]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getRelease: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the release */ - releaseId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested release */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Release"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + queryResources: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getReleaseVerifications: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the release */ - releaseId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of verifications for the release */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["JobVerification"][]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; + requestBody: { + content: { + "application/json": { + filter?: components["schemas"]["Selector"]; }; + }; }; - getResourceProviders: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["ResourceProvider"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - }; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Resource"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - cacheBatch: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - /** @description The ID of the resource provider */ - providerId: string; - /** @description Array of resources to cache */ - resources: components["schemas"]["Resource"][]; - }; - }; - }; - responses: { - /** @description Batch cached successfully */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @description Unique ID for this cached batch */ - batchId?: string; - /** @description Number of resources cached */ - resourceCount?: number; - }; - }; - }; - }; + }; + getResourceByIdentifier: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + resourceIdentifier: string; + }; + cookie?: never; }; - getResourceProviderByName: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Name of the resource provider */ - name: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description OK response */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ResourceProvider"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested resource */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Resource"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getKindsForWorkspace: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested kinds */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": string[]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getDeploymentsForResource: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + resourceIdentifier: string; + }; + cookie?: never; }; - queryResources: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": { - filter?: components["schemas"]["Selector"]; - }; - }; - }; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Resource"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["Deployment"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getResourceByIdentifier: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - resourceIdentifier: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested resource */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Resource"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getRelationshipsForResource: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + resourceIdentifier: string; + }; + cookie?: never; }; - getDeploymentsForResource: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - resourceIdentifier: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["Deployment"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested relationships */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + [key: string]: components["schemas"]["EntityRelation"][]; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getRelationshipsForResource: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - resourceIdentifier: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested relationships */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - [key: string]: components["schemas"]["EntityRelation"][]; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getReleaseTargetsForResource: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + resourceIdentifier: string; + }; + cookie?: never; }; - getReleaseTargetsForResource: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - resourceIdentifier: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["ReleaseTargetWithState"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["ReleaseTargetWithState"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getReleaseTargetForResourceInDeployment: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - resourceIdentifier: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested release target */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ReleaseTarget"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getReleaseTargetForResourceInDeployment: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + resourceIdentifier: string; + /** @description ID of the deployment */ + deploymentId: string; + }; + cookie?: never; }; - getVariablesForResource: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description Identifier of the resource */ - resourceIdentifier: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested variables */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ResourceVariable"][]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested release target */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReleaseTarget"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getEngineStatus: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The status of the engine */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - healthy?: boolean; - message?: string; - }; - }; - }; - }; + }; + getVariablesForResource: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description Identifier of the resource */ + resourceIdentifier: string; + }; + cookie?: never; }; - listSystems: { - parameters: { - query?: { - /** @description Number of items to skip */ - offset?: number; - /** @description Maximum number of items to return */ - limit?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description A list of systems */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["System"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + requestBody?: never; + responses: { + /** @description The requested variables */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceVariable"][]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; - getSystem: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the system */ - systemId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested system with its environments and deployments */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - /** @description Deployments associated with the system */ - deployments: components["schemas"]["Deployment"][]; - /** @description Environments associated with the system */ - environments: components["schemas"]["Environment"][]; - system: components["schemas"]["System"]; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + getEngineStatus: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getWorkflowTemplates: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["WorkflowTemplate"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; + requestBody?: never; + responses: { + /** @description The status of the engine */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + healthy?: boolean; + message?: string; + }; }; + }; }; - getWorkflowTemplate: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the workflow template */ - workflowTemplateId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Get workflow template */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["WorkflowTemplate"]; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - }; + }; + listSystems: { + parameters: { + query?: { + /** @description Number of items to skip */ + offset?: number; + /** @description Maximum number of items to return */ + limit?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; }; - getWorkflowsByTemplate: { - parameters: { - query?: { - /** @description Maximum number of items to return */ - limit?: number; - /** @description Number of items to skip */ - offset?: number; - }; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the workflow template */ - workflowTemplateId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["WorkflowWithJobs"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - /** @description Invalid request */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description Resource not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; + requestBody?: never; + responses: { + /** @description A list of systems */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["System"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getSystem: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the system */ + systemId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested system with its environments and deployments */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @description Deployments associated with the system */ + deployments: components["schemas"]["Deployment"][]; + /** @description Environments associated with the system */ + environments: components["schemas"]["Environment"][]; + system: components["schemas"]["System"]; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getWorkflowTemplates: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["WorkflowTemplate"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getWorkflowTemplate: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the workflow template */ + workflowTemplateId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Get workflow template */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WorkflowTemplate"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getWorkflowsByTemplate: { + parameters: { + query?: { + /** @description Maximum number of items to return */ + limit?: number; + /** @description Number of items to skip */ + offset?: number; + }; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the workflow template */ + workflowTemplateId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["WorkflowWithJobs"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; }; + }; }