- 在部署DTO中添加sparseCheckoutPaths字段支持稀疏检出路径 - 数据模型Deployment新增稀疏检出路径字段及相关数据库映射 - 部署创建时支持设置稀疏检出路径字段 - 部署重试接口实现,支持复制原始部署记录并加入执行队列 - 新增流水线模板初始化与基于模板创建流水线接口 - 优化应用初始化流程,确保执行队列和流水线模板正确加载 - 添加启动日志,提示执行队列初始化完成
248 lines
6.8 KiB
TypeScript
248 lines
6.8 KiB
TypeScript
import { prisma } from './prisma.ts';
|
||
|
||
// 默认流水线模板
|
||
export interface PipelineTemplate {
|
||
name: string;
|
||
description: string;
|
||
steps: Array<{
|
||
name: string;
|
||
order: number;
|
||
script: string;
|
||
}>;
|
||
}
|
||
|
||
// 系统默认的流水线模板
|
||
export const DEFAULT_PIPELINE_TEMPLATES: PipelineTemplate[] = [
|
||
{
|
||
name: 'Git Clone Pipeline',
|
||
description: '默认的Git克隆流水线,用于从仓库克隆代码',
|
||
steps: [
|
||
{
|
||
name: 'Clone Repository',
|
||
order: 0,
|
||
script: '# 克隆指定commit的代码\ngit init\ngit remote add origin $REPOSITORY_URL\ngit fetch --depth 1 origin $COMMIT_HASH\ngit checkout -q FETCH_HEAD\n\n# 显示当前提交信息\ngit log --oneline -1',
|
||
},
|
||
{
|
||
name: 'Install Dependencies',
|
||
order: 1,
|
||
script: '# 安装项目依赖\nnpm install',
|
||
},
|
||
{
|
||
name: 'Run Tests',
|
||
order: 2,
|
||
script: '# 运行测试\nnpm test',
|
||
},
|
||
{
|
||
name: 'Build Project',
|
||
order: 3,
|
||
script: '# 构建项目\nnpm run build',
|
||
}
|
||
]
|
||
},
|
||
{
|
||
name: 'Sparse Checkout Pipeline',
|
||
description: '稀疏检出流水线,适用于monorepo项目,只获取指定目录的代码',
|
||
steps: [
|
||
{
|
||
name: 'Sparse Checkout Repository',
|
||
order: 0,
|
||
script: '# 进行稀疏检出指定目录的代码\ngit init\ngit remote add origin $REPOSITORY_URL\ngit config core.sparseCheckout true\necho "$SPARSE_CHECKOUT_PATHS" > .git/info/sparse-checkout\ngit fetch --depth 1 origin $COMMIT_HASH\ngit checkout -q FETCH_HEAD\n\n# 显示当前提交信息\ngit log --oneline -1',
|
||
},
|
||
{
|
||
name: 'Install Dependencies',
|
||
order: 1,
|
||
script: '# 安装项目依赖\nnpm install',
|
||
},
|
||
{
|
||
name: 'Run Tests',
|
||
order: 2,
|
||
script: '# 运行测试\nnpm test',
|
||
},
|
||
{
|
||
name: 'Build Project',
|
||
order: 3,
|
||
script: '# 构建项目\nnpm run build',
|
||
}
|
||
]
|
||
},
|
||
{
|
||
name: 'Simple Deploy Pipeline',
|
||
description: '简单的部署流水线,包含基本的构建和部署步骤',
|
||
steps: [
|
||
{
|
||
name: 'Clone Repository',
|
||
order: 0,
|
||
script: '# 克隆指定commit的代码\ngit init\ngit remote add origin $REPOSITORY_URL\ngit fetch --depth 1 origin $COMMIT_HASH\ngit checkout -q FETCH_HEAD',
|
||
},
|
||
{
|
||
name: 'Build and Deploy',
|
||
order: 1,
|
||
script: '# 构建并部署项目\nnpm run build\n\n# 部署到目标服务器\n# 这里可以添加具体的部署命令',
|
||
}
|
||
]
|
||
}
|
||
];
|
||
|
||
/**
|
||
* 初始化系统默认流水线模板
|
||
*/
|
||
export async function initializePipelineTemplates(): Promise<void> {
|
||
console.log('Initializing pipeline templates...');
|
||
|
||
try {
|
||
// 检查是否已经存在模板流水线
|
||
const existingTemplates = await prisma.pipeline.findMany({
|
||
where: {
|
||
name: {
|
||
in: DEFAULT_PIPELINE_TEMPLATES.map(template => template.name)
|
||
},
|
||
valid: 1
|
||
}
|
||
});
|
||
|
||
// 如果没有现有的模板,则创建默认模板
|
||
if (existingTemplates.length === 0) {
|
||
console.log('Creating default pipeline templates...');
|
||
|
||
for (const template of DEFAULT_PIPELINE_TEMPLATES) {
|
||
// 创建模板流水线(使用负数ID表示模板)
|
||
const pipeline = await prisma.pipeline.create({
|
||
data: {
|
||
name: template.name,
|
||
description: template.description,
|
||
createdBy: 'system',
|
||
updatedBy: 'system',
|
||
valid: 1,
|
||
projectId: null // 模板不属于任何特定项目
|
||
}
|
||
});
|
||
|
||
// 创建模板步骤
|
||
for (const step of template.steps) {
|
||
await prisma.step.create({
|
||
data: {
|
||
name: step.name,
|
||
order: step.order,
|
||
script: step.script,
|
||
pipelineId: pipeline.id,
|
||
createdBy: 'system',
|
||
updatedBy: 'system',
|
||
valid: 1
|
||
}
|
||
});
|
||
}
|
||
|
||
console.log(`Created template: ${template.name}`);
|
||
}
|
||
} else {
|
||
console.log('Pipeline templates already exist, skipping initialization');
|
||
}
|
||
|
||
console.log('Pipeline templates initialization completed');
|
||
} catch (error) {
|
||
console.error('Failed to initialize pipeline templates:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取所有可用的流水线模板
|
||
*/
|
||
export async function getAvailableTemplates(): Promise<Array<{id: number, name: string, description: string}>> {
|
||
try {
|
||
const templates = await prisma.pipeline.findMany({
|
||
where: {
|
||
projectId: null, // 模板流水线没有关联的项目
|
||
valid: 1
|
||
},
|
||
select: {
|
||
id: true,
|
||
name: true,
|
||
description: true
|
||
}
|
||
});
|
||
|
||
// 处理可能为null的description字段
|
||
return templates.map(template => ({
|
||
id: template.id,
|
||
name: template.name,
|
||
description: template.description || ''
|
||
}));
|
||
} catch (error) {
|
||
console.error('Failed to get pipeline templates:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 基于模板创建新的流水线
|
||
* @param templateId 模板ID
|
||
* @param projectId 项目ID
|
||
* @param pipelineName 新流水线名称
|
||
* @param pipelineDescription 新流水线描述
|
||
*/
|
||
export async function createPipelineFromTemplate(
|
||
templateId: number,
|
||
projectId: number,
|
||
pipelineName: string,
|
||
pipelineDescription: string
|
||
): Promise<number> {
|
||
try {
|
||
// 获取模板流水线及其步骤
|
||
const templatePipeline = await prisma.pipeline.findUnique({
|
||
where: {
|
||
id: templateId,
|
||
projectId: null, // 确保是模板流水线
|
||
valid: 1
|
||
},
|
||
include: {
|
||
steps: {
|
||
where: {
|
||
valid: 1
|
||
},
|
||
orderBy: {
|
||
order: 'asc'
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
if (!templatePipeline) {
|
||
throw new Error(`Template with id ${templateId} not found`);
|
||
}
|
||
|
||
// 创建新的流水线
|
||
const newPipeline = await prisma.pipeline.create({
|
||
data: {
|
||
name: pipelineName,
|
||
description: pipelineDescription,
|
||
projectId: projectId,
|
||
createdBy: 'system',
|
||
updatedBy: 'system',
|
||
valid: 1
|
||
}
|
||
});
|
||
|
||
// 复制模板步骤到新流水线
|
||
for (const templateStep of templatePipeline.steps) {
|
||
await prisma.step.create({
|
||
data: {
|
||
name: templateStep.name,
|
||
order: templateStep.order,
|
||
script: templateStep.script,
|
||
pipelineId: newPipeline.id,
|
||
createdBy: 'system',
|
||
updatedBy: 'system',
|
||
valid: 1
|
||
}
|
||
});
|
||
}
|
||
|
||
console.log(`Created pipeline from template ${templateId}: ${newPipeline.name}`);
|
||
return newPipeline.id;
|
||
} catch (error) {
|
||
console.error('Failed to create pipeline from template:', error);
|
||
throw error;
|
||
}
|
||
}
|