Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: publish.yaml schema 验证 #29

Merged
merged 1 commit into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/registry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"dependencies": {
"@serverless-devs/utils": "workspace:^",
"@serverless-devs/zip": "workspace:^",
"ajv": "^8.12.0",
"chalk": "^5.3.0",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
Expand Down
158 changes: 158 additions & 0 deletions packages/registry/src/actions/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
export const publishSchema = {
"type": "object",
"required": [
"Edition",
"Type",
"Name",
"Provider",
"Version",
"Description",
"HomePage",
"Tags",
"Category",
"Service",
// "Commands",
"Organization",
"Effective",
"Parameters"
],
"properties": {
"Edition": {
"type": "string",
"enum": ["3.0.0"],
},
"Type": {
"type": "string",
"enum": [
"Component", "Plugin", "Project"
]
},
"Name": {
"type": "string"
},
"Provider": {
"type": "array",
"items": {
"type": "string",
"enum": [
"阿里云",
"腾讯云",
"华为云",
"百度智能云",
"AWS",
"Azure",
"Google Cloud Platform",
"专有云",
"其它",
"Alibaba Cloud",
"Tencent Cloud",
"Huawei Cloud",
"Baidu Cloud",
"Private Cloud",
"Others"
]
}
},
"Version": {
"type": "string"
},
"Description": {
"type": "string"
},
"HomePage": {
"type": "string",
// "pattern": "^(https?|ftp)://[^\\s/$.?#].[^\\s]*$"
},
"Tags": {
"type": "array",
"items": {
"type": "string"
}
},
"Category": {
"type": "string",
"enum": [
"人工智能",
"Web 应用",
"基础云服务",
"新手入门",
"开源项目",
"Jamstack",
"函数Connector",
"IoT",
"其它",
"数据处理",
"监控告警",
"图文处理",
"音视频处理",
"全栈应用",
"Web框架",
"云应用",
"基础云产品",
"Artificial Intelligence",
"Web Appilication",
"Basic cloud services",
"onboarding",
"Open Source",
"Function Connector",
"Others",
"Big Data",
"Monitoring alarm",
"Image and text processing",
"Audio and video processing",
"Fullstack application",
"Web Framework",
"Cloud Application",
"Basic cloud products"
]
},
"Service": {
"type": "object",
"patternProperties": {
"^(函数计算|对象存储|内容分发网络|资源编排|硬盘挂载|专有网络|日志服务|容器镜像服务|事件总线|表格存储|Serverless应用引擎|云数据库RDS MySQL 版|视频点播|智能媒体服务|媒体处理|低代码音视频工厂|音视频通信|其它|FC|OSS|CDN|ROS|NAS|VPC|SLS|CR|EventBridge|Tablestore|SAE|RDS MySQL|VOD|ICE|MTS|IMP|RTC|Other)$": {
"type": "object",
"properties": {
"Authorities": {
"type": "array",
"items": {
"type": "string"
}
},
"Runtime": {
"type": "string"
}
},
"required": ["Authorities"]
}
},
},
"Organization": {
"type": "string"
},
"Effective": {
"type": "string",
"enum": [
"Public",
"Private",
"Organization"
]
},
"Parameters": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"additionalProperties": {
"type": "boolean"
},
"required": {
"type": "array"
},
"properties": {
"type": "object"
},
}
}
}
}
26 changes: 26 additions & 0 deletions packages/registry/src/actions/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import yaml from 'js-yaml';
import querystring from 'querystring';
import { forEach, get, isEmpty, includes } from 'lodash';
import chalk from 'chalk';
import { publishSchema } from './constant';
import Ajv from 'ajv';

interface IRequest {
/**
Expand Down Expand Up @@ -99,6 +101,30 @@ function getFlowsYaml(str: string | undefined, codeUri: string) {
async function getUploadUrl(codeUri: string): Promise<string> {
const publishYaml = getYamlContentText(path.join(codeUri, 'publish')) as string;
checkEdition(publishYaml);

const yamlObject = yaml.load(publishYaml) as Record<string, any>;
const errorMsg = `Publish.yaml illegal.
应用开发示例: https://docs.serverless-devs.com/serverless-devs/development-manual/readme#%E5%BA%94%E7%94%A8%E6%A8%A1%E5%9E%8B%E5%85%83%E6%95%B0%E6%8D%AE
组件开发示例: https://docs.serverless-devs.com/serverless-devs/development-manual/component#%E7%BB%84%E4%BB%B6%E6%A8%A1%E5%9E%8B%E5%85%83%E6%95%B0%E6%8D%AE
插件开发示例: https://docs.serverless-devs.com/serverless-devs/development-manual/plugin#%E6%8F%92%E4%BB%B6%E6%A8%A1%E5%9E%8B%E5%85%83%E6%95%B0%E6%8D%AE
`
const ajv = new Ajv({ allErrors: true });
const validate = ajv.compile(publishSchema);
if(!validate(yamlObject)) {
const errors = validate.errors;
if(errors) {
errors.forEach((error) => {
const {schemaPath, message} = error;
logger.error(`Publish.yaml illegal:\nyamlPath: ${path.join(codeUri, 'publish.yaml')}\nschemaPath: ${schemaPath}\nmessage: ${message}`)
})
throw new Error(errorMsg);
}
}
if(yamlObject.Type === 'Component' && (!yamlObject.Commands || yamlObject.Commands.length === 0)) {
logger.write('Publish.yaml illegal, \'Commands\' should be defined in Component\'s publish.yaml , please check the yaml.')
throw new Error(errorMsg);
}

const publishEnYaml = getYamlContentText(path.join(codeUri, 'publish_en'));
const sYaml = getYamlContentText(path.join(codeUri, 'src', 's'));
const flowYaml = getFlowsYaml(sYaml, codeUri);
Expand Down