feat: add approval step

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
2026-03-15 19:46:33 +01:00
parent 533b738692
commit 7eb6ae7cbb
41 changed files with 7886 additions and 1724 deletions

View File

@@ -35,6 +35,8 @@ message ReleaseRequest {
// When true, use the project's release pipeline (DAG) instead of
// deploying directly to the specified destinations/environments.
bool use_pipeline = 5;
// When true, create a plan-only pipeline (single Plan stage, no deploy).
bool prepare_only = 6;
}
message ReleaseResponse {
// List of release intents created (one per destination)
@@ -55,9 +57,23 @@ message WaitReleaseEvent {
oneof event {
ReleaseStatusUpdate status_update = 1;
ReleaseLogLine log_line = 2;
PipelineStageUpdate stage_update = 3;
}
}
// Streamed in WaitRelease for pipeline releases: reports stage status changes.
message PipelineStageUpdate {
string stage_id = 1;
string stage_type = 2; // "deploy", "wait"
string status = 3; // PENDING, ACTIVE, SUCCEEDED, FAILED, CANCELLED
optional string queued_at = 4;
optional string started_at = 5;
optional string completed_at = 6;
optional string wait_until = 7;
optional string error_message = 8;
optional string approval_status = 9;
}
message ReleaseStatusUpdate {
string destination = 1;
string status = 2;
@@ -90,6 +106,13 @@ message GetProjectsResponse {
repeated string projects = 1;
}
message CreateProjectRequest {
string organisation = 1;
string project = 2;
}
message CreateProjectResponse {
Project project = 1;
}
message GetReleasesByActorRequest {
@@ -125,6 +148,67 @@ message GetDestinationStatesRequest {
message GetDestinationStatesResponse {
repeated DestinationState destinations = 1;
// Active pipeline runs affecting these destinations (if any).
repeated PipelineRunState pipeline_runs = 2;
}
// ── Release intent states (release-centric view) ─────────────────────
message GetReleaseIntentStatesRequest {
string organisation = 1;
optional string project = 2;
// When true, also include recently completed release intents.
bool include_completed = 3;
}
message GetReleaseIntentStatesResponse {
repeated ReleaseIntentState release_intents = 1;
}
// Full state of a release intent: pipeline stages + individual release steps.
message ReleaseIntentState {
string release_intent_id = 1;
string artifact_id = 2;
string project = 3;
string created_at = 4;
// Pipeline stages (empty for non-pipeline releases).
repeated PipelineStageState stages = 5;
// All release_states rows for this intent (deploy steps).
repeated ReleaseStepState steps = 6;
}
// Status of a single pipeline stage (saga coordinator view).
message PipelineStageState {
string stage_id = 1;
repeated string depends_on = 2;
PipelineRunStageType stage_type = 3;
PipelineRunStageStatus status = 4;
// Consistent timestamps for all stage types.
optional string queued_at = 5;
optional string started_at = 6;
optional string completed_at = 7;
optional string error_message = 8;
// Type-specific context.
optional string environment = 9; // deploy/plan stages
optional int64 duration_seconds = 10; // wait stages
optional string wait_until = 11; // wait stages
repeated string release_ids = 12; // deploy/plan stages: individual release IDs
optional string approval_status = 13; // plan stages: AWAITING_APPROVAL, APPROVED, REJECTED
optional bool auto_approve = 14; // plan stages
}
// Status of a single release step (release_states row).
message ReleaseStepState {
string release_id = 1;
optional string stage_id = 2;
string destination_name = 3;
string environment = 4;
string status = 5;
optional string queued_at = 6;
optional string assigned_at = 7;
optional string started_at = 8;
optional string completed_at = 9;
optional string error_message = 10;
}
message DestinationState {
@@ -138,6 +222,83 @@ message DestinationState {
optional string queued_at = 8;
optional string completed_at = 9;
optional int32 queue_position = 10;
// Pipeline context: set when this release was created by a pipeline stage.
optional string release_intent_id = 11;
optional string stage_id = 12;
// When a runner was assigned to this release.
optional string assigned_at = 13;
// When the runner actually started executing.
optional string started_at = 14;
}
// ── Pipeline run progress ────────────────────────────────────────────
// Snapshot of an active (or recently completed) pipeline run.
message PipelineRunState {
string release_intent_id = 1;
string artifact_id = 2;
string created_at = 3;
repeated PipelineRunStage stages = 4;
}
// Status of a single stage within a pipeline run.
message PipelineRunStage {
string stage_id = 1;
repeated string depends_on = 2;
PipelineRunStageType stage_type = 3;
PipelineRunStageStatus status = 4;
// Type-specific context
optional string environment = 5; // deploy stages
optional int64 duration_seconds = 6; // wait stages
optional string queued_at = 7; // when dependencies were met
optional string started_at = 8;
optional string completed_at = 9;
optional string error_message = 10;
optional string wait_until = 11;
repeated string release_ids = 12; // deploy stages: individual release IDs
optional string approval_status = 13; // plan stages: AWAITING_APPROVAL, APPROVED, REJECTED
optional bool auto_approve = 14; // plan stages
}
enum PipelineRunStageType {
PIPELINE_RUN_STAGE_TYPE_UNSPECIFIED = 0;
PIPELINE_RUN_STAGE_TYPE_DEPLOY = 1;
PIPELINE_RUN_STAGE_TYPE_WAIT = 2;
PIPELINE_RUN_STAGE_TYPE_PLAN = 3;
}
enum PipelineRunStageStatus {
PIPELINE_RUN_STAGE_STATUS_UNSPECIFIED = 0;
PIPELINE_RUN_STAGE_STATUS_PENDING = 1;
PIPELINE_RUN_STAGE_STATUS_ACTIVE = 2;
PIPELINE_RUN_STAGE_STATUS_SUCCEEDED = 3;
PIPELINE_RUN_STAGE_STATUS_FAILED = 4;
PIPELINE_RUN_STAGE_STATUS_CANCELLED = 5;
PIPELINE_RUN_STAGE_STATUS_AWAITING_APPROVAL = 6;
}
// ── Plan stage approval ──────────────────────────────────────────────
message ApprovePlanStageRequest {
string release_intent_id = 1;
string stage_id = 2;
}
message ApprovePlanStageResponse {}
message RejectPlanStageRequest {
string release_intent_id = 1;
string stage_id = 2;
optional string reason = 3;
}
message RejectPlanStageResponse {}
message GetPlanOutputRequest {
string release_intent_id = 1;
string stage_id = 2;
}
message GetPlanOutputResponse {
string plan_output = 1;
string status = 2; // RUNNING, AWAITING_APPROVAL, APPROVED, REJECTED
}
service ReleaseService {
@@ -150,7 +311,13 @@ service ReleaseService {
rpc GetReleasesByActor(GetReleasesByActorRequest) returns (GetReleasesByActorResponse);
rpc GetOrganisations(GetOrganisationsRequest) returns (GetOrganisationsResponse);
rpc GetProjects(GetProjectsRequest) returns (GetProjectsResponse);
rpc CreateProject(CreateProjectRequest) returns (CreateProjectResponse);
rpc GetDestinationStates(GetDestinationStatesRequest) returns (GetDestinationStatesResponse);
rpc GetReleaseIntentStates(GetReleaseIntentStatesRequest) returns (GetReleaseIntentStatesResponse);
rpc ApprovePlanStage(ApprovePlanStageRequest) returns (ApprovePlanStageResponse);
rpc RejectPlanStage(RejectPlanStageRequest) returns (RejectPlanStageResponse);
rpc GetPlanOutput(GetPlanOutputRequest) returns (GetPlanOutputResponse);
}
message Source {
@@ -158,6 +325,8 @@ message Source {
optional string email = 2;
optional string source_type = 3;
optional string run_url = 4;
// The actor ID (user, app, or service account UUID) that created this annotation.
optional string user_id = 5;
}
message ArtifactContext {
@@ -177,6 +346,7 @@ message Artifact {
Project project = 7;
repeated ArtifactDestination destinations = 8;
string created_at = 9;
Ref ref = 10;
}
message ArtifactDestination {