UNPKG

alibabacloud-devops-mcp-server

Version:

MCP Server for using the alibabacloud-devops API: allows AI assistants to directly participate in development collaboration, helping teams optimize development processes and improve efficiency.

484 lines (481 loc) 17.7 kB
/** * 模块化流水线模板定义 * 基于云效Flow官方文档,将Sources、构建步骤、部署组件分离 */ // Codeup 源码模板 export const CODEUP_SOURCE_TEMPLATE = { type: 'codeup', name: 'Codeup 代码源', description: '阿里云 Codeup 代码仓库', keywords: ['codeup', 'aliyun', '阿里云'], template: `sources: main_repo: type: codeup name: {{serviceName || '项目'}} endpoint: {{repoUrl || 'https://codeup.aliyun.com/your-org/your-repo.git'}} branch: {{branch || 'main'}} triggerEvents: push certificate: type: serviceConnection serviceConnection: {{serviceConnectionId || 'your-service-connection-id'}}`, defaultVariables: { branch: 'main' } }; // GitHub 源码模板 export const GITHUB_SOURCE_TEMPLATE = { type: 'github', name: 'GitHub 代码源', description: 'GitHub 代码仓库', keywords: ['github'], template: `sources: main_repo: type: github name: {{serviceName || '项目'}} endpoint: {{repoUrl || 'https://github.com/your-org/your-repo.git'}} branch: {{branch || 'main'}} triggerEvents: push certificate: type: serviceConnection serviceConnection: {{serviceConnectionId || 'your-service-connection-id'}}`, defaultVariables: { branch: 'main' } }; // Java Maven 构建步骤 export const JAVA_MAVEN_BUILD_TEMPLATE = { type: 'java_maven', name: 'Java Maven 构建', description: 'Java项目使用Maven进行构建', keywords: ['java', 'maven', 'mvn'], languages: ['java'], buildTools: ['maven'], template: ` build_job: name: Maven构建 runsOn: group: public/cn-beijing container: build-steps-public-registry.cn-beijing.cr.aliyuncs.com/build-steps/alinux3:latest steps: setup_maven_settings_step: name: "下载MavenSettings" step: SetupMavenSettings with: mavenSettingXmlPath: "/root/.m2/settings.xml" setup_java_step: name: "安装Java环境" step: SetupJava with: jdkVersion: {{jdkVersion || "1.8"}} mavenVersion: {{mavenVersion || "3.5.2"}} command_step: name: "执行命令" step: Command with: run: | {{buildCommand || 'mvn clean package -Dmaven.test.skip=true'}}`, defaultVariables: { jdkVersion: '"1.8"', mavenVersion: '"3.5.2"', buildCommand: 'mvn clean package -Dmaven.test.skip=true', testCommand: 'mvn test', artifactPath: 'target/' } }; // Node.js NPM 构建步骤 export const NODEJS_NPM_BUILD_TEMPLATE = { type: 'nodejs_npm', name: 'Node.js NPM 构建', description: 'Node.js项目使用NPM进行构建', keywords: ['nodejs', 'node.js', 'npm', 'javascript'], languages: ['nodejs', 'javascript', 'js'], buildTools: ['npm'], template: ` build_job: name: Node.js构建 runsOn: group: public/cn-beijing container: build-steps-public-registry.cn-beijing.cr.aliyuncs.com/build-steps/alinux3:latest steps: setup_npmrc_step: name: "下载npmrc" step: SetupNpmrc with: npmPrivateRepoConfigPath: "/root/.npmrc" setup_node_step: name: "安装Node" step: SetupNode with: versionType: "predefined" # 支持填写 predefined、custom、nvmrc nodeVersion: {{nodeVersion || "18.12"}} npmType: "npm" command_step: name: "执行命令" step: Command with: run: | {{buildCommand || 'npm install && npm run build'}}`, defaultVariables: { nodeVersion: '"18.12"', buildCommand: 'npm install && npm run build', testCommand: 'npm test', artifactPath: 'dist/' } }; // Python 构建步骤 export const PYTHON_BUILD_TEMPLATE = { type: 'python', name: 'Python 构建', description: 'Python项目构建', keywords: ['python', 'pip'], languages: ['python'], buildTools: ['pip', 'poetry'], template: ` build_job: name: Python构建 runsOn: group: public/cn-beijing container: build-steps-public-registry.cn-beijing.cr.aliyuncs.com/build-steps/alinux3:latest steps: setup_python_step: name: "安装Python" step: SetupPython with: pythonVersion: {{pythonVersion || "3.7"}} command_step: name: "执行命令" step: Command with: run: | {{buildCommand || 'python --version'}}`, defaultVariables: { pythonVersion: '"3.7"', buildCommand: 'python --version', testCommand: 'python -m pytest', artifactPath: '.' } }; // Go 构建步骤 export const GO_BUILD_TEMPLATE = { type: 'go', name: 'Go 构建', description: 'Go项目构建', keywords: ['go', 'golang'], languages: ['go', 'golang'], buildTools: ['go'], template: ` build_job: name: Go构建 runsOn: group: public/cn-beijing container: build-steps-public-registry.cn-beijing.cr.aliyuncs.com/build-steps/alinux3:latest steps: golang_build_step: name: "安装 Golang" step: SetupGo with: goVersion: {{goVersion || "1.21"}} command_step: name: "执行命令" step: Command with: run: | {{buildCommand || 'make build'}}`, defaultVariables: { goVersion: '"1.21"', buildCommand: 'make build', testCommand: 'go test ./...', artifactPath: '.' } }; // .NET Core 构建步骤 export const DOTNET_BUILD_TEMPLATE = { type: 'dotnet', name: '.NET Core 构建', description: '.NET Core项目构建', keywords: ['dotnet', '.net', 'csharp'], languages: ['csharp'], buildTools: ['dotnet'], template: ` build_job: name: .NET Core构建 runsOn: group: public/cn-beijing container: build-steps-public-registry.cn-beijing.cr.aliyuncs.com/build-steps/dotnetcore:8.0 steps: command_step: name: "执行命令" step: Command with: run: | dotnet --info {{buildCommand || 'dotnet restore && dotnet publish -c Release -o out'}}`, defaultVariables: { buildCommand: 'dotnet restore && dotnet publish -c Release -o out', testCommand: 'dotnet test', artifactPath: 'out/' } }; // Packages 制品库上传 export const PACKAGES_UPLOAD_TEMPLATE = { type: 'packages', name: 'Packages 制品库上传', description: '上传到云效制品库', template: ` upload_step: step: ArtifactUpload name: 构建物上传 with: uploadType: packages serviceConnection: {{packagesServiceConnection || 'your-packages-service-connection-id'}} repo: {{packagesRepoId || 'flow_generic_repo'}} artifact: {{artifactName || 'default'}} version: {{artifactVersion || '1.0.0'}} filePath: - {{artifactPath || '.'}} includePathInArtifact: {{includePathInArtifact || false}}`, defaultVariables: { uploadType: 'packages', artifactName: 'default', artifactVersion: '1.0.0', includePathInArtifact: false } }; // Flow Public 上传 export const FLOW_PUBLIC_UPLOAD_TEMPLATE = { type: 'flowPublic', name: 'Flow Public 上传', description: '上传到Flow公共存储', template: ` upload_step: step: ArtifactUpload name: 构建物上传 with: uploadType: flowPublic artifact: {{artifactName || 'default'}} filePath: - {{artifactPath || '.'}} includePathInArtifact: {{includePathInArtifact || false}}`, defaultVariables: { uploadType: 'flowPublic', artifactName: 'default', includePathInArtifact: false } }; // 主机部署组件 export const VM_DEPLOY_COMPONENT_TEMPLATE = { type: 'vm_deploy', name: '主机部署', description: '部署到虚拟主机/ECS', keywords: ['vm', 'host', '主机', 'ecs'], deployTargets: ['vm', 'host', '主机'], template: ` deploy_job: name: 主机部署 component: VMDeploy with: artifact: $[stages.build_stage.build_job.upload_step.artifacts.{{artifactName || 'default'}}] machineGroup: {{machineGroupId || 'your-machine-group-id'}} artifactDownloadPath: {{artifactDownloadPath || '/home/admin/app/package.tgz'}} executeUser: {{executeUser || 'root'}} pauseStrategy: {{pauseStrategy || 'firstBatchPause'}} batchNumber: {{batchNumber || 2}} run: | cd /home/admin/app tar -xzf package.tgz {{deployCommand || 'echo "请配置部署命令"'}}`, defaultVariables: { executeUser: 'root', artifactDownloadPath: '/home/admin/app/package.tgz', pauseStrategy: 'firstBatchPause', batchNumber: 2 } }; // Kubernetes 部署组件 export const KUBERNETES_DEPLOY_COMPONENT_TEMPLATE = { type: 'kubernetes_deploy', name: 'Kubernetes发布', description: '部署到Kubernetes集群', keywords: ['kubernetes', 'k8s', 'kubectl', 'deploy', 'apply'], deployTargets: ['kubernetes', 'k8s'], template: ` kubectl_apply_job: name: Kubernetes发布 runsOn: group: public/cn-beijing container: build-steps-public-registry.cn-beijing.cr.aliyuncs.com/build-steps/alinux3:latest setps: kubectl_apply: step: KubectlApply name: "Kubectl 发布" with: kubernetesCluster: {{kubernetesClusterId || 'your-kubernetesCluster-id'}} kubectlVersion: {{kubectlVersion || "1.27.9"}} namespace: {{namespace || default}} yamlPath: {{yamlPath || app-configs/manifest-app}} variables: - key: image value: $[stages.java_build_stage.java_build_job.acr_docker_build_step.artifacts.{{dockerImage || my_image}}]`, defaultVariables: { namespace: 'default', kubectlVersion: "1.27.9", yamlPath: 'app-configs/manifest-app' } }; // ===== 模板集合 ===== export const SOURCE_TEMPLATES = [ CODEUP_SOURCE_TEMPLATE, GITHUB_SOURCE_TEMPLATE ]; export const BUILD_STEP_TEMPLATES = [ JAVA_MAVEN_BUILD_TEMPLATE, NODEJS_NPM_BUILD_TEMPLATE, PYTHON_BUILD_TEMPLATE, GO_BUILD_TEMPLATE, DOTNET_BUILD_TEMPLATE ]; export const ARTIFACT_UPLOAD_TEMPLATES = [ PACKAGES_UPLOAD_TEMPLATE, FLOW_PUBLIC_UPLOAD_TEMPLATE ]; export const DEPLOY_COMPONENT_TEMPLATES = [ VM_DEPLOY_COMPONENT_TEMPLATE, KUBERNETES_DEPLOY_COMPONENT_TEMPLATE ]; // ===== 模板匹配函数 ===== export function findMatchingSourceTemplate(keywords) { const normalizedKeywords = keywords.map(k => k.toLowerCase()); const matched = SOURCE_TEMPLATES.find(template => template.keywords.some(keyword => normalizedKeywords.some(nk => nk.includes(keyword) || keyword.includes(nk)))); return matched || CODEUP_SOURCE_TEMPLATE; // 默认使用 Codeup } export function findMatchingBuildTemplate(keywords, languages, buildTools) { const normalizedKeywords = keywords.map(k => k.toLowerCase()); const normalizedLanguages = languages.map(l => l.toLowerCase()); const normalizedBuildTools = buildTools.map(t => t.toLowerCase()); // 使用评分系统选择最佳匹配模板 let bestTemplate = null; let bestScore = 0; for (const template of BUILD_STEP_TEMPLATES) { let score = 0; // 语言匹配 (权重最高) for (const lang of template.languages) { if (normalizedLanguages.some(nl => nl.includes(lang) || lang.includes(nl))) { score += 10; } } // 构建工具匹配 (权重中等) for (const tool of template.buildTools) { if (normalizedBuildTools.some(nt => nt.includes(tool) || tool.includes(nt))) { score += 5; } } // 关键词匹配 (权重较低) for (const keyword of template.keywords) { if (normalizedKeywords.some(nk => nk.includes(keyword) || keyword.includes(nk))) { score += 2; } } if (score > bestScore) { bestScore = score; bestTemplate = template; } } return bestTemplate; } export function findMatchingUploadTemplate(uploadType) { return ARTIFACT_UPLOAD_TEMPLATES.find(template => template.type === uploadType) || PACKAGES_UPLOAD_TEMPLATE; // 默认使用 packages } export function findMatchingDeployTemplate(keywords, deployTargets) { const normalizedKeywords = keywords.map(k => k.toLowerCase()); const normalizedTargets = deployTargets.map(t => t.toLowerCase()); return DEPLOY_COMPONENT_TEMPLATES.find(template => { return template.keywords.some(keyword => normalizedKeywords.some(nk => nk.includes(keyword) || keyword.includes(nk))) || template.deployTargets.some(target => normalizedTargets.some(nt => nt.includes(target) || target.includes(nt))); }) || null; } export function generateModularPipeline(options) { const { sourceType, buildLanguages = [], buildTools = [], uploadType = 'packages', deployTargets = [], keywords = [], variables = {} } = options; // 1. 选择源码模板 const sourceTemplate = findMatchingSourceTemplate(keywords); // 2. 选择构建模板 const buildTemplate = findMatchingBuildTemplate(keywords, buildLanguages, buildTools); // 3. 选择上传模板 const uploadTemplate = findMatchingUploadTemplate(uploadType); // 4. 选择部署模板 const deployTemplate = deployTargets.length > 0 ? findMatchingDeployTemplate(keywords, deployTargets) : null; // 5. 合并默认变量 const mergedVariables = { ...sourceTemplate.defaultVariables, ...buildTemplate?.defaultVariables, ...uploadTemplate.defaultVariables, ...deployTemplate?.defaultVariables, ...variables }; // 6. 生成完整YAML let pipeline = sourceTemplate.template; if (buildTemplate) { pipeline += ` stages: build_stage: name: 构建阶段 jobs: ${buildTemplate.template} ${uploadTemplate.template}`; } if (deployTemplate) { pipeline += ` deploy_stage: name: 部署阶段 jobs: ${deployTemplate.template}`; } // 7. 替换变量 return replaceTemplateVariables(pipeline, mergedVariables); } // 变量替换函数 (复用原有逻辑) function replaceTemplateVariables(template, variables) { let result = template; result = result.replace(/\{\{([^}]+)\}\}/g, (match, expression) => { const trimmed = expression.trim(); if (trimmed.includes('||')) { const [varName, defaultValue] = trimmed.split('||').map((s) => s.trim()); const cleanVarName = varName.trim(); const cleanDefaultValue = defaultValue.replace(/['"]/g, ''); const value = variables[cleanVarName]; if (value !== undefined && value !== null) { if (cleanVarName === 'repoUrl' && (value === '<your-repository-url>' || value.includes('<your-') || value.includes('>'))) { const serviceName = variables['serviceName']; if (serviceName && serviceName !== '<service-name>') { return `https://codeup.aliyun.com/your-org/${serviceName}.git`; } } if (cleanVarName === 'serviceConnectionId' && (value === '<your-service-connection-id>' || value.includes('<your-'))) { return 'your-service-connection-id'; } if (cleanVarName === 'machineGroupId' && (value === '<your-machine-group-id>' || value.includes('<your-'))) { return 'your-machine-group-id'; } return value; } else { return cleanDefaultValue; } } else { const value = variables[trimmed]; if (value !== undefined && value !== null) { if (typeof value === 'string' && value.includes('<your-')) { if (trimmed === 'repoUrl') { const serviceName = variables['serviceName']; return serviceName && !serviceName.includes('<') ? `https://codeup.aliyun.com/your-org/${serviceName}.git` : 'https://codeup.aliyun.com/your-org/your-repo.git'; } if (trimmed === 'serviceConnectionId') { return 'your-service-connection-id'; } if (trimmed === 'machineGroupId') { return 'your-machine-group-id'; } } return value; } return match; } }); return result; }