feat(#135): implement Quality Gate Configuration System

Add database-backed quality gate configuration for workspaces with
full CRUD operations and default gate seeding.

Schema:
- Add QualityGate model with workspace relation
- Support for custom commands and regex patterns
- Enable/disable and ordering support

Service:
- CRUD operations for quality gates
- findEnabled: Get ordered, enabled gates
- reorder: Bulk reorder with transaction
- seedDefaults: Seed 4 default gates
- toOrchestratorFormat: Convert to orchestrator interface

Endpoints:
- GET /workspaces/:id/quality-gates - List
- GET /workspaces/:id/quality-gates/:gateId - Get one
- POST /workspaces/:id/quality-gates - Create
- PATCH /workspaces/:id/quality-gates/:gateId - Update
- DELETE /workspaces/:id/quality-gates/:gateId - Delete
- POST /workspaces/:id/quality-gates/reorder
- POST /workspaces/:id/quality-gates/seed-defaults

Default gates: Build, Lint, Test, Coverage (85%)

Tests: 25 passing with 95.16% coverage

Fixes #135

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 13:33:04 -06:00
parent a25e9048be
commit 4a2909ce1e
10 changed files with 980 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
import { IsString, IsOptional, IsBoolean, IsIn, IsInt, IsNotEmpty } from "class-validator";
/**
* DTO for creating a new quality gate
*/
export class CreateQualityGateDto {
@IsString()
@IsNotEmpty()
name!: string;
@IsOptional()
@IsString()
description?: string;
@IsIn(["build", "lint", "test", "coverage", "custom"])
type!: string;
@IsOptional()
@IsString()
command?: string;
@IsOptional()
@IsString()
expectedOutput?: string;
@IsOptional()
@IsBoolean()
isRegex?: boolean;
@IsOptional()
@IsBoolean()
required?: boolean;
@IsOptional()
@IsInt()
order?: number;
}

View File

@@ -0,0 +1,2 @@
export * from "./create-quality-gate.dto";
export * from "./update-quality-gate.dto";

View File

@@ -0,0 +1,42 @@
import { IsString, IsOptional, IsBoolean, IsIn, IsInt } from "class-validator";
/**
* DTO for updating an existing quality gate
*/
export class UpdateQualityGateDto {
@IsOptional()
@IsString()
name?: string;
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsIn(["build", "lint", "test", "coverage", "custom"])
type?: string;
@IsOptional()
@IsString()
command?: string;
@IsOptional()
@IsString()
expectedOutput?: string;
@IsOptional()
@IsBoolean()
isRegex?: boolean;
@IsOptional()
@IsBoolean()
required?: boolean;
@IsOptional()
@IsInt()
order?: number;
@IsOptional()
@IsBoolean()
isEnabled?: boolean;
}