import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { z } from 'zod'; import { DeployEnvironment } from './deploy-run.types'; const optionalTrimmedString = (maxLength: number) => z .string() .trim() .max(maxLength) .optional() .or(z.literal('').transform(() => undefined)); /** * 创建发布单的运行时校验规则;真实密钥和第三方参数不允许从前端传入。 */ export const createDeployRunSchema = z.object({ projectKey: z.string().trim().min(1).max(80), environment: z.enum(['test', 'production']), ref: z.string().trim().min(1).max(200), operator: optionalTrimmedString(120), remark: optionalTrimmedString(500), idempotencyKey: optionalTrimmedString(260), productionConfirmation: z .object({ confirmed: z.boolean(), confirmedAt: optionalTrimmedString(80), summary: optionalTrimmedString(300), }) .optional(), }); export type CreateDeployRunRequestInput = z.infer; export class CreateDeployRunDto { @ApiProperty({ example: 'access-manage' }) projectKey!: string; @ApiProperty({ enum: ['test', 'production'], example: 'test' }) environment!: DeployEnvironment; @ApiProperty({ example: 'develop' }) ref!: string; @ApiPropertyOptional({ example: 'operator@example.com', description: '兼容旧前端字段;后端会优先使用当前登录账号', }) operator?: string; @ApiPropertyOptional({ example: 'Manual test deploy before release.' }) remark?: string; @ApiPropertyOptional({ example: 'access-manage:test:develop:2026-06-11T10:00:00Z', }) idempotencyKey?: string; @ApiPropertyOptional({ description: '生产环境发布必须提交的人工确认摘要;测试环境忽略。', example: { confirmed: true, confirmedAt: '2026-06-12T02:30:00.000Z', summary: '已确认 ref、回滚方案、通知对象和业务窗口', }, }) productionConfirmation?: { confirmed: boolean; confirmedAt?: string; summary?: string; }; }