From 6e2ec4fff3aec4dbf3017e18ea30466b74b6b404 Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 1 Mar 2026 22:18:31 -0500 Subject: [PATCH 01/10] fix: add missing newline at the end of _journal.json file to ensure proper file formatting --- packages/db/drizzle/meta/0155_snapshot.json | 607 +++++------------- packages/db/drizzle/meta/_journal.json | 2 +- .../db/src/schema/job-verification-metric.ts | 3 +- 3 files changed, 150 insertions(+), 462 deletions(-) diff --git a/packages/db/drizzle/meta/0155_snapshot.json b/packages/db/drizzle/meta/0155_snapshot.json index 7dbbb6ab5..2f61910a6 100644 --- a/packages/db/drizzle/meta/0155_snapshot.json +++ b/packages/db/drizzle/meta/0155_snapshot.json @@ -112,12 +112,8 @@ "name": "account_user_id_user_id_fk", "tableFrom": "account", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -205,12 +201,8 @@ "name": "session_user_id_user_id_fk", "tableFrom": "session", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -220,9 +212,7 @@ "session_session_token_unique": { "name": "session_session_token_unique", "nullsNotDistinct": false, - "columns": [ - "session_token" - ] + "columns": ["session_token"] } }, "policies": {}, @@ -308,12 +298,8 @@ "name": "user_active_workspace_id_workspace_id_fk", "tableFrom": "user", "tableTo": "workspace", - "columnsFrom": [ - "active_workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["active_workspace_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -400,12 +386,8 @@ "name": "user_api_key_user_id_user_id_fk", "tableFrom": "user_api_key", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -525,12 +507,8 @@ "name": "changelog_entry_workspace_id_workspace_id_fk", "tableFrom": "changelog_entry", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -538,11 +516,7 @@ "compositePrimaryKeys": { "changelog_entry_workspace_id_entity_type_entity_id_pk": { "name": "changelog_entry_workspace_id_entity_type_entity_id_pk", - "columns": [ - "workspace_id", - "entity_type", - "entity_id" - ] + "columns": ["workspace_id", "entity_type", "entity_id"] } }, "uniqueConstraints": {}, @@ -599,12 +573,8 @@ "name": "dashboard_workspace_id_workspace_id_fk", "tableFrom": "dashboard", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -683,12 +653,8 @@ "name": "dashboard_widget_dashboard_id_dashboard_id_fk", "tableFrom": "dashboard_widget", "tableTo": "dashboard", - "columnsFrom": [ - "dashboard_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["dashboard_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1019,12 +985,8 @@ "name": "deployment_trace_span_workspace_id_workspace_id_fk", "tableFrom": "deployment_trace_span", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1077,12 +1039,8 @@ "name": "deployment_variable_deployment_id_deployment_id_fk", "tableFrom": "deployment_variable", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1092,10 +1050,7 @@ "deployment_variable_deployment_id_key_unique": { "name": "deployment_variable_deployment_id_key_unique", "nullsNotDistinct": false, - "columns": [ - "deployment_id", - "key" - ] + "columns": ["deployment_id", "key"] } }, "policies": {}, @@ -1145,12 +1100,8 @@ "name": "deployment_variable_value_deployment_variable_id_deployment_variable_id_fk", "tableFrom": "deployment_variable_value", "tableTo": "deployment_variable", - "columnsFrom": [ - "deployment_variable_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_variable_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1282,12 +1233,8 @@ "name": "deployment_version_workspace_id_workspace_id_fk", "tableFrom": "deployment_version", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -1334,12 +1281,8 @@ "name": "computed_deployment_resource_deployment_id_deployment_id_fk", "tableFrom": "computed_deployment_resource", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1347,12 +1290,8 @@ "name": "computed_deployment_resource_resource_id_resource_id_fk", "tableFrom": "computed_deployment_resource", "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1360,10 +1299,7 @@ "compositePrimaryKeys": { "computed_deployment_resource_deployment_id_resource_id_pk": { "name": "computed_deployment_resource_deployment_id_resource_id_pk", - "columns": [ - "deployment_id", - "resource_id" - ] + "columns": ["deployment_id", "resource_id"] } }, "uniqueConstraints": {}, @@ -1441,12 +1377,8 @@ "name": "deployment_workspace_id_workspace_id_fk", "tableFrom": "deployment", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -1493,12 +1425,8 @@ "name": "computed_environment_resource_environment_id_environment_id_fk", "tableFrom": "computed_environment_resource", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -1506,12 +1434,8 @@ "name": "computed_environment_resource_resource_id_resource_id_fk", "tableFrom": "computed_environment_resource", "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1519,10 +1443,7 @@ "compositePrimaryKeys": { "computed_environment_resource_environment_id_resource_id_pk": { "name": "computed_environment_resource_environment_id_resource_id_pk", - "columns": [ - "environment_id", - "resource_id" - ] + "columns": ["environment_id", "resource_id"] } }, "uniqueConstraints": {}, @@ -1588,12 +1509,8 @@ "name": "environment_workspace_id_workspace_id_fk", "tableFrom": "environment", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -1647,12 +1564,8 @@ "name": "event_workspace_id_workspace_id_fk", "tableFrom": "event", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1772,12 +1685,8 @@ "name": "resource_provider_id_resource_provider_id_fk", "tableFrom": "resource", "tableTo": "resource_provider", - "columnsFrom": [ - "provider_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["provider_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" }, @@ -1785,12 +1694,8 @@ "name": "resource_workspace_id_workspace_id_fk", "tableFrom": "resource", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -1871,12 +1776,8 @@ "name": "resource_schema_workspace_id_workspace_id_fk", "tableFrom": "resource_schema", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -1953,12 +1854,8 @@ "name": "resource_provider_workspace_id_workspace_id_fk", "tableFrom": "resource_provider", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2013,12 +1910,8 @@ "name": "system_workspace_id_workspace_id_fk", "tableFrom": "system", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2059,12 +1952,8 @@ "name": "system_deployment_system_id_system_id_fk", "tableFrom": "system_deployment", "tableTo": "system", - "columnsFrom": [ - "system_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["system_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2072,12 +1961,8 @@ "name": "system_deployment_deployment_id_deployment_id_fk", "tableFrom": "system_deployment", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2085,10 +1970,7 @@ "compositePrimaryKeys": { "system_deployment_system_id_deployment_id_pk": { "name": "system_deployment_system_id_deployment_id_pk", - "columns": [ - "system_id", - "deployment_id" - ] + "columns": ["system_id", "deployment_id"] } }, "uniqueConstraints": {}, @@ -2126,12 +2008,8 @@ "name": "system_environment_system_id_system_id_fk", "tableFrom": "system_environment", "tableTo": "system", - "columnsFrom": [ - "system_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["system_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2139,12 +2017,8 @@ "name": "system_environment_environment_id_environment_id_fk", "tableFrom": "system_environment", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2152,10 +2026,7 @@ "compositePrimaryKeys": { "system_environment_system_id_environment_id_pk": { "name": "system_environment_system_id_environment_id_pk", - "columns": [ - "system_id", - "environment_id" - ] + "columns": ["system_id", "environment_id"] } }, "uniqueConstraints": {}, @@ -2193,12 +2064,8 @@ "name": "team_workspace_id_workspace_id_fk", "tableFrom": "team", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2261,12 +2128,8 @@ "name": "team_member_team_id_team_id_fk", "tableFrom": "team_member", "tableTo": "team", - "columnsFrom": [ - "team_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["team_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2274,12 +2137,8 @@ "name": "team_member_user_id_user_id_fk", "tableFrom": "team_member", "tableTo": "user", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["user_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2434,12 +2293,8 @@ "name": "job_job_agent_id_job_agent_id_fk", "tableFrom": "job", "tableTo": "job_agent", - "columnsFrom": [ - "job_agent_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], "onDelete": "set null", "onUpdate": "no action" } @@ -2523,12 +2378,8 @@ "name": "job_metadata_job_id_job_id_fk", "tableFrom": "job_metadata", "tableTo": "job", - "columnsFrom": [ - "job_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2604,12 +2455,8 @@ "name": "job_variable_job_id_job_id_fk", "tableFrom": "job_variable", "tableTo": "job", - "columnsFrom": [ - "job_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2658,9 +2505,7 @@ "workspace_slug_unique": { "name": "workspace_slug_unique", "nullsNotDistinct": false, - "columns": [ - "slug" - ] + "columns": ["slug"] } }, "policies": {}, @@ -2751,12 +2596,8 @@ "name": "workspace_email_domain_matching_workspace_id_workspace_id_fk", "tableFrom": "workspace_email_domain_matching", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2764,12 +2605,8 @@ "name": "workspace_email_domain_matching_role_id_role_id_fk", "tableFrom": "workspace_email_domain_matching", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2829,12 +2666,8 @@ "name": "workspace_invite_token_role_id_role_id_fk", "tableFrom": "workspace_invite_token", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2842,12 +2675,8 @@ "name": "workspace_invite_token_workspace_id_workspace_id_fk", "tableFrom": "workspace_invite_token", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" }, @@ -2855,12 +2684,8 @@ "name": "workspace_invite_token_created_by_user_id_fk", "tableFrom": "workspace_invite_token", "tableTo": "user", - "columnsFrom": [ - "created_by" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["created_by"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -2870,9 +2695,7 @@ "workspace_invite_token_token_unique": { "name": "workspace_invite_token_token_unique", "nullsNotDistinct": false, - "columns": [ - "token" - ] + "columns": ["token"] } }, "policies": {}, @@ -2969,12 +2792,8 @@ "name": "entity_role_role_id_role_id_fk", "tableFrom": "entity_role", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3021,12 +2840,8 @@ "name": "role_workspace_id_workspace_id_fk", "tableFrom": "role", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3089,12 +2904,8 @@ "name": "role_permission_role_id_role_id_fk", "tableFrom": "role_permission", "tableTo": "role", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["role_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3154,12 +2965,8 @@ "name": "release_resource_id_resource_id_fk", "tableFrom": "release", "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -3167,12 +2974,8 @@ "name": "release_environment_id_environment_id_fk", "tableFrom": "release", "tableTo": "environment", - "columnsFrom": [ - "environment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -3180,12 +2983,8 @@ "name": "release_deployment_id_deployment_id_fk", "tableFrom": "release", "tableTo": "deployment", - "columnsFrom": [ - "deployment_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" }, @@ -3193,12 +2992,8 @@ "name": "release_version_id_deployment_version_id_fk", "tableFrom": "release", "tableTo": "deployment_version", - "columnsFrom": [ - "version_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["version_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -3281,12 +3076,8 @@ "name": "release_variable_release_id_release_id_fk", "tableFrom": "release_variable", "tableTo": "release", - "columnsFrom": [ - "release_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["release_id"], + "columnsTo": ["id"], "onDelete": "no action", "onUpdate": "no action" } @@ -3422,12 +3213,8 @@ "name": "reconcile_work_payload_scope_ref_reconcile_work_scope_id_fk", "tableFrom": "reconcile_work_payload", "tableTo": "reconcile_work_scope", - "columnsFrom": [ - "scope_ref" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["scope_ref"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3685,12 +3472,8 @@ "name": "policy_workspace_id_workspace_id_fk", "tableFrom": "policy", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3738,12 +3521,8 @@ "name": "policy_rule_any_approval_policy_id_policy_id_fk", "tableFrom": "policy_rule_any_approval", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3791,12 +3570,8 @@ "name": "policy_rule_deployment_dependency_policy_id_policy_id_fk", "tableFrom": "policy_rule_deployment_dependency", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3862,12 +3637,8 @@ "name": "policy_rule_deployment_window_policy_id_policy_id_fk", "tableFrom": "policy_rule_deployment_window", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3939,12 +3710,8 @@ "name": "policy_rule_environment_progression_policy_id_policy_id_fk", "tableFrom": "policy_rule_environment_progression", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -3998,12 +3765,8 @@ "name": "policy_rule_gradual_rollout_policy_id_policy_id_fk", "tableFrom": "policy_rule_gradual_rollout", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4075,12 +3838,8 @@ "name": "policy_rule_retry_policy_id_policy_id_fk", "tableFrom": "policy_rule_retry", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4134,12 +3893,8 @@ "name": "policy_rule_rollback_policy_id_policy_id_fk", "tableFrom": "policy_rule_rollback", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4194,12 +3949,8 @@ "name": "policy_rule_verification_policy_id_policy_id_fk", "tableFrom": "policy_rule_verification", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4247,12 +3998,8 @@ "name": "policy_rule_version_cooldown_policy_id_policy_id_fk", "tableFrom": "policy_rule_version_cooldown", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4306,12 +4053,8 @@ "name": "policy_rule_version_selector_policy_id_policy_id_fk", "tableFrom": "policy_rule_version_selector", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4369,11 +4112,7 @@ "compositePrimaryKeys": { "user_approval_record_version_id_user_id_environment_id_pk": { "name": "user_approval_record_version_id_user_id_environment_id_pk", - "columns": [ - "version_id", - "user_id", - "environment_id" - ] + "columns": ["version_id", "user_id", "environment_id"] } }, "uniqueConstraints": {}, @@ -4410,12 +4149,8 @@ "name": "resource_variable_resource_id_resource_id_fk", "tableFrom": "resource_variable", "tableTo": "resource", - "columnsFrom": [ - "resource_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4423,10 +4158,7 @@ "compositePrimaryKeys": { "resource_variable_resource_id_key_pk": { "name": "resource_variable_resource_id_key_pk", - "columns": [ - "resource_id", - "key" - ] + "columns": ["resource_id", "key"] } }, "uniqueConstraints": {}, @@ -4478,12 +4210,8 @@ "name": "workflow_workspace_id_workspace_id_fk", "tableFrom": "workflow", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4538,12 +4266,8 @@ "name": "workflow_job_workflow_run_id_workflow_run_id_fk", "tableFrom": "workflow_job", "tableTo": "workflow_run", - "columnsFrom": [ - "workflow_run_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_run_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4609,12 +4333,8 @@ "name": "workflow_job_template_workflow_id_workflow_id_fk", "tableFrom": "workflow_job_template", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4656,12 +4376,8 @@ "name": "workflow_run_workflow_id_workflow_id_fk", "tableFrom": "workflow_run", "tableTo": "workflow", - "columnsFrom": [ - "workflow_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4724,12 +4440,8 @@ "name": "job_verification_metric_measurement_job_verification_metric_status_id_job_verification_metric_id_fk", "tableFrom": "job_verification_metric_measurement", "tableTo": "job_verification_metric", - "columnsFrom": [ - "job_verification_metric_status_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["job_verification_metric_status_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4907,12 +4619,8 @@ "name": "policy_rule_job_verification_metric_policy_id_policy_id_fk", "tableFrom": "policy_rule_job_verification_metric", "tableTo": "policy", - "columnsFrom": [ - "policy_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -4988,12 +4696,8 @@ "name": "job_agent_workspace_id_workspace_id_fk", "tableFrom": "job_agent", "tableTo": "workspace", - "columnsFrom": [ - "workspace_id" - ], - "columnsTo": [ - "id" - ], + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" } @@ -5009,10 +4713,7 @@ "public.system_role": { "name": "system_role", "schema": "public", - "values": [ - "user", - "admin" - ] + "values": ["user", "admin"] }, "public.deployment_version_status": { "name": "deployment_version_status", @@ -5055,10 +4756,7 @@ "public.entity_type": { "name": "entity_type", "schema": "public", - "values": [ - "user", - "team" - ] + "values": ["user", "team"] }, "public.scope_type": { "name": "scope_type", @@ -5076,21 +4774,12 @@ "public.job_verification_status": { "name": "job_verification_status", "schema": "public", - "values": [ - "failed", - "inconclusive", - "passed" - ] + "values": ["failed", "inconclusive", "passed"] }, "public.job_verification_trigger_on": { "name": "job_verification_trigger_on", "schema": "public", - "values": [ - "jobCreated", - "jobStarted", - "jobSuccess", - "jobFailure" - ] + "values": ["jobCreated", "jobStarted", "jobSuccess", "jobFailure"] } }, "schemas": {}, @@ -5103,4 +4792,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index 058c03ccc..5e173e5be 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -1095,4 +1095,4 @@ "breakpoints": true } ] -} \ No newline at end of file +} diff --git a/packages/db/src/schema/job-verification-metric.ts b/packages/db/src/schema/job-verification-metric.ts index c7ad5e952..3c8a3eb1f 100644 --- a/packages/db/src/schema/job-verification-metric.ts +++ b/packages/db/src/schema/job-verification-metric.ts @@ -58,8 +58,7 @@ export const jobVerificationMetricStatus = pgTable("job_verification_metric", { .notNull() .defaultNow(), - jobId: uuid("job_id") - .notNull(), + jobId: uuid("job_id").notNull(), name: text("name").notNull(), provider: jsonb("provider").notNull(), From 3f0fb518d11546737c29eda884c2740eef755184 Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 1 Mar 2026 22:24:48 -0500 Subject: [PATCH 02/10] feat: update workflow job structure to include workflowId and enhance job mapping; modify OpenAPI paths for deployment variable management and streamline deployment-related endpoints --- .../api/src/routes/v1/workspaces/workflows.ts | 7 +- apps/web/app/api/openapi.ts | 573 +- packages/workspace-engine-sdk/src/schema.ts | 10289 ++++++++-------- 3 files changed, 5488 insertions(+), 5381 deletions(-) diff --git a/apps/api/src/routes/v1/workspaces/workflows.ts b/apps/api/src/routes/v1/workspaces/workflows.ts index 6c2a8804d..623841f22 100644 --- a/apps/api/src/routes/v1/workspaces/workflows.ts +++ b/apps/api/src/routes/v1/workspaces/workflows.ts @@ -26,7 +26,7 @@ function buildWorkflow( body: { name: string; inputs: Workflow["inputs"]; - jobs: Omit[]; + jobs: Omit[]; }, ): Workflow { return { @@ -34,10 +34,9 @@ function buildWorkflow( name: body.name, inputs: body.inputs, jobs: body.jobs.map((job) => ({ + ...job, id: uuidv4(), - name: job.name, - ref: job.ref, - config: job.config, + workflowId: id, })), }; } diff --git a/apps/web/app/api/openapi.ts b/apps/web/app/api/openapi.ts index d8f6814e0..4d4dc43af 100644 --- a/apps/web/app/api/openapi.ts +++ b/apps/web/app/api/openapi.ts @@ -82,109 +82,117 @@ export interface paths { patch: operations["updateWorkspace"]; trace?: never; }; - "/v1/workspaces/{workspaceId}/deployment-versions/{deploymentVersionId}/user-approval-records": { + "/v1/workspaces/{workspaceId}/deployment-variable-values/{valueId}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; - /** Upsert user approval record */ - put: operations["requestUserApprovalRecordUpsert"]; + /** + * Get deployment variable value + * @description Returns a specific variable value override by ID. + */ + get: operations["getDeploymentVariableValue"]; + /** + * Upsert deployment variable value + * @description Creates or updates a variable value override by ID. + */ + put: operations["requestDeploymentVariableValueUpsert"]; post?: never; - delete?: never; + /** + * Delete deployment variable value + * @description Deletes a variable value override by ID. + */ + delete: operations["requestDeploymentVariableValueDeletion"]; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/workspaces/{workspaceId}/deployments": { + "/v1/workspaces/{workspaceId}/deployment-variables/{variableId}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** List deployments */ - get: operations["listDeployments"]; - put?: never; - /** Create deployment */ - post: operations["requestDeploymentCreation"]; - delete?: never; + /** + * Get deployment variable + * @description Returns a specific deployment variable by ID. + */ + get: operations["getDeploymentVariable"]; + /** + * Upsert deployment variable + * @description Creates or updates a deployment variable by ID. + */ + put: operations["requestDeploymentVariableUpdate"]; + post?: never; + /** + * Delete deployment variable + * @description Deletes a deployment variable by ID. + */ + delete: operations["requestDeploymentVariableDeletion"]; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}": { + "/v1/workspaces/{workspaceId}/deployment-versions/{deploymentVersionId}/user-approval-records": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get deployment */ - get: operations["getDeployment"]; - /** Upsert deployment */ - put: operations["requestDeploymentUpsert"]; + get?: never; + /** Upsert user approval record */ + put: operations["requestUserApprovalRecordUpsert"]; post?: never; - /** Delete deployment */ - delete: operations["requestDeploymentDeletion"]; + delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/variables": { + "/v1/workspaces/{workspaceId}/deployments": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** - * List deployment variables - * @description Returns a list of variables for a deployment, including their configured values. - */ - get: operations["listDeploymentVariables"]; + /** List deployments */ + get: operations["listDeployments"]; put?: never; - post?: never; + /** Create deployment */ + post: operations["requestDeploymentCreation"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/variables/{variableId}": { + "/v1/workspaces/{workspaceId}/deployments/{deploymentId}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** - * Get deployment variable - * @description Returns a specific deployment variable by ID, including its configured values. - */ - get: operations["getDeploymentVariable"]; - /** - * Upsert deployment variable - * @description Creates or updates a deployment variable by ID. - */ - put: operations["requestDeploymentVariableUpdate"]; + /** Get deployment */ + get: operations["getDeployment"]; + /** Upsert deployment */ + put: operations["requestDeploymentUpsert"]; post?: never; - /** - * Delete deployment variable - * @description Deletes a deployment variable by ID. - */ - delete: operations["requestDeploymentVariableDeletion"]; + /** Delete deployment */ + delete: operations["requestDeploymentDeletion"]; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/variables/{variableId}/values": { + "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/variables": { parameters: { query?: never; header?: never; @@ -192,10 +200,10 @@ export interface paths { cookie?: never; }; /** - * List deployment variable values - * @description Returns a list of value overrides for a specific deployment variable. + * List deployment variables by deployment + * @description Returns a list of variables for a deployment, including their configured values. */ - get: operations["listDeploymentVariableValues"]; + get: operations["listDeploymentVariablesByDeployment"]; put?: never; post?: never; delete?: never; @@ -204,34 +212,6 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/variables/{variableId}/values/{valueId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployment variable value - * @description Returns a specific variable value override by ID. - */ - get: operations["getDeploymentVariableValue"]; - /** - * Upsert deployment variable value - * @description Creates or updates a variable value override by ID. - */ - put: operations["requestDeploymentVariableValueUpsert"]; - post?: never; - /** - * Delete deployment variable value - * @description Deletes a variable value override by ID. - */ - delete: operations["requestDeploymentVariableValueDeletion"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; "/v1/workspaces/{workspaceId}/deployments/{deploymentId}/versions": { parameters: { query?: never; @@ -520,6 +500,26 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/workspaces/{workspaceId}/release-targets/state": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Get release target states by deployment and environment + * @description Returns paginated release target states for a given deployment and environment. + */ + post: operations["getReleaseTargetStates"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/workspaces/{workspaceId}/release-targets/{releaseTargetKey}/desired-release": { parameters: { query?: never; @@ -950,10 +950,21 @@ export interface components { }; name: string; priority?: number; - rules?: components["schemas"]["PolicyRule"][]; + rules?: components["schemas"]["CreatePolicyRule"][]; /** @description CEL expression for matching release targets. Use "true" to match all targets. */ selector?: string; }; + CreatePolicyRule: { + anyApproval?: components["schemas"]["AnyApprovalRule"]; + deploymentDependency?: components["schemas"]["DeploymentDependencyRule"]; + deploymentWindow?: components["schemas"]["DeploymentWindowRule"]; + environmentProgression?: components["schemas"]["EnvironmentProgressionRule"]; + gradualRollout?: components["schemas"]["GradualRolloutRule"]; + retry?: components["schemas"]["RetryRule"]; + verification?: components["schemas"]["VerificationRule"]; + versionCooldown?: components["schemas"]["VersionCooldownRule"]; + versionSelector?: components["schemas"]["VersionSelectorRule"]; + }; CreateRelationshipRuleRequest: { description?: string; fromSelector?: components["schemas"]["Selector"]; @@ -1368,6 +1379,7 @@ export interface components { retry?: components["schemas"]["RetryRule"]; verification?: components["schemas"]["VerificationRule"]; versionCooldown?: components["schemas"]["VersionCooldownRule"]; + versionSelector?: components["schemas"]["VersionSelectorRule"]; }; PrometheusMetricProvider: { /** @@ -1493,6 +1505,10 @@ export interface components { desiredRelease?: components["schemas"]["Release"]; latestJob?: components["schemas"]["Job"]; }; + ReleaseTargetWithState: { + releaseTarget: components["schemas"]["ReleaseTarget"]; + state: components["schemas"]["ReleaseTargetState"]; + }; Resource: { config: { [key: string]: unknown; @@ -1706,10 +1722,12 @@ export interface components { }; UpsertDeploymentVariableRequest: { defaultValue?: components["schemas"]["LiteralValue"]; + deploymentId: string; description?: string; key: string; }; UpsertDeploymentVariableValueRequest: { + deploymentVariableId: string; /** Format: int64 */ priority: number; resourceSelector?: components["schemas"]["Selector"]; @@ -1759,10 +1777,24 @@ export interface components { }; name: string; priority: number; - rules: components["schemas"]["PolicyRule"][]; + rules: components["schemas"]["UpsertPolicyRule"][]; /** @description CEL expression for matching release targets. Use "true" to match all targets. */ selector: string; }; + UpsertPolicyRule: { + 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"]; + verification?: components["schemas"]["VerificationRule"]; + versionCooldown?: components["schemas"]["VersionCooldownRule"]; + versionSelector?: components["schemas"]["VersionSelectorRule"]; + }; UpsertRelationshipRuleRequest: { description?: string; fromSelector?: components["schemas"]["Selector"]; @@ -1885,6 +1917,11 @@ export interface components { */ 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: components["schemas"]["WorkflowInput"][]; @@ -2334,31 +2371,27 @@ export interface operations { }; }; }; - requestUserApprovalRecordUpsert: { + getDeploymentVariableValue: { parameters: { query?: never; header?: never; path: { /** @description ID of the workspace */ workspaceId: string; - /** @description ID of the deployment version */ - deploymentVersionId: string; + /** @description ID of the variable value */ + valueId: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["UpsertUserApprovalRecordRequest"]; - }; - }; + requestBody?: never; responses: { - /** @description Accepted response */ - 202: { + /** @description The requested variable value */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["UserApprovalRecordRequestAccepted"]; + "application/json": components["schemas"]["DeploymentVariableValue"]; }; }; /** @description Invalid request */ @@ -2381,55 +2414,21 @@ export interface operations { }; }; }; - 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"]["DeploymentAndSystems"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - }; - }; - requestDeploymentCreation: { + requestDeploymentVariableValueUpsert: { parameters: { query?: never; header?: never; path: { /** @description ID of the workspace */ workspaceId: string; + /** @description ID of the variable value */ + valueId: string; }; cookie?: never; }; requestBody: { content: { - "application/json": components["schemas"]["CreateDeploymentRequest"]; + "application/json": components["schemas"]["UpsertDeploymentVariableValueRequest"]; }; }; responses: { @@ -2439,32 +2438,50 @@ export interface operations { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentRequestAccepted"]; + "application/json": components["schemas"]["DeploymentVariableValueRequestAccepted"]; + }; + }; + /** @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: { + requestDeploymentVariableValueDeletion: { parameters: { query?: never; header?: never; path: { /** @description ID of the workspace */ workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; + /** @description ID of the variable value */ + valueId: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description OK response */ - 200: { + /** @description Accepted response */ + 202: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentWithVariablesAndSystems"]; + "application/json": components["schemas"]["DeploymentVariableValueRequestAccepted"]; }; }; /** @description Invalid request */ @@ -2487,56 +2504,27 @@ export interface operations { }; }; }; - requestDeploymentUpsert: { + getDeploymentVariable: { parameters: { query?: never; header?: never; path: { /** @description ID of the workspace */ workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["UpsertDeploymentRequest"]; - }; - }; - responses: { - /** @description Accepted response */ - 202: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeploymentRequestAccepted"]; - }; - }; - }; - }; - requestDeploymentDeletion: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; + /** @description ID of the deployment variable */ + variableId: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Accepted response */ - 202: { + /** @description The requested deployment variable */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentRequestAccepted"]; + "application/json": components["schemas"]["DeploymentVariableWithValues"]; }; }; /** @description Invalid request */ @@ -2559,67 +2547,31 @@ export interface operations { }; }; }; - listDeploymentVariables: { - 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"]["DeploymentVariableWithValues"][]; - /** @description Maximum number of items returned */ - limit: number; - /** @description Number of items skipped */ - offset: number; - /** @description Total number of items available */ - total: number; - }; - }; - }; - }; - }; - getDeploymentVariable: { + requestDeploymentVariableUpdate: { parameters: { query?: never; header?: never; path: { /** @description ID of the workspace */ workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; /** @description ID of the deployment variable */ variableId: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertDeploymentVariableRequest"]; + }; + }; responses: { - /** @description The requested deployment variable */ - 200: { + /** @description Accepted response */ + 202: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentVariableWithValues"]; + "application/json": components["schemas"]["DeploymentVariableRequestAccepted"]; }; }; /** @description Invalid request */ @@ -2642,25 +2594,19 @@ export interface operations { }; }; }; - requestDeploymentVariableUpdate: { + requestDeploymentVariableDeletion: { parameters: { query?: never; header?: never; path: { /** @description ID of the workspace */ workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; /** @description ID of the deployment variable */ variableId: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["UpsertDeploymentVariableRequest"]; - }; - }; + requestBody?: never; responses: { /** @description Accepted response */ 202: { @@ -2691,21 +2637,23 @@ export interface operations { }; }; }; - requestDeploymentVariableDeletion: { + requestUserApprovalRecordUpsert: { parameters: { query?: never; header?: never; path: { /** @description ID of the workspace */ workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - /** @description ID of the deployment variable */ - variableId: string; + /** @description ID of the deployment version */ + deploymentVersionId: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertUserApprovalRecordRequest"]; + }; + }; responses: { /** @description Accepted response */ 202: { @@ -2713,7 +2661,7 @@ export interface operations { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentVariableRequestAccepted"]; + "application/json": components["schemas"]["UserApprovalRecordRequestAccepted"]; }; }; /** @description Invalid request */ @@ -2736,7 +2684,7 @@ export interface operations { }; }; }; - listDeploymentVariableValues: { + listDeployments: { parameters: { query?: { /** @description Maximum number of items to return */ @@ -2748,10 +2696,6 @@ export interface operations { path: { /** @description ID of the workspace */ workspaceId: string; - /** @description ID of the deployment */ - deploymentId: string; - /** @description ID of the deployment variable */ - variableId: string; }; cookie?: never; }; @@ -2764,7 +2708,7 @@ export interface operations { }; content: { "application/json": { - items: components["schemas"]["DeploymentVariableValue"][]; + items: components["schemas"]["DeploymentAndSystems"][]; /** @description Maximum number of items returned */ limit: number; /** @description Number of items skipped */ @@ -2776,7 +2720,34 @@ export interface operations { }; }; }; - getDeploymentVariableValue: { + requestDeploymentCreation: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateDeploymentRequest"]; + }; + }; + responses: { + /** @description Accepted response */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeploymentRequestAccepted"]; + }; + }; + }; + }; + getDeployment: { parameters: { query?: never; header?: never; @@ -2785,22 +2756,18 @@ export interface operations { workspaceId: string; /** @description ID of the deployment */ deploymentId: string; - /** @description ID of the deployment variable */ - variableId: string; - /** @description ID of the variable value */ - valueId: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description The requested variable value */ + /** @description OK response */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentVariableValue"]; + "application/json": components["schemas"]["DeploymentWithVariablesAndSystems"]; }; }; /** @description Invalid request */ @@ -2823,7 +2790,7 @@ export interface operations { }; }; }; - requestDeploymentVariableValueUpsert: { + requestDeploymentUpsert: { parameters: { query?: never; header?: never; @@ -2832,16 +2799,12 @@ export interface operations { workspaceId: string; /** @description ID of the deployment */ deploymentId: string; - /** @description ID of the deployment variable */ - variableId: string; - /** @description ID of the variable value */ - valueId: string; }; cookie?: never; }; requestBody: { content: { - "application/json": components["schemas"]["UpsertDeploymentVariableValueRequest"]; + "application/json": components["schemas"]["UpsertDeploymentRequest"]; }; }; responses: { @@ -2851,30 +2814,12 @@ export interface operations { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentVariableValueRequestAccepted"]; - }; - }; - /** @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"]; + "application/json": components["schemas"]["DeploymentRequestAccepted"]; }; }; }; }; - requestDeploymentVariableValueDeletion: { + requestDeploymentDeletion: { parameters: { query?: never; header?: never; @@ -2883,10 +2828,6 @@ export interface operations { workspaceId: string; /** @description ID of the deployment */ deploymentId: string; - /** @description ID of the deployment variable */ - variableId: string; - /** @description ID of the variable value */ - valueId: string; }; cookie?: never; }; @@ -2898,7 +2839,7 @@ export interface operations { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["DeploymentVariableValueRequestAccepted"]; + "application/json": components["schemas"]["DeploymentRequestAccepted"]; }; }; /** @description Invalid request */ @@ -2921,6 +2862,44 @@ export interface operations { }; }; }; + listDeploymentVariablesByDeployment: { + 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"]["DeploymentVariableWithValues"][]; + /** @description Maximum number of items returned */ + limit: number; + /** @description Number of items skipped */ + offset: number; + /** @description Total number of items available */ + total: number; + }; + }; + }; + }; + }; listDeploymentVersions: { parameters: { query?: { @@ -4073,6 +4052,58 @@ export interface operations { }; }; }; + getReleaseTargetStates: { + 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": { + deploymentId: string; + environmentId: string; + }; + }; + }; + 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"]; + }; + }; + }; + }; getReleaseTargetDesiredRelease: { parameters: { query?: never; diff --git a/packages/workspace-engine-sdk/src/schema.ts b/packages/workspace-engine-sdk/src/schema.ts index 8125544ae..a189574c5 100644 --- a/packages/workspace-engine-sdk/src/schema.ts +++ b/packages/workspace-engine-sdk/src/schema.ts @@ -4,5134 +4,5211 @@ */ 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-variable-values/{valueId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployment variable value - * @description Returns a specific deployment variable value by ID. - */ - get: operations["getDeploymentVariableValue"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/deployment-variables/{variableId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployment variable - * @description Returns a specific deployment variable by ID. - */ - get: operations["getDeploymentVariable"]; - 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; - }; + "/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-variable-values/{valueId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployment variable value + * @description Returns a specific deployment variable value by ID. + */ + get: operations["getDeploymentVariableValue"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/deployment-variables/{variableId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployment variable + * @description Returns a specific deployment variable by ID. + */ + get: operations["getDeploymentVariable"]; + 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/resource-preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Preview release targets for a resource + * @description Simulates which release targets would be created if the given resource were added to the workspace. This is a dry-run endpoint — no resources or release targets are actually created. + */ + post: operations["previewReleaseTargetsForResource"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/release-targets/state": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Get release target states by deployment and environment + * @description Returns paginated release target states for a given deployment and environment. + */ + post: operations["getReleaseTargetStates"]; + 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}/systems/{systemId}/deployments/{deploymentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get deployment system link + * @description Returns a specific deployment system link by ID. + */ + get: operations["getDeploymentSystemLink"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/systems/{systemId}/environments/{environmentId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get environment system link + * @description Returns a specific environment system link by ID. + */ + get: operations["getEnvironmentSystemLink"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/workflows": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List workflows + * @description Returns a list of workflows. + */ + get: operations["listWorkflows"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/workflows/{workflowId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get a workflow + * @description Gets a workflow by ID. + */ + get: operations["getWorkflow"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/workspaces/{workspaceId}/workflows/{workflowId}/runs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get all workflow runs for a workflow + * @description Gets all workflow runs for a workflow by ID. + */ + get: operations["getWorkflowRuns"]; + 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; + jobAgents?: components["schemas"]["DeploymentJobAgent"][]; + metadata: { + [key: string]: string; + }; + name: string; + resourceSelector?: components["schemas"]["Selector"]; + slug: string; + }; + DeploymentAndSystems: { + deployment: components["schemas"]["Deployment"]; + systems: components["schemas"]["System"][]; + }; + DeploymentDependencyRule: { + /** @description CEL expression to match upstream deployment(s) that must have a successful release before this deployment can proceed. */ + dependsOn: string; + }; + DeploymentJobAgent: { + config: components["schemas"]["JobAgentConfig"]; + ref: string; + /** @description CEL expression to determine if the job agent should be used */ + selector: 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; + }; + DeploymentWithVariablesAndSystems: { + deployment: components["schemas"]["Deployment"]; + systems: components["schemas"]["System"][]; + variables: components["schemas"]["DeploymentVariableWithValues"][]; + }; + DispatchContext: { + deployment?: components["schemas"]["Deployment"]; + environment?: components["schemas"]["Environment"]; + jobAgent: components["schemas"]["JobAgent"]; + jobAgentConfig: components["schemas"]["JobAgentConfig"]; + release?: components["schemas"]["Release"]; + resource?: components["schemas"]["Resource"]; + variables?: { + [key: string]: components["schemas"]["LiteralValue"]; + }; + version?: components["schemas"]["DeploymentVersion"]; + workflow?: components["schemas"]["Workflow"]; + workflowJob?: components["schemas"]["WorkflowJob"]; + workflowRun?: components["schemas"]["WorkflowRun"]; + }; + 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"]; + }; + 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"][]; + }; + EnvironmentSummary: { + id: string; + name: string; + }; + EnvironmentWithSystems: components["schemas"]["Environment"] & { + systems: components["schemas"]["System"][]; + }; + 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; + dispatchContext?: components["schemas"]["DispatchContext"]; + 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"; + JobSummary: { + id: string; + /** @description External links extracted from job metadata */ + links?: { + [key: string]: string; + }; + message?: string; + status: components["schemas"]["JobStatus"]; + verifications: components["schemas"]["JobVerification"][]; + }; + JobUpdateEvent: { + agentId?: string; + externalId?: string; + fieldsToUpdate?: ( + | "completedAt" + | "createdAt" + | "dispatchContext" + | "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 policy - * @description Returns a specific policy by ID. + * @description Bearer token for authentication (supports Go templates for variable references) + * @example {{.variables.prometheus_token}} */ - 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; - }; + 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 release targets for a policy - * @description Returns a list of release targets for a policy {policyId}. + * @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["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; - }; + end?: string; /** - * Get rule - * @description Returns a specific rule by ID. + * @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["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; - }; + start?: string; /** - * List policy skips for a workspace - * @description Returns a list of policy skips for workspace {workspaceId}. + * @description Query resolution step width as a Prometheus duration (e.g., "15s", "1m", "500ms") + * @example 1m */ - 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; + 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"; + }; + 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; + }; + ReleaseTargetAndState: { + releaseTarget: components["schemas"]["ReleaseTarget"]; + state: components["schemas"]["ReleaseTargetState"]; + }; + ReleaseTargetPreview: { + deployment: components["schemas"]["Deployment"]; + environment: components["schemas"]["Environment"]; + system: components["schemas"]["System"]; + }; + ReleaseTargetState: { + currentRelease?: components["schemas"]["Release"]; + desiredRelease?: components["schemas"]["Release"]; + latestJob?: components["schemas"]["JobWithVerifications"]; + }; + ReleaseTargetSummary: { + currentVersion?: components["schemas"]["VersionSummary"]; + desiredVersion?: components["schemas"]["VersionSummary"]; + environment: components["schemas"]["EnvironmentSummary"]; + latestJob?: components["schemas"]["JobSummary"]; + releaseTarget: components["schemas"]["ReleaseTarget"]; + resource: components["schemas"]["ResourceSummary"]; + }; + 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; + }; + ResourcePreviewRequest: { + config: { + [key: string]: unknown; + }; + identifier: string; + kind: string; + metadata: { + [key: string]: string; + }; + name: string; + version: string; + }; + ResourceProvider: { + /** Format: date-time */ + createdAt: string; + id: string; + metadata: { + [key: string]: string; + }; + name: string; + /** Format: uuid */ + workspaceId: string; + }; + ResourceSummary: { + id: string; + identifier: string; + kind: string; + name: string; + version: 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; + }; + SystemDeploymentLink: { + deploymentId: string; + systemId: string; + }; + SystemEnvironmentLink: { + environmentId: string; + systemId: 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"]; + }; + VersionSummary: { + id: string; + name: string; + tag: string; + }; + Workflow: { + id: string; + inputs: components["schemas"]["WorkflowInput"][]; + jobs: components["schemas"]["WorkflowJobTemplate"][]; + name: string; + }; + WorkflowArrayInput: + | components["schemas"]["WorkflowManualArrayInput"] + | components["schemas"]["WorkflowSelectorArrayInput"]; + WorkflowBooleanInput: { + default?: boolean; + key: string; + /** @enum {string} */ + type: "boolean"; + }; + WorkflowInput: + | components["schemas"]["WorkflowStringInput"] + | components["schemas"]["WorkflowNumberInput"] + | components["schemas"]["WorkflowBooleanInput"] + | components["schemas"]["WorkflowArrayInput"] + | components["schemas"]["WorkflowObjectInput"]; + WorkflowJob: { + /** @description Configuration for the job agent */ + config: { + [key: string]: unknown; + }; + id: string; + index: number; + /** @description Reference to the job agent */ + ref: string; + workflowRunId: 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; + /** @description CEL expression to determine if the job should run */ + if?: string; + matrix?: components["schemas"]["WorkflowJobMatrix"]; + name: string; + /** @description Reference to the job agent */ + ref: string; + workflowId: string; + }; + WorkflowJobWithJobs: components["schemas"]["WorkflowJob"] & { + jobs: components["schemas"]["Job"][]; + }; + WorkflowManualArrayInput: { + default?: { + [key: string]: unknown; + }[]; + key: string; + /** @enum {string} */ + type: "array"; + }; + WorkflowNumberInput: { + default?: number; + key: string; + /** @enum {string} */ + type: "number"; + }; + WorkflowObjectInput: { + default?: { + [key: string]: unknown; + }; + key: string; + /** @enum {string} */ + type: "object"; + }; + WorkflowRun: { + id: string; + inputs: { + [key: string]: unknown; + }; + workflowId: string; + }; + WorkflowRunWithJobs: components["schemas"]["WorkflowRun"] & { + jobs: components["schemas"]["WorkflowJobWithJobs"][]; + }; + WorkflowSelectorArrayInput: { + key: string; + selector: { + default?: components["schemas"]["Selector"]; + /** @enum {string} */ + entityType: "resource" | "environment" | "deployment"; + }; + /** @enum {string} */ + type: "array"; + }; + WorkflowStringInput: { + default?: string; + key: string; + /** @enum {string} */ + type: "string"; + }; + }; + 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"]; + }; + }; + }; + 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[]; + }; + }; + }; + }; + }; + getDeploymentVariableValue: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment variable value */ + valueId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested deployment variable value */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeploymentVariableValue"]; + }; + }; + /** @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"]; + }; + }; + }; + }; + getDeploymentVariable: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the deployment variable */ + variableId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested deployment variable */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeploymentVariableWithValues"]; + }; + }; + /** @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"]; + }; + }; + }; + }; + 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; + }[]; + }[]; }; - /** - * 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; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; }; - /** - * 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; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; - /** - * 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/resource-preview": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Preview release targets for a resource - * @description Simulates which release targets would be created if the given resource were added to the workspace. This is a dry-run endpoint — no resources or release targets are actually created. - */ - post: operations["previewReleaseTargetsForResource"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/release-targets/state": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * Get release target states by deployment and environment - * @description Returns paginated release target states for a given deployment and environment. - */ - post: operations["getReleaseTargetStates"]; - 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; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; }; - /** - * 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; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; - /** - * 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; + }; + }; + }; + 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"]["DeploymentAndSystems"][]; + /** @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"]["DeploymentWithVariablesAndSystems"]; + }; + }; + /** @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"]["ReleaseTargetSummary"][]; + /** @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; + }; + 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["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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]["EnvironmentWithSystems"]; + }; + }; + /** @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; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]["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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + previewReleaseTargetsForResource: { + 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": components["schemas"]["ResourcePreviewRequest"]; + }; + }; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["ReleaseTargetPreview"][]; + /** @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"]; + }; + }; + }; + }; + getReleaseTargetStates: { + 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": { + deploymentId: string; + environmentId: string; + }; + }; + }; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["ReleaseTargetAndState"][]; + /** @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"]; + }; + }; + }; + }; + 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"]; + }; }; - /** - * 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; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; }; - /** - * 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; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; - /** - * 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; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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; + }; }; - /** - * 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; + }; + }; + }; + 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"]; + }; + }; + }; + }; + 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"]; + }; }; - /** - * 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; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; }; - /** - * 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; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; - /** - * 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; + }; + /** @description Resource not found */ + 404: { + headers: { + [name: string]: unknown; }; - /** - * 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}/systems/{systemId}/deployments/{deploymentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get deployment system link - * @description Returns a specific deployment system link by ID. - */ - get: operations["getDeploymentSystemLink"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/systems/{systemId}/environments/{environmentId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get environment system link - * @description Returns a specific environment system link by ID. - */ - get: operations["getEnvironmentSystemLink"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/workflows": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * List workflows - * @description Returns a list of workflows. - */ - get: operations["listWorkflows"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/workflows/{workflowId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get a workflow - * @description Gets a workflow by ID. - */ - get: operations["getWorkflow"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/v1/workspaces/{workspaceId}/workflows/{workflowId}/runs": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get all workflow runs for a workflow - * @description Gets all workflow runs for a workflow by ID. - */ - get: operations["getWorkflowRuns"]; - 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; - jobAgents?: components["schemas"]["DeploymentJobAgent"][]; - metadata: { - [key: string]: string; - }; - name: string; - resourceSelector?: components["schemas"]["Selector"]; - slug: string; - }; - DeploymentAndSystems: { - deployment: components["schemas"]["Deployment"]; - systems: components["schemas"]["System"][]; - }; - DeploymentDependencyRule: { - /** @description CEL expression to match upstream deployment(s) that must have a successful release before this deployment can proceed. */ - dependsOn: string; - }; - DeploymentJobAgent: { - config: components["schemas"]["JobAgentConfig"]; - ref: string; - /** @description CEL expression to determine if the job agent should be used */ - selector: 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; - }; - DeploymentWithVariablesAndSystems: { - deployment: components["schemas"]["Deployment"]; - systems: components["schemas"]["System"][]; - variables: components["schemas"]["DeploymentVariableWithValues"][]; - }; - DispatchContext: { - deployment?: components["schemas"]["Deployment"]; - environment?: components["schemas"]["Environment"]; - jobAgent: components["schemas"]["JobAgent"]; - jobAgentConfig: components["schemas"]["JobAgentConfig"]; - release?: components["schemas"]["Release"]; - resource?: components["schemas"]["Resource"]; - variables?: { - [key: string]: components["schemas"]["LiteralValue"]; - }; - version?: components["schemas"]["DeploymentVersion"]; - workflow?: components["schemas"]["Workflow"]; - workflowJob?: components["schemas"]["WorkflowJob"]; - workflowRun?: components["schemas"]["WorkflowRun"]; - }; - 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"]; - }; - 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"][]; - }; - EnvironmentSummary: { - id: string; - name: string; - }; - EnvironmentWithSystems: components["schemas"]["Environment"] & { - systems: components["schemas"]["System"][]; - }; - 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; - dispatchContext?: components["schemas"]["DispatchContext"]; - 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"; - JobSummary: { - id: string; - /** @description External links extracted from job metadata */ - links?: { - [key: string]: string; - }; - message?: string; - status: components["schemas"]["JobStatus"]; - verifications: components["schemas"]["JobVerification"][]; - }; - JobUpdateEvent: { - agentId?: string; - externalId?: string; - fieldsToUpdate?: ("completedAt" | "createdAt" | "dispatchContext" | "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?: { - /** - * @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"; - }; - 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; - }; - ReleaseTargetAndState: { - releaseTarget: components["schemas"]["ReleaseTarget"]; - state: components["schemas"]["ReleaseTargetState"]; - }; - ReleaseTargetPreview: { - deployment: components["schemas"]["Deployment"]; - environment: components["schemas"]["Environment"]; - system: components["schemas"]["System"]; - }; - ReleaseTargetState: { - currentRelease?: components["schemas"]["Release"]; - desiredRelease?: components["schemas"]["Release"]; - latestJob?: components["schemas"]["JobWithVerifications"]; - }; - ReleaseTargetSummary: { - currentVersion?: components["schemas"]["VersionSummary"]; - desiredVersion?: components["schemas"]["VersionSummary"]; - environment: components["schemas"]["EnvironmentSummary"]; - latestJob?: components["schemas"]["JobSummary"]; - releaseTarget: components["schemas"]["ReleaseTarget"]; - resource: components["schemas"]["ResourceSummary"]; - }; - 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; - }; - ResourcePreviewRequest: { - config: { - [key: string]: unknown; - }; - identifier: string; - kind: string; - metadata: { - [key: string]: string; - }; - name: string; - version: string; - }; - ResourceProvider: { - /** Format: date-time */ - createdAt: string; - id: string; - metadata: { - [key: string]: string; - }; - name: string; - /** Format: uuid */ - workspaceId: string; - }; - ResourceSummary: { - id: string; - identifier: string; - kind: string; - name: string; - version: 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; - }; - SystemDeploymentLink: { - deploymentId: string; - systemId: string; - }; - SystemEnvironmentLink: { - environmentId: string; - systemId: 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"]; - }; - VersionSummary: { - id: string; - name: string; - tag: string; - }; - Workflow: { - id: string; - inputs: components["schemas"]["WorkflowInput"][]; - jobs: components["schemas"]["WorkflowJobTemplate"][]; - name: string; - }; - WorkflowArrayInput: components["schemas"]["WorkflowManualArrayInput"] | components["schemas"]["WorkflowSelectorArrayInput"]; - WorkflowBooleanInput: { - default?: boolean; - key: string; - /** @enum {string} */ - type: "boolean"; - }; - WorkflowInput: components["schemas"]["WorkflowStringInput"] | components["schemas"]["WorkflowNumberInput"] | components["schemas"]["WorkflowBooleanInput"] | components["schemas"]["WorkflowArrayInput"] | components["schemas"]["WorkflowObjectInput"]; - WorkflowJob: { - /** @description Configuration for the job agent */ - config: { - [key: string]: unknown; - }; - id: string; - index: number; - /** @description Reference to the job agent */ - ref: string; - workflowRunId: 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; - /** @description CEL expression to determine if the job should run */ - if?: string; - matrix?: components["schemas"]["WorkflowJobMatrix"]; - name: string; - /** @description Reference to the job agent */ - ref: string; - workflowId: string; - }; - WorkflowJobWithJobs: components["schemas"]["WorkflowJob"] & { - jobs: components["schemas"]["Job"][]; - }; - WorkflowManualArrayInput: { - default?: { - [key: string]: unknown; - }[]; - key: string; - /** @enum {string} */ - type: "array"; - }; - WorkflowNumberInput: { - default?: number; - key: string; - /** @enum {string} */ - type: "number"; - }; - WorkflowObjectInput: { - default?: { - [key: string]: unknown; - }; - key: string; - /** @enum {string} */ - type: "object"; - }; - WorkflowRun: { - id: string; - inputs: { - [key: string]: unknown; - }; - workflowId: string; - }; - WorkflowRunWithJobs: components["schemas"]["WorkflowRun"] & { - jobs: components["schemas"]["WorkflowJobWithJobs"][]; - }; - WorkflowSelectorArrayInput: { - key: string; - selector: { - default?: components["schemas"]["Selector"]; - /** @enum {string} */ - entityType: "resource" | "environment" | "deployment"; - }; - /** @enum {string} */ - type: "array"; - }; - WorkflowStringInput: { - default?: string; - key: string; - /** @enum {string} */ - type: "string"; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; + }; }; - responses: never; + }; + getDeploymentSystemLink: { 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"]; - }; - }; - }; - 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[]; - }; - }; - }; - }; - }; - getDeploymentVariableValue: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment variable value */ - valueId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested deployment variable value */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeploymentVariableValue"]; - }; - }; - /** @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"]; - }; - }; - }; - }; - getDeploymentVariable: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the deployment variable */ - variableId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested deployment variable */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["DeploymentVariableWithValues"]; - }; - }; - /** @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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]["DeploymentAndSystems"][]; - /** @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"]["DeploymentWithVariablesAndSystems"]; - }; - }; - /** @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"]["ReleaseTargetSummary"][]; - /** @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; - }; - 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["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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]["EnvironmentWithSystems"]; - }; - }; - /** @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; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]["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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - previewReleaseTargetsForResource: { - 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": components["schemas"]["ResourcePreviewRequest"]; - }; - }; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["ReleaseTargetPreview"][]; - /** @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"]; - }; - }; - }; - }; - getReleaseTargetStates: { - 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": { - deploymentId: string; - environmentId: string; - }; - }; - }; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["ReleaseTargetAndState"][]; - /** @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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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; - }; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - 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"]; - }; - }; - }; - }; - getDeploymentSystemLink: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the system */ - systemId: string; - /** @description ID of the deployment */ - deploymentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested deployment system link */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["SystemDeploymentLink"]; - }; - }; - /** @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"]; - }; - }; - }; - }; - getEnvironmentSystemLink: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the system */ - systemId: string; - /** @description ID of the environment */ - environmentId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The requested environment system link */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["SystemEnvironmentLink"]; - }; - }; - /** @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"]; - }; - }; - }; - }; - listWorkflows: { - 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"]["Workflow"][]; - /** @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"]; - }; - }; - }; - }; - getWorkflow: { - parameters: { - query?: never; - header?: never; - path: { - /** @description ID of the workspace */ - workspaceId: string; - /** @description ID of the workflow */ - workflowId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Get workflow */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Workflow"]; - }; - }; - /** @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"]; - }; - }; - }; - }; - getWorkflowRuns: { - 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 */ - workflowId: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Paginated list of items */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": { - items: components["schemas"]["WorkflowRunWithJobs"][]; - /** @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"]; - }; - }; - }; - }; + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the system */ + systemId: string; + /** @description ID of the deployment */ + deploymentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested deployment system link */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SystemDeploymentLink"]; + }; + }; + /** @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"]; + }; + }; + }; + }; + getEnvironmentSystemLink: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the system */ + systemId: string; + /** @description ID of the environment */ + environmentId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The requested environment system link */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SystemEnvironmentLink"]; + }; + }; + /** @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"]; + }; + }; + }; + }; + listWorkflows: { + 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"]["Workflow"][]; + /** @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"]; + }; + }; + }; + }; + getWorkflow: { + parameters: { + query?: never; + header?: never; + path: { + /** @description ID of the workspace */ + workspaceId: string; + /** @description ID of the workflow */ + workflowId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Get workflow */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Workflow"]; + }; + }; + /** @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"]; + }; + }; + }; + }; + getWorkflowRuns: { + 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 */ + workflowId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of items */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + items: components["schemas"]["WorkflowRunWithJobs"][]; + /** @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"]; + }; + }; + }; + }; } From 154d77ac5fbd2a8207bb6b2062c2e95889cbc75a Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 1 Mar 2026 22:39:24 -0500 Subject: [PATCH 03/10] refactor: remove unused tracer variables and pointer helper functions to clean up code and improve readability --- apps/workspace-engine/pkg/concurrency/chunks.go | 3 --- .../jobagents/github/githubaction_test.go | 2 -- .../jobagents/testrunner/testrunner.go | 4 ---- .../jobverificationmetric/metrics/metric.go | 17 ++++++----------- .../jobverificationmetric/reconcile_test.go | 2 -- .../test/controllers/harness/mocks.go | 4 +--- 6 files changed, 7 insertions(+), 25 deletions(-) diff --git a/apps/workspace-engine/pkg/concurrency/chunks.go b/apps/workspace-engine/pkg/concurrency/chunks.go index 6e1480cbd..262eeeb83 100644 --- a/apps/workspace-engine/pkg/concurrency/chunks.go +++ b/apps/workspace-engine/pkg/concurrency/chunks.go @@ -4,7 +4,6 @@ import ( "context" "runtime" - "go.opentelemetry.io/otel" "golang.org/x/sync/errgroup" ) @@ -26,8 +25,6 @@ func Chunk[T any](slice []T, chunkSize int) [][]T { return chunks } -var tracer = otel.Tracer("workspace-engine/pkg/concurrency") - type options struct { chunkSize int maxConcurrency int diff --git a/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/github/githubaction_test.go b/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/github/githubaction_test.go index 1906501ac..a3341b0a1 100644 --- a/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/github/githubaction_test.go +++ b/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/github/githubaction_test.go @@ -71,8 +71,6 @@ func (m *mockSetter) getCalls() []updateCall { // ----- Helpers ----- -func ptr[T any](v T) *T { return &v } - func validConfig() oapi.JobAgentConfig { return oapi.JobAgentConfig{ "installationId": float64(12345), diff --git a/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/testrunner/testrunner.go b/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/testrunner/testrunner.go index 3b0d9ce86..ae2e82e78 100644 --- a/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/testrunner/testrunner.go +++ b/apps/workspace-engine/svc/controllers/jobdispatch/jobagents/testrunner/testrunner.go @@ -7,12 +7,8 @@ import ( "workspace-engine/pkg/oapi" "workspace-engine/pkg/workspace/jobagents/types" - - "go.opentelemetry.io/otel" ) -var tracer = otel.Tracer("jobagents/testrunner") - var _ types.Dispatchable = &TestRunner{} type TestRunner struct { diff --git a/apps/workspace-engine/svc/controllers/jobverificationmetric/metrics/metric.go b/apps/workspace-engine/svc/controllers/jobverificationmetric/metrics/metric.go index 6e92ea8d3..43c2d3843 100644 --- a/apps/workspace-engine/svc/controllers/jobverificationmetric/metrics/metric.go +++ b/apps/workspace-engine/svc/controllers/jobverificationmetric/metrics/metric.go @@ -53,7 +53,6 @@ func Measure(ctx context.Context, metric *VerificationMetric, providerCtx *provi return Measurement{}, err } - message := "Measurement completed" hasFailureCondition := metric.FailureCondition != nil && *metric.FailureCondition != "" if hasFailureCondition { @@ -65,14 +64,13 @@ func Measure(ctx context.Context, metric *VerificationMetric, providerCtx *provi failed, err := failureEvaluator.Evaluate(data) if err != nil { - message = fmt.Sprintf("Failure evaluation failed: %s", err.Error()) + log.Error("Failure evaluation failed", "error", err) } if failed { - message = "Failure condition met" return Measurement{ MetricID: metric.ID, - Message: message, + Message: "Failure condition met", Status: StatusFailed, Data: data, MeasuredAt: measuredAt, @@ -88,14 +86,13 @@ func Measure(ctx context.Context, metric *VerificationMetric, providerCtx *provi passed, err := successEvaluator.Evaluate(data) if err != nil { - message = fmt.Sprintf("Success evaluation failed: %s", err.Error()) + log.Error("Success evaluation failed", "error", err) } if passed { - message = "Success condition met" return Measurement{ MetricID: metric.ID, - Message: message, + Message: "Success condition met", Status: StatusPassed, Data: data, MeasuredAt: measuredAt, @@ -103,20 +100,18 @@ func Measure(ctx context.Context, metric *VerificationMetric, providerCtx *provi } if hasFailureCondition { - message = "Waiting for success or failure condition" return Measurement{ MetricID: metric.ID, - Message: message, + Message: "Waiting for success or failure condition", Status: StatusInconclusive, Data: data, MeasuredAt: measuredAt, }, nil } - message = "Success condition not met" return Measurement{ MetricID: metric.ID, - Message: message, + Message: "Success condition not met", Status: StatusFailed, Data: data, MeasuredAt: measuredAt, diff --git a/apps/workspace-engine/svc/controllers/jobverificationmetric/reconcile_test.go b/apps/workspace-engine/svc/controllers/jobverificationmetric/reconcile_test.go index f2ff813cb..efcd99ac9 100644 --- a/apps/workspace-engine/svc/controllers/jobverificationmetric/reconcile_test.go +++ b/apps/workspace-engine/svc/controllers/jobverificationmetric/reconcile_test.go @@ -161,8 +161,6 @@ func reconcileItem(scopeID, kind string) reconcile.Item { func int32Ptr(i int32) *int32 { return &i } -func strPtr(s string) *string { return &s } - // --------------------------------------------------------------------------- // Controller.Process tests // --------------------------------------------------------------------------- diff --git a/apps/workspace-engine/test/controllers/harness/mocks.go b/apps/workspace-engine/test/controllers/harness/mocks.go index 654f9f470..c232f3fe9 100644 --- a/apps/workspace-engine/test/controllers/harness/mocks.go +++ b/apps/workspace-engine/test/controllers/harness/mocks.go @@ -63,9 +63,7 @@ func (s *SelectorEvalSetter) SetComputedDeploymentResources(_ context.Context, _ // DesiredReleaseGetter implements desiredrelease.Getter. type DesiredReleaseGetter struct { - mu sync.Mutex - - Scope *evaluator.EvaluatorScope + Scope *evaluator.EvaluatorScope Versions []*oapi.DeploymentVersion Policies []*oapi.Policy ApprovalRecords []*oapi.UserApprovalRecord From b680369534e6d103dd0fa308d8f82bb428d5ebc0 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 2 Mar 2026 01:21:09 -0500 Subject: [PATCH 04/10] feat: add 'id' field to Release schema and update related database models and queries; enhance job management with unique release IDs --- apps/workspace-engine/oapi/openapi.json | 4 + .../oapi/spec/schemas/entities.jsonnet | 3 +- apps/workspace-engine/pkg/db/models.go | 2 + .../pkg/db/queries/releases.sql | 9 +- .../pkg/db/queries/schema.sql | 4 +- apps/workspace-engine/pkg/db/releases.sql.go | 21 +- .../events/handler/deployment/deployment.go | 19 + .../pkg/events/handler/resources/resources.go | 19 + apps/workspace-engine/pkg/oapi/oapi.gen.go | 1 + apps/workspace-engine/pkg/oapi/oapi.go | 23 +- .../pkg/oapi/oapi_extra_test.go | 15 +- .../pkg/persistence/integration_test.go | 1 + .../pkg/workspace/jobs/factory_test.go | 1 + .../action/orchestrator_test.go | 1 + .../releasemanager/action/rollback/hooks.go | 4 +- .../action/rollback/rollback.go | 2 +- .../action/verification/verification_test.go | 1 + .../releasemanager/deployment/executor.go | 4 +- .../deployment/executor_test.go | 25 +- .../deployment/job_eligibility_retry_test.go | 18 + .../deployment/job_eligibility_test.go | 30 + .../releasemanager/deployment/planner_test.go | 6 +- .../workspace/releasemanager/manager_test.go | 3 + .../deployableversions_test.go | 10 + .../deployment_dependency_test.go | 1 + .../deploymentwindow/deploymentwindow_test.go | 1 + .../environmentprogression_test.go | 13 + .../environmentprogression/jobtracker_test.go | 27 + .../environmentprogression/passrate_test.go | 12 + .../environmentprogression/soaktime_test.go | 10 + .../environment_summary_test.go | 1 + .../gradualrollout/gradualrollout_test.go | 8 + .../releasetargetconcurrency_test.go | 22 + .../policy/evaluator/retry/retry.go | 20 +- .../policy/evaluator/retry/retry_test.go | 393 +- .../evaluator/retry/smart_defaults_test.go | 176 +- .../evaluator/rollback/rollback_test.go | 1 + .../versioncooldown/version_summary_test.go | 1 + .../versioncooldown/versioncooldown_test.go | 1 + .../releasemanager/state_index_test.go | 3 + .../verification/scheduler_test.go | 1 + .../pkg/workspace/store/jobs.go | 22 +- .../workspace/store/release_targets_test.go | 7 + .../store/repository/db/releases/mapper.go | 13 +- .../store/repository/db/releases/repo.go | 10 +- .../e2e/engine_job_agent_retrigger_test.go | 11 +- .../e2e/engine_nil_release_handling_test.go | 39 +- .../e2e/engine_releasetarget_state_test.go | 8 +- .../test/integration/dbtest.go | 4 +- packages/db/drizzle/0156_fine_talkback.sql | 12 + .../drizzle/0157_supreme_matthew_murdock.sql | 11 + packages/db/drizzle/meta/0156_snapshot.json | 4795 ++++++++++++++++ packages/db/drizzle/meta/0157_snapshot.json | 4846 +++++++++++++++++ packages/db/drizzle/meta/_journal.json | 14 + packages/db/src/schema/job.ts | 18 +- packages/db/src/schema/release.ts | 25 +- 56 files changed, 10399 insertions(+), 353 deletions(-) create mode 100644 packages/db/drizzle/0156_fine_talkback.sql create mode 100644 packages/db/drizzle/0157_supreme_matthew_murdock.sql create mode 100644 packages/db/drizzle/meta/0156_snapshot.json create mode 100644 packages/db/drizzle/meta/0157_snapshot.json diff --git a/apps/workspace-engine/oapi/openapi.json b/apps/workspace-engine/oapi/openapi.json index 57541e60d..2cb91c28a 100644 --- a/apps/workspace-engine/oapi/openapi.json +++ b/apps/workspace-engine/oapi/openapi.json @@ -1627,6 +1627,9 @@ }, "type": "array" }, + "id": { + "type": "string" + }, "releaseTarget": { "$ref": "#/components/schemas/ReleaseTarget" }, @@ -1641,6 +1644,7 @@ } }, "required": [ + "id", "version", "variables", "encryptedVariables", diff --git a/apps/workspace-engine/oapi/spec/schemas/entities.jsonnet b/apps/workspace-engine/oapi/spec/schemas/entities.jsonnet index d145ca0bd..81a0ca3ca 100644 --- a/apps/workspace-engine/oapi/spec/schemas/entities.jsonnet +++ b/apps/workspace-engine/oapi/spec/schemas/entities.jsonnet @@ -141,8 +141,9 @@ local openapi = import '../lib/openapi.libsonnet'; Release: { type: 'object', - required: ['version', 'variables', 'encryptedVariables', 'releaseTarget', 'createdAt'], + required: ['id', 'version', 'variables', 'encryptedVariables', 'releaseTarget', 'createdAt'], properties: { + id: { type: 'string' }, version: openapi.schemaRef('DeploymentVersion'), variables: { type: 'object', diff --git a/apps/workspace-engine/pkg/db/models.go b/apps/workspace-engine/pkg/db/models.go index ff117a3bc..812878dc3 100644 --- a/apps/workspace-engine/pkg/db/models.go +++ b/apps/workspace-engine/pkg/db/models.go @@ -483,10 +483,12 @@ type Release struct { EnvironmentID uuid.UUID DeploymentID uuid.UUID VersionID uuid.UUID + VersionStatus pgtype.Text CreatedAt pgtype.Timestamptz } type ReleaseJob struct { + ID uuid.UUID ReleaseID uuid.UUID JobID uuid.UUID } diff --git a/apps/workspace-engine/pkg/db/queries/releases.sql b/apps/workspace-engine/pkg/db/queries/releases.sql index 532b3e15e..d2e63ae54 100644 --- a/apps/workspace-engine/pkg/db/queries/releases.sql +++ b/apps/workspace-engine/pkg/db/queries/releases.sql @@ -6,7 +6,7 @@ SELECT * FROM release WHERE resource_id = $1 AND environment_id = $2 AND deployment_id = $3; -- name: ListReleasesByWorkspaceID :many -SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.created_at +SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.version_status, r.created_at FROM release r JOIN deployment d ON d.id = r.deployment_id WHERE d.workspace_id = $1 @@ -16,13 +16,14 @@ LIMIT COALESCE(sqlc.narg('limit')::int, 5000); SELECT * FROM release_variable WHERE release_id = $1; -- name: UpsertRelease :one -INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, created_at) -VALUES ($1, $2, $3, $4, $5, COALESCE(sqlc.narg('created_at')::timestamptz, NOW())) +INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, version_status, created_at) +VALUES ($1, $2, $3, $4, $5, $6, COALESCE(sqlc.narg('created_at')::timestamptz, NOW())) ON CONFLICT (id) DO UPDATE SET resource_id = EXCLUDED.resource_id, environment_id = EXCLUDED.environment_id, deployment_id = EXCLUDED.deployment_id, - version_id = EXCLUDED.version_id + version_id = EXCLUDED.version_id, + version_status = EXCLUDED.version_status RETURNING *; -- name: UpsertReleaseVariable :one diff --git a/apps/workspace-engine/pkg/db/queries/schema.sql b/apps/workspace-engine/pkg/db/queries/schema.sql index 82795507e..2817c7a3b 100644 --- a/apps/workspace-engine/pkg/db/queries/schema.sql +++ b/apps/workspace-engine/pkg/db/queries/schema.sql @@ -113,6 +113,7 @@ CREATE TABLE release ( environment_id UUID NOT NULL, deployment_id UUID NOT NULL, version_id UUID NOT NULL, + version_status TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); @@ -359,9 +360,10 @@ CREATE TABLE job_metadata ( ); CREATE TABLE release_job ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), release_id UUID NOT NULL REFERENCES release(id) ON DELETE CASCADE, job_id UUID NOT NULL REFERENCES job(id) ON DELETE CASCADE, - PRIMARY KEY (release_id, job_id) + UNIQUE (release_id, job_id) ); -- Verification Metric Table (as in packages/db/src/schema/verification.ts) diff --git a/apps/workspace-engine/pkg/db/releases.sql.go b/apps/workspace-engine/pkg/db/releases.sql.go index 7bca8133c..a7b8b9f2e 100644 --- a/apps/workspace-engine/pkg/db/releases.sql.go +++ b/apps/workspace-engine/pkg/db/releases.sql.go @@ -31,7 +31,7 @@ func (q *Queries) DeleteReleaseVariablesByReleaseID(ctx context.Context, release } const getReleaseByID = `-- name: GetReleaseByID :one -SELECT id, resource_id, environment_id, deployment_id, version_id, created_at FROM release WHERE id = $1 +SELECT id, resource_id, environment_id, deployment_id, version_id, version_status, created_at FROM release WHERE id = $1 ` func (q *Queries) GetReleaseByID(ctx context.Context, id uuid.UUID) (Release, error) { @@ -43,6 +43,7 @@ func (q *Queries) GetReleaseByID(ctx context.Context, id uuid.UUID) (Release, er &i.EnvironmentID, &i.DeploymentID, &i.VersionID, + &i.VersionStatus, &i.CreatedAt, ) return i, err @@ -80,7 +81,7 @@ func (q *Queries) GetReleaseVariablesByReleaseID(ctx context.Context, releaseID } const listReleasesByReleaseTarget = `-- name: ListReleasesByReleaseTarget :many -SELECT id, resource_id, environment_id, deployment_id, version_id, created_at FROM release +SELECT id, resource_id, environment_id, deployment_id, version_id, version_status, created_at FROM release WHERE resource_id = $1 AND environment_id = $2 AND deployment_id = $3 ` @@ -105,6 +106,7 @@ func (q *Queries) ListReleasesByReleaseTarget(ctx context.Context, arg ListRelea &i.EnvironmentID, &i.DeploymentID, &i.VersionID, + &i.VersionStatus, &i.CreatedAt, ); err != nil { return nil, err @@ -118,7 +120,7 @@ func (q *Queries) ListReleasesByReleaseTarget(ctx context.Context, arg ListRelea } const listReleasesByWorkspaceID = `-- name: ListReleasesByWorkspaceID :many -SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.created_at +SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.version_status, r.created_at FROM release r JOIN deployment d ON d.id = r.deployment_id WHERE d.workspace_id = $1 @@ -145,6 +147,7 @@ func (q *Queries) ListReleasesByWorkspaceID(ctx context.Context, arg ListRelease &i.EnvironmentID, &i.DeploymentID, &i.VersionID, + &i.VersionStatus, &i.CreatedAt, ); err != nil { return nil, err @@ -158,14 +161,15 @@ func (q *Queries) ListReleasesByWorkspaceID(ctx context.Context, arg ListRelease } const upsertRelease = `-- name: UpsertRelease :one -INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, created_at) -VALUES ($1, $2, $3, $4, $5, COALESCE($6::timestamptz, NOW())) +INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, version_status, created_at) +VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7::timestamptz, NOW())) ON CONFLICT (id) DO UPDATE SET resource_id = EXCLUDED.resource_id, environment_id = EXCLUDED.environment_id, deployment_id = EXCLUDED.deployment_id, - version_id = EXCLUDED.version_id -RETURNING id, resource_id, environment_id, deployment_id, version_id, created_at + version_id = EXCLUDED.version_id, + version_status = EXCLUDED.version_status +RETURNING id, resource_id, environment_id, deployment_id, version_id, version_status, created_at ` type UpsertReleaseParams struct { @@ -174,6 +178,7 @@ type UpsertReleaseParams struct { EnvironmentID uuid.UUID DeploymentID uuid.UUID VersionID uuid.UUID + VersionStatus pgtype.Text CreatedAt pgtype.Timestamptz } @@ -184,6 +189,7 @@ func (q *Queries) UpsertRelease(ctx context.Context, arg UpsertReleaseParams) (R arg.EnvironmentID, arg.DeploymentID, arg.VersionID, + arg.VersionStatus, arg.CreatedAt, ) var i Release @@ -193,6 +199,7 @@ func (q *Queries) UpsertRelease(ctx context.Context, arg UpsertReleaseParams) (R &i.EnvironmentID, &i.DeploymentID, &i.VersionID, + &i.VersionStatus, &i.CreatedAt, ) return i, err diff --git a/apps/workspace-engine/pkg/events/handler/deployment/deployment.go b/apps/workspace-engine/pkg/events/handler/deployment/deployment.go index 3828c0e0c..0a3a68e46 100644 --- a/apps/workspace-engine/pkg/events/handler/deployment/deployment.go +++ b/apps/workspace-engine/pkg/events/handler/deployment/deployment.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "time" "workspace-engine/pkg/events/handler" "workspace-engine/pkg/oapi" @@ -249,6 +250,12 @@ func HandleDeploymentDeleted( return err } + // Cancel processing jobs BEFORE removing the deployment, because DB + // cascade deletes on the release table would remove the releases that + // link jobs to release targets, making it impossible to locate them + // later in ProcessChanges. + cancelJobsForReleaseTargets(ctx, ws, oldReleaseTargets) + ws.Store().RelationshipIndexes.RemoveEntity(ctx, deployment.Id) ws.Deployments().Remove(ctx, deployment.Id) @@ -258,3 +265,15 @@ func HandleDeploymentDeleted( return nil } + +func cancelJobsForReleaseTargets(ctx context.Context, ws *workspace.Workspace, releaseTargets []*oapi.ReleaseTarget) { + for _, rt := range releaseTargets { + for _, job := range ws.Store().Jobs.GetJobsForReleaseTarget(rt) { + if job != nil && job.IsInProcessingState() { + job.Status = oapi.JobStatusCancelled + job.UpdatedAt = time.Now() + ws.Store().Jobs.Upsert(ctx, job) + } + } + } +} diff --git a/apps/workspace-engine/pkg/events/handler/resources/resources.go b/apps/workspace-engine/pkg/events/handler/resources/resources.go index 5d884dbf3..2d2f67c02 100644 --- a/apps/workspace-engine/pkg/events/handler/resources/resources.go +++ b/apps/workspace-engine/pkg/events/handler/resources/resources.go @@ -3,6 +3,7 @@ package resources import ( "context" "encoding/json" + "time" "workspace-engine/pkg/events/handler" "workspace-engine/pkg/oapi" @@ -160,6 +161,12 @@ func HandleResourceDeleted( oldReleaseTargets := ws.ReleaseTargets().GetForResource(ctx, resource.Id) + // Cancel processing jobs BEFORE removing the resource, because DB + // cascade deletes on the release table would remove the releases that + // link jobs to release targets, making it impossible to locate them + // later in ProcessChanges. + cancelJobsForReleaseTargets(ctx, ws, oldReleaseTargets) + ws.Store().RelationshipIndexes.RemoveEntity(ctx, resource.Id) ws.Resources().Remove(ctx, resource.Id) @@ -169,3 +176,15 @@ func HandleResourceDeleted( return nil } + +func cancelJobsForReleaseTargets(ctx context.Context, ws *workspace.Workspace, releaseTargets []*oapi.ReleaseTarget) { + for _, rt := range releaseTargets { + for _, job := range ws.Store().Jobs.GetJobsForReleaseTarget(rt) { + if job != nil && job.IsInProcessingState() { + job.Status = oapi.JobStatusCancelled + job.UpdatedAt = time.Now() + ws.Store().Jobs.Upsert(ctx, job) + } + } + } +} diff --git a/apps/workspace-engine/pkg/oapi/oapi.gen.go b/apps/workspace-engine/pkg/oapi/oapi.gen.go index 52bb3f35d..e1c1a9627 100644 --- a/apps/workspace-engine/pkg/oapi/oapi.gen.go +++ b/apps/workspace-engine/pkg/oapi/oapi.gen.go @@ -849,6 +849,7 @@ type RelationshipRule_Matcher struct { type Release struct { CreatedAt string `json:"createdAt"` EncryptedVariables []string `json:"encryptedVariables"` + Id string `json:"id"` ReleaseTarget ReleaseTarget `json:"releaseTarget"` Variables map[string]LiteralValue `json:"variables"` Version DeploymentVersion `json:"version"` diff --git a/apps/workspace-engine/pkg/oapi/oapi.go b/apps/workspace-engine/pkg/oapi/oapi.go index 989904be8..cc68f34df 100644 --- a/apps/workspace-engine/pkg/oapi/oapi.go +++ b/apps/workspace-engine/pkg/oapi/oapi.go @@ -17,12 +17,26 @@ import ( ) func (r *Release) ID() string { - // Collect relevant fields for deterministic ID + return r.Id +} + +func (r *Release) UUID() uuid.UUID { + id, err := uuid.Parse(r.Id) + if err != nil { + return uuid.Nil + } + return id +} + +// VersionKey returns a deterministic key for the logical "same release" +// concept (same version + variables on the same target). Used by the retry +// evaluator to decide whether an old job counts toward the new release's +// attempt budget. +func (r *Release) VersionKey() string { var sb strings.Builder sb.WriteString(r.Version.Id) sb.WriteString(r.Version.Tag) - // Sort variable keys for determinism keys := make([]string, 0, len(r.Variables)) for k := range r.Variables { keys = append(keys, k) @@ -38,15 +52,10 @@ func (r *Release) ID() string { sb.WriteString(r.ReleaseTarget.Key()) - // Hash the concatenated string hash := sha256.Sum256([]byte(sb.String())) return hex.EncodeToString(hash[:]) } -func (r *Release) UUID() uuid.UUID { - return uuid.NewSHA1(uuid.NameSpaceOID, []byte(r.ID())) -} - func toString(v any) string { switch t := v.(type) { case string: diff --git a/apps/workspace-engine/pkg/oapi/oapi_extra_test.go b/apps/workspace-engine/pkg/oapi/oapi_extra_test.go index 6d4ff0eb1..f9708e23c 100644 --- a/apps/workspace-engine/pkg/oapi/oapi_extra_test.go +++ b/apps/workspace-engine/pkg/oapi/oapi_extra_test.go @@ -4,12 +4,15 @@ import ( "testing" "time" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestRelease_UUID(t *testing.T) { + id := uuid.New().String() release := &Release{ + Id: id, ReleaseTarget: ReleaseTarget{ DeploymentId: "dep-1", EnvironmentId: "env-1", @@ -22,10 +25,14 @@ func TestRelease_UUID(t *testing.T) { CreatedAt: "2024-01-01T00:00:00Z", } - u1 := release.UUID() - u2 := release.UUID() - assert.Equal(t, u1, u2, "UUID should be deterministic") - assert.NotEqual(t, u1.String(), "00000000-0000-0000-0000-000000000000", "UUID should not be nil UUID") + assert.Equal(t, id, release.ID(), "ID() should return the stored Id") + u := release.UUID() + assert.Equal(t, id, u.String(), "UUID() should parse the stored Id") + assert.NotEqual(t, uuid.Nil, u, "UUID should not be nil UUID") + + // Invalid Id should return nil UUID + release2 := &Release{Id: "not-a-uuid"} + assert.Equal(t, uuid.Nil, release2.UUID(), "UUID() should return Nil for unparseable Id") } func TestVerificationMetricSpec_GetInterval(t *testing.T) { diff --git a/apps/workspace-engine/pkg/persistence/integration_test.go b/apps/workspace-engine/pkg/persistence/integration_test.go index 115c68fa6..6ad11de27 100644 --- a/apps/workspace-engine/pkg/persistence/integration_test.go +++ b/apps/workspace-engine/pkg/persistence/integration_test.go @@ -572,6 +572,7 @@ func TestPersistence_ComplexWorkspaceWithComputedValues(t *testing.T) { _ = replicasValue.FromStringValue("3") release := &oapi.Release{ + Id: releaseId, Version: oapi.DeploymentVersion{ Id: versionId, DeploymentId: deploymentId, diff --git a/apps/workspace-engine/pkg/workspace/jobs/factory_test.go b/apps/workspace-engine/pkg/workspace/jobs/factory_test.go index 1f3bd4630..e5e2dfdec 100644 --- a/apps/workspace-engine/pkg/workspace/jobs/factory_test.go +++ b/apps/workspace-engine/pkg/workspace/jobs/factory_test.go @@ -90,6 +90,7 @@ func createTestRelease(t *testing.T, deploymentId, environmentId, resourceId, ve func createTestReleaseWithJobAgentConfig(t *testing.T, deploymentId, environmentId, resourceId, versionId string, jobAgentConfig map[string]interface{}) *oapi.Release { t.Helper() return &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: deploymentId, EnvironmentId: environmentId, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go index 4665a59c7..76e8f4182 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/orchestrator_test.go @@ -110,6 +110,7 @@ func createTestData(s *store.Store, ctx context.Context) (*oapi.Release, *oapi.P // Create release release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go index 8628fd222..07aabe394 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/hooks.go @@ -98,8 +98,8 @@ func (h *RollbackHooks) OnVerificationComplete(ctx context.Context, verification return nil } - // Don't rollback to the same release - if currentRelease.ID() == release.ID() { + // Don't rollback to the same logical release (same version + variables + target) + if currentRelease.VersionKey() == release.VersionKey() { span.AddEvent("Current release is the same as failed release, no rollback needed") span.SetStatus(codes.Ok, "already on current release") return nil diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go index bcacd996b..ca3595fd1 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/rollback/rollback.go @@ -63,7 +63,7 @@ func (r *RollbackAction) Execute( return nil } - if currentRelease.ID() == actx.Release.ID() { + if currentRelease.VersionKey() == actx.Release.VersionKey() { span.AddEvent("Current release is the same as failed release, no rollback needed") span.SetStatus(codes.Ok, "already on current release") return nil diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go index 92e3c368a..7cb31ba56 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/action/verification/verification_test.go @@ -86,6 +86,7 @@ func createTestRelease(s *store.Store, ctx context.Context) *oapi.Release { // Create release release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go index ff7c598bd..4f02c5ed5 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor.go @@ -11,6 +11,7 @@ import ( "workspace-engine/pkg/workspace/releasemanager/trace" "workspace-engine/pkg/workspace/store" + "github.com/google/uuid" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" oteltrace "go.opentelemetry.io/otel/trace" @@ -183,10 +184,11 @@ func BuildRelease( } return &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *version, Variables: clonedVariables, - EncryptedVariables: []string{}, // TODO: Handle encrypted variables + EncryptedVariables: []string{}, CreatedAt: time.Now().Format(time.RFC3339), } } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go index 96eeb28e2..bb01ede86 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/executor_test.go @@ -79,6 +79,7 @@ func createTestResourceForExecutor(id, name, workspaceID string) *oapi.Resource func createTestRelease(deploymentID, environmentID, resourceID, versionID, versionTag string) *oapi.Release { return &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: deploymentID, EnvironmentId: environmentID, @@ -597,23 +598,15 @@ func TestBuildRelease_ReleaseIDDetermination(t *testing.T) { "replicas": &replicas, } - // Build first release release1 := BuildRelease(ctx, releaseTarget, version, variables1) - - // Build second release with same parameters release2 := BuildRelease(ctx, releaseTarget, version, variables1) - // Same inputs should produce same release ID - assert.Equal(t, release1.ID(), release2.ID()) - - // Different variables should produce different release ID - replicas2 := oapi.LiteralValue{} - require.NoError(t, replicas2.FromIntegerValue(5)) - - variables2 := map[string]*oapi.LiteralValue{ - "replicas": &replicas2, - } - - release3 := BuildRelease(ctx, releaseTarget, version, variables2) - assert.NotEqual(t, release1.ID(), release3.ID()) + // Each call generates a unique random UUID + assert.NotEmpty(t, release1.ID()) + assert.NotEmpty(t, release2.ID()) + _, err := uuid.Parse(release1.ID()) + require.NoError(t, err, "Release ID should be a valid UUID") + _, err = uuid.Parse(release2.ID()) + require.NoError(t, err, "Release ID should be a valid UUID") + assert.NotEqual(t, release1.ID(), release2.ID(), "Two calls should produce different IDs") } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go index 1eca2a3df..be0142519 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_retry_test.go @@ -86,6 +86,9 @@ func TestRetryPolicy_MultipleRules_FirstNoRetry_SecondHasRetry(t *testing.T) { Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Second attempt should be allowed (1 failure <= 3 max retries) @@ -103,6 +106,9 @@ func TestRetryPolicy_MultipleRules_FirstNoRetry_SecondHasRetry(t *testing.T) { Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) } @@ -200,6 +206,9 @@ func TestRetryPolicy_MultiplePolicies_MostRestrictiveWins(t *testing.T) { Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Second attempt should be allowed (1 failure <= 1 max retry from strict policy) @@ -215,6 +224,9 @@ func TestRetryPolicy_MultiplePolicies_MostRestrictiveWins(t *testing.T) { Status: oapi.JobStatusFailure, CreatedAt: time.Now(), CompletedAt: &completedAt2, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Third attempt should be DENIED because the stricter policy (maxRetries=1) blocks it @@ -298,6 +310,9 @@ func TestRetryPolicy_AllRulesNoRetry_UsesDefault(t *testing.T) { Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Second attempt should be DENIED (uses default maxRetries=0 behavior) @@ -370,6 +385,9 @@ func TestRetryPolicy_DisabledPolicy_NotApplied(t *testing.T) { Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Second attempt should be DENIED because disabled policy is ignored, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go index 185d3ea2b..c441382a3 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/job_eligibility_test.go @@ -38,6 +38,7 @@ func setupStoreWithResourceForEligibility(t *testing.T, resourceID string) *stor func createReleaseForEligibility(deploymentID, environmentID, resourceID, versionID, versionTag string) *oapi.Release { return &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: deploymentID, EnvironmentId: environmentID, @@ -89,6 +90,9 @@ func TestShouldCreateJob_AlreadyDeployed(t *testing.T) { Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Act @@ -119,6 +123,9 @@ func TestShouldCreateJob_NewVersionAfterSuccessfulDeployment(t *testing.T) { Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: releaseV1, + }, }) // Try to deploy v2.0.0 @@ -213,6 +220,9 @@ func TestShouldCreateJob_FailedJobPreventsRedeploy(t *testing.T) { Status: oapi.JobStatusFailure, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Act - try to redeploy same release @@ -244,6 +254,9 @@ func TestShouldCreateJob_CancelledJobPreventsRedeploy(t *testing.T) { Status: oapi.JobStatusCancelled, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Act - try to redeploy same release @@ -266,6 +279,7 @@ func TestShouldCreateJob_DifferentVariablesAllowsNewJob(t *testing.T) { require.NoError(t, replicas1.FromIntegerValue(3)) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: "deployment-1", EnvironmentId: "env-1", @@ -292,6 +306,9 @@ func TestShouldCreateJob_DifferentVariablesAllowsNewJob(t *testing.T) { Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release1, + }, }) // Create second release with replicas=5 (different variables) @@ -299,6 +316,7 @@ func TestShouldCreateJob_DifferentVariablesAllowsNewJob(t *testing.T) { require.NoError(t, replicas2.FromIntegerValue(5)) release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: "deployment-1", EnvironmentId: "env-1", @@ -424,6 +442,7 @@ func TestShouldCreateJob_MultipleCompletedJobs(t *testing.T) { // Create multiple historical releases with completed jobs for i := 1; i <= 3; i++ { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: releaseTarget, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), @@ -444,11 +463,15 @@ func TestShouldCreateJob_MultipleCompletedJobs(t *testing.T) { Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-time.Duration(4-i) * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) } // Try to create job for new release newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: releaseTarget, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), @@ -489,6 +512,9 @@ func TestShouldCreateJob_SkippedJobPreventsRedeploy(t *testing.T) { Status: oapi.JobStatusSkipped, CreatedAt: time.Now().Add(-1 * time.Hour), CompletedAt: &completedAt, + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Act - try to redeploy same release @@ -518,6 +544,9 @@ func TestShouldCreateJob_InvalidJobAgentStatusPreventsRedeploy(t *testing.T) { ReleaseId: release.ID(), Status: oapi.JobStatusInvalidJobAgent, CreatedAt: time.Now().Add(-1 * time.Hour), + DispatchContext: &oapi.DispatchContext{ + Release: release, + }, }) // Act - try to redeploy same release @@ -537,6 +566,7 @@ func TestShouldCreateJob_EmptyReleaseID(t *testing.T) { // Create a release that would have empty components release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: "deployment-1", EnvironmentId: "env-1", diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner_test.go index 8bfdc025d..0baa334e8 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/deployment/planner_test.go @@ -743,6 +743,8 @@ func TestPlanDeployment_ConsistentReleaseIDs(t *testing.T) { require.NotNil(t, release1) require.NotNil(t, release2) - // Same inputs should produce same release ID - assert.Equal(t, release1.ID(), release2.ID()) + // Each plan generates a unique random UUID + assert.NotEmpty(t, release1.ID()) + assert.NotEmpty(t, release2.ID()) + assert.NotEqual(t, release1.ID(), release2.ID(), "Each plan should produce a unique release ID") } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go index 5cff571f7..9d8228132 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/manager_test.go @@ -92,6 +92,7 @@ func TestProcessChanges_DeleteOnly(t *testing.T) { // Create a release for this target release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *target, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), @@ -255,6 +256,7 @@ func TestProcessChanges_OnlyPendingJobsCancelled(t *testing.T) { // Create a release release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *target, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), @@ -314,6 +316,7 @@ func TestProcessChanges_MixedOperations(t *testing.T) { // Setup target2 with a job to be cancelled release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *target2, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deployableversions/deployableversions_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deployableversions/deployableversions_test.go index 417fd11ce..e298df004 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deployableversions/deployableversions_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deployableversions/deployableversions_test.go @@ -8,6 +8,7 @@ import ( "workspace-engine/pkg/workspace/releasemanager/policy/evaluator" "workspace-engine/pkg/workspace/store" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -96,6 +97,7 @@ func TestDeployableVersionStatusEvaluator_PausedVersionWithRelease(t *testing.T) // Create an existing release for this paused version release := &oapi.Release{ + Id: uuid.New().String(), Version: *version, ReleaseTarget: *releaseTarget, } @@ -404,6 +406,7 @@ func TestDeployableVersionStatusEvaluator_PausedVersionMultipleTargets(t *testin // Create release for target1 only release := &oapi.Release{ + Id: uuid.New().String(), Version: *version, ReleaseTarget: *target1, } @@ -476,6 +479,7 @@ func TestDeployableVersionStatusEvaluator_StatusTransitions(t *testing.T) { // Step 3: Add release for paused version, then evaluate again - should be allowed release := &oapi.Release{ + Id: uuid.New().String(), Version: *version2, ReleaseTarget: *releaseTarget, } @@ -531,10 +535,12 @@ func TestDeployableVersionStatusEvaluator_PausedWithMultipleReleases(t *testing. // Create releases: paused version on target1, ready version on target2 release1 := &oapi.Release{ + Id: uuid.New().String(), Version: *pausedVersion, ReleaseTarget: *target1, } release2 := &oapi.Release{ + Id: uuid.New().String(), Version: *readyVersion, ReleaseTarget: *target2, } @@ -599,6 +605,7 @@ func TestDeployableVersionStatusEvaluator_PausedVersionDifferentEnvironments(t * // Create release for dev only devRelease := &oapi.Release{ + Id: uuid.New().String(), Version: *version, ReleaseTarget: *devTarget, } @@ -684,6 +691,7 @@ func TestDeployableVersionStatusEvaluator_WrongVersionRelease(t *testing.T) { // Create release for OTHER version release := &oapi.Release{ + Id: uuid.New().String(), Version: *otherVersion, ReleaseTarget: *target, } @@ -729,6 +737,7 @@ func TestDeployableVersionStatusEvaluator_PausedVersionCaching(t *testing.T) { // Create release for target1 release := &oapi.Release{ + Id: uuid.New().String(), Version: *version, ReleaseTarget: *target1, } @@ -817,6 +826,7 @@ func TestDeployableVersionStatusEvaluator_AllStatusesComprehensive(t *testing.T) // For paused status, also test with release if tc.status == oapi.DeploymentVersionStatusPaused { release := &oapi.Release{ + Id: uuid.New().String(), Version: *version, ReleaseTarget: *target, } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go index 12334994b..834c642d2 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentdependency/deployment_dependency_test.go @@ -72,6 +72,7 @@ func generateDependencyRule(cel string) *oapi.PolicyRule { func generateReleaseAndJob(ctx context.Context, releaseTarget *oapi.ReleaseTarget, jobStatus oapi.JobStatus, st *store.Store) *oapi.Job { now := time.Now() release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go index a6a14633b..fa2fb36f3 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/deploymentwindow/deploymentwindow_test.go @@ -81,6 +81,7 @@ func seedSuccessfulRelease( st.DeploymentVersions.Upsert(ctx, version.Id, version) release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *version, CreatedAt: versionCreatedAt.Add(30 * time.Minute).Format(time.RFC3339), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go index 1c6846f9d..8a7c0e6e4 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/environmentprogression_test.go @@ -9,6 +9,7 @@ import ( "workspace-engine/pkg/workspace/releasemanager/policy/evaluator" "workspace-engine/pkg/workspace/store" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -184,6 +185,7 @@ func TestEnvironmentProgressionEvaluator_VersionSuccessfulInDependency(t *testin _ = st.ReleaseTargets.Upsert(ctx, stagingReleaseTarget) stagingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -264,6 +266,7 @@ func TestEnvironmentProgressionEvaluator_SoakTimeNotMet(t *testing.T) { } stagingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -412,18 +415,21 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateOnly(t *testing.T) // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget3, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -561,6 +567,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_SoakTimeOnly(t *testing.T) _ = st.ReleaseTargets.Upsert(ctx, stagingReleaseTarget) stagingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -652,12 +659,14 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_BothPassRateAndSoakTime(t * _ = st.ReleaseTargets.Upsert(ctx, stagingReleaseTarget2) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget2, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -790,18 +799,21 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_PassRateBeforeSoakTime(t *t _ = st.ReleaseTargets.Upsert(ctx, stagingReleaseTarget3) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget3, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -953,6 +965,7 @@ func TestEnvironmentProgressionEvaluator_SatisfiedAt_NotSatisfied(t *testing.T) _ = st.ReleaseTargets.Upsert(ctx, stagingReleaseTarget) stagingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingReleaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go index ec416c32b..cf8fb2e84 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/jobtracker_test.go @@ -8,6 +8,7 @@ import ( "workspace-engine/pkg/statechange" "workspace-engine/pkg/workspace/store" + "github.com/google/uuid" "github.com/stretchr/testify/assert" ) @@ -159,18 +160,21 @@ func TestReleaseTargetJobTracker_GetSuccessPercentage_WithSuccesses(t *testing.T // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt3, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -240,12 +244,14 @@ func TestReleaseTargetJobTracker_GetSuccessPercentage_AllSuccessful(t *testing.T // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -328,6 +334,7 @@ func TestReleaseTargetJobTracker_MeetsSoakTimeRequirement_SoakTimeMet(t *testing // Create release release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -383,12 +390,14 @@ func TestReleaseTargetJobTracker_MeetsSoakTimeRequirement_MultipleJobs(t *testin // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -455,6 +464,7 @@ func TestReleaseTargetJobTracker_GetSoakTimeRemaining(t *testing.T) { _ = st.ReleaseTargets.Upsert(ctx, rt1) // Create release release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -515,6 +525,7 @@ func TestReleaseTargetJobTracker_GetMostRecentSuccess(t *testing.T) { // Create release release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -575,6 +586,7 @@ func TestReleaseTargetJobTracker_IsWithinMaxAge_WithinAge(t *testing.T) { _ = st.ReleaseTargets.Upsert(ctx, rt1) // Create release release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -631,12 +643,14 @@ func TestReleaseTargetJobTracker_Jobs(t *testing.T) { // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -708,12 +722,14 @@ func TestReleaseTargetJobTracker_FiltersByEnvironmentAndDeployment(t *testing.T) // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -782,6 +798,7 @@ func TestReleaseTargetJobTracker_MultipleJobsPerTarget_TracksOldestSuccess(t *te // Create release release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -866,18 +883,21 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_Basic(t *testin // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt3, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -980,12 +1000,14 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_NotEnoughSucces // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -1087,12 +1109,14 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_ZeroMinimumPerc // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -1172,18 +1196,21 @@ func TestReleaseTargetJobTracker_GetSuccessPercentageSatisfiedAt_OutOfOrderCompl // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt3, Version: *version, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go index 4cfc80789..2df81123b 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/passrate_test.go @@ -9,6 +9,7 @@ import ( "workspace-engine/pkg/workspace/releasemanager/policy/evaluator" "workspace-engine/pkg/workspace/store" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -101,18 +102,21 @@ func TestPassRateEvaluator_MeetsMinimumRequirement(t *testing.T) { // Create releases release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt3, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -231,18 +235,21 @@ func TestPassRateEvaluator_BelowMinimumRequirement(t *testing.T) { _ = st.ReleaseTargets.Upsert(ctx, rt3) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt3, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -348,18 +355,21 @@ func TestPassRateEvaluator_SatisfiedAt_ExactThreshold(t *testing.T) { _ = st.ReleaseTargets.Upsert(ctx, rt3) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt2, Version: *version, Variables: map[string]oapi.LiteralValue{}, CreatedAt: time.Now().Format(time.RFC3339), } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt3, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -473,6 +483,7 @@ func TestPassRateEvaluator_ZeroMinimumPercentage(t *testing.T) { _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -577,6 +588,7 @@ func TestPassRateEvaluator_CustomSuccessStatuses(t *testing.T) { _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go index 346a4fe21..43a891177 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/environmentprogression/soaktime_test.go @@ -9,6 +9,7 @@ import ( "workspace-engine/pkg/workspace/releasemanager/policy/evaluator" "workspace-engine/pkg/workspace/store" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -83,6 +84,7 @@ func TestSoakTimeEvaluator_SoakTimeMet(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -148,6 +150,7 @@ func TestSoakTimeEvaluator_SoakTimeNotMet(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -212,6 +215,7 @@ func TestSoakTimeEvaluator_NoSuccessfulJobs(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -271,6 +275,7 @@ func TestSoakTimeEvaluator_SatisfiedAt_Calculation(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -335,6 +340,7 @@ func TestSoakTimeEvaluator_MultipleJobs_UseMostRecent(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -432,6 +438,7 @@ func TestSoakTimeEvaluator_CustomSuccessStatuses(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -497,6 +504,7 @@ func TestSoakTimeEvaluator_ExactlyAtThreshold(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -561,6 +569,7 @@ func TestSoakTimeEvaluator_NextEvaluationTime_WhenPending(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -628,6 +637,7 @@ func TestSoakTimeEvaluator_NextEvaluationTime_WhenSatisfied(t *testing.T) { } _ = st.ReleaseTargets.Upsert(ctx, rt1) release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *version, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/environment_summary_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/environment_summary_test.go index 28d782789..b961ab431 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/environment_summary_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/environment_summary_test.go @@ -410,6 +410,7 @@ func TestGradualRolloutEnvironmentSummaryEvaluator_PartiallyBlocked(t *testing.T for _, rt := range releaseTargets { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: *version, } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go index 17fc1647f..eb964c1d2 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/gradualrollout/gradualrollout_test.go @@ -84,6 +84,7 @@ func seedSuccessfulRelease(ctx context.Context, store *store.Store, releaseTarge store.DeploymentVersions.Upsert(ctx, version.Id, version) release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *version, CreatedAt: versionCreatedAt.Add(30 * time.Minute).Format(time.RFC3339), @@ -945,6 +946,7 @@ func TestGradualRolloutEvaluator_EnvironmentProgressionOnly_SuccessPercentage(t successTime := baseTime.Add(1 * time.Hour) // Success happens 1 hour after version creation for i, rt := range stagingReleaseTargets { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: *version, } @@ -1061,6 +1063,7 @@ func TestGradualRolloutEvaluator_EnvironmentProgressionOnly_SoakTime(t *testing. // Create release and successful job in staging release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingRT, Version: *version, } @@ -1183,6 +1186,7 @@ func TestGradualRolloutEvaluator_EnvironmentProgressionOnly_BothSuccessPercentag lastJobCompletedAt := successTime.Add(2 * time.Minute) // Last job completes at this time for i, rt := range stagingReleaseTargets { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: *version, } @@ -1421,6 +1425,7 @@ func TestGradualRolloutEvaluator_BothPolicies_BothSatisfied(t *testing.T) { for i, rt := range stagingReleaseTargets { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: *version, } @@ -1545,6 +1550,7 @@ func TestGradualRolloutEvaluator_BothPolicies_ApprovalLater(t *testing.T) { for i, rt := range stagingReleaseTargets { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: *version, } @@ -1686,6 +1692,7 @@ func TestGradualRolloutEvaluator_BothPolicies_ApprovalUnsatisfied(t *testing.T) for i, rt := range stagingReleaseTargets { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: *version, } @@ -2157,6 +2164,7 @@ func TestGradualRolloutEvaluator_EnvProgressionJustSatisfied_OnlyPosition0Allowe // Create successful staging jobs (all complete at stagingCompletionTime) for i, stagingRT := range stagingReleaseTargets { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *stagingRT, Version: *version, } diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go index 702aa9e5d..3f21870f8 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go @@ -7,6 +7,8 @@ import ( "workspace-engine/pkg/oapi" "workspace-engine/pkg/statechange" "workspace-engine/pkg/workspace/store" + + "github.com/google/uuid" ) // Helper function to create a test store with a resource @@ -38,6 +40,7 @@ func TestReleaseTargetConcurrencyEvaluator_NoActiveJobs(t *testing.T) { eval := NewReleaseTargetConcurrencyEvaluator(st) release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: "deployment-1", EnvironmentId: "env-1", @@ -74,6 +77,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInPendingState(t *testing.T) { } existingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -96,6 +100,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInPendingState(t *testing.T) { // Try to deploy a new release to the same target newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-2", @@ -136,6 +141,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInProgressState(t *testing.T) { } existingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -158,6 +164,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInProgressState(t *testing.T) { // Try to deploy a new release to the same target newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-2", @@ -190,6 +197,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInActionRequiredState(t *testing.T } existingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -212,6 +220,7 @@ func TestReleaseTargetConcurrencyEvaluator_JobInActionRequiredState(t *testing.T // Try to deploy a new release to the same target newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-2", @@ -245,6 +254,7 @@ func TestReleaseTargetConcurrencyEvaluator_MultipleActiveJobs(t *testing.T) { // Create multiple releases with active jobs release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -253,6 +263,7 @@ func TestReleaseTargetConcurrencyEvaluator_MultipleActiveJobs(t *testing.T) { } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-2", @@ -285,6 +296,7 @@ func TestReleaseTargetConcurrencyEvaluator_MultipleActiveJobs(t *testing.T) { // Try to deploy a new release newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-3", @@ -323,6 +335,7 @@ func TestReleaseTargetConcurrencyEvaluator_TerminalStateJobsDoNotBlock(t *testin // Create releases with terminal jobs release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -331,6 +344,7 @@ func TestReleaseTargetConcurrencyEvaluator_TerminalStateJobsDoNotBlock(t *testin } release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-2", @@ -339,6 +353,7 @@ func TestReleaseTargetConcurrencyEvaluator_TerminalStateJobsDoNotBlock(t *testin } release3 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-3", @@ -386,6 +401,7 @@ func TestReleaseTargetConcurrencyEvaluator_TerminalStateJobsDoNotBlock(t *testin // Try to deploy a new release newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-4", @@ -440,6 +456,7 @@ func TestReleaseTargetConcurrencyEvaluator_DifferentReleaseTargetsDoNotInterfere // Create a release with active job for target 1 release1 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget1, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -462,6 +479,7 @@ func TestReleaseTargetConcurrencyEvaluator_DifferentReleaseTargetsDoNotInterfere // Try to deploy to target 2 (different resource) release2 := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget2, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -499,6 +517,7 @@ func TestReleaseTargetConcurrencyEvaluator_AllProcessingStatesBlock(t *testing.T } existingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -521,6 +540,7 @@ func TestReleaseTargetConcurrencyEvaluator_AllProcessingStatesBlock(t *testing.T // Try to deploy a new release newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-2", @@ -572,6 +592,7 @@ func TestReleaseTargetConcurrencyEvaluator_AllTerminalStatesAllow(t *testing.T) } existingRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-1", @@ -596,6 +617,7 @@ func TestReleaseTargetConcurrencyEvaluator_AllTerminalStatesAllow(t *testing.T) // Try to deploy a new release newRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: oapi.DeploymentVersion{ Id: "version-2", diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go index 07d026b55..30e14b0d1 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry.go @@ -108,19 +108,21 @@ func (e *RetryEvaluator) Evaluate( // Build a map of retryable statuses for efficient lookup retryableStatuses := e.buildRetryableStatusMap() - // Count previous consecutive attempts and find most recent retryable job + // Count previous consecutive attempts and find most recent retryable job. + // Jobs are matched by VersionKey (same version + variables + target) rather + // than by release ID, because release IDs are random UUIDs — the same + // logical deployment produces a different release ID each time it is planned. attemptCount := 0 matchingJobIds := make([]string, 0) var mostRecentJob *oapi.Job var mostRecentTime time.Time + versionKey := release.VersionKey() for _, job := range jobs { - // Only count jobs for this exact release - if job.ReleaseId != release.ID() { + if !jobMatchesVersionKey(job, versionKey) { break } - // Check if job status is retryable (or if all statuses count) isRetryable := retryableStatuses == nil || retryableStatuses[job.Status] if !isRetryable { break @@ -294,3 +296,13 @@ func (e *RetryEvaluator) calculateBackoffDuration(attemptCount int, baseBackoffS return time.Duration(backoffSeconds) * time.Second } + +// jobMatchesVersionKey checks whether a job belongs to the same logical +// release (same version + variables + target) by comparing VersionKeys. +// It extracts the release snapshot from the job's DispatchContext. +func jobMatchesVersionKey(job *oapi.Job, versionKey string) bool { + if job.DispatchContext == nil || job.DispatchContext.Release == nil { + return false + } + return job.DispatchContext.Release.VersionKey() == versionKey +} diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go index 7e3950e8a..5029f87fb 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/retry_test.go @@ -8,6 +8,7 @@ import ( "workspace-engine/pkg/statechange" "workspace-engine/pkg/workspace/store" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -37,6 +38,7 @@ func setupStoreWithResource(t *testing.T, resourceID string) *store.Store { func createRelease(deploymentID, envID, resourceID, versionID, tag string) *oapi.Release { return &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: deploymentID, EnvironmentId: envID, @@ -49,6 +51,17 @@ func createRelease(deploymentID, envID, resourceID, versionID, tag string) *oapi } } +func dispatchContextFor(release *oapi.Release) *oapi.DispatchContext { + return &oapi.DispatchContext{ + Release: &oapi.Release{ + Id: uuid.New().String(), + ReleaseTarget: release.ReleaseTarget, + Version: release.Version, + Variables: release.Variables, + }, + } +} + // ============================================================================= // Default Behavior Tests (nil rule = maxRetries:0, no retries allowed) // ============================================================================= @@ -82,14 +95,14 @@ func TestRetryEvaluator_DefaultBehavior_SecondAttemptDenied(t *testing.T) { t.Fatalf("Failed to upsert release: %v", err) } - // Create a job for this release completedAt := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-2 * time.Hour), - CompletedAt: &completedAt, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-2 * time.Hour), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) eval := NewEvaluatorFromStore(st, nil) @@ -111,14 +124,14 @@ func TestRetryEvaluator_DefaultBehavior_AllStatusesCount(t *testing.T) { t.Fatalf("Failed to upsert release: %v", err) } - // Create job with successful status completedAt := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-success", - ReleaseId: release.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-2 * time.Hour), - CompletedAt: &completedAt, + Id: "job-success", + ReleaseId: release.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-2 * time.Hour), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) eval := NewEvaluatorFromStore(st, nil) @@ -158,11 +171,12 @@ func TestRetryEvaluator_MaxRetries_Zero(t *testing.T) { // Add a failed job completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) // Second attempt denied @@ -190,11 +204,12 @@ func TestRetryEvaluator_MaxRetries_Three(t *testing.T) { for i := 1; i <= 3; i++ { completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-" + string(rune(i)), - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-" + string(rune(i)), + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -205,11 +220,12 @@ func TestRetryEvaluator_MaxRetries_Three(t *testing.T) { // Add 4th failed job completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-4", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-4", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) // 5th attempt should be denied @@ -243,21 +259,23 @@ func TestRetryEvaluator_RetryOnStatuses_OnlyCountsFailures(t *testing.T) { // Add successful job - should NOT count completedAt1 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-success", - ReleaseId: release.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-3 * time.Hour), - CompletedAt: &completedAt1, + Id: "job-success", + ReleaseId: release.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-3 * time.Hour), + CompletedAt: &completedAt1, + DispatchContext: dispatchContextFor(release), }) // Add cancelled job - should NOT count completedAt2 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-cancelled", - ReleaseId: release.ID(), - Status: oapi.JobStatusCancelled, - CreatedAt: time.Now().Add(-90 * time.Minute), - CompletedAt: &completedAt2, + Id: "job-cancelled", + ReleaseId: release.ID(), + Status: oapi.JobStatusCancelled, + CreatedAt: time.Now().Add(-90 * time.Minute), + CompletedAt: &completedAt2, + DispatchContext: dispatchContextFor(release), }) // Should still be allowed (no failures yet) @@ -268,11 +286,12 @@ func TestRetryEvaluator_RetryOnStatuses_OnlyCountsFailures(t *testing.T) { // Add failed job - should count completedAt3 := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-failed", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now(), - CompletedAt: &completedAt3, + Id: "job-failed", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now(), + CompletedAt: &completedAt3, + DispatchContext: dispatchContextFor(release), }) // Should still allow one more retry @@ -283,11 +302,12 @@ func TestRetryEvaluator_RetryOnStatuses_OnlyCountsFailures(t *testing.T) { // Add second failed job completedAt4 := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-failed-2", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now(), - CompletedAt: &completedAt4, + Id: "job-failed-2", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now(), + CompletedAt: &completedAt4, + DispatchContext: dispatchContextFor(release), }) // Now should deny (2 failures > maxRetries of 1) @@ -319,20 +339,22 @@ func TestRetryEvaluator_RetryOnStatuses_MultipleStatuses(t *testing.T) { // Add jobs with different retryable statuses completedAt1 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-4 * time.Hour), - CompletedAt: &completedAt1, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-4 * time.Hour), + CompletedAt: &completedAt1, + DispatchContext: dispatchContextFor(release), }) completedAt2 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-2", - ReleaseId: release.ID(), - Status: oapi.JobStatusInvalidJobAgent, - CreatedAt: time.Now().Add(-150 * time.Minute), - CompletedAt: &completedAt2, + Id: "job-2", + ReleaseId: release.ID(), + Status: oapi.JobStatusInvalidJobAgent, + CreatedAt: time.Now().Add(-150 * time.Minute), + CompletedAt: &completedAt2, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -342,11 +364,12 @@ func TestRetryEvaluator_RetryOnStatuses_MultipleStatuses(t *testing.T) { // Add third retryable status job completedAt3 := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-3", - ReleaseId: release.ID(), - Status: oapi.JobStatusExternalRunNotFound, - CreatedAt: time.Now(), - CompletedAt: &completedAt3, + Id: "job-3", + ReleaseId: release.ID(), + Status: oapi.JobStatusExternalRunNotFound, + CreatedAt: time.Now(), + CompletedAt: &completedAt3, + DispatchContext: dispatchContextFor(release), }) result = eval.Evaluate(ctx, release) @@ -384,11 +407,12 @@ func TestRetryEvaluator_DifferentReleasesIndependent(t *testing.T) { // Add failed job for release1 completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-r1", - ReleaseId: release1.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-r1", + ReleaseId: release1.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release1), }) // Release2 should still be allowed (different release) @@ -422,11 +446,12 @@ func TestRetryEvaluator_LinearBackoff_StillWaiting(t *testing.T) { // Add job that completed 30 seconds ago completedAt := time.Now().Add(-30 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-1 * time.Hour), - CompletedAt: &completedAt, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-1 * time.Hour), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -465,11 +490,12 @@ func TestRetryEvaluator_LinearBackoff_BackoffElapsed(t *testing.T) { // Add job that completed 90 seconds ago (backoff elapsed) completedAt := time.Now().Add(-90 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-2 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-2 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -502,11 +528,12 @@ func TestRetryEvaluator_LinearBackoff_ConstantDelay(t *testing.T) { for i := 1; i <= 3; i++ { completedAt := time.Now().Add(-20 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-" + string(rune(i)), - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-1 * time.Minute), - CompletedAt: &completedAt, + Id: "job-" + string(rune(i)), + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-1 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -552,11 +579,12 @@ func TestRetryEvaluator_ExponentialBackoff_DoublesEachRetry(t *testing.T) { for i := 1; i <= attemptCount; i++ { completedAt := time.Now().Add(-10 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-" + string(rune(i)), - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-1 * time.Minute), - CompletedAt: &completedAt, + Id: "job-" + string(rune(i)), + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-1 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) } @@ -603,11 +631,12 @@ func TestRetryEvaluator_ExponentialBackoff_WithCap(t *testing.T) { for i := 1; i <= 4; i++ { completedAt := time.Now().Add(-5 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-" + string(rune(i)), - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-1 * time.Minute), - CompletedAt: &completedAt, + Id: "job-" + string(rune(i)), + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-1 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) } @@ -640,11 +669,12 @@ func TestRetryEvaluator_NoBackoff_ImmediateRetry(t *testing.T) { // Add job that just completed completedAt := time.Now().Add(-1 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-1 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-1 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -677,11 +707,12 @@ func TestRetryEvaluator_Backoff_UsesCompletedAt(t *testing.T) { // Job created 2 hours ago but completed 30 seconds ago completedAt := time.Now().Add(-30 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-2 * time.Hour), - CompletedAt: &completedAt, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-2 * time.Hour), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -712,11 +743,12 @@ func TestRetryEvaluator_Backoff_FallsBackToCreatedAt(t *testing.T) { // Job with no completedAt (still running) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusInProgress, - CreatedAt: time.Now().Add(-30 * time.Second), - CompletedAt: nil, // No completion time + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusInProgress, + CreatedAt: time.Now().Add(-30 * time.Second), + CompletedAt: nil, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -744,11 +776,12 @@ func TestRetryEvaluator_Backoff_NextEvaluationTime(t *testing.T) { completedAt := time.Now().Add(-60 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-2 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-2 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) @@ -789,11 +822,12 @@ func TestRetryEvaluator_Backoff_OnlyForRetryableStatuses(t *testing.T) { // Add successful job (not retryable) completedAt1 := time.Now().Add(-5 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-success", - ReleaseId: release.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-1 * time.Hour), - CompletedAt: &completedAt1, + Id: "job-success", + ReleaseId: release.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-1 * time.Hour), + CompletedAt: &completedAt1, + DispatchContext: dispatchContextFor(release), }) // Should be allowed immediately (successful job doesn't count) @@ -803,11 +837,12 @@ func TestRetryEvaluator_Backoff_OnlyForRetryableStatuses(t *testing.T) { // Add failed job (retryable) completedAt2 := time.Now().Add(-5 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-failed", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-10 * time.Second), - CompletedAt: &completedAt2, + Id: "job-failed", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-10 * time.Second), + CompletedAt: &completedAt2, + DispatchContext: dispatchContextFor(release), }) // Now should be in backoff (failed job counts) @@ -843,21 +878,23 @@ func TestRetryEvaluator_VersionFlip_AllowsRedeployAfterDifferentRelease(t *testi // Job 1: v1 deployed successfully (oldest) completedAt1 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v1-first", - ReleaseId: releaseV1.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-4 * time.Hour), - CompletedAt: &completedAt1, + Id: "job-v1-first", + ReleaseId: releaseV1.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-4 * time.Hour), + CompletedAt: &completedAt1, + DispatchContext: dispatchContextFor(releaseV1), }) // Job 2: v2 deployed successfully (middle) completedAt2 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v2", - ReleaseId: releaseV2.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-150 * time.Minute), - CompletedAt: &completedAt2, + Id: "job-v2", + ReleaseId: releaseV2.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-150 * time.Minute), + CompletedAt: &completedAt2, + DispatchContext: dispatchContextFor(releaseV2), }) // Now we want to redeploy v1: the most recent job is for v2, @@ -890,31 +927,34 @@ func TestRetryEvaluator_VersionFlip_CountsOnlyLatestConsecutiveJobs(t *testing.T // Old v1 job (should be ignored because v2 job separates it) completedAt1 := time.Now().Add(-5 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v1-old", - ReleaseId: releaseV1.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-6 * time.Hour), - CompletedAt: &completedAt1, + Id: "job-v1-old", + ReleaseId: releaseV1.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-6 * time.Hour), + CompletedAt: &completedAt1, + DispatchContext: dispatchContextFor(releaseV1), }) // v2 job in between completedAt2 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v2", - ReleaseId: releaseV2.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-4 * time.Hour), - CompletedAt: &completedAt2, + Id: "job-v2", + ReleaseId: releaseV2.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-4 * time.Hour), + CompletedAt: &completedAt2, + DispatchContext: dispatchContextFor(releaseV2), }) // Recent v1 job (only this one should count) completedAt3 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v1-recent", - ReleaseId: releaseV1.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-2 * time.Hour), - CompletedAt: &completedAt3, + Id: "job-v1-recent", + ReleaseId: releaseV1.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-2 * time.Hour), + CompletedAt: &completedAt3, + DispatchContext: dispatchContextFor(releaseV1), }) result := eval.Evaluate(ctx, releaseV1) @@ -944,30 +984,33 @@ func TestRetryEvaluator_VersionFlip_DeniesWhenConsecutiveExceedsLimit(t *testing // v2 job (old, will be skipped because newer v1 jobs come after) completedAt1 := time.Now().Add(-5 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v2", - ReleaseId: releaseV2.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-6 * time.Hour), - CompletedAt: &completedAt1, + Id: "job-v2", + ReleaseId: releaseV2.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-6 * time.Hour), + CompletedAt: &completedAt1, + DispatchContext: dispatchContextFor(releaseV2), }) // Two consecutive v1 jobs (most recent) completedAt2 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v1-a", - ReleaseId: releaseV1.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-3 * time.Hour), - CompletedAt: &completedAt2, + Id: "job-v1-a", + ReleaseId: releaseV1.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-3 * time.Hour), + CompletedAt: &completedAt2, + DispatchContext: dispatchContextFor(releaseV1), }) completedAt3 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-v1-b", - ReleaseId: releaseV1.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-90 * time.Minute), - CompletedAt: &completedAt3, + Id: "job-v1-b", + ReleaseId: releaseV1.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-90 * time.Minute), + CompletedAt: &completedAt3, + DispatchContext: dispatchContextFor(releaseV1), }) result := eval.Evaluate(ctx, releaseV1) @@ -999,21 +1042,25 @@ func TestRetryEvaluator_VersionFlip_MultipleFlips(t *testing.T) { st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-1-v1", ReleaseId: releaseV1.ID(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-5 * time.Hour), CompletedAt: &completedAt1, + DispatchContext: dispatchContextFor(releaseV1), }) completedAt2 := time.Now().Add(-3 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-2-v2", ReleaseId: releaseV2.ID(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-210 * time.Minute), CompletedAt: &completedAt2, + DispatchContext: dispatchContextFor(releaseV2), }) completedAt3 := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-3-v1", ReleaseId: releaseV1.ID(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-150 * time.Minute), CompletedAt: &completedAt3, + DispatchContext: dispatchContextFor(releaseV1), }) completedAt4 := time.Now().Add(-1 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ Id: "job-4-v2", ReleaseId: releaseV2.ID(), Status: oapi.JobStatusSuccessful, CreatedAt: time.Now().Add(-90 * time.Minute), CompletedAt: &completedAt4, + DispatchContext: dispatchContextFor(releaseV2), }) // Most recent is v2 → evaluating v1 should see 0 consecutive → first attempt @@ -1057,21 +1104,23 @@ func TestRetryEvaluator_MultipleJobsSameRelease_FindsMostRecent(t *testing.T) { // Add older job oldCompletedAt := time.Now().Add(-2 * time.Hour) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-old", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-3 * time.Hour), - CompletedAt: &oldCompletedAt, + Id: "job-old", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-3 * time.Hour), + CompletedAt: &oldCompletedAt, + DispatchContext: dispatchContextFor(release), }) // Add recent job (30s ago) recentCompletedAt := time.Now().Add(-30 * time.Second) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-recent", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-1 * time.Minute), - CompletedAt: &recentCompletedAt, + Id: "job-recent", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-1 * time.Minute), + CompletedAt: &recentCompletedAt, + DispatchContext: dispatchContextFor(release), }) result := eval.Evaluate(ctx, release) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go index 709aa5461..d9dd0d0fd 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/retry/smart_defaults_test.go @@ -35,11 +35,12 @@ func TestRetryEvaluator_SmartDefault_OnlyCountsFailures(t *testing.T) { // Add a successful job - should NOT count toward retry limit completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-success", - ReleaseId: release.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-5 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1-success", + ReleaseId: release.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-5 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) // Should still allow deployment (successful jobs don't count) @@ -49,11 +50,12 @@ func TestRetryEvaluator_SmartDefault_OnlyCountsFailures(t *testing.T) { // Add a failed job - should count st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-2-failure", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-3 * time.Minute), - CompletedAt: &completedAt, + Id: "job-2-failure", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-3 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result = evaluator.Evaluate(ctx, release) @@ -80,11 +82,12 @@ func TestRetryEvaluator_SmartDefault_CountsInvalidIntegration(t *testing.T) { // Add an invalidIntegration job - should count completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-invalid", - ReleaseId: release.ID(), - Status: oapi.JobStatusInvalidIntegration, - CreatedAt: time.Now().Add(-1 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1-invalid", + ReleaseId: release.ID(), + Status: oapi.JobStatusInvalidIntegration, + CreatedAt: time.Now().Add(-1 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := evaluator.Evaluate(ctx, release) @@ -93,11 +96,12 @@ func TestRetryEvaluator_SmartDefault_CountsInvalidIntegration(t *testing.T) { // Add another invalidIntegration - should exceed limit st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-2-invalid", - ReleaseId: release.ID(), - Status: oapi.JobStatusInvalidIntegration, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-2-invalid", + ReleaseId: release.ID(), + Status: oapi.JobStatusInvalidIntegration, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result = evaluator.Evaluate(ctx, release) @@ -123,18 +127,20 @@ func TestRetryEvaluator_SmartDefault_DoesNotCountCancelled(t *testing.T) { // Add multiple cancelled jobs - should NOT count completedAt := time.Now() st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-cancelled", - ReleaseId: release.ID(), - Status: oapi.JobStatusCancelled, - CreatedAt: time.Now().Add(-5 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1-cancelled", + ReleaseId: release.ID(), + Status: oapi.JobStatusCancelled, + CreatedAt: time.Now().Add(-5 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-2-cancelled", - ReleaseId: release.ID(), - Status: oapi.JobStatusCancelled, - CreatedAt: time.Now().Add(-3 * time.Minute), - CompletedAt: &completedAt, + Id: "job-2-cancelled", + ReleaseId: release.ID(), + Status: oapi.JobStatusCancelled, + CreatedAt: time.Now().Add(-3 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) // Should still allow (cancelled jobs don't count with smart default) @@ -163,44 +169,49 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { // Non-retryable jobs (oldest) — these break the consecutive streak // so they must be older than the retryable ones. st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-success", - ReleaseId: release.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now().Add(-10 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1-success", + ReleaseId: release.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now().Add(-10 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-2-cancelled", - ReleaseId: release.ID(), - Status: oapi.JobStatusCancelled, - CreatedAt: time.Now().Add(-8 * time.Minute), - CompletedAt: &completedAt, + Id: "job-2-cancelled", + ReleaseId: release.ID(), + Status: oapi.JobStatusCancelled, + CreatedAt: time.Now().Add(-8 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-3-skipped", - ReleaseId: release.ID(), - Status: oapi.JobStatusSkipped, - CreatedAt: time.Now().Add(-6 * time.Minute), - CompletedAt: &completedAt, + Id: "job-3-skipped", + ReleaseId: release.ID(), + Status: oapi.JobStatusSkipped, + CreatedAt: time.Now().Add(-6 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) // Retryable jobs (most recent consecutive) — only these count st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-4-failure", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-4 * time.Minute), - CompletedAt: &completedAt, + Id: "job-4-failure", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-4 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-5-invalid", - ReleaseId: release.ID(), - Status: oapi.JobStatusInvalidIntegration, - CreatedAt: time.Now().Add(-2 * time.Minute), - CompletedAt: &completedAt, + Id: "job-5-invalid", + ReleaseId: release.ID(), + Status: oapi.JobStatusInvalidIntegration, + CreatedAt: time.Now().Add(-2 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) // Only the 2 most recent consecutive retryable jobs count (failure + invalidIntegration) @@ -210,11 +221,12 @@ func TestRetryEvaluator_SmartDefault_MixedStatuses(t *testing.T) { // Add one more failure - should exceed st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-6-failure", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-6-failure", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result = evaluator.Evaluate(ctx, release) @@ -246,11 +258,12 @@ func TestRetryEvaluator_ExplicitStatuses_OverridesSmartDefault(t *testing.T) { // Add a failure - should NOT count (only cancelled counts) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-failure", - ReleaseId: release.ID(), - Status: oapi.JobStatusFailure, - CreatedAt: time.Now().Add(-5 * time.Minute), - CompletedAt: &completedAt, + Id: "job-1-failure", + ReleaseId: release.ID(), + Status: oapi.JobStatusFailure, + CreatedAt: time.Now().Add(-5 * time.Minute), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := evaluator.Evaluate(ctx, release) @@ -259,11 +272,12 @@ func TestRetryEvaluator_ExplicitStatuses_OverridesSmartDefault(t *testing.T) { // Add cancelled job - should count st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-2-cancelled", - ReleaseId: release.ID(), - Status: oapi.JobStatusCancelled, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-2-cancelled", + ReleaseId: release.ID(), + Status: oapi.JobStatusCancelled, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result = evaluator.Evaluate(ctx, release) @@ -292,11 +306,12 @@ func TestRetryEvaluator_ZeroMaxRetries_CountsSuccessfulAndErrors(t *testing.T) { // Add a successful job - should count (strict mode: successful counts for maxRetries=0) st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-success", - ReleaseId: release.ID(), - Status: oapi.JobStatusSuccessful, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-1-success", + ReleaseId: release.ID(), + Status: oapi.JobStatusSuccessful, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := evaluator.Evaluate(ctx, release) @@ -325,11 +340,12 @@ func TestRetryEvaluator_ZeroMaxRetries_AllowsAfterCancelled(t *testing.T) { // Add a cancelled job - should NOT count st.Jobs.Upsert(ctx, &oapi.Job{ - Id: "job-1-cancelled", - ReleaseId: release.ID(), - Status: oapi.JobStatusCancelled, - CreatedAt: time.Now(), - CompletedAt: &completedAt, + Id: "job-1-cancelled", + ReleaseId: release.ID(), + Status: oapi.JobStatusCancelled, + CreatedAt: time.Now(), + CompletedAt: &completedAt, + DispatchContext: dispatchContextFor(release), }) result := evaluator.Evaluate(ctx, release) diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go index c627fa8cf..26953d5d9 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/rollback/rollback_test.go @@ -83,6 +83,7 @@ func createJob(t *testing.T, s *store.Store, ctx context.Context, e testEntities // Create release to link job to release target release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *e.rt, Version: *e.version, CreatedAt: createdAt.Format(time.RFC3339), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go index b8e9caad1..1a4ddb533 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/version_summary_test.go @@ -149,6 +149,7 @@ func TestSummaryEvaluator_SomeTargetsDenied(t *testing.T) { // Create a release with the older version on rt1 release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt1, Version: *olderVersion, CreatedAt: time.Now().Add(-10 * time.Second).Format(time.RFC3339), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go index d2df8c6ea..ee17e300d 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/versioncooldown/versioncooldown_test.go @@ -76,6 +76,7 @@ func createTestReleaseTarget(ctx context.Context, s *store.Store, deployment *oa func createTestRelease(ctx context.Context, s *store.Store, rt *oapi.ReleaseTarget, version *oapi.DeploymentVersion) *oapi.Release { release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: *version, CreatedAt: time.Now().Format(time.RFC3339), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go index 06138a3b9..699858703 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/state_index_test.go @@ -75,6 +75,7 @@ func TestRestoreAll_ComputesLatestJob(t *testing.T) { // Create a release and a job in the store. release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), @@ -160,6 +161,7 @@ func TestGetReleaseTargetState_AfterRestore(t *testing.T) { // Add a job so we can verify state is fully populated. release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), @@ -213,6 +215,7 @@ func TestRecomputeEntity_RefreshesAfterRestore(t *testing.T) { // Now add a job to the store (simulates a new job arriving after boot). release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *rt, Version: oapi.DeploymentVersion{ Id: uuid.New().String(), diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go index 8254bd351..6457074a7 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/verification/scheduler_test.go @@ -166,6 +166,7 @@ func createTestRelease(s *store.Store, ctx context.Context) *oapi.Release { // Create release release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/store/jobs.go b/apps/workspace-engine/pkg/workspace/store/jobs.go index a92218bf9..3f8d38e24 100644 --- a/apps/workspace-engine/pkg/workspace/store/jobs.go +++ b/apps/workspace-engine/pkg/workspace/store/jobs.go @@ -76,13 +76,25 @@ func (j *Jobs) GetJobsForReleaseTarget(releaseTarget *oapi.ReleaseTarget) map[st } releases, err := j.store.Releases.GetByReleaseTargetKey(releaseTarget.Key()) - if err != nil { - return jobs + if err == nil { + for _, release := range releases { + releaseJobs := j.store.Releases.Jobs(release.ID()) + for _, job := range releaseJobs { + jobs[job.Id] = job + } + } } - for _, release := range releases { - releaseJobs := j.store.Releases.Jobs(release.ID()) - for _, job := range releaseJobs { + // Also scan for orphaned jobs whose releases were cascade-deleted from + // the DB but still exist in the in-memory job store. These jobs carry + // the release target in their DispatchContext. + targetKey := releaseTarget.Key() + for _, job := range j.repo.Items() { + if _, found := jobs[job.Id]; found { + continue + } + if job.DispatchContext != nil && job.DispatchContext.Release != nil && + job.DispatchContext.Release.ReleaseTarget.Key() == targetKey { jobs[job.Id] = job } } diff --git a/apps/workspace-engine/pkg/workspace/store/release_targets_test.go b/apps/workspace-engine/pkg/workspace/store/release_targets_test.go index 32907a160..f24e58ed8 100644 --- a/apps/workspace-engine/pkg/workspace/store/release_targets_test.go +++ b/apps/workspace-engine/pkg/workspace/store/release_targets_test.go @@ -84,6 +84,7 @@ func createTestReleaseAndJob(s *store.Store, ctx context.Context, tag string, co // Create release release := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *version, Variables: map[string]oapi.LiteralValue{}, @@ -285,6 +286,7 @@ func TestGetCurrentRelease_FailedVerification_FallbackToPrevious(t *testing.T) { s.DeploymentVersions.Upsert(ctx, olderVersionId, olderVersion) olderRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *olderVersion, Variables: map[string]oapi.LiteralValue{}, @@ -316,6 +318,7 @@ func TestGetCurrentRelease_FailedVerification_FallbackToPrevious(t *testing.T) { s.DeploymentVersions.Upsert(ctx, newerVersionId, newerVersion) newerRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *newerVersion, Variables: map[string]oapi.LiteralValue{}, @@ -400,6 +403,7 @@ func TestGetCurrentRelease_RunningVerification_FallbackToPrevious(t *testing.T) s.DeploymentVersions.Upsert(ctx, olderVersionId, olderVersion) olderRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *olderVersion, Variables: map[string]oapi.LiteralValue{}, @@ -431,6 +435,7 @@ func TestGetCurrentRelease_RunningVerification_FallbackToPrevious(t *testing.T) s.DeploymentVersions.Upsert(ctx, newerVersionId, newerVersion) newerRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *newerVersion, Variables: map[string]oapi.LiteralValue{}, @@ -542,6 +547,7 @@ func TestGetCurrentRelease_CancelledVerification_FallbackToPrevious(t *testing.T s.DeploymentVersions.Upsert(ctx, olderVersionId, olderVersion) olderRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *olderVersion, Variables: map[string]oapi.LiteralValue{}, @@ -570,6 +576,7 @@ func TestGetCurrentRelease_CancelledVerification_FallbackToPrevious(t *testing.T s.DeploymentVersions.Upsert(ctx, newerVersionId, newerVersion) newerRelease := &oapi.Release{ + Id: uuid.New().String(), ReleaseTarget: *releaseTarget, Version: *newerVersion, Variables: map[string]oapi.LiteralValue{}, diff --git a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go index 2de1c936f..d8f2878e4 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go @@ -12,7 +12,9 @@ import ( ) // ToOapi converts a db.Release row, its associated deployment version, and -// its variables into an oapi.Release. +// its variables into an oapi.Release. The version_status stored on the release +// row overrides the live deployment version status to preserve the snapshot +// captured at release creation time. func ToOapi( row db.Release, version *oapi.DeploymentVersion, @@ -35,7 +37,13 @@ func ToOapi( createdAt = row.CreatedAt.Time.Format(time.RFC3339) } + snapshotVersion := *version + if row.VersionStatus.Valid { + snapshotVersion.Status = oapi.DeploymentVersionStatus(row.VersionStatus.String) + } + return &oapi.Release{ + Id: row.ID.String(), CreatedAt: createdAt, EncryptedVariables: encrypted, ReleaseTarget: oapi.ReleaseTarget{ @@ -44,7 +52,7 @@ func ToOapi( DeploymentId: row.DeploymentID.String(), }, Variables: variables, - Version: *version, + Version: snapshotVersion, } } @@ -84,6 +92,7 @@ func ToUpsertParams(release *oapi.Release) (db.UpsertReleaseParams, error) { EnvironmentID: environmentID, DeploymentID: deploymentID, VersionID: versionID, + VersionStatus: pgtype.Text{String: string(release.Version.Status), Valid: true}, CreatedAt: createdAt, }, nil } diff --git a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go index e1a37d50b..b997bd4a7 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/repo.go @@ -44,7 +44,10 @@ func (r *Repo) fetchOapiRelease(row db.Release) (*oapi.Release, error) { } func (r *Repo) Get(id string) (*oapi.Release, bool) { - uid := uuid.NewSHA1(uuid.NameSpaceOID, []byte(id)) + uid, err := uuid.Parse(id) + if err != nil { + return nil, false + } row, err := db.GetQueries(r.ctx).GetReleaseByID(r.ctx, uid) if err != nil { @@ -134,7 +137,10 @@ func (r *Repo) Set(entity *oapi.Release) error { } func (r *Repo) Remove(id string) error { - uid := uuid.NewSHA1(uuid.NameSpaceOID, []byte(id)) + uid, err := uuid.Parse(id) + if err != nil { + return fmt.Errorf("parse release id: %w", err) + } if err := db.GetQueries(r.ctx).DeleteReleaseVariablesByReleaseID(r.ctx, uid); err != nil { return fmt.Errorf("delete release variables: %w", err) diff --git a/apps/workspace-engine/test/e2e/engine_job_agent_retrigger_test.go b/apps/workspace-engine/test/e2e/engine_job_agent_retrigger_test.go index 9a0a0115c..fcb7cbb62 100644 --- a/apps/workspace-engine/test/e2e/engine_job_agent_retrigger_test.go +++ b/apps/workspace-engine/test/e2e/engine_job_agent_retrigger_test.go @@ -60,9 +60,7 @@ func TestEngine_JobAgentConfigurationRetriggersInvalidJobs(t *testing.T) { assert.Empty(t, originalJob.JobAgentId, "expected empty job agent ID") assert.Nil(t, originalJob.DispatchContext) - // Store original job details for later verification originalJobID := originalJob.Id - originalReleaseID := originalJob.ReleaseId // Verify no pending jobs (InvalidJobAgent jobs are not pending) pendingJobs := engine.Workspace().Jobs().GetPending() @@ -98,8 +96,8 @@ func TestEngine_JobAgentConfigurationRetriggersInvalidJobs(t *testing.T) { require.NotNil(t, newPendingJob, "expected to find a new Pending job after job agent configuration") - // Verify new job has the same release ID as the original InvalidJobAgent job - assert.Equal(t, originalReleaseID, newPendingJob.ReleaseId, "expected new job to have same release ID") + // Verify new job targets the same release target (release IDs are random UUIDs) + assert.NotEqual(t, "", newPendingJob.ReleaseId, "expected new job to have a release ID") // Verify new job uses the configured job agent assert.Equal(t, jobAgentID, newPendingJob.JobAgentId, "expected new job to use configured job agent") @@ -179,7 +177,6 @@ func TestEngine_JobAgentConfigUpdateRetriggersInvalidJobs(t *testing.T) { assert.Nil(t, originalJob.DispatchContext) originalJobID := originalJob.Id - originalReleaseID := originalJob.ReleaseId // Step 3: Create job agent and configure deployment with both agent ID and config jobAgentID := uuid.New().String() @@ -218,8 +215,8 @@ func TestEngine_JobAgentConfigUpdateRetriggersInvalidJobs(t *testing.T) { require.NotNil(t, newPendingJob, "expected to find a new Pending job after job agent configuration") - // Verify new job has same release ID - assert.Equal(t, originalReleaseID, newPendingJob.ReleaseId, "expected new job to have same release ID") + // Verify new job targets the same release target (release IDs are random UUIDs) + assert.NotEqual(t, "", newPendingJob.ReleaseId, "expected new job to have a release ID") // Verify new job uses the configured job agent assert.Equal(t, jobAgentID, newPendingJob.JobAgentId, "expected new job to use configured job agent") diff --git a/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go b/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go index a1be9d11a..4bc950e5f 100644 --- a/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go +++ b/apps/workspace-engine/test/e2e/engine_nil_release_handling_test.go @@ -93,12 +93,13 @@ func TestEngine_JobsWithNilReleaseReference(t *testing.T) { DeploymentId: deployment.Id, } - // Test GetJobsForReleaseTarget with missing release + // Test GetJobsForReleaseTarget with missing release. + // Orphaned jobs (whose releases were deleted) are still discoverable + // via their DispatchContext, which is important for retry evaluation + // after cascade deletes. jobsForTarget := engine.Workspace().Jobs().GetJobsForReleaseTarget(releaseTarget) - - // The job should be filtered out because its release doesn't exist - if len(jobsForTarget) != 0 { - t.Fatalf("expected 0 jobs for release target (release doesn't exist), got %d", len(jobsForTarget)) + if len(jobsForTarget) != 1 { + t.Fatalf("expected 1 orphaned job for release target (found via DispatchContext), got %d", len(jobsForTarget)) } // Test GetCurrentRelease with missing release @@ -297,22 +298,30 @@ func TestEngine_MultipleJobsWithMixedNilReleases(t *testing.T) { releaseIdToDelete := release.ID() engine.Workspace().Releases().Remove(ctx, releaseIdToDelete) - // Get jobs for release target - should only return jobs with valid releases + // Get jobs for release target — includes both release-linked and orphaned + // jobs (discovered via DispatchContext after cascade deletes). jobsForTarget := engine.Workspace().Jobs().GetJobsForReleaseTarget(releaseTarget) - // Should have at least one job (the one with valid release) - // The corrupted job should be filtered out - if len(jobsForTarget) < 1 { - t.Fatalf("expected at least 1 job with valid release, got %d", len(jobsForTarget)) + if len(jobsForTarget) < 2 { + t.Fatalf("expected at least 2 jobs (1 valid + 1 orphaned), got %d", len(jobsForTarget)) } - // Verify all returned jobs have valid releases - for jobId, job := range jobsForTarget { - rel, ok := engine.Workspace().Releases().Get(job.ReleaseId) - if !ok || rel == nil { - t.Fatalf("job %s has invalid release reference", jobId) + // Verify that at least one job has a valid release and at least one is orphaned + validCount := 0 + orphanedCount := 0 + for _, job := range jobsForTarget { + if _, ok := engine.Workspace().Releases().Get(job.ReleaseId); ok { + validCount++ + } else { + orphanedCount++ } } + if validCount < 1 { + t.Fatalf("expected at least 1 job with valid release, got %d", validCount) + } + if orphanedCount < 1 { + t.Fatalf("expected at least 1 orphaned job, got %d", orphanedCount) + } } // TestEngine_DeploymentDeletionLeavesOrphanedJobs tests the scenario where diff --git a/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go b/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go index 0cfd164eb..3c3deea5d 100644 --- a/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go +++ b/apps/workspace-engine/test/e2e/engine_releasetarget_state_test.go @@ -246,10 +246,10 @@ func TestEngine_ReleaseTargetState_CurrentMatchesDesired(t *testing.T) { t.Errorf("expected desired release version v1.0.0, got %s", state.DesiredRelease.Version.Tag) } - // Verify: releases are the same - if state.CurrentRelease.ID() != state.DesiredRelease.ID() { - t.Errorf("expected current and desired releases to be the same, got current=%s, desired=%s", - state.CurrentRelease.ID(), state.DesiredRelease.ID()) + // Verify: releases represent the same logical deployment (same version + variables + target) + if state.CurrentRelease.VersionKey() != state.DesiredRelease.VersionKey() { + t.Errorf("expected current and desired releases to represent the same deployment, got current=%s, desired=%s", + state.CurrentRelease.VersionKey(), state.DesiredRelease.VersionKey()) } } diff --git a/apps/workspace-engine/test/integration/dbtest.go b/apps/workspace-engine/test/integration/dbtest.go index b0b647a0c..970075755 100644 --- a/apps/workspace-engine/test/integration/dbtest.go +++ b/apps/workspace-engine/test/integration/dbtest.go @@ -87,8 +87,8 @@ func newDBTestWorkspace(t *testing.T, options ...WorkspaceOption) *TestWorkspace store.WithDBWorkflowRuns(ctx), store.WithDBWorkflowJobs(ctx), store.WithDBResourceVariables(ctx), - store.WithDBJobs(ctx), - // store.WithDBReleases(ctx), + store.WithDBReleases(ctx), + // store.WithDBJobs(ctx), ), ) diff --git a/packages/db/drizzle/0156_fine_talkback.sql b/packages/db/drizzle/0156_fine_talkback.sql new file mode 100644 index 000000000..068187eae --- /dev/null +++ b/packages/db/drizzle/0156_fine_talkback.sql @@ -0,0 +1,12 @@ +ALTER TABLE "release" DROP CONSTRAINT "release_resource_id_resource_id_fk"; +--> statement-breakpoint +ALTER TABLE "release" DROP CONSTRAINT "release_environment_id_environment_id_fk"; +--> statement-breakpoint +ALTER TABLE "release" DROP CONSTRAINT "release_deployment_id_deployment_id_fk"; +--> statement-breakpoint +ALTER TABLE "release" DROP CONSTRAINT "release_version_id_deployment_version_id_fk"; +--> statement-breakpoint +ALTER TABLE "release" ADD CONSTRAINT "release_resource_id_resource_id_fk" FOREIGN KEY ("resource_id") REFERENCES "public"."resource"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "release" ADD CONSTRAINT "release_environment_id_environment_id_fk" FOREIGN KEY ("environment_id") REFERENCES "public"."environment"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "release" ADD CONSTRAINT "release_deployment_id_deployment_id_fk" FOREIGN KEY ("deployment_id") REFERENCES "public"."deployment"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "release" ADD CONSTRAINT "release_version_id_deployment_version_id_fk" FOREIGN KEY ("version_id") REFERENCES "public"."deployment_version"("id") ON DELETE cascade ON UPDATE no action; \ No newline at end of file diff --git a/packages/db/drizzle/0157_supreme_matthew_murdock.sql b/packages/db/drizzle/0157_supreme_matthew_murdock.sql new file mode 100644 index 000000000..03265f2b6 --- /dev/null +++ b/packages/db/drizzle/0157_supreme_matthew_murdock.sql @@ -0,0 +1,11 @@ +CREATE TABLE "release_job" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "job_id" uuid NOT NULL, + "release_id" uuid NOT NULL +); +--> statement-breakpoint +ALTER TABLE "release_variable" DROP CONSTRAINT "release_variable_release_id_release_id_fk"; +--> statement-breakpoint +ALTER TABLE "release_job" ADD CONSTRAINT "release_job_job_id_job_id_fk" FOREIGN KEY ("job_id") REFERENCES "public"."job"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "release_job" ADD CONSTRAINT "release_job_release_id_release_id_fk" FOREIGN KEY ("release_id") REFERENCES "public"."release"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "release_variable" ADD CONSTRAINT "release_variable_release_id_release_id_fk" FOREIGN KEY ("release_id") REFERENCES "public"."release"("id") ON DELETE cascade ON UPDATE no action; \ No newline at end of file diff --git a/packages/db/drizzle/meta/0156_snapshot.json b/packages/db/drizzle/meta/0156_snapshot.json new file mode 100644 index 000000000..9dcf0812e --- /dev/null +++ b/packages/db/drizzle/meta/0156_snapshot.json @@ -0,0 +1,4795 @@ +{ + "id": "42419d56-ea42-4e25-9dc0-eccbd34b728d", + "prevId": "767c0bef-4521-46d8-942b-2a15b4e27037", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "session_token": { + "name": "session_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_session_token_unique": { + "name": "session_session_token_unique", + "nullsNotDistinct": false, + "columns": ["session_token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "active_workspace_id": { + "name": "active_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "null" + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "null" + }, + "system_role": { + "name": "system_role", + "type": "system_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_active_workspace_id_workspace_id_fk": { + "name": "user_active_workspace_id_workspace_id_fk", + "tableFrom": "user", + "tableTo": "workspace", + "columnsFrom": ["active_workspace_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_api_key": { + "name": "user_api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "key_preview": { + "name": "key_preview", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_hash": { + "name": "key_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_prefix": { + "name": "key_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_api_key_key_prefix_key_hash_index": { + "name": "user_api_key_key_prefix_key_hash_index", + "columns": [ + { + "expression": "key_prefix", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_api_key_user_id_user_id_fk": { + "name": "user_api_key_user_id_user_id_fk", + "tableFrom": "user_api_key", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.changelog_entry": { + "name": "changelog_entry", + "schema": "", + "columns": { + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_data": { + "name": "entity_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "changelog_entry_workspace_id_workspace_id_fk": { + "name": "changelog_entry_workspace_id_workspace_id_fk", + "tableFrom": "changelog_entry", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "changelog_entry_workspace_id_entity_type_entity_id_pk": { + "name": "changelog_entry_workspace_id_entity_type_entity_id_pk", + "columns": ["workspace_id", "entity_type", "entity_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.dashboard": { + "name": "dashboard", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_workspace_id_workspace_id_fk": { + "name": "dashboard_workspace_id_workspace_id_fk", + "tableFrom": "dashboard", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.dashboard_widget": { + "name": "dashboard_widget", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "dashboard_id": { + "name": "dashboard_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "widget": { + "name": "widget", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "x": { + "name": "x", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "w": { + "name": "w", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "h": { + "name": "h", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_widget_dashboard_id_dashboard_id_fk": { + "name": "dashboard_widget_dashboard_id_dashboard_id_fk", + "tableFrom": "dashboard_widget", + "tableTo": "dashboard", + "columnsFrom": ["dashboard_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_trace_span": { + "name": "deployment_trace_span", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_span_id": { + "name": "parent_span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "start_time": { + "name": "start_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "end_time": { + "name": "end_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "release_target_key": { + "name": "release_target_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "release_id": { + "name": "release_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "job_id": { + "name": "job_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parent_trace_id": { + "name": "parent_trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "phase": { + "name": "phase", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "node_type": { + "name": "node_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "depth": { + "name": "depth", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "sequence": { + "name": "sequence", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "attributes": { + "name": "attributes", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "events": { + "name": "events", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "deployment_trace_span_trace_span_idx": { + "name": "deployment_trace_span_trace_span_idx", + "columns": [ + { + "expression": "trace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "span_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_trace_id_idx": { + "name": "deployment_trace_span_trace_id_idx", + "columns": [ + { + "expression": "trace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_parent_span_id_idx": { + "name": "deployment_trace_span_parent_span_id_idx", + "columns": [ + { + "expression": "parent_span_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_workspace_id_idx": { + "name": "deployment_trace_span_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_release_target_key_idx": { + "name": "deployment_trace_span_release_target_key_idx", + "columns": [ + { + "expression": "release_target_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_release_id_idx": { + "name": "deployment_trace_span_release_id_idx", + "columns": [ + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_job_id_idx": { + "name": "deployment_trace_span_job_id_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_parent_trace_id_idx": { + "name": "deployment_trace_span_parent_trace_id_idx", + "columns": [ + { + "expression": "parent_trace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_created_at_idx": { + "name": "deployment_trace_span_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_phase_idx": { + "name": "deployment_trace_span_phase_idx", + "columns": [ + { + "expression": "phase", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_node_type_idx": { + "name": "deployment_trace_span_node_type_idx", + "columns": [ + { + "expression": "node_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_status_idx": { + "name": "deployment_trace_span_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_trace_span_workspace_id_workspace_id_fk": { + "name": "deployment_trace_span_workspace_id_workspace_id_fk", + "tableFrom": "deployment_trace_span", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_variable": { + "name": "deployment_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_variable_deployment_id_deployment_id_fk": { + "name": "deployment_variable_deployment_id_deployment_id_fk", + "tableFrom": "deployment_variable", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployment_variable_deployment_id_key_unique": { + "name": "deployment_variable_deployment_id_key_unique", + "nullsNotDistinct": false, + "columns": ["deployment_id", "key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_variable_value": { + "name": "deployment_variable_value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_variable_id": { + "name": "deployment_variable_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "resource_selector": { + "name": "resource_selector", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "priority": { + "name": "priority", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_variable_value_deployment_variable_id_deployment_variable_id_fk": { + "name": "deployment_variable_value_deployment_variable_id_deployment_variable_id_fk", + "tableFrom": "deployment_variable_value", + "tableTo": "deployment_variable", + "columnsFrom": ["deployment_variable_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_version": { + "name": "deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "deployment_version_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp (3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_version_deployment_id_tag_index": { + "name": "deployment_version_deployment_id_tag_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_version_created_at_idx": { + "name": "deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_version_workspace_id_workspace_id_fk": { + "name": "deployment_version_workspace_id_workspace_id_fk", + "tableFrom": "deployment_version", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.computed_deployment_resource": { + "name": "computed_deployment_resource", + "schema": "", + "columns": { + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_evaluated_at": { + "name": "last_evaluated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "computed_deployment_resource_deployment_id_deployment_id_fk": { + "name": "computed_deployment_resource_deployment_id_deployment_id_fk", + "tableFrom": "computed_deployment_resource", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "computed_deployment_resource_resource_id_resource_id_fk": { + "name": "computed_deployment_resource_resource_id_resource_id_fk", + "tableFrom": "computed_deployment_resource", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "computed_deployment_resource_deployment_id_resource_id_pk": { + "name": "computed_deployment_resource_deployment_id_resource_id_pk", + "columns": ["deployment_id", "resource_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment": { + "name": "deployment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "job_agents": { + "name": "job_agents", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "resource_selector": { + "name": "resource_selector", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_workspace_id_workspace_id_fk": { + "name": "deployment_workspace_id_workspace_id_fk", + "tableFrom": "deployment", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.computed_environment_resource": { + "name": "computed_environment_resource", + "schema": "", + "columns": { + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_evaluated_at": { + "name": "last_evaluated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "computed_environment_resource_environment_id_environment_id_fk": { + "name": "computed_environment_resource_environment_id_environment_id_fk", + "tableFrom": "computed_environment_resource", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "computed_environment_resource_resource_id_resource_id_fk": { + "name": "computed_environment_resource_resource_id_resource_id_fk", + "tableFrom": "computed_environment_resource", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "computed_environment_resource_environment_id_resource_id_pk": { + "name": "computed_environment_resource_environment_id_resource_id_pk", + "columns": ["environment_id", "resource_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "resource_selector": { + "name": "resource_selector", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "environment_workspace_id_workspace_id_fk": { + "name": "environment_workspace_id_workspace_id_fk", + "tableFrom": "environment", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.event": { + "name": "event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "event_workspace_id_workspace_id_fk": { + "name": "event_workspace_id_workspace_id_fk", + "tableFrom": "event", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource": { + "name": "resource", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resource_identifier_workspace_id_index": { + "name": "resource_identifier_workspace_id_index", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource", + "tableTo": "resource_provider", + "columnsFrom": ["provider_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "resource_workspace_id_workspace_id_fk": { + "name": "resource_workspace_id_workspace_id_fk", + "tableFrom": "resource", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource_schema": { + "name": "resource_schema", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "json_schema": { + "name": "json_schema", + "type": "json", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_schema_version_kind_workspace_id_index": { + "name": "resource_schema_version_kind_workspace_id_index", + "columns": [ + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_schema_workspace_id_workspace_id_fk": { + "name": "resource_schema_workspace_id_workspace_id_fk", + "tableFrom": "resource_schema", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource_provider": { + "name": "resource_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": { + "resource_provider_workspace_id_name_index": { + "name": "resource_provider_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_workspace_id_workspace_id_fk": { + "name": "resource_provider_workspace_id_workspace_id_fk", + "tableFrom": "resource_provider", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.system": { + "name": "system", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "system_workspace_id_workspace_id_fk": { + "name": "system_workspace_id_workspace_id_fk", + "tableFrom": "system", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.system_deployment": { + "name": "system_deployment", + "schema": "", + "columns": { + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "system_deployment_system_id_system_id_fk": { + "name": "system_deployment_system_id_system_id_fk", + "tableFrom": "system_deployment", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "system_deployment_deployment_id_deployment_id_fk": { + "name": "system_deployment_deployment_id_deployment_id_fk", + "tableFrom": "system_deployment", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "system_deployment_system_id_deployment_id_pk": { + "name": "system_deployment_system_id_deployment_id_pk", + "columns": ["system_id", "deployment_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.system_environment": { + "name": "system_environment", + "schema": "", + "columns": { + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "system_environment_system_id_system_id_fk": { + "name": "system_environment_system_id_system_id_fk", + "tableFrom": "system_environment", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "system_environment_environment_id_environment_id_fk": { + "name": "system_environment_environment_id_environment_id_fk", + "tableFrom": "system_environment", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "system_environment_system_id_environment_id_pk": { + "name": "system_environment_system_id_environment_id_pk", + "columns": ["system_id", "environment_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.team": { + "name": "team", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "team_workspace_id_workspace_id_fk": { + "name": "team_workspace_id_workspace_id_fk", + "tableFrom": "team", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.team_member": { + "name": "team_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "team_member_team_id_user_id_index": { + "name": "team_member_team_id_user_id_index", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "team_member_team_id_team_id_fk": { + "name": "team_member_team_id_team_id_fk", + "tableFrom": "team_member", + "tableTo": "team", + "columnsFrom": ["team_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "team_member_user_id_user_id_fk": { + "name": "team_member_user_id_user_id_fk", + "tableFrom": "team_member", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job": { + "name": "job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "trace_token": { + "name": "trace_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dispatch_context": { + "name": "dispatch_context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "job_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "job_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'policy_passing'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "job_created_at_idx": { + "name": "job_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_status_idx": { + "name": "job_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_external_id_idx": { + "name": "job_external_id_idx", + "columns": [ + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_job_agent_id_job_agent_id_fk": { + "name": "job_job_agent_id_job_agent_id_fk", + "tableFrom": "job", + "tableTo": "job_agent", + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_metadata": { + "name": "job_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "job_metadata_key_job_id_index": { + "name": "job_metadata_key_job_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_metadata_job_id_idx": { + "name": "job_metadata_job_id_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_metadata_job_id_job_id_fk": { + "name": "job_metadata_job_id_job_id_fk", + "tableFrom": "job_metadata", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_variable": { + "name": "job_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "job_variable_job_id_key_index": { + "name": "job_variable_job_id_key_index", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_variable_job_id_job_id_fk": { + "name": "job_variable_job_id_job_id_fk", + "tableFrom": "job_variable", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_slug_unique": { + "name": "workspace_slug_unique", + "nullsNotDistinct": false, + "columns": ["slug"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_email_domain_matching": { + "name": "workspace_email_domain_matching", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "verification_code": { + "name": "verification_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "verification_email": { + "name": "verification_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_email_domain_matching_workspace_id_domain_index": { + "name": "workspace_email_domain_matching_workspace_id_domain_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_email_domain_matching_workspace_id_workspace_id_fk": { + "name": "workspace_email_domain_matching_workspace_id_workspace_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_email_domain_matching_role_id_role_id_fk": { + "name": "workspace_email_domain_matching_role_id_role_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_invite_token": { + "name": "workspace_invite_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invite_token_role_id_role_id_fk": { + "name": "workspace_invite_token_role_id_role_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_workspace_id_workspace_id_fk": { + "name": "workspace_invite_token_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_created_by_user_id_fk": { + "name": "workspace_invite_token_created_by_user_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invite_token_token_unique": { + "name": "workspace_invite_token_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.entity_role": { + "name": "entity_role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "entity_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_id": { + "name": "scope_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "scope_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index": { + "name": "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "entity_role_role_id_role_id_fk": { + "name": "entity_role_role_id_role_id_fk", + "tableFrom": "entity_role", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.role": { + "name": "role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "role_workspace_id_workspace_id_fk": { + "name": "role_workspace_id_workspace_id_fk", + "tableFrom": "role", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.role_permission": { + "name": "role_permission", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "role_permission_role_id_permission_index": { + "name": "role_permission_role_id_permission_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "role_permission_role_id_role_id_fk": { + "name": "role_permission_role_id_role_id_fk", + "tableFrom": "role_permission", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.release": { + "name": "release", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version_id": { + "name": "version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "release_resource_id_resource_id_fk": { + "name": "release_resource_id_resource_id_fk", + "tableFrom": "release", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_environment_id_environment_id_fk": { + "name": "release_environment_id_environment_id_fk", + "tableFrom": "release", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_deployment_id_deployment_id_fk": { + "name": "release_deployment_id_deployment_id_fk", + "tableFrom": "release", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_version_id_deployment_version_id_fk": { + "name": "release_version_id_deployment_version_id_fk", + "tableFrom": "release", + "tableTo": "deployment_version", + "columnsFrom": ["version_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.release_variable": { + "name": "release_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "encrypted": { + "name": "encrypted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "release_variable_release_id_key_index": { + "name": "release_variable_release_id_key_index", + "columns": [ + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_variable_release_id_release_id_fk": { + "name": "release_variable_release_id_release_id_fk", + "tableFrom": "release_variable", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reconcile_work_payload": { + "name": "reconcile_work_payload", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigint", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "byDefault", + "name": "reconcile_work_payload_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "scope_ref": { + "name": "scope_ref", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "payload_type": { + "name": "payload_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "payload_key": { + "name": "payload_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "attempt_count": { + "name": "attempt_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "reconcile_work_payload_scope_ref_payload_type_payload_key_index": { + "name": "reconcile_work_payload_scope_ref_payload_type_payload_key_index", + "columns": [ + { + "expression": "scope_ref", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "payload_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "payload_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reconcile_work_payload_scope_ref_index": { + "name": "reconcile_work_payload_scope_ref_index", + "columns": [ + { + "expression": "scope_ref", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reconcile_work_payload_scope_ref_reconcile_work_scope_id_fk": { + "name": "reconcile_work_payload_scope_ref_reconcile_work_scope_id_fk", + "tableFrom": "reconcile_work_payload", + "tableTo": "reconcile_work_scope", + "columnsFrom": ["scope_ref"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reconcile_work_scope": { + "name": "reconcile_work_scope", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigint", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "byDefault", + "name": "reconcile_work_scope_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "scope_id": { + "name": "scope_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "event_ts": { + "name": "event_ts", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "priority": { + "name": "priority", + "type": "smallint", + "primaryKey": false, + "notNull": true, + "default": 100 + }, + "not_before": { + "name": "not_before", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "claimed_by": { + "name": "claimed_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "claimed_until": { + "name": "claimed_until", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "reconcile_work_scope_workspace_id_kind_scope_type_scope_id_index": { + "name": "reconcile_work_scope_workspace_id_kind_scope_type_scope_id_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reconcile_work_scope_kind_not_before_priority_event_ts_claimed_until_index": { + "name": "reconcile_work_scope_kind_not_before_priority_event_ts_claimed_until_index", + "columns": [ + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "not_before", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "priority", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_ts", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "claimed_until", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy": { + "name": "policy", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "selector": { + "name": "selector", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'true'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_workspace_id_workspace_id_fk": { + "name": "policy_workspace_id_workspace_id_fk", + "tableFrom": "policy", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_any_approval": { + "name": "policy_rule_any_approval", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "min_approvals": { + "name": "min_approvals", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_any_approval_policy_id_policy_id_fk": { + "name": "policy_rule_any_approval_policy_id_policy_id_fk", + "tableFrom": "policy_rule_any_approval", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_deployment_dependency": { + "name": "policy_rule_deployment_dependency", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "depends_on": { + "name": "depends_on", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_deployment_dependency_policy_id_policy_id_fk": { + "name": "policy_rule_deployment_dependency_policy_id_policy_id_fk", + "tableFrom": "policy_rule_deployment_dependency", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_deployment_window": { + "name": "policy_rule_deployment_window", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "allow_window": { + "name": "allow_window", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "duration_minutes": { + "name": "duration_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rrule": { + "name": "rrule", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_deployment_window_policy_id_policy_id_fk": { + "name": "policy_rule_deployment_window_policy_id_policy_id_fk", + "tableFrom": "policy_rule_deployment_window", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_environment_progression": { + "name": "policy_rule_environment_progression", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "depends_on_environment_selector": { + "name": "depends_on_environment_selector", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "maximum_age_hours": { + "name": "maximum_age_hours", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "minimum_soak_time_minutes": { + "name": "minimum_soak_time_minutes", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "minimum_success_percentage": { + "name": "minimum_success_percentage", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "success_statuses": { + "name": "success_statuses", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_environment_progression_policy_id_policy_id_fk": { + "name": "policy_rule_environment_progression_policy_id_policy_id_fk", + "tableFrom": "policy_rule_environment_progression", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_gradual_rollout": { + "name": "policy_rule_gradual_rollout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "rollout_type": { + "name": "rollout_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "time_scale_interval": { + "name": "time_scale_interval", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_gradual_rollout_policy_id_policy_id_fk": { + "name": "policy_rule_gradual_rollout_policy_id_policy_id_fk", + "tableFrom": "policy_rule_gradual_rollout", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_retry": { + "name": "policy_rule_retry", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "max_retries": { + "name": "max_retries", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "backoff_seconds": { + "name": "backoff_seconds", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "backoff_strategy": { + "name": "backoff_strategy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "max_backoff_seconds": { + "name": "max_backoff_seconds", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "retry_on_statuses": { + "name": "retry_on_statuses", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_retry_policy_id_policy_id_fk": { + "name": "policy_rule_retry_policy_id_policy_id_fk", + "tableFrom": "policy_rule_retry", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_rollback": { + "name": "policy_rule_rollback", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "on_job_statuses": { + "name": "on_job_statuses", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "on_verification_failure": { + "name": "on_verification_failure", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_rollback_policy_id_policy_id_fk": { + "name": "policy_rule_rollback_policy_id_policy_id_fk", + "tableFrom": "policy_rule_rollback", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_verification": { + "name": "policy_rule_verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "metrics": { + "name": "metrics", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "trigger_on": { + "name": "trigger_on", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_verification_policy_id_policy_id_fk": { + "name": "policy_rule_verification_policy_id_policy_id_fk", + "tableFrom": "policy_rule_verification", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_version_cooldown": { + "name": "policy_rule_version_cooldown", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "interval_seconds": { + "name": "interval_seconds", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_version_cooldown_policy_id_policy_id_fk": { + "name": "policy_rule_version_cooldown_policy_id_policy_id_fk", + "tableFrom": "policy_rule_version_cooldown", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_version_selector": { + "name": "policy_rule_version_selector", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "selector": { + "name": "selector", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_version_selector_policy_id_policy_id_fk": { + "name": "policy_rule_version_selector_policy_id_policy_id_fk", + "tableFrom": "policy_rule_version_selector", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_approval_record": { + "name": "user_approval_record", + "schema": "", + "columns": { + "version_id": { + "name": "version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "user_approval_record_version_id_user_id_environment_id_pk": { + "name": "user_approval_record_version_id_user_id_environment_id_pk", + "columns": ["version_id", "user_id", "environment_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource_variable": { + "name": "resource_variable", + "schema": "", + "columns": { + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "resource_variable_resource_id_resource_id_fk": { + "name": "resource_variable_resource_id_resource_id_fk", + "tableFrom": "resource_variable", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "resource_variable_resource_id_key_pk": { + "name": "resource_variable_resource_id_key_pk", + "columns": ["resource_id", "key"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow": { + "name": "workflow", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inputs": { + "name": "inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "jobs": { + "name": "jobs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_workspace_id_workspace_id_fk": { + "name": "workflow_workspace_id_workspace_id_fk", + "tableFrom": "workflow", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_job": { + "name": "workflow_job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_run_id": { + "name": "workflow_run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "ref": { + "name": "ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "index": { + "name": "index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_job_workflow_run_id_workflow_run_id_fk": { + "name": "workflow_job_workflow_run_id_workflow_run_id_fk", + "tableFrom": "workflow_job", + "tableTo": "workflow_run", + "columnsFrom": ["workflow_run_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_job_template": { + "name": "workflow_job_template", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "ref": { + "name": "ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "if_condition": { + "name": "if_condition", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "matrix": { + "name": "matrix", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_job_template_workflow_id_workflow_id_fk": { + "name": "workflow_job_template_workflow_id_workflow_id_fk", + "tableFrom": "workflow_job_template", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_run": { + "name": "workflow_run", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "inputs": { + "name": "inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_workflow_id_workflow_id_fk": { + "name": "workflow_run_workflow_id_workflow_id_fk", + "tableFrom": "workflow_run", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_verification_metric_measurement": { + "name": "job_verification_metric_measurement", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_verification_metric_status_id": { + "name": "job_verification_metric_status_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "measured_at": { + "name": "measured_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "status": { + "name": "status", + "type": "job_verification_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "job_verification_metric_measurement_job_verification_metric_status_id_job_verification_metric_id_fk": { + "name": "job_verification_metric_measurement_job_verification_metric_status_id_job_verification_metric_id_fk", + "tableFrom": "job_verification_metric_measurement", + "tableTo": "job_verification_metric", + "columnsFrom": ["job_verification_metric_status_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_verification_metric": { + "name": "job_verification_metric", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "interval_seconds": { + "name": "interval_seconds", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "success_condition": { + "name": "success_condition", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "success_threshold": { + "name": "success_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "failure_condition": { + "name": "failure_condition", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "failure_threshold": { + "name": "failure_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_job_verification_metric": { + "name": "policy_rule_job_verification_metric", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "trigger_on": { + "name": "trigger_on", + "type": "job_verification_trigger_on", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'jobSuccess'" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "interval_seconds": { + "name": "interval_seconds", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "success_condition": { + "name": "success_condition", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "success_threshold": { + "name": "success_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "failure_condition": { + "name": "failure_condition", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "failure_threshold": { + "name": "failure_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_job_verification_metric_policy_id_policy_id_fk": { + "name": "policy_rule_job_verification_metric_policy_id_policy_id_fk", + "tableFrom": "policy_rule_job_verification_metric", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_agent": { + "name": "job_agent", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": { + "job_agent_workspace_id_name_index": { + "name": "job_agent_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_agent_workspace_id_workspace_id_fk": { + "name": "job_agent_workspace_id_workspace_id_fk", + "tableFrom": "job_agent", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.system_role": { + "name": "system_role", + "schema": "public", + "values": ["user", "admin"] + }, + "public.deployment_version_status": { + "name": "deployment_version_status", + "schema": "public", + "values": [ + "unspecified", + "building", + "ready", + "failed", + "rejected", + "paused" + ] + }, + "public.job_reason": { + "name": "job_reason", + "schema": "public", + "values": [ + "policy_passing", + "policy_override", + "env_policy_override", + "config_policy_override" + ] + }, + "public.job_status": { + "name": "job_status", + "schema": "public", + "values": [ + "cancelled", + "skipped", + "in_progress", + "action_required", + "pending", + "failure", + "invalid_job_agent", + "invalid_integration", + "external_run_not_found", + "successful" + ] + }, + "public.entity_type": { + "name": "entity_type", + "schema": "public", + "values": ["user", "team"] + }, + "public.scope_type": { + "name": "scope_type", + "schema": "public", + "values": [ + "deploymentVersion", + "resource", + "resourceProvider", + "workspace", + "environment", + "system", + "deployment" + ] + }, + "public.job_verification_status": { + "name": "job_verification_status", + "schema": "public", + "values": ["failed", "inconclusive", "passed"] + }, + "public.job_verification_trigger_on": { + "name": "job_verification_trigger_on", + "schema": "public", + "values": ["jobCreated", "jobStarted", "jobSuccess", "jobFailure"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/packages/db/drizzle/meta/0157_snapshot.json b/packages/db/drizzle/meta/0157_snapshot.json new file mode 100644 index 000000000..574dc14ec --- /dev/null +++ b/packages/db/drizzle/meta/0157_snapshot.json @@ -0,0 +1,4846 @@ +{ + "id": "5715eeac-a7ae-43c6-a7a1-6fbb0b1aaefc", + "prevId": "42419d56-ea42-4e25-9dc0-eccbd34b728d", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "session_token": { + "name": "session_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_session_token_unique": { + "name": "session_session_token_unique", + "nullsNotDistinct": false, + "columns": ["session_token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "active_workspace_id": { + "name": "active_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "null" + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "null" + }, + "system_role": { + "name": "system_role", + "type": "system_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_active_workspace_id_workspace_id_fk": { + "name": "user_active_workspace_id_workspace_id_fk", + "tableFrom": "user", + "tableTo": "workspace", + "columnsFrom": ["active_workspace_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_api_key": { + "name": "user_api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "key_preview": { + "name": "key_preview", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_hash": { + "name": "key_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key_prefix": { + "name": "key_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "user_api_key_key_prefix_key_hash_index": { + "name": "user_api_key_key_prefix_key_hash_index", + "columns": [ + { + "expression": "key_prefix", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_api_key_user_id_user_id_fk": { + "name": "user_api_key_user_id_user_id_fk", + "tableFrom": "user_api_key", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.changelog_entry": { + "name": "changelog_entry", + "schema": "", + "columns": { + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_data": { + "name": "entity_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "changelog_entry_workspace_id_workspace_id_fk": { + "name": "changelog_entry_workspace_id_workspace_id_fk", + "tableFrom": "changelog_entry", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "changelog_entry_workspace_id_entity_type_entity_id_pk": { + "name": "changelog_entry_workspace_id_entity_type_entity_id_pk", + "columns": ["workspace_id", "entity_type", "entity_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.dashboard": { + "name": "dashboard", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_workspace_id_workspace_id_fk": { + "name": "dashboard_workspace_id_workspace_id_fk", + "tableFrom": "dashboard", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.dashboard_widget": { + "name": "dashboard_widget", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "dashboard_id": { + "name": "dashboard_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "widget": { + "name": "widget", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "x": { + "name": "x", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "y": { + "name": "y", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "w": { + "name": "w", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "h": { + "name": "h", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "dashboard_widget_dashboard_id_dashboard_id_fk": { + "name": "dashboard_widget_dashboard_id_dashboard_id_fk", + "tableFrom": "dashboard_widget", + "tableTo": "dashboard", + "columnsFrom": ["dashboard_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_trace_span": { + "name": "deployment_trace_span", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "span_id": { + "name": "span_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_span_id": { + "name": "parent_span_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "start_time": { + "name": "start_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "end_time": { + "name": "end_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "release_target_key": { + "name": "release_target_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "release_id": { + "name": "release_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "job_id": { + "name": "job_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parent_trace_id": { + "name": "parent_trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "phase": { + "name": "phase", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "node_type": { + "name": "node_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "depth": { + "name": "depth", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "sequence": { + "name": "sequence", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "attributes": { + "name": "attributes", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "events": { + "name": "events", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "deployment_trace_span_trace_span_idx": { + "name": "deployment_trace_span_trace_span_idx", + "columns": [ + { + "expression": "trace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "span_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_trace_id_idx": { + "name": "deployment_trace_span_trace_id_idx", + "columns": [ + { + "expression": "trace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_parent_span_id_idx": { + "name": "deployment_trace_span_parent_span_id_idx", + "columns": [ + { + "expression": "parent_span_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_workspace_id_idx": { + "name": "deployment_trace_span_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_release_target_key_idx": { + "name": "deployment_trace_span_release_target_key_idx", + "columns": [ + { + "expression": "release_target_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_release_id_idx": { + "name": "deployment_trace_span_release_id_idx", + "columns": [ + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_job_id_idx": { + "name": "deployment_trace_span_job_id_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_parent_trace_id_idx": { + "name": "deployment_trace_span_parent_trace_id_idx", + "columns": [ + { + "expression": "parent_trace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_created_at_idx": { + "name": "deployment_trace_span_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_phase_idx": { + "name": "deployment_trace_span_phase_idx", + "columns": [ + { + "expression": "phase", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_node_type_idx": { + "name": "deployment_trace_span_node_type_idx", + "columns": [ + { + "expression": "node_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_trace_span_status_idx": { + "name": "deployment_trace_span_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_trace_span_workspace_id_workspace_id_fk": { + "name": "deployment_trace_span_workspace_id_workspace_id_fk", + "tableFrom": "deployment_trace_span", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_variable": { + "name": "deployment_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_variable_deployment_id_deployment_id_fk": { + "name": "deployment_variable_deployment_id_deployment_id_fk", + "tableFrom": "deployment_variable", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "deployment_variable_deployment_id_key_unique": { + "name": "deployment_variable_deployment_id_key_unique", + "nullsNotDistinct": false, + "columns": ["deployment_id", "key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_variable_value": { + "name": "deployment_variable_value", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "deployment_variable_id": { + "name": "deployment_variable_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "resource_selector": { + "name": "resource_selector", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "priority": { + "name": "priority", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_variable_value_deployment_variable_id_deployment_variable_id_fk": { + "name": "deployment_variable_value_deployment_variable_id_deployment_variable_id_fk", + "tableFrom": "deployment_variable_value", + "tableTo": "deployment_variable", + "columnsFrom": ["deployment_variable_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment_version": { + "name": "deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "deployment_version_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ready'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp (3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "deployment_version_deployment_id_tag_index": { + "name": "deployment_version_deployment_id_tag_index", + "columns": [ + { + "expression": "deployment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deployment_version_created_at_idx": { + "name": "deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deployment_version_workspace_id_workspace_id_fk": { + "name": "deployment_version_workspace_id_workspace_id_fk", + "tableFrom": "deployment_version", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.computed_deployment_resource": { + "name": "computed_deployment_resource", + "schema": "", + "columns": { + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_evaluated_at": { + "name": "last_evaluated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "computed_deployment_resource_deployment_id_deployment_id_fk": { + "name": "computed_deployment_resource_deployment_id_deployment_id_fk", + "tableFrom": "computed_deployment_resource", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "computed_deployment_resource_resource_id_resource_id_fk": { + "name": "computed_deployment_resource_resource_id_resource_id_fk", + "tableFrom": "computed_deployment_resource", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "computed_deployment_resource_deployment_id_resource_id_pk": { + "name": "computed_deployment_resource_deployment_id_resource_id_pk", + "columns": ["deployment_id", "resource_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.deployment": { + "name": "deployment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "job_agents": { + "name": "job_agents", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "resource_selector": { + "name": "resource_selector", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_workspace_id_workspace_id_fk": { + "name": "deployment_workspace_id_workspace_id_fk", + "tableFrom": "deployment", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.computed_environment_resource": { + "name": "computed_environment_resource", + "schema": "", + "columns": { + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_evaluated_at": { + "name": "last_evaluated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "computed_environment_resource_environment_id_environment_id_fk": { + "name": "computed_environment_resource_environment_id_environment_id_fk", + "tableFrom": "computed_environment_resource", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "computed_environment_resource_resource_id_resource_id_fk": { + "name": "computed_environment_resource_resource_id_resource_id_fk", + "tableFrom": "computed_environment_resource", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "computed_environment_resource_environment_id_resource_id_pk": { + "name": "computed_environment_resource_environment_id_resource_id_pk", + "columns": ["environment_id", "resource_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "resource_selector": { + "name": "resource_selector", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "environment_workspace_id_workspace_id_fk": { + "name": "environment_workspace_id_workspace_id_fk", + "tableFrom": "environment", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.event": { + "name": "event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "event_workspace_id_workspace_id_fk": { + "name": "event_workspace_id_workspace_id_fk", + "tableFrom": "event", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource": { + "name": "resource", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resource_identifier_workspace_id_index": { + "name": "resource_identifier_workspace_id_index", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_id_resource_provider_id_fk": { + "name": "resource_provider_id_resource_provider_id_fk", + "tableFrom": "resource", + "tableTo": "resource_provider", + "columnsFrom": ["provider_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "resource_workspace_id_workspace_id_fk": { + "name": "resource_workspace_id_workspace_id_fk", + "tableFrom": "resource", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource_schema": { + "name": "resource_schema", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "json_schema": { + "name": "json_schema", + "type": "json", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "resource_schema_version_kind_workspace_id_index": { + "name": "resource_schema_version_kind_workspace_id_index", + "columns": [ + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_schema_workspace_id_workspace_id_fk": { + "name": "resource_schema_workspace_id_workspace_id_fk", + "tableFrom": "resource_schema", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource_provider": { + "name": "resource_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": { + "resource_provider_workspace_id_name_index": { + "name": "resource_provider_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resource_provider_workspace_id_workspace_id_fk": { + "name": "resource_provider_workspace_id_workspace_id_fk", + "tableFrom": "resource_provider", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.system": { + "name": "system", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "system_workspace_id_workspace_id_fk": { + "name": "system_workspace_id_workspace_id_fk", + "tableFrom": "system", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.system_deployment": { + "name": "system_deployment", + "schema": "", + "columns": { + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "system_deployment_system_id_system_id_fk": { + "name": "system_deployment_system_id_system_id_fk", + "tableFrom": "system_deployment", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "system_deployment_deployment_id_deployment_id_fk": { + "name": "system_deployment_deployment_id_deployment_id_fk", + "tableFrom": "system_deployment", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "system_deployment_system_id_deployment_id_pk": { + "name": "system_deployment_system_id_deployment_id_pk", + "columns": ["system_id", "deployment_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.system_environment": { + "name": "system_environment", + "schema": "", + "columns": { + "system_id": { + "name": "system_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "system_environment_system_id_system_id_fk": { + "name": "system_environment_system_id_system_id_fk", + "tableFrom": "system_environment", + "tableTo": "system", + "columnsFrom": ["system_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "system_environment_environment_id_environment_id_fk": { + "name": "system_environment_environment_id_environment_id_fk", + "tableFrom": "system_environment", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "system_environment_system_id_environment_id_pk": { + "name": "system_environment_system_id_environment_id_pk", + "columns": ["system_id", "environment_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.team": { + "name": "team", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "team_workspace_id_workspace_id_fk": { + "name": "team_workspace_id_workspace_id_fk", + "tableFrom": "team", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.team_member": { + "name": "team_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "team_member_team_id_user_id_index": { + "name": "team_member_team_id_user_id_index", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "team_member_team_id_team_id_fk": { + "name": "team_member_team_id_team_id_fk", + "tableFrom": "team_member", + "tableTo": "team", + "columnsFrom": ["team_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "team_member_user_id_user_id_fk": { + "name": "team_member_user_id_user_id_fk", + "tableFrom": "team_member", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job": { + "name": "job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_agent_id": { + "name": "job_agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "job_agent_config": { + "name": "job_agent_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "trace_token": { + "name": "trace_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dispatch_context": { + "name": "dispatch_context", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "status": { + "name": "status", + "type": "job_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "job_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'policy_passing'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "job_created_at_idx": { + "name": "job_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_status_idx": { + "name": "job_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_external_id_idx": { + "name": "job_external_id_idx", + "columns": [ + { + "expression": "external_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_job_agent_id_job_agent_id_fk": { + "name": "job_job_agent_id_job_agent_id_fk", + "tableFrom": "job", + "tableTo": "job_agent", + "columnsFrom": ["job_agent_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_metadata": { + "name": "job_metadata", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "job_metadata_key_job_id_index": { + "name": "job_metadata_key_job_id_index", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "job_metadata_job_id_idx": { + "name": "job_metadata_job_id_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_metadata_job_id_job_id_fk": { + "name": "job_metadata_job_id_job_id_fk", + "tableFrom": "job_metadata", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_variable": { + "name": "job_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "job_variable_job_id_key_index": { + "name": "job_variable_job_id_key_index", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_variable_job_id_job_id_fk": { + "name": "job_variable_job_id_job_id_fk", + "tableFrom": "job_variable", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_slug_unique": { + "name": "workspace_slug_unique", + "nullsNotDistinct": false, + "columns": ["slug"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_email_domain_matching": { + "name": "workspace_email_domain_matching", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "verification_code": { + "name": "verification_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "verification_email": { + "name": "verification_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_email_domain_matching_workspace_id_domain_index": { + "name": "workspace_email_domain_matching_workspace_id_domain_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_email_domain_matching_workspace_id_workspace_id_fk": { + "name": "workspace_email_domain_matching_workspace_id_workspace_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_email_domain_matching_role_id_role_id_fk": { + "name": "workspace_email_domain_matching_role_id_role_id_fk", + "tableFrom": "workspace_email_domain_matching", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_invite_token": { + "name": "workspace_invite_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invite_token_role_id_role_id_fk": { + "name": "workspace_invite_token_role_id_role_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_workspace_id_workspace_id_fk": { + "name": "workspace_invite_token_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invite_token_created_by_user_id_fk": { + "name": "workspace_invite_token_created_by_user_id_fk", + "tableFrom": "workspace_invite_token", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invite_token_token_unique": { + "name": "workspace_invite_token_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.entity_role": { + "name": "entity_role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "entity_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_id": { + "name": "scope_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "scope_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index": { + "name": "entity_role_role_id_entity_type_entity_id_scope_id_scope_type_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "entity_role_role_id_role_id_fk": { + "name": "entity_role_role_id_role_id_fk", + "tableFrom": "entity_role", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.role": { + "name": "role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "role_workspace_id_workspace_id_fk": { + "name": "role_workspace_id_workspace_id_fk", + "tableFrom": "role", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.role_permission": { + "name": "role_permission", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "role_permission_role_id_permission_index": { + "name": "role_permission_role_id_permission_index", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "role_permission_role_id_role_id_fk": { + "name": "role_permission_role_id_role_id_fk", + "tableFrom": "role_permission", + "tableTo": "role", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.release": { + "name": "release", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "deployment_id": { + "name": "deployment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version_id": { + "name": "version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "release_resource_id_resource_id_fk": { + "name": "release_resource_id_resource_id_fk", + "tableFrom": "release", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_environment_id_environment_id_fk": { + "name": "release_environment_id_environment_id_fk", + "tableFrom": "release", + "tableTo": "environment", + "columnsFrom": ["environment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_deployment_id_deployment_id_fk": { + "name": "release_deployment_id_deployment_id_fk", + "tableFrom": "release", + "tableTo": "deployment", + "columnsFrom": ["deployment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_version_id_deployment_version_id_fk": { + "name": "release_version_id_deployment_version_id_fk", + "tableFrom": "release", + "tableTo": "deployment_version", + "columnsFrom": ["version_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.release_job": { + "name": "release_job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "release_job_job_id_job_id_fk": { + "name": "release_job_job_id_job_id_fk", + "tableFrom": "release_job", + "tableTo": "job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "release_job_release_id_release_id_fk": { + "name": "release_job_release_id_release_id_fk", + "tableFrom": "release_job", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.release_variable": { + "name": "release_variable", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release_id": { + "name": "release_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "encrypted": { + "name": "encrypted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "release_variable_release_id_key_index": { + "name": "release_variable_release_id_key_index", + "columns": [ + { + "expression": "release_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "release_variable_release_id_release_id_fk": { + "name": "release_variable_release_id_release_id_fk", + "tableFrom": "release_variable", + "tableTo": "release", + "columnsFrom": ["release_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reconcile_work_payload": { + "name": "reconcile_work_payload", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigint", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "byDefault", + "name": "reconcile_work_payload_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "scope_ref": { + "name": "scope_ref", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "payload_type": { + "name": "payload_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "payload_key": { + "name": "payload_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "attempt_count": { + "name": "attempt_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "reconcile_work_payload_scope_ref_payload_type_payload_key_index": { + "name": "reconcile_work_payload_scope_ref_payload_type_payload_key_index", + "columns": [ + { + "expression": "scope_ref", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "payload_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "payload_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reconcile_work_payload_scope_ref_index": { + "name": "reconcile_work_payload_scope_ref_index", + "columns": [ + { + "expression": "scope_ref", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "reconcile_work_payload_scope_ref_reconcile_work_scope_id_fk": { + "name": "reconcile_work_payload_scope_ref_reconcile_work_scope_id_fk", + "tableFrom": "reconcile_work_payload", + "tableTo": "reconcile_work_scope", + "columnsFrom": ["scope_ref"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reconcile_work_scope": { + "name": "reconcile_work_scope", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "bigint", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "byDefault", + "name": "reconcile_work_scope_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": "1", + "cycle": false + } + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "scope_type": { + "name": "scope_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "scope_id": { + "name": "scope_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "event_ts": { + "name": "event_ts", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "priority": { + "name": "priority", + "type": "smallint", + "primaryKey": false, + "notNull": true, + "default": 100 + }, + "not_before": { + "name": "not_before", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "claimed_by": { + "name": "claimed_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "claimed_until": { + "name": "claimed_until", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "reconcile_work_scope_workspace_id_kind_scope_type_scope_id_index": { + "name": "reconcile_work_scope_workspace_id_kind_scope_type_scope_id_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "reconcile_work_scope_kind_not_before_priority_event_ts_claimed_until_index": { + "name": "reconcile_work_scope_kind_not_before_priority_event_ts_claimed_until_index", + "columns": [ + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "not_before", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "priority", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_ts", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "claimed_until", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy": { + "name": "policy", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "selector": { + "name": "selector", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'true'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_workspace_id_workspace_id_fk": { + "name": "policy_workspace_id_workspace_id_fk", + "tableFrom": "policy", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_any_approval": { + "name": "policy_rule_any_approval", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "min_approvals": { + "name": "min_approvals", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_any_approval_policy_id_policy_id_fk": { + "name": "policy_rule_any_approval_policy_id_policy_id_fk", + "tableFrom": "policy_rule_any_approval", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_deployment_dependency": { + "name": "policy_rule_deployment_dependency", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "depends_on": { + "name": "depends_on", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_deployment_dependency_policy_id_policy_id_fk": { + "name": "policy_rule_deployment_dependency_policy_id_policy_id_fk", + "tableFrom": "policy_rule_deployment_dependency", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_deployment_window": { + "name": "policy_rule_deployment_window", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "allow_window": { + "name": "allow_window", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "duration_minutes": { + "name": "duration_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "rrule": { + "name": "rrule", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_deployment_window_policy_id_policy_id_fk": { + "name": "policy_rule_deployment_window_policy_id_policy_id_fk", + "tableFrom": "policy_rule_deployment_window", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_environment_progression": { + "name": "policy_rule_environment_progression", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "depends_on_environment_selector": { + "name": "depends_on_environment_selector", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "maximum_age_hours": { + "name": "maximum_age_hours", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "minimum_soak_time_minutes": { + "name": "minimum_soak_time_minutes", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "minimum_success_percentage": { + "name": "minimum_success_percentage", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "success_statuses": { + "name": "success_statuses", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_environment_progression_policy_id_policy_id_fk": { + "name": "policy_rule_environment_progression_policy_id_policy_id_fk", + "tableFrom": "policy_rule_environment_progression", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_gradual_rollout": { + "name": "policy_rule_gradual_rollout", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "rollout_type": { + "name": "rollout_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "time_scale_interval": { + "name": "time_scale_interval", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_gradual_rollout_policy_id_policy_id_fk": { + "name": "policy_rule_gradual_rollout_policy_id_policy_id_fk", + "tableFrom": "policy_rule_gradual_rollout", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_retry": { + "name": "policy_rule_retry", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "max_retries": { + "name": "max_retries", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "backoff_seconds": { + "name": "backoff_seconds", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "backoff_strategy": { + "name": "backoff_strategy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "max_backoff_seconds": { + "name": "max_backoff_seconds", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "retry_on_statuses": { + "name": "retry_on_statuses", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_retry_policy_id_policy_id_fk": { + "name": "policy_rule_retry_policy_id_policy_id_fk", + "tableFrom": "policy_rule_retry", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_rollback": { + "name": "policy_rule_rollback", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "on_job_statuses": { + "name": "on_job_statuses", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "on_verification_failure": { + "name": "on_verification_failure", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_rollback_policy_id_policy_id_fk": { + "name": "policy_rule_rollback_policy_id_policy_id_fk", + "tableFrom": "policy_rule_rollback", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_verification": { + "name": "policy_rule_verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "metrics": { + "name": "metrics", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "trigger_on": { + "name": "trigger_on", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_verification_policy_id_policy_id_fk": { + "name": "policy_rule_verification_policy_id_policy_id_fk", + "tableFrom": "policy_rule_verification", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_version_cooldown": { + "name": "policy_rule_version_cooldown", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "interval_seconds": { + "name": "interval_seconds", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_version_cooldown_policy_id_policy_id_fk": { + "name": "policy_rule_version_cooldown_policy_id_policy_id_fk", + "tableFrom": "policy_rule_version_cooldown", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_version_selector": { + "name": "policy_rule_version_selector", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "selector": { + "name": "selector", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_version_selector_policy_id_policy_id_fk": { + "name": "policy_rule_version_selector_policy_id_policy_id_fk", + "tableFrom": "policy_rule_version_selector", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_approval_record": { + "name": "user_approval_record", + "schema": "", + "columns": { + "version_id": { + "name": "version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "user_approval_record_version_id_user_id_environment_id_pk": { + "name": "user_approval_record_version_id_user_id_environment_id_pk", + "columns": ["version_id", "user_id", "environment_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resource_variable": { + "name": "resource_variable", + "schema": "", + "columns": { + "resource_id": { + "name": "resource_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "resource_variable_resource_id_resource_id_fk": { + "name": "resource_variable_resource_id_resource_id_fk", + "tableFrom": "resource_variable", + "tableTo": "resource", + "columnsFrom": ["resource_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "resource_variable_resource_id_key_pk": { + "name": "resource_variable_resource_id_key_pk", + "columns": ["resource_id", "key"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow": { + "name": "workflow", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inputs": { + "name": "inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "jobs": { + "name": "jobs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_workspace_id_workspace_id_fk": { + "name": "workflow_workspace_id_workspace_id_fk", + "tableFrom": "workflow", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_job": { + "name": "workflow_job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_run_id": { + "name": "workflow_run_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "ref": { + "name": "ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "index": { + "name": "index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_job_workflow_run_id_workflow_run_id_fk": { + "name": "workflow_job_workflow_run_id_workflow_run_id_fk", + "tableFrom": "workflow_job", + "tableTo": "workflow_run", + "columnsFrom": ["workflow_run_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_job_template": { + "name": "workflow_job_template", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "ref": { + "name": "ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "if_condition": { + "name": "if_condition", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "matrix": { + "name": "matrix", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_job_template_workflow_id_workflow_id_fk": { + "name": "workflow_job_template_workflow_id_workflow_id_fk", + "tableFrom": "workflow_job_template", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_run": { + "name": "workflow_run", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workflow_id": { + "name": "workflow_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "inputs": { + "name": "inputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "workflow_run_workflow_id_workflow_id_fk": { + "name": "workflow_run_workflow_id_workflow_id_fk", + "tableFrom": "workflow_run", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_verification_metric_measurement": { + "name": "job_verification_metric_measurement", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_verification_metric_status_id": { + "name": "job_verification_metric_status_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "measured_at": { + "name": "measured_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "status": { + "name": "status", + "type": "job_verification_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "job_verification_metric_measurement_job_verification_metric_status_id_job_verification_metric_id_fk": { + "name": "job_verification_metric_measurement_job_verification_metric_status_id_job_verification_metric_id_fk", + "tableFrom": "job_verification_metric_measurement", + "tableTo": "job_verification_metric", + "columnsFrom": ["job_verification_metric_status_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_verification_metric": { + "name": "job_verification_metric", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "interval_seconds": { + "name": "interval_seconds", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "success_condition": { + "name": "success_condition", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "success_threshold": { + "name": "success_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "failure_condition": { + "name": "failure_condition", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "failure_threshold": { + "name": "failure_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.policy_rule_job_verification_metric": { + "name": "policy_rule_job_verification_metric", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "trigger_on": { + "name": "trigger_on", + "type": "job_verification_trigger_on", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'jobSuccess'" + }, + "policy_id": { + "name": "policy_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "interval_seconds": { + "name": "interval_seconds", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "success_condition": { + "name": "success_condition", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "success_threshold": { + "name": "success_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "failure_condition": { + "name": "failure_condition", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'false'" + }, + "failure_threshold": { + "name": "failure_threshold", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "policy_rule_job_verification_metric_policy_id_policy_id_fk": { + "name": "policy_rule_job_verification_metric_policy_id_policy_id_fk", + "tableFrom": "policy_rule_job_verification_metric", + "tableTo": "policy", + "columnsFrom": ["policy_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_agent": { + "name": "job_agent", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + } + }, + "indexes": { + "job_agent_workspace_id_name_index": { + "name": "job_agent_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "job_agent_workspace_id_workspace_id_fk": { + "name": "job_agent_workspace_id_workspace_id_fk", + "tableFrom": "job_agent", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.system_role": { + "name": "system_role", + "schema": "public", + "values": ["user", "admin"] + }, + "public.deployment_version_status": { + "name": "deployment_version_status", + "schema": "public", + "values": [ + "unspecified", + "building", + "ready", + "failed", + "rejected", + "paused" + ] + }, + "public.job_reason": { + "name": "job_reason", + "schema": "public", + "values": [ + "policy_passing", + "policy_override", + "env_policy_override", + "config_policy_override" + ] + }, + "public.job_status": { + "name": "job_status", + "schema": "public", + "values": [ + "cancelled", + "skipped", + "in_progress", + "action_required", + "pending", + "failure", + "invalid_job_agent", + "invalid_integration", + "external_run_not_found", + "successful" + ] + }, + "public.entity_type": { + "name": "entity_type", + "schema": "public", + "values": ["user", "team"] + }, + "public.scope_type": { + "name": "scope_type", + "schema": "public", + "values": [ + "deploymentVersion", + "resource", + "resourceProvider", + "workspace", + "environment", + "system", + "deployment" + ] + }, + "public.job_verification_status": { + "name": "job_verification_status", + "schema": "public", + "values": ["failed", "inconclusive", "passed"] + }, + "public.job_verification_trigger_on": { + "name": "job_verification_trigger_on", + "schema": "public", + "values": ["jobCreated", "jobStarted", "jobSuccess", "jobFailure"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index 5e173e5be..07c9b71e1 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -1093,6 +1093,20 @@ "when": 1772393255000, "tag": "0155_medical_komodo", "breakpoints": true + }, + { + "idx": 156, + "version": "7", + "when": 1772425021332, + "tag": "0156_fine_talkback", + "breakpoints": true + }, + { + "idx": 157, + "version": "7", + "when": 1772425836003, + "tag": "0157_supreme_matthew_murdock", + "breakpoints": true } ] } diff --git a/packages/db/src/schema/job.ts b/packages/db/src/schema/job.ts index 7762fab95..d45dceded 100644 --- a/packages/db/src/schema/job.ts +++ b/packages/db/src/schema/job.ts @@ -73,11 +73,11 @@ export const job = pgTable( .defaultNow() .$onUpdate(() => new Date()), }, - (t) => ({ - idx: index("job_created_at_idx").on(t.createdAt), - statusIdx: index("job_status_idx").on(t.status), - externalIdIdx: index("job_external_id_idx").on(t.externalId), - }), + (t) => [ + index("job_created_at_idx").on(t.createdAt), + index("job_status_idx").on(t.status), + index("job_external_id_idx").on(t.externalId), + ], ); export const jobRelations = relations(job, ({ many, one }) => ({ @@ -99,10 +99,10 @@ export const jobMetadata = pgTable( key: text("key").notNull(), value: text("value").notNull(), }, - (t) => ({ - uniq: uniqueIndex().on(t.key, t.jobId), - jobIdIdx: index("job_metadata_job_id_idx").on(t.jobId), - }), + (t) => [ + uniqueIndex().on(t.key, t.jobId), + index("job_metadata_job_id_idx").on(t.jobId), + ], ); export type JobMetadata = InferSelectModel; diff --git a/packages/db/src/schema/release.ts b/packages/db/src/schema/release.ts index 8a370165c..e624d629d 100644 --- a/packages/db/src/schema/release.ts +++ b/packages/db/src/schema/release.ts @@ -12,34 +12,49 @@ import { import { deploymentVersion } from "./deployment-version.js"; import { deployment } from "./deployment.js"; import { environment } from "./environment.js"; +import { job } from "./job.js"; import { resource } from "./resource.js"; export const release = pgTable("release", { id: uuid("id").primaryKey().defaultRandom(), resourceId: uuid("resource_id") .notNull() - .references(() => resource.id), + .references(() => resource.id, { onDelete: "cascade" }), environmentId: uuid("environment_id") .notNull() - .references(() => environment.id), + .references(() => environment.id, { onDelete: "cascade" }), deploymentId: uuid("deployment_id") .notNull() - .references(() => deployment.id), + .references(() => deployment.id, { onDelete: "cascade" }), versionId: uuid("version_id") .notNull() - .references(() => deploymentVersion.id), + .references(() => deploymentVersion.id, { onDelete: "cascade" }), createdAt: timestamp("created_at", { withTimezone: true }) .notNull() .defaultNow(), }); +export const releaseJob = pgTable( + "release_job", + { + id: uuid("id").primaryKey().defaultRandom(), + jobId: uuid("job_id") + .notNull() + .references(() => job.id, { onDelete: "cascade" }), + releaseId: uuid("release_id") + .notNull() + .references(() => release.id, { onDelete: "cascade" }), + }, + (t) => [uniqueIndex().on(t.releaseId, t.jobId)], +); + export const releaseVariable = pgTable( "release_variable", { id: uuid("id").primaryKey().defaultRandom(), releaseId: uuid("release_id") .notNull() - .references(() => release.id), + .references(() => release.id, { onDelete: "cascade" }), key: text("key").notNull(), value: jsonb("value").notNull(), encrypted: boolean("encrypted").notNull().default(false), From 665efb42b807551c07dbc5e4fdfb25ea7dd8a872 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 2 Mar 2026 11:30:37 -0500 Subject: [PATCH 05/10] feat: enhance job management by adding dispatch context to job schema and related queries; update job retrieval and insertion logic to support new field --- apps/workspace-engine/pkg/db/jobs.sql.go | 149 +++++++++++------- apps/workspace-engine/pkg/db/queries/jobs.sql | 37 ++++- .../pkg/events/handler/jobs/jobs.go | 11 ++ .../releasetargetconcurrency_test.go | 2 +- .../pkg/workspace/store/jobs.go | 5 + .../store/repository/db/jobs/mapper.go | 125 +++++++++++---- .../jobdispatch/setters_postgres.go | 27 +++- .../test/controllers/harness/mocks.go | 2 +- ...ngine_deployment_version_jobs_list_test.go | 3 + 9 files changed, 259 insertions(+), 102 deletions(-) diff --git a/apps/workspace-engine/pkg/db/jobs.sql.go b/apps/workspace-engine/pkg/db/jobs.sql.go index f47ec6f7c..83a891ffd 100644 --- a/apps/workspace-engine/pkg/db/jobs.sql.go +++ b/apps/workspace-engine/pkg/db/jobs.sql.go @@ -36,6 +36,7 @@ SELECT j.job_agent_id, j.job_agent_config, j.external_id, + j.dispatch_context, j.status, j.message, j.created_at, @@ -54,18 +55,19 @@ WHERE j.id = $1 ` type GetJobByIDRow struct { - ID uuid.UUID - JobAgentID uuid.UUID - JobAgentConfig []byte - ExternalID pgtype.Text - Status JobStatus - Message pgtype.Text - CreatedAt pgtype.Timestamptz - StartedAt pgtype.Timestamptz - CompletedAt pgtype.Timestamptz - UpdatedAt pgtype.Timestamptz - ReleaseID uuid.UUID - Metadata []byte + ID uuid.UUID + JobAgentID uuid.UUID + JobAgentConfig []byte + ExternalID pgtype.Text + DispatchContext []byte + Status JobStatus + Message pgtype.Text + CreatedAt pgtype.Timestamptz + StartedAt pgtype.Timestamptz + CompletedAt pgtype.Timestamptz + UpdatedAt pgtype.Timestamptz + ReleaseID uuid.UUID + Metadata []byte } func (q *Queries) GetJobByID(ctx context.Context, id uuid.UUID) (GetJobByIDRow, error) { @@ -76,6 +78,7 @@ func (q *Queries) GetJobByID(ctx context.Context, id uuid.UUID) (GetJobByIDRow, &i.JobAgentID, &i.JobAgentConfig, &i.ExternalID, + &i.DispatchContext, &i.Status, &i.Message, &i.CreatedAt, @@ -103,17 +106,18 @@ func (q *Queries) GetWorkspaceIDByReleaseID(ctx context.Context, id uuid.UUID) ( } const insertJob = `-- name: InsertJob :exec -INSERT INTO job (id, job_agent_id, job_agent_config, status, created_at, updated_at) -VALUES ($1, $2, $3, $4, $5, $6) +INSERT INTO job (id, job_agent_id, job_agent_config, dispatch_context, status, created_at, updated_at) +VALUES ($1, NULLIF($2::UUID, '00000000-0000-0000-0000-000000000000'::UUID), $3, $4, $5, $6, $7) ` type InsertJobParams struct { - ID uuid.UUID - JobAgentID uuid.UUID - JobAgentConfig []byte - Status JobStatus - CreatedAt pgtype.Timestamptz - UpdatedAt pgtype.Timestamptz + ID uuid.UUID + JobAgentID uuid.UUID + JobAgentConfig []byte + DispatchContext []byte + Status JobStatus + CreatedAt pgtype.Timestamptz + UpdatedAt pgtype.Timestamptz } func (q *Queries) InsertJob(ctx context.Context, arg InsertJobParams) error { @@ -121,6 +125,7 @@ func (q *Queries) InsertJob(ctx context.Context, arg InsertJobParams) error { arg.ID, arg.JobAgentID, arg.JobAgentConfig, + arg.DispatchContext, arg.Status, arg.CreatedAt, arg.UpdatedAt, @@ -148,6 +153,7 @@ SELECT j.job_agent_id, j.job_agent_config, j.external_id, + j.dispatch_context, j.status, j.message, j.created_at, @@ -166,18 +172,19 @@ WHERE j.job_agent_id = $1 ` type ListJobsByAgentIDRow struct { - ID uuid.UUID - JobAgentID uuid.UUID - JobAgentConfig []byte - ExternalID pgtype.Text - Status JobStatus - Message pgtype.Text - CreatedAt pgtype.Timestamptz - StartedAt pgtype.Timestamptz - CompletedAt pgtype.Timestamptz - UpdatedAt pgtype.Timestamptz - ReleaseID uuid.UUID - Metadata []byte + ID uuid.UUID + JobAgentID uuid.UUID + JobAgentConfig []byte + ExternalID pgtype.Text + DispatchContext []byte + Status JobStatus + Message pgtype.Text + CreatedAt pgtype.Timestamptz + StartedAt pgtype.Timestamptz + CompletedAt pgtype.Timestamptz + UpdatedAt pgtype.Timestamptz + ReleaseID uuid.UUID + Metadata []byte } func (q *Queries) ListJobsByAgentID(ctx context.Context, jobAgentID uuid.UUID) ([]ListJobsByAgentIDRow, error) { @@ -194,6 +201,7 @@ func (q *Queries) ListJobsByAgentID(ctx context.Context, jobAgentID uuid.UUID) ( &i.JobAgentID, &i.JobAgentConfig, &i.ExternalID, + &i.DispatchContext, &i.Status, &i.Message, &i.CreatedAt, @@ -219,6 +227,7 @@ SELECT j.job_agent_id, j.job_agent_config, j.external_id, + j.dispatch_context, j.status, j.message, j.created_at, @@ -236,21 +245,45 @@ JOIN release_job rj ON rj.job_id = j.id JOIN release r ON r.id = rj.release_id JOIN deployment d ON d.id = r.deployment_id WHERE d.workspace_id = $1 +UNION ALL +SELECT + j.id, + j.job_agent_id, + j.job_agent_config, + j.external_id, + j.dispatch_context, + j.status, + j.message, + j.created_at, + j.started_at, + j.completed_at, + j.updated_at, + '00000000-0000-0000-0000-000000000000'::UUID AS release_id, + COALESCE( + (SELECT json_agg(json_build_object('key', m.key, 'value', m.value)) + FROM job_metadata m WHERE m.job_id = j.id), + '[]' + )::jsonb AS metadata +FROM job j +JOIN job_agent ja ON ja.id = j.job_agent_id +WHERE ja.workspace_id = $1 + AND NOT EXISTS (SELECT 1 FROM release_job rj WHERE rj.job_id = j.id) ` type ListJobsByWorkspaceIDRow struct { - ID uuid.UUID - JobAgentID uuid.UUID - JobAgentConfig []byte - ExternalID pgtype.Text - Status JobStatus - Message pgtype.Text - CreatedAt pgtype.Timestamptz - StartedAt pgtype.Timestamptz - CompletedAt pgtype.Timestamptz - UpdatedAt pgtype.Timestamptz - ReleaseID uuid.UUID - Metadata []byte + ID uuid.UUID + JobAgentID uuid.UUID + JobAgentConfig []byte + ExternalID pgtype.Text + DispatchContext []byte + Status JobStatus + Message pgtype.Text + CreatedAt pgtype.Timestamptz + StartedAt pgtype.Timestamptz + CompletedAt pgtype.Timestamptz + UpdatedAt pgtype.Timestamptz + ReleaseID uuid.UUID + Metadata []byte } func (q *Queries) ListJobsByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) ([]ListJobsByWorkspaceIDRow, error) { @@ -267,6 +300,7 @@ func (q *Queries) ListJobsByWorkspaceID(ctx context.Context, workspaceID uuid.UU &i.JobAgentID, &i.JobAgentConfig, &i.ExternalID, + &i.DispatchContext, &i.Status, &i.Message, &i.CreatedAt, @@ -287,12 +321,13 @@ func (q *Queries) ListJobsByWorkspaceID(ctx context.Context, workspaceID uuid.UU } const upsertJob = `-- name: UpsertJob :exec -INSERT INTO job (id, job_agent_id, job_agent_config, external_id, status, message, created_at, started_at, completed_at, updated_at) -VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) +INSERT INTO job (id, job_agent_id, job_agent_config, external_id, dispatch_context, status, message, created_at, started_at, completed_at, updated_at) +VALUES ($1, NULLIF($2::UUID, '00000000-0000-0000-0000-000000000000'::UUID), $3, $4, $5, $6, $7, $8, $9, $10, $11) ON CONFLICT (id) DO UPDATE SET job_agent_id = EXCLUDED.job_agent_id, job_agent_config = EXCLUDED.job_agent_config, external_id = EXCLUDED.external_id, + dispatch_context = EXCLUDED.dispatch_context, status = EXCLUDED.status, message = EXCLUDED.message, started_at = EXCLUDED.started_at, @@ -301,16 +336,17 @@ SET job_agent_id = EXCLUDED.job_agent_id, ` type UpsertJobParams struct { - ID uuid.UUID - JobAgentID uuid.UUID - JobAgentConfig []byte - ExternalID pgtype.Text - Status JobStatus - Message pgtype.Text - CreatedAt pgtype.Timestamptz - StartedAt pgtype.Timestamptz - CompletedAt pgtype.Timestamptz - UpdatedAt pgtype.Timestamptz + ID uuid.UUID + JobAgentID uuid.UUID + JobAgentConfig []byte + ExternalID pgtype.Text + DispatchContext []byte + Status JobStatus + Message pgtype.Text + CreatedAt pgtype.Timestamptz + StartedAt pgtype.Timestamptz + CompletedAt pgtype.Timestamptz + UpdatedAt pgtype.Timestamptz } func (q *Queries) UpsertJob(ctx context.Context, arg UpsertJobParams) error { @@ -319,6 +355,7 @@ func (q *Queries) UpsertJob(ctx context.Context, arg UpsertJobParams) error { arg.JobAgentID, arg.JobAgentConfig, arg.ExternalID, + arg.DispatchContext, arg.Status, arg.Message, arg.CreatedAt, diff --git a/apps/workspace-engine/pkg/db/queries/jobs.sql b/apps/workspace-engine/pkg/db/queries/jobs.sql index 00bdce42b..a6181a7a0 100644 --- a/apps/workspace-engine/pkg/db/queries/jobs.sql +++ b/apps/workspace-engine/pkg/db/queries/jobs.sql @@ -1,6 +1,6 @@ -- name: InsertJob :exec -INSERT INTO job (id, job_agent_id, job_agent_config, status, created_at, updated_at) -VALUES ($1, $2, $3, $4, $5, $6); +INSERT INTO job (id, job_agent_id, job_agent_config, dispatch_context, status, created_at, updated_at) +VALUES ($1, NULLIF(sqlc.arg('job_agent_id')::UUID, '00000000-0000-0000-0000-000000000000'::UUID), $3, $4, $5, $6, $7); -- name: InsertReleaseJob :exec INSERT INTO release_job (release_id, job_id) VALUES ($1, $2); @@ -17,6 +17,7 @@ SELECT j.job_agent_id, j.job_agent_config, j.external_id, + j.dispatch_context, j.status, j.message, j.created_at, @@ -34,12 +35,13 @@ LEFT JOIN release_job rj ON rj.job_id = j.id WHERE j.id = $1; -- name: UpsertJob :exec -INSERT INTO job (id, job_agent_id, job_agent_config, external_id, status, message, created_at, started_at, completed_at, updated_at) -VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) +INSERT INTO job (id, job_agent_id, job_agent_config, external_id, dispatch_context, status, message, created_at, started_at, completed_at, updated_at) +VALUES ($1, NULLIF(sqlc.arg('job_agent_id')::UUID, '00000000-0000-0000-0000-000000000000'::UUID), $3, $4, $5, $6, $7, $8, $9, $10, $11) ON CONFLICT (id) DO UPDATE SET job_agent_id = EXCLUDED.job_agent_id, job_agent_config = EXCLUDED.job_agent_config, external_id = EXCLUDED.external_id, + dispatch_context = EXCLUDED.dispatch_context, status = EXCLUDED.status, message = EXCLUDED.message, started_at = EXCLUDED.started_at, @@ -64,6 +66,7 @@ SELECT j.job_agent_id, j.job_agent_config, j.external_id, + j.dispatch_context, j.status, j.message, j.created_at, @@ -80,7 +83,30 @@ FROM job j JOIN release_job rj ON rj.job_id = j.id JOIN release r ON r.id = rj.release_id JOIN deployment d ON d.id = r.deployment_id -WHERE d.workspace_id = $1; +WHERE d.workspace_id = $1 +UNION ALL +SELECT + j.id, + j.job_agent_id, + j.job_agent_config, + j.external_id, + j.dispatch_context, + j.status, + j.message, + j.created_at, + j.started_at, + j.completed_at, + j.updated_at, + '00000000-0000-0000-0000-000000000000'::UUID AS release_id, + COALESCE( + (SELECT json_agg(json_build_object('key', m.key, 'value', m.value)) + FROM job_metadata m WHERE m.job_id = j.id), + '[]' + )::jsonb AS metadata +FROM job j +JOIN job_agent ja ON ja.id = j.job_agent_id +WHERE ja.workspace_id = $1 + AND NOT EXISTS (SELECT 1 FROM release_job rj WHERE rj.job_id = j.id); -- name: ListJobsByAgentID :many SELECT @@ -88,6 +114,7 @@ SELECT j.job_agent_id, j.job_agent_config, j.external_id, + j.dispatch_context, j.status, j.message, j.created_at, diff --git a/apps/workspace-engine/pkg/events/handler/jobs/jobs.go b/apps/workspace-engine/pkg/events/handler/jobs/jobs.go index 94cbeb15f..e221a159a 100644 --- a/apps/workspace-engine/pkg/events/handler/jobs/jobs.go +++ b/apps/workspace-engine/pkg/events/handler/jobs/jobs.go @@ -21,6 +21,17 @@ func HandleJobUpdated( return err } + // When a bare *oapi.Job is pushed (no wrapping "job" key), the + // JobUpdateEvent.Job field stays zero-valued because UnmarshalJSON + // only populates it from a "job" key. Fall back to interpreting the + // entire payload as a Job so status updates persist in DB-backed mode. + if jobUpdateEvent.Job.Id == "" { + var bareJob oapi.Job + if err := json.Unmarshal(event.Data, &bareJob); err == nil && bareJob.Id != "" { + jobUpdateEvent.Job = bareJob + } + } + job, exists := getJob(ws, jobUpdateEvent) if !exists { return nil diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go index 3f21870f8..6d71f8a7c 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/policy/evaluator/releasetargetconcurrency/releasetargetconcurrency_test.go @@ -40,7 +40,7 @@ func TestReleaseTargetConcurrencyEvaluator_NoActiveJobs(t *testing.T) { eval := NewReleaseTargetConcurrencyEvaluator(st) release := &oapi.Release{ - Id: uuid.New().String(), + Id: uuid.New().String(), ReleaseTarget: oapi.ReleaseTarget{ DeploymentId: "deployment-1", EnvironmentId: "env-1", diff --git a/apps/workspace-engine/pkg/workspace/store/jobs.go b/apps/workspace-engine/pkg/workspace/store/jobs.go index 3f8d38e24..d22227948 100644 --- a/apps/workspace-engine/pkg/workspace/store/jobs.go +++ b/apps/workspace-engine/pkg/workspace/store/jobs.go @@ -170,6 +170,11 @@ func (j *Jobs) GetByWorkflowJobId(workflowJobId string) []*oapi.Job { for _, job := range j.repo.Items() { if job.WorkflowJobId == workflowJobId { jobs = append(jobs, job) + continue + } + if job.DispatchContext != nil && job.DispatchContext.WorkflowJob != nil && + job.DispatchContext.WorkflowJob.Id == workflowJobId { + jobs = append(jobs, job) } } return jobs diff --git a/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go b/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go index d7db30338..402248fc7 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go @@ -13,24 +13,26 @@ import ( ) type jobRow struct { - ID uuid.UUID - JobAgentID uuid.UUID - JobAgentConfig []byte - ExternalID pgtype.Text - Status db.JobStatus - Message pgtype.Text - CreatedAt pgtype.Timestamptz - StartedAt pgtype.Timestamptz - CompletedAt pgtype.Timestamptz - UpdatedAt pgtype.Timestamptz - ReleaseID uuid.UUID - Metadata []byte + ID uuid.UUID + JobAgentID uuid.UUID + JobAgentConfig []byte + ExternalID pgtype.Text + DispatchContext []byte + Status db.JobStatus + Message pgtype.Text + CreatedAt pgtype.Timestamptz + StartedAt pgtype.Timestamptz + CompletedAt pgtype.Timestamptz + UpdatedAt pgtype.Timestamptz + ReleaseID uuid.UUID + Metadata []byte } func fromGetRow(r db.GetJobByIDRow) jobRow { return jobRow{ ID: r.ID, JobAgentID: r.JobAgentID, JobAgentConfig: r.JobAgentConfig, - ExternalID: r.ExternalID, Status: r.Status, Message: r.Message, + ExternalID: r.ExternalID, DispatchContext: r.DispatchContext, + Status: r.Status, Message: r.Message, CreatedAt: r.CreatedAt, StartedAt: r.StartedAt, CompletedAt: r.CompletedAt, UpdatedAt: r.UpdatedAt, ReleaseID: r.ReleaseID, Metadata: r.Metadata, } @@ -39,7 +41,8 @@ func fromGetRow(r db.GetJobByIDRow) jobRow { func fromWorkspaceRow(r db.ListJobsByWorkspaceIDRow) jobRow { return jobRow{ ID: r.ID, JobAgentID: r.JobAgentID, JobAgentConfig: r.JobAgentConfig, - ExternalID: r.ExternalID, Status: r.Status, Message: r.Message, + ExternalID: r.ExternalID, DispatchContext: r.DispatchContext, + Status: r.Status, Message: r.Message, CreatedAt: r.CreatedAt, StartedAt: r.StartedAt, CompletedAt: r.CompletedAt, UpdatedAt: r.UpdatedAt, ReleaseID: r.ReleaseID, Metadata: r.Metadata, } @@ -48,7 +51,8 @@ func fromWorkspaceRow(r db.ListJobsByWorkspaceIDRow) jobRow { func fromAgentRow(r db.ListJobsByAgentIDRow) jobRow { return jobRow{ ID: r.ID, JobAgentID: r.JobAgentID, JobAgentConfig: r.JobAgentConfig, - ExternalID: r.ExternalID, Status: r.Status, Message: r.Message, + ExternalID: r.ExternalID, DispatchContext: r.DispatchContext, + Status: r.Status, Message: r.Message, CreatedAt: r.CreatedAt, StartedAt: r.StartedAt, CompletedAt: r.CompletedAt, UpdatedAt: r.UpdatedAt, ReleaseID: r.ReleaseID, Metadata: r.Metadata, } @@ -59,6 +63,34 @@ type metadataEntry struct { Value string `json:"value"` } +// OapiToDBStatus maps OpenAPI camelCase job statuses to Postgres snake_case enum values. +var OapiToDBStatus = map[oapi.JobStatus]db.JobStatus{ + oapi.JobStatusCancelled: db.JobStatusCancelled, + oapi.JobStatusSkipped: db.JobStatusSkipped, + oapi.JobStatusInProgress: db.JobStatusInProgress, + oapi.JobStatusActionRequired: db.JobStatusActionRequired, + oapi.JobStatusPending: db.JobStatusPending, + oapi.JobStatusFailure: db.JobStatusFailure, + oapi.JobStatusInvalidJobAgent: db.JobStatusInvalidJobAgent, + oapi.JobStatusInvalidIntegration: db.JobStatusInvalidIntegration, + oapi.JobStatusExternalRunNotFound: db.JobStatusExternalRunNotFound, + oapi.JobStatusSuccessful: db.JobStatusSuccessful, +} + +// DBToOapiStatus maps Postgres snake_case enum values to OpenAPI camelCase job statuses. +var DBToOapiStatus = map[db.JobStatus]oapi.JobStatus{ + db.JobStatusCancelled: oapi.JobStatusCancelled, + db.JobStatusSkipped: oapi.JobStatusSkipped, + db.JobStatusInProgress: oapi.JobStatusInProgress, + db.JobStatusActionRequired: oapi.JobStatusActionRequired, + db.JobStatusPending: oapi.JobStatusPending, + db.JobStatusFailure: oapi.JobStatusFailure, + db.JobStatusInvalidJobAgent: oapi.JobStatusInvalidJobAgent, + db.JobStatusInvalidIntegration: oapi.JobStatusInvalidIntegration, + db.JobStatusExternalRunNotFound: oapi.JobStatusExternalRunNotFound, + db.JobStatusSuccessful: oapi.JobStatusSuccessful, +} + func ToOapi(row jobRow) *oapi.Job { config := make(oapi.JobAgentConfig) if len(row.JobAgentConfig) > 0 { @@ -75,15 +107,29 @@ func ToOapi(row jobRow) *oapi.Job { } } + var dc *oapi.DispatchContext + if len(row.DispatchContext) > 0 && string(row.DispatchContext) != "{}" { + dc = &oapi.DispatchContext{} + if err := json.Unmarshal(row.DispatchContext, dc); err != nil { + dc = nil + } + } + + var jobAgentId string + if row.JobAgentID != uuid.Nil { + jobAgentId = row.JobAgentID.String() + } + j := &oapi.Job{ - Id: row.ID.String(), - JobAgentId: row.JobAgentID.String(), - JobAgentConfig: config, - Status: oapi.JobStatus(row.Status), - ReleaseId: row.ReleaseID.String(), - Metadata: metadata, - CreatedAt: row.CreatedAt.Time, - UpdatedAt: row.UpdatedAt.Time, + Id: row.ID.String(), + JobAgentId: jobAgentId, + JobAgentConfig: config, + DispatchContext: dc, + Status: DBToOapiStatus[row.Status], + ReleaseId: row.ReleaseID.String(), + Metadata: metadata, + CreatedAt: row.CreatedAt.Time, + UpdatedAt: row.UpdatedAt.Time, } if row.ExternalID.Valid { @@ -101,6 +147,10 @@ func ToOapi(row jobRow) *oapi.Job { j.CompletedAt = &t } + if dc != nil && dc.WorkflowJob != nil && j.WorkflowJobId == "" { + j.WorkflowJobId = dc.WorkflowJob.Id + } + return j } @@ -110,9 +160,12 @@ func ToUpsertParams(j *oapi.Job) (db.UpsertJobParams, error) { return db.UpsertJobParams{}, fmt.Errorf("parse job id: %w", err) } - agentID, err := uuid.Parse(j.JobAgentId) - if err != nil { - return db.UpsertJobParams{}, fmt.Errorf("parse job_agent_id: %w", err) + var agentID uuid.UUID + if j.JobAgentId != "" { + agentID, err = uuid.Parse(j.JobAgentId) + if err != nil { + return db.UpsertJobParams{}, fmt.Errorf("parse job_agent_id: %w", err) + } } agentConfig, err := json.Marshal(j.JobAgentConfig) @@ -120,13 +173,21 @@ func ToUpsertParams(j *oapi.Job) (db.UpsertJobParams, error) { return db.UpsertJobParams{}, fmt.Errorf("marshal job_agent_config: %w", err) } + dcBytes := []byte("{}") + if j.DispatchContext != nil { + if b, err := json.Marshal(j.DispatchContext); err == nil { + dcBytes = b + } + } + params := db.UpsertJobParams{ - ID: id, - JobAgentID: agentID, - JobAgentConfig: agentConfig, - Status: db.JobStatus(j.Status), - CreatedAt: pgtype.Timestamptz{Time: j.CreatedAt, Valid: !j.CreatedAt.IsZero()}, - UpdatedAt: pgtype.Timestamptz{Time: j.UpdatedAt, Valid: !j.UpdatedAt.IsZero()}, + ID: id, + JobAgentID: agentID, + JobAgentConfig: agentConfig, + DispatchContext: dcBytes, + Status: OapiToDBStatus[j.Status], + CreatedAt: pgtype.Timestamptz{Time: j.CreatedAt, Valid: !j.CreatedAt.IsZero()}, + UpdatedAt: pgtype.Timestamptz{Time: j.UpdatedAt, Valid: !j.UpdatedAt.IsZero()}, } if j.ExternalId != nil { diff --git a/apps/workspace-engine/svc/controllers/jobdispatch/setters_postgres.go b/apps/workspace-engine/svc/controllers/jobdispatch/setters_postgres.go index 4a65ca94b..d8d6886ff 100644 --- a/apps/workspace-engine/svc/controllers/jobdispatch/setters_postgres.go +++ b/apps/workspace-engine/svc/controllers/jobdispatch/setters_postgres.go @@ -8,6 +8,7 @@ import ( "workspace-engine/pkg/db" "workspace-engine/pkg/oapi" "workspace-engine/pkg/reconcile" + jobsmapper "workspace-engine/pkg/workspace/store/repository/db/jobs" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" @@ -36,20 +37,32 @@ func (s *PostgresSetter) CreateJobWithVerification(ctx context.Context, job *oap jobID := uuid.MustParse(job.Id) releaseID := uuid.MustParse(job.ReleaseId) - agentID := uuid.MustParse(job.JobAgentId) + + var agentID uuid.UUID + if job.JobAgentId != "" { + agentID = uuid.MustParse(job.JobAgentId) + } agentConfig, err := json.Marshal(job.JobAgentConfig) if err != nil { return fmt.Errorf("marshal job agent config: %w", err) } + dcBytes := []byte("{}") + if job.DispatchContext != nil { + if b, marshalErr := json.Marshal(job.DispatchContext); marshalErr == nil { + dcBytes = b + } + } + if err := queries.InsertJob(ctx, db.InsertJobParams{ - ID: jobID, - JobAgentID: agentID, - JobAgentConfig: agentConfig, - Status: db.JobStatus(job.Status), - CreatedAt: pgtype.Timestamptz{Time: job.CreatedAt, Valid: true}, - UpdatedAt: pgtype.Timestamptz{Time: job.UpdatedAt, Valid: true}, + ID: jobID, + JobAgentID: agentID, + JobAgentConfig: agentConfig, + DispatchContext: dcBytes, + Status: jobsmapper.OapiToDBStatus[job.Status], + CreatedAt: pgtype.Timestamptz{Time: job.CreatedAt, Valid: true}, + UpdatedAt: pgtype.Timestamptz{Time: job.UpdatedAt, Valid: true}, }); err != nil { return fmt.Errorf("insert job: %w", err) } diff --git a/apps/workspace-engine/test/controllers/harness/mocks.go b/apps/workspace-engine/test/controllers/harness/mocks.go index c232f3fe9..e2dad1686 100644 --- a/apps/workspace-engine/test/controllers/harness/mocks.go +++ b/apps/workspace-engine/test/controllers/harness/mocks.go @@ -63,7 +63,7 @@ func (s *SelectorEvalSetter) SetComputedDeploymentResources(_ context.Context, _ // DesiredReleaseGetter implements desiredrelease.Getter. type DesiredReleaseGetter struct { - Scope *evaluator.EvaluatorScope + Scope *evaluator.EvaluatorScope Versions []*oapi.DeploymentVersion Policies []*oapi.Policy ApprovalRecords []*oapi.UserApprovalRecord diff --git a/apps/workspace-engine/test/e2e/engine_deployment_version_jobs_list_test.go b/apps/workspace-engine/test/e2e/engine_deployment_version_jobs_list_test.go index 517a640ee..6c89efa50 100644 --- a/apps/workspace-engine/test/e2e/engine_deployment_version_jobs_list_test.go +++ b/apps/workspace-engine/test/e2e/engine_deployment_version_jobs_list_test.go @@ -1,6 +1,7 @@ package e2e import ( + "context" "reflect" "sort" "testing" @@ -189,6 +190,7 @@ func TestEngine_DeploymentVersionJobsList_SortingOrder(t *testing.T) { baseTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC) timestampIndex := 0 + ctx := context.Background() for _, rt := range releaseTargets { resource, _ := ws.Resources().Get(rt.ResourceId) jobs := ws.Jobs().GetJobsForReleaseTarget(rt) @@ -206,6 +208,7 @@ func TestEngine_DeploymentVersionJobsList_SortingOrder(t *testing.T) { job.CreatedAt = baseTime.Add(time.Duration(timestampIndex) * time.Millisecond) } timestampIndex++ + ws.Jobs().Upsert(ctx, job) } } From e8050b8efcdb792282748b5a08d1d662c2b2fcdd Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 2 Mar 2026 12:32:31 -0500 Subject: [PATCH 06/10] feat: add ListJobsByReleaseID query and related data structures to enhance job retrieval by release ID; implement GetByReleaseID method in job repository --- apps/workspace-engine/pkg/db/jobs.sql.go | 74 +++++++++++++++++++ apps/workspace-engine/pkg/db/queries/jobs.sql | 23 ++++++ .../pkg/workspace/releasemanager/manager.go | 1 - .../pkg/workspace/store/releases.go | 2 +- .../store/repository/db/jobs/mapper.go | 10 +++ .../store/repository/db/jobs/repo.go | 18 +++++ .../workspace/store/repository/interfaces.go | 1 + .../workspace/store/repository/memory/repo.go | 4 + .../test/integration/dbtest.go | 2 +- 9 files changed, 132 insertions(+), 3 deletions(-) diff --git a/apps/workspace-engine/pkg/db/jobs.sql.go b/apps/workspace-engine/pkg/db/jobs.sql.go index 83a891ffd..9ef40e7e4 100644 --- a/apps/workspace-engine/pkg/db/jobs.sql.go +++ b/apps/workspace-engine/pkg/db/jobs.sql.go @@ -221,6 +221,80 @@ func (q *Queries) ListJobsByAgentID(ctx context.Context, jobAgentID uuid.UUID) ( return items, nil } +const listJobsByReleaseID = `-- name: ListJobsByReleaseID :many +SELECT + j.id, + j.job_agent_id, + j.job_agent_config, + j.external_id, + j.dispatch_context, + j.status, + j.message, + j.created_at, + j.started_at, + j.completed_at, + j.updated_at, + rj.release_id, + COALESCE( + (SELECT json_agg(json_build_object('key', m.key, 'value', m.value)) + FROM job_metadata m WHERE m.job_id = j.id), + '[]' + )::jsonb AS metadata +FROM job j +JOIN release_job rj ON rj.job_id = j.id +WHERE rj.release_id = $1 +` + +type ListJobsByReleaseIDRow struct { + ID uuid.UUID + JobAgentID uuid.UUID + JobAgentConfig []byte + ExternalID pgtype.Text + DispatchContext []byte + Status JobStatus + Message pgtype.Text + CreatedAt pgtype.Timestamptz + StartedAt pgtype.Timestamptz + CompletedAt pgtype.Timestamptz + UpdatedAt pgtype.Timestamptz + ReleaseID uuid.UUID + Metadata []byte +} + +func (q *Queries) ListJobsByReleaseID(ctx context.Context, releaseID uuid.UUID) ([]ListJobsByReleaseIDRow, error) { + rows, err := q.db.Query(ctx, listJobsByReleaseID, releaseID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []ListJobsByReleaseIDRow + for rows.Next() { + var i ListJobsByReleaseIDRow + if err := rows.Scan( + &i.ID, + &i.JobAgentID, + &i.JobAgentConfig, + &i.ExternalID, + &i.DispatchContext, + &i.Status, + &i.Message, + &i.CreatedAt, + &i.StartedAt, + &i.CompletedAt, + &i.UpdatedAt, + &i.ReleaseID, + &i.Metadata, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const listJobsByWorkspaceID = `-- name: ListJobsByWorkspaceID :many SELECT j.id, diff --git a/apps/workspace-engine/pkg/db/queries/jobs.sql b/apps/workspace-engine/pkg/db/queries/jobs.sql index a6181a7a0..0d0a5b95a 100644 --- a/apps/workspace-engine/pkg/db/queries/jobs.sql +++ b/apps/workspace-engine/pkg/db/queries/jobs.sql @@ -108,6 +108,29 @@ JOIN job_agent ja ON ja.id = j.job_agent_id WHERE ja.workspace_id = $1 AND NOT EXISTS (SELECT 1 FROM release_job rj WHERE rj.job_id = j.id); +-- name: ListJobsByReleaseID :many +SELECT + j.id, + j.job_agent_id, + j.job_agent_config, + j.external_id, + j.dispatch_context, + j.status, + j.message, + j.created_at, + j.started_at, + j.completed_at, + j.updated_at, + rj.release_id, + COALESCE( + (SELECT json_agg(json_build_object('key', m.key, 'value', m.value)) + FROM job_metadata m WHERE m.job_id = j.id), + '[]' + )::jsonb AS metadata +FROM job j +JOIN release_job rj ON rj.job_id = j.id +WHERE rj.release_id = $1; + -- name: ListJobsByAgentID :many SELECT j.id, diff --git a/apps/workspace-engine/pkg/workspace/releasemanager/manager.go b/apps/workspace-engine/pkg/workspace/releasemanager/manager.go index 65cf9980c..4c5b76a23 100644 --- a/apps/workspace-engine/pkg/workspace/releasemanager/manager.go +++ b/apps/workspace-engine/pkg/workspace/releasemanager/manager.go @@ -152,7 +152,6 @@ func (m *Manager) ProcessChanges(ctx context.Context, changes *statechange.Chang job.Status = oapi.JobStatusCancelled job.UpdatedAt = time.Now() m.store.Jobs.Upsert(ctx, job) - fmt.Printf("cancelled job: %+v\n", job) jobsCancelled++ } } diff --git a/apps/workspace-engine/pkg/workspace/store/releases.go b/apps/workspace-engine/pkg/workspace/store/releases.go index e54806e2a..45f2e1ddf 100644 --- a/apps/workspace-engine/pkg/workspace/store/releases.go +++ b/apps/workspace-engine/pkg/workspace/store/releases.go @@ -55,7 +55,7 @@ func (r *Releases) Remove(ctx context.Context, id string) { func (r *Releases) Jobs(releaseId string) map[string]*oapi.Job { jobs := make(map[string]*oapi.Job) - jobItems, err := r.store.repo.Jobs.GetBy("release_id", releaseId) + jobItems, err := r.store.Jobs.repo.GetByReleaseID(releaseId) if err != nil { return jobs } diff --git a/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go b/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go index 402248fc7..1e8b4d93b 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/mapper.go @@ -48,6 +48,16 @@ func fromWorkspaceRow(r db.ListJobsByWorkspaceIDRow) jobRow { } } +func fromReleaseRow(r db.ListJobsByReleaseIDRow) jobRow { + return jobRow{ + ID: r.ID, JobAgentID: r.JobAgentID, JobAgentConfig: r.JobAgentConfig, + ExternalID: r.ExternalID, DispatchContext: r.DispatchContext, + Status: r.Status, Message: r.Message, + CreatedAt: r.CreatedAt, StartedAt: r.StartedAt, CompletedAt: r.CompletedAt, + UpdatedAt: r.UpdatedAt, ReleaseID: r.ReleaseID, Metadata: r.Metadata, + } +} + func fromAgentRow(r db.ListJobsByAgentIDRow) jobRow { return jobRow{ ID: r.ID, JobAgentID: r.JobAgentID, JobAgentConfig: r.JobAgentConfig, diff --git a/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/repo.go b/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/repo.go index 37150ee6c..a92ce60cc 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/repo.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/db/jobs/repo.go @@ -104,6 +104,24 @@ func (r *Repo) Items() map[string]*oapi.Job { return result } +func (r *Repo) GetByReleaseID(releaseID string) ([]*oapi.Job, error) { + uid, err := uuid.Parse(releaseID) + if err != nil { + return nil, fmt.Errorf("parse release id: %w", err) + } + + rows, err := db.GetQueries(r.ctx).ListJobsByReleaseID(r.ctx, uid) + if err != nil { + return nil, fmt.Errorf("list jobs by release: %w", err) + } + + result := make([]*oapi.Job, 0, len(rows)) + for _, row := range rows { + result = append(result, ToOapi(fromReleaseRow(row))) + } + return result, nil +} + func (r *Repo) GetByAgentID(agentID string) ([]*oapi.Job, error) { uid, err := uuid.Parse(agentID) if err != nil { diff --git a/apps/workspace-engine/pkg/workspace/store/repository/interfaces.go b/apps/workspace-engine/pkg/workspace/store/repository/interfaces.go index 7441e564e..32ca46d1b 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/interfaces.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/interfaces.go @@ -176,6 +176,7 @@ type JobRepo interface { Remove(id string) error Items() map[string]*oapi.Job GetByAgentID(agentID string) ([]*oapi.Job, error) + GetByReleaseID(releaseID string) ([]*oapi.Job, error) } // ResourceVariableRepo defines the contract for resource variable storage. diff --git a/apps/workspace-engine/pkg/workspace/store/repository/memory/repo.go b/apps/workspace-engine/pkg/workspace/store/repository/memory/repo.go index 571d382a1..2f0a8a9a9 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/memory/repo.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/memory/repo.go @@ -705,6 +705,10 @@ func (a *jobRepoAdapter) GetByAgentID(agentID string) ([]*oapi.Job, error) { return a.store.GetBy("job_agent_id", agentID) } +func (a *jobRepoAdapter) GetByReleaseID(releaseID string) ([]*oapi.Job, error) { + return a.store.GetBy("release_id", releaseID) +} + func (s *InMemory) JobsRepo() repository.JobRepo { return &jobRepoAdapter{store: s.Jobs} } diff --git a/apps/workspace-engine/test/integration/dbtest.go b/apps/workspace-engine/test/integration/dbtest.go index 970075755..0b9219594 100644 --- a/apps/workspace-engine/test/integration/dbtest.go +++ b/apps/workspace-engine/test/integration/dbtest.go @@ -88,7 +88,7 @@ func newDBTestWorkspace(t *testing.T, options ...WorkspaceOption) *TestWorkspace store.WithDBWorkflowJobs(ctx), store.WithDBResourceVariables(ctx), store.WithDBReleases(ctx), - // store.WithDBJobs(ctx), + store.WithDBJobs(ctx), ), ) From 97a221e84f469ceb0cb028d664c7b398ea7ec06c Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Mon, 2 Mar 2026 11:04:59 -0800 Subject: [PATCH 07/10] fix: drop version status in db package --- apps/workspace-engine/pkg/db/models.go | 1 - .../pkg/db/queries/releases.sql | 9 ++++---- .../pkg/db/queries/schema.sql | 1 - apps/workspace-engine/pkg/db/releases.sql.go | 21 +++++++------------ .../store/repository/db/releases/mapper.go | 12 ++--------- .../e2e/engine_policy_paused_versions_test.go | 6 +----- 6 files changed, 14 insertions(+), 36 deletions(-) diff --git a/apps/workspace-engine/pkg/db/models.go b/apps/workspace-engine/pkg/db/models.go index 812878dc3..839400333 100644 --- a/apps/workspace-engine/pkg/db/models.go +++ b/apps/workspace-engine/pkg/db/models.go @@ -483,7 +483,6 @@ type Release struct { EnvironmentID uuid.UUID DeploymentID uuid.UUID VersionID uuid.UUID - VersionStatus pgtype.Text CreatedAt pgtype.Timestamptz } diff --git a/apps/workspace-engine/pkg/db/queries/releases.sql b/apps/workspace-engine/pkg/db/queries/releases.sql index d2e63ae54..532b3e15e 100644 --- a/apps/workspace-engine/pkg/db/queries/releases.sql +++ b/apps/workspace-engine/pkg/db/queries/releases.sql @@ -6,7 +6,7 @@ SELECT * FROM release WHERE resource_id = $1 AND environment_id = $2 AND deployment_id = $3; -- name: ListReleasesByWorkspaceID :many -SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.version_status, r.created_at +SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.created_at FROM release r JOIN deployment d ON d.id = r.deployment_id WHERE d.workspace_id = $1 @@ -16,14 +16,13 @@ LIMIT COALESCE(sqlc.narg('limit')::int, 5000); SELECT * FROM release_variable WHERE release_id = $1; -- name: UpsertRelease :one -INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, version_status, created_at) -VALUES ($1, $2, $3, $4, $5, $6, COALESCE(sqlc.narg('created_at')::timestamptz, NOW())) +INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, created_at) +VALUES ($1, $2, $3, $4, $5, COALESCE(sqlc.narg('created_at')::timestamptz, NOW())) ON CONFLICT (id) DO UPDATE SET resource_id = EXCLUDED.resource_id, environment_id = EXCLUDED.environment_id, deployment_id = EXCLUDED.deployment_id, - version_id = EXCLUDED.version_id, - version_status = EXCLUDED.version_status + version_id = EXCLUDED.version_id RETURNING *; -- name: UpsertReleaseVariable :one diff --git a/apps/workspace-engine/pkg/db/queries/schema.sql b/apps/workspace-engine/pkg/db/queries/schema.sql index 2817c7a3b..e05daa1b6 100644 --- a/apps/workspace-engine/pkg/db/queries/schema.sql +++ b/apps/workspace-engine/pkg/db/queries/schema.sql @@ -113,7 +113,6 @@ CREATE TABLE release ( environment_id UUID NOT NULL, deployment_id UUID NOT NULL, version_id UUID NOT NULL, - version_status TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); diff --git a/apps/workspace-engine/pkg/db/releases.sql.go b/apps/workspace-engine/pkg/db/releases.sql.go index a7b8b9f2e..7bca8133c 100644 --- a/apps/workspace-engine/pkg/db/releases.sql.go +++ b/apps/workspace-engine/pkg/db/releases.sql.go @@ -31,7 +31,7 @@ func (q *Queries) DeleteReleaseVariablesByReleaseID(ctx context.Context, release } const getReleaseByID = `-- name: GetReleaseByID :one -SELECT id, resource_id, environment_id, deployment_id, version_id, version_status, created_at FROM release WHERE id = $1 +SELECT id, resource_id, environment_id, deployment_id, version_id, created_at FROM release WHERE id = $1 ` func (q *Queries) GetReleaseByID(ctx context.Context, id uuid.UUID) (Release, error) { @@ -43,7 +43,6 @@ func (q *Queries) GetReleaseByID(ctx context.Context, id uuid.UUID) (Release, er &i.EnvironmentID, &i.DeploymentID, &i.VersionID, - &i.VersionStatus, &i.CreatedAt, ) return i, err @@ -81,7 +80,7 @@ func (q *Queries) GetReleaseVariablesByReleaseID(ctx context.Context, releaseID } const listReleasesByReleaseTarget = `-- name: ListReleasesByReleaseTarget :many -SELECT id, resource_id, environment_id, deployment_id, version_id, version_status, created_at FROM release +SELECT id, resource_id, environment_id, deployment_id, version_id, created_at FROM release WHERE resource_id = $1 AND environment_id = $2 AND deployment_id = $3 ` @@ -106,7 +105,6 @@ func (q *Queries) ListReleasesByReleaseTarget(ctx context.Context, arg ListRelea &i.EnvironmentID, &i.DeploymentID, &i.VersionID, - &i.VersionStatus, &i.CreatedAt, ); err != nil { return nil, err @@ -120,7 +118,7 @@ func (q *Queries) ListReleasesByReleaseTarget(ctx context.Context, arg ListRelea } const listReleasesByWorkspaceID = `-- name: ListReleasesByWorkspaceID :many -SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.version_status, r.created_at +SELECT r.id, r.resource_id, r.environment_id, r.deployment_id, r.version_id, r.created_at FROM release r JOIN deployment d ON d.id = r.deployment_id WHERE d.workspace_id = $1 @@ -147,7 +145,6 @@ func (q *Queries) ListReleasesByWorkspaceID(ctx context.Context, arg ListRelease &i.EnvironmentID, &i.DeploymentID, &i.VersionID, - &i.VersionStatus, &i.CreatedAt, ); err != nil { return nil, err @@ -161,15 +158,14 @@ func (q *Queries) ListReleasesByWorkspaceID(ctx context.Context, arg ListRelease } const upsertRelease = `-- name: UpsertRelease :one -INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, version_status, created_at) -VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7::timestamptz, NOW())) +INSERT INTO release (id, resource_id, environment_id, deployment_id, version_id, created_at) +VALUES ($1, $2, $3, $4, $5, COALESCE($6::timestamptz, NOW())) ON CONFLICT (id) DO UPDATE SET resource_id = EXCLUDED.resource_id, environment_id = EXCLUDED.environment_id, deployment_id = EXCLUDED.deployment_id, - version_id = EXCLUDED.version_id, - version_status = EXCLUDED.version_status -RETURNING id, resource_id, environment_id, deployment_id, version_id, version_status, created_at + version_id = EXCLUDED.version_id +RETURNING id, resource_id, environment_id, deployment_id, version_id, created_at ` type UpsertReleaseParams struct { @@ -178,7 +174,6 @@ type UpsertReleaseParams struct { EnvironmentID uuid.UUID DeploymentID uuid.UUID VersionID uuid.UUID - VersionStatus pgtype.Text CreatedAt pgtype.Timestamptz } @@ -189,7 +184,6 @@ func (q *Queries) UpsertRelease(ctx context.Context, arg UpsertReleaseParams) (R arg.EnvironmentID, arg.DeploymentID, arg.VersionID, - arg.VersionStatus, arg.CreatedAt, ) var i Release @@ -199,7 +193,6 @@ func (q *Queries) UpsertRelease(ctx context.Context, arg UpsertReleaseParams) (R &i.EnvironmentID, &i.DeploymentID, &i.VersionID, - &i.VersionStatus, &i.CreatedAt, ) return i, err diff --git a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go index d8f2878e4..7a8032809 100644 --- a/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go +++ b/apps/workspace-engine/pkg/workspace/store/repository/db/releases/mapper.go @@ -12,9 +12,7 @@ import ( ) // ToOapi converts a db.Release row, its associated deployment version, and -// its variables into an oapi.Release. The version_status stored on the release -// row overrides the live deployment version status to preserve the snapshot -// captured at release creation time. +// its variables into an oapi.Release. func ToOapi( row db.Release, version *oapi.DeploymentVersion, @@ -37,11 +35,6 @@ func ToOapi( createdAt = row.CreatedAt.Time.Format(time.RFC3339) } - snapshotVersion := *version - if row.VersionStatus.Valid { - snapshotVersion.Status = oapi.DeploymentVersionStatus(row.VersionStatus.String) - } - return &oapi.Release{ Id: row.ID.String(), CreatedAt: createdAt, @@ -52,7 +45,7 @@ func ToOapi( DeploymentId: row.DeploymentID.String(), }, Variables: variables, - Version: snapshotVersion, + Version: *version, } } @@ -92,7 +85,6 @@ func ToUpsertParams(release *oapi.Release) (db.UpsertReleaseParams, error) { EnvironmentID: environmentID, DeploymentID: deploymentID, VersionID: versionID, - VersionStatus: pgtype.Text{String: string(release.Version.Status), Valid: true}, CreatedAt: createdAt, }, nil } diff --git a/apps/workspace-engine/test/e2e/engine_policy_paused_versions_test.go b/apps/workspace-engine/test/e2e/engine_policy_paused_versions_test.go index 2620b3b50..96c5a73fe 100644 --- a/apps/workspace-engine/test/e2e/engine_policy_paused_versions_test.go +++ b/apps/workspace-engine/test/e2e/engine_policy_paused_versions_test.go @@ -135,14 +135,10 @@ func TestEngine_PausedVersionWithExistingRelease(t *testing.T) { // Note: Releases capture a snapshot of the version at creation time. // They do not automatically update when the source version status changes. for _, releaseID := range releaseIDs { - release, ok := engine.Workspace().Releases().Get(releaseID) + _, ok := engine.Workspace().Releases().Get(releaseID) if !ok { t.Errorf("expected release %s to still exist after version paused", releaseID) } - // Release version is a snapshot - will still show "ready" even though source version is paused - if release.Version.Status != oapi.DeploymentVersionStatusReady { - t.Errorf("expected release version status to remain ready (snapshot), got %s", release.Version.Status) - } } // Verify jobs still exist (pausing doesn't delete existing jobs) From 19cc8e0abc8287acfe867719a1c0ab623725c007 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Mon, 2 Mar 2026 13:01:08 -0800 Subject: [PATCH 08/10] chore: update sdk --- packages/workspace-engine-sdk/src/schema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/workspace-engine-sdk/src/schema.ts b/packages/workspace-engine-sdk/src/schema.ts index a189574c5..9e861ed84 100644 --- a/packages/workspace-engine-sdk/src/schema.ts +++ b/packages/workspace-engine-sdk/src/schema.ts @@ -1879,6 +1879,7 @@ export interface components { Release: { createdAt: string; encryptedVariables: string[]; + id: string; releaseTarget: components["schemas"]["ReleaseTarget"]; variables: { [key: string]: components["schemas"]["LiteralValue"]; From b26b7f5046e8541b3f1260ea9392a2bf0e5a7642 Mon Sep 17 00:00:00 2001 From: Zachary Blasczyk Date: Mon, 2 Mar 2026 15:24:23 -0600 Subject: [PATCH 09/10] test: add failing test for policy priority with anyApproval rules When two policies with anyApproval rules target the same deployment, the higher priority policy should be authoritative. Currently both policies are applied independently, so a lower priority policy can block a deployment that a higher priority policy explicitly allows. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../test/e2e/engine_policy_priority_test.go | 92 +++++++++++++++++++ .../workspace-engine/test/integration/opts.go | 6 ++ 2 files changed, 98 insertions(+) create mode 100644 apps/workspace-engine/test/e2e/engine_policy_priority_test.go diff --git a/apps/workspace-engine/test/e2e/engine_policy_priority_test.go b/apps/workspace-engine/test/e2e/engine_policy_priority_test.go new file mode 100644 index 000000000..5f5471f07 --- /dev/null +++ b/apps/workspace-engine/test/e2e/engine_policy_priority_test.go @@ -0,0 +1,92 @@ +package e2e + +import ( + "context" + "testing" + "workspace-engine/pkg/events/handler" + "workspace-engine/test/integration" + c "workspace-engine/test/integration/creators" + + "github.com/google/uuid" +) + +// TestEngine_PolicyPriority_HigherPriorityAnyApprovalIsAuthoritative tests that +// when two policies both have anyApproval rules targeting the same deployment, +// only the higher priority policy's rule should be authoritative. +// +// Scenario: +// - Policy A (priority 1): anyApproval with minApprovals=0 (no approval needed) +// - Policy B (priority 0): anyApproval with minApprovals=1 (needs 1 approval) +// - Both target the same deployment via selector "true" +// +// Expected: The higher priority policy (priority 1, minApprovals=0) should win, +// so the deployment should proceed without any approvals. +// +// Current bug: Both policies are applied independently, so the lower priority +// policy's requirement of 1 approval blocks the deployment. +func TestEngine_PolicyPriority_HigherPriorityAnyApprovalIsAuthoritative(t *testing.T) { + jobAgentID := uuid.New().String() + deploymentID := uuid.New().String() + environmentID := uuid.New().String() + resourceID := uuid.New().String() + highPriorityPolicyID := uuid.New().String() + lowPriorityPolicyID := uuid.New().String() + + engine := integration.NewTestWorkspace(t, + integration.WithJobAgent( + integration.JobAgentID(jobAgentID), + ), + integration.WithSystem( + integration.WithDeployment( + integration.DeploymentID(deploymentID), + integration.DeploymentName("api-service"), + integration.DeploymentJobAgent(jobAgentID), + integration.DeploymentCelResourceSelector("true"), + ), + integration.WithEnvironment( + integration.EnvironmentID(environmentID), + integration.EnvironmentName("production"), + integration.EnvironmentCelResourceSelector("true"), + ), + ), + integration.WithResource( + integration.ResourceID(resourceID), + ), + // High priority policy (priority=1): no approval needed + integration.WithPolicy( + integration.PolicyID(highPriorityPolicyID), + integration.PolicyName("no-approval-override"), + integration.PolicyPriority(1), + integration.WithPolicySelector("true"), + integration.WithPolicyRule( + integration.WithRuleAnyApproval(0), + ), + ), + // Low priority policy (priority=0): requires 1 approval + integration.WithPolicy( + integration.PolicyID(lowPriorityPolicyID), + integration.PolicyName("requires-approval"), + integration.PolicyPriority(0), + integration.WithPolicySelector("true"), + integration.WithPolicyRule( + integration.WithRuleAnyApproval(1), + ), + ), + ) + + ctx := context.Background() + + // Create a deployment version + version := c.NewDeploymentVersion() + version.DeploymentId = deploymentID + version.Tag = "v1.0.0" + engine.PushEvent(ctx, handler.DeploymentVersionCreate, version) + + // The higher priority policy says minApprovals=0, so no approval should be + // needed. The deployment should proceed immediately. + allJobs := engine.Workspace().Jobs().Items() + if len(allJobs) != 1 { + t.Fatalf("expected 1 job (higher priority policy requires 0 approvals), got %d — "+ + "the lower priority policy's anyApproval rule should not block deployment", len(allJobs)) + } +} diff --git a/apps/workspace-engine/test/integration/opts.go b/apps/workspace-engine/test/integration/opts.go index 698664d97..9edbdf65b 100644 --- a/apps/workspace-engine/test/integration/opts.go +++ b/apps/workspace-engine/test/integration/opts.go @@ -743,6 +743,12 @@ func PolicyID(id string) PolicyOption { } } +func PolicyPriority(priority int) PolicyOption { + return func(_ *TestWorkspace, p *oapi.Policy, _ *eventsBuilder) { + p.Priority = priority + } +} + // WithPolicySelector sets the policy's CEL selector expression. func WithPolicySelector(cel string) PolicyOption { return func(_ *TestWorkspace, p *oapi.Policy, _ *eventsBuilder) { From 4df91a47ea76b1d8228783116be09ecdf9516451 Mon Sep 17 00:00:00 2001 From: Zachary Blasczyk Date: Mon, 2 Mar 2026 15:25:38 -0600 Subject: [PATCH 10/10] docs: clarify policy priority semantics Make explicit that higher numeric values mean higher priority, and that when multiple policies define the same rule type for the same target, only the highest priority policy's rule is authoritative. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/policies/overview.mdx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/policies/overview.mdx b/docs/policies/overview.mdx index 26312a5f1..28957f3e2 100644 --- a/docs/policies/overview.mdx +++ b/docs/policies/overview.mdx @@ -44,7 +44,8 @@ A policy consists of: 2. **Selector** - A CEL expression defining which release targets the policy applies to 3. **Rules** - One or more rules specifying behavior or requirements -4. **Priority** - Higher priority policies are evaluated first +4. **Priority** - Higher numeric value = higher priority. For the same rule + type, the highest priority policy wins. 5. **Metadata** - Arbitrary key-value pairs for organization @@ -290,8 +291,10 @@ When a release is created, Ctrlplane: 1. **Finds matching policies** - Evaluates the `selector` CEL expression against each release target -2. **Merges rules** - Combines rules from all matching policies -3. **Applies rules** - Enforces each rule type +2. **Resolves rules by priority** - For each rule type, only the highest + priority policy's rule is used. Different rule types are combined across + policies. +3. **Applies rules** - Enforces each resolved rule type ### Rule Interactions