openubmc-bingo 0.5.240__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of openubmc-bingo might be problematic. Click here for more details.

Files changed (242) hide show
  1. bmcgo/__init__.py +12 -0
  2. bmcgo/bmcgo.py +22 -0
  3. bmcgo/bmcgo_config.py +176 -0
  4. bmcgo/cli/__init__.py +10 -0
  5. bmcgo/cli/cli.py +584 -0
  6. bmcgo/codegen/__init__.py +14 -0
  7. bmcgo/codegen/c/__init__.py +9 -0
  8. bmcgo/codegen/c/annotation.py +52 -0
  9. bmcgo/codegen/c/argument.py +42 -0
  10. bmcgo/codegen/c/codegen.py +153 -0
  11. bmcgo/codegen/c/comment.py +22 -0
  12. bmcgo/codegen/c/ctype_defination.py +353 -0
  13. bmcgo/codegen/c/helper.py +87 -0
  14. bmcgo/codegen/c/interface.py +63 -0
  15. bmcgo/codegen/c/method.py +82 -0
  16. bmcgo/codegen/c/property.py +180 -0
  17. bmcgo/codegen/c/renderer.py +21 -0
  18. bmcgo/codegen/c/signal.py +64 -0
  19. bmcgo/codegen/c/template/client.c.mako +145 -0
  20. bmcgo/codegen/c/template/client.h.mako +36 -0
  21. bmcgo/codegen/c/template/interface.c.mako +0 -0
  22. bmcgo/codegen/c/template/interface.introspect.xml.mako +99 -0
  23. bmcgo/codegen/c/template/micro_component.c.mako +32 -0
  24. bmcgo/codegen/c/template/public.c.mako +228 -0
  25. bmcgo/codegen/c/template/public.h.mako +128 -0
  26. bmcgo/codegen/c/template/server.c.mako +104 -0
  27. bmcgo/codegen/c/template/server.h.mako +36 -0
  28. bmcgo/codegen/lua/.lua-format +7 -0
  29. bmcgo/codegen/lua/Makefile +101 -0
  30. bmcgo/codegen/lua/__init__.py +9 -0
  31. bmcgo/codegen/lua/codegen.py +171 -0
  32. bmcgo/codegen/lua/proto/Makefile +87 -0
  33. bmcgo/codegen/lua/proto/ipmi_types.proto +17 -0
  34. bmcgo/codegen/lua/proto/types.proto +52 -0
  35. bmcgo/codegen/lua/script/check_intfs.py +161 -0
  36. bmcgo/codegen/lua/script/dto/__init__.py +11 -0
  37. bmcgo/codegen/lua/script/dto/exception.py +53 -0
  38. bmcgo/codegen/lua/script/dto/kepler_abstract.py +47 -0
  39. bmcgo/codegen/lua/script/dto/options.py +33 -0
  40. bmcgo/codegen/lua/script/dto/print_simple.py +19 -0
  41. bmcgo/codegen/lua/script/dto/redfish_api.py +241 -0
  42. bmcgo/codegen/lua/script/dto/url_route.py +195 -0
  43. bmcgo/codegen/lua/script/gen_db_json.py +444 -0
  44. bmcgo/codegen/lua/script/gen_depends.py +89 -0
  45. bmcgo/codegen/lua/script/gen_entry.py +263 -0
  46. bmcgo/codegen/lua/script/gen_feature_json.py +156 -0
  47. bmcgo/codegen/lua/script/gen_historical_local_db_json.py +88 -0
  48. bmcgo/codegen/lua/script/gen_intf_json.py +261 -0
  49. bmcgo/codegen/lua/script/gen_intf_rpc_json.py +575 -0
  50. bmcgo/codegen/lua/script/gen_ipmi_json.py +485 -0
  51. bmcgo/codegen/lua/script/gen_mdb_json.py +117 -0
  52. bmcgo/codegen/lua/script/gen_rpc_msg_json.py +487 -0
  53. bmcgo/codegen/lua/script/gen_schema.py +302 -0
  54. bmcgo/codegen/lua/script/ipmi_types_pb2.py +135 -0
  55. bmcgo/codegen/lua/script/loader/__init__.py +11 -0
  56. bmcgo/codegen/lua/script/loader/file_utils.py +33 -0
  57. bmcgo/codegen/lua/script/loader/kepler_abstract_collect.py +79 -0
  58. bmcgo/codegen/lua/script/loader/kepler_abstract_loader.py +47 -0
  59. bmcgo/codegen/lua/script/loader/redfish_loader.py +127 -0
  60. bmcgo/codegen/lua/script/lua_format.py +62 -0
  61. bmcgo/codegen/lua/script/mds_util.py +385 -0
  62. bmcgo/codegen/lua/script/merge_model.py +330 -0
  63. bmcgo/codegen/lua/script/merge_proto_algo.py +85 -0
  64. bmcgo/codegen/lua/script/proto_loader.py +47 -0
  65. bmcgo/codegen/lua/script/proto_plugin.py +140 -0
  66. bmcgo/codegen/lua/script/redfish_source_tree.py +118 -0
  67. bmcgo/codegen/lua/script/render_utils/__init__.py +38 -0
  68. bmcgo/codegen/lua/script/render_utils/base.py +25 -0
  69. bmcgo/codegen/lua/script/render_utils/client_lua.py +98 -0
  70. bmcgo/codegen/lua/script/render_utils/controller_lua.py +71 -0
  71. bmcgo/codegen/lua/script/render_utils/db_lua.py +224 -0
  72. bmcgo/codegen/lua/script/render_utils/error_lua.py +185 -0
  73. bmcgo/codegen/lua/script/render_utils/factory.py +52 -0
  74. bmcgo/codegen/lua/script/render_utils/ipmi_lua.py +159 -0
  75. bmcgo/codegen/lua/script/render_utils/ipmi_message_lua.py +24 -0
  76. bmcgo/codegen/lua/script/render_utils/mdb_lua.py +177 -0
  77. bmcgo/codegen/lua/script/render_utils/mdb_register.py +215 -0
  78. bmcgo/codegen/lua/script/render_utils/message_lua.py +26 -0
  79. bmcgo/codegen/lua/script/render_utils/messages_lua.py +156 -0
  80. bmcgo/codegen/lua/script/render_utils/model_lua.py +485 -0
  81. bmcgo/codegen/lua/script/render_utils/old_model_lua.py +429 -0
  82. bmcgo/codegen/lua/script/render_utils/plugin_lua.py +38 -0
  83. bmcgo/codegen/lua/script/render_utils/redfish_proto.py +86 -0
  84. bmcgo/codegen/lua/script/render_utils/request_lua.py +76 -0
  85. bmcgo/codegen/lua/script/render_utils/service_lua.py +130 -0
  86. bmcgo/codegen/lua/script/render_utils/utils_message_lua.py +125 -0
  87. bmcgo/codegen/lua/script/render_utils/validate_lua.py +221 -0
  88. bmcgo/codegen/lua/script/sep_ipmi_message_cmds.py +217 -0
  89. bmcgo/codegen/lua/script/template.py +166 -0
  90. bmcgo/codegen/lua/script/types_pb2.py +516 -0
  91. bmcgo/codegen/lua/script/utils.py +663 -0
  92. bmcgo/codegen/lua/script/validate.py +80 -0
  93. bmcgo/codegen/lua/script/yaml_to_json.py +73 -0
  94. bmcgo/codegen/lua/templates/Makefile +114 -0
  95. bmcgo/codegen/lua/templates/apps/Makefile +261 -0
  96. bmcgo/codegen/lua/templates/apps/Makefile.mdb.mk +64 -0
  97. bmcgo/codegen/lua/templates/apps/app.lua.mako +19 -0
  98. bmcgo/codegen/lua/templates/apps/class.lua.mako +35 -0
  99. bmcgo/codegen/lua/templates/apps/client.lua.mako +429 -0
  100. bmcgo/codegen/lua/templates/apps/controller.lua.mako +276 -0
  101. bmcgo/codegen/lua/templates/apps/datas.lua.mako +8 -0
  102. bmcgo/codegen/lua/templates/apps/db.lua.mako +89 -0
  103. bmcgo/codegen/lua/templates/apps/entry.lua.mako +128 -0
  104. bmcgo/codegen/lua/templates/apps/feature.lua.mako +37 -0
  105. bmcgo/codegen/lua/templates/apps/generate_route.mako +25 -0
  106. bmcgo/codegen/lua/templates/apps/impl_feature.lua.mako +72 -0
  107. bmcgo/codegen/lua/templates/apps/ipmi.lua.mako +97 -0
  108. bmcgo/codegen/lua/templates/apps/ipmi_cmd.lua.mako +18 -0
  109. bmcgo/codegen/lua/templates/apps/ipmi_message.lua.mako +36 -0
  110. bmcgo/codegen/lua/templates/apps/local_db.lua.mako +263 -0
  111. bmcgo/codegen/lua/templates/apps/main.lua.mako +25 -0
  112. bmcgo/codegen/lua/templates/apps/mc.lua.mako +77 -0
  113. bmcgo/codegen/lua/templates/apps/mdb.lua.mako +45 -0
  114. bmcgo/codegen/lua/templates/apps/mdb_interface.lua.mako +73 -0
  115. bmcgo/codegen/lua/templates/apps/message.lua.mako +38 -0
  116. bmcgo/codegen/lua/templates/apps/model.lua.mako +239 -0
  117. bmcgo/codegen/lua/templates/apps/orm_classes.lua.mako +16 -0
  118. bmcgo/codegen/lua/templates/apps/plugin.lua.mako +8 -0
  119. bmcgo/codegen/lua/templates/apps/redfish.proto.mako +47 -0
  120. bmcgo/codegen/lua/templates/apps/service.lua.mako +440 -0
  121. bmcgo/codegen/lua/templates/apps/signal_listen.lua.mako +19 -0
  122. bmcgo/codegen/lua/templates/apps/utils/default_intf.lua.mako +41 -0
  123. bmcgo/codegen/lua/templates/apps/utils/enum.mako +10 -0
  124. bmcgo/codegen/lua/templates/apps/utils/imports.mako +13 -0
  125. bmcgo/codegen/lua/templates/apps/utils/mdb_intf.lua.mako +25 -0
  126. bmcgo/codegen/lua/templates/apps/utils/mdb_obj.lua.mako +23 -0
  127. bmcgo/codegen/lua/templates/apps/utils/message.mako +160 -0
  128. bmcgo/codegen/lua/templates/apps/utils/request.lua.mako +59 -0
  129. bmcgo/codegen/lua/templates/apps/utils/validate.mako +83 -0
  130. bmcgo/codegen/lua/templates/errors.lua.mako +36 -0
  131. bmcgo/codegen/lua/templates/messages.lua.mako +32 -0
  132. bmcgo/codegen/lua/templates/new_app/.clang-format.mako +170 -0
  133. bmcgo/codegen/lua/templates/new_app/.gitignore.mako +26 -0
  134. bmcgo/codegen/lua/templates/new_app/CHANGELOG.md.mako +0 -0
  135. bmcgo/codegen/lua/templates/new_app/CMakeLists.txt.mako +29 -0
  136. bmcgo/codegen/lua/templates/new_app/Makefile.mako +25 -0
  137. bmcgo/codegen/lua/templates/new_app/README.md.mako +0 -0
  138. bmcgo/codegen/lua/templates/new_app/conanfile.py.mako +7 -0
  139. bmcgo/codegen/lua/templates/new_app/config.cfg.mako +6 -0
  140. bmcgo/codegen/lua/templates/new_app/mds/model.json.mako +3 -0
  141. bmcgo/codegen/lua/templates/new_app/mds/service.json.mako +21 -0
  142. bmcgo/codegen/lua/templates/new_app/permissions.ini.mako +16 -0
  143. bmcgo/codegen/lua/templates/new_app/src/lualib/${project_name}_app.lua.mako +16 -0
  144. bmcgo/codegen/lua/templates/new_app/src/service/main.lua.mako +25 -0
  145. bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.conf.mako +9 -0
  146. bmcgo/codegen/lua/templates/new_app/test/integration/test_${project_name}.lua.mako +47 -0
  147. bmcgo/codegen/lua/templates/new_app/test/unit/test.lua.mako +23 -0
  148. bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/${project_name}.service.mako +18 -0
  149. bmcgo/codegen/lua/templates/new_app/user_conf/rootfs/etc/systemd/system/multi-user.target.wants/${project_name}.service.link +1 -0
  150. bmcgo/component/__init__.py +10 -0
  151. bmcgo/component/analysis/analysis.py +183 -0
  152. bmcgo/component/analysis/build_deps.py +165 -0
  153. bmcgo/component/analysis/data_deps.py +333 -0
  154. bmcgo/component/analysis/dep-rules.json +912 -0
  155. bmcgo/component/analysis/dep_node.py +110 -0
  156. bmcgo/component/analysis/intf_deps.py +163 -0
  157. bmcgo/component/analysis/intf_validation.py +254 -0
  158. bmcgo/component/analysis/rule.py +211 -0
  159. bmcgo/component/analysis/smc_dfx_whitelist.json +11 -0
  160. bmcgo/component/analysis/sr_validation.py +391 -0
  161. bmcgo/component/build.py +222 -0
  162. bmcgo/component/component_dt_version_parse.py +348 -0
  163. bmcgo/component/component_helper.py +114 -0
  164. bmcgo/component/coverage/__init__.py +11 -0
  165. bmcgo/component/coverage/c_incremental_cov_report.template +53 -0
  166. bmcgo/component/coverage/incremental_cov.py +464 -0
  167. bmcgo/component/deploy.py +110 -0
  168. bmcgo/component/gen.py +169 -0
  169. bmcgo/component/package_info.py +236 -0
  170. bmcgo/component/template/conanbase.py.mako +278 -0
  171. bmcgo/component/template/conanfile.deploy.py.mako +40 -0
  172. bmcgo/component/test.py +947 -0
  173. bmcgo/errors.py +119 -0
  174. bmcgo/frame.py +217 -0
  175. bmcgo/functional/__init__.py +10 -0
  176. bmcgo/functional/analysis.py +96 -0
  177. bmcgo/functional/bmc_studio_action.py +98 -0
  178. bmcgo/functional/check.py +185 -0
  179. bmcgo/functional/conan_index_build.py +251 -0
  180. bmcgo/functional/config.py +332 -0
  181. bmcgo/functional/csr_build.py +724 -0
  182. bmcgo/functional/deploy.py +263 -0
  183. bmcgo/functional/diff.py +235 -0
  184. bmcgo/functional/fetch.py +235 -0
  185. bmcgo/functional/full_component.py +391 -0
  186. bmcgo/functional/maintain.py +381 -0
  187. bmcgo/functional/new.py +166 -0
  188. bmcgo/functional/schema_valid.py +111 -0
  189. bmcgo/functional/simple_sign.py +104 -0
  190. bmcgo/functional/upgrade.py +78 -0
  191. bmcgo/ipmigen/__init__.py +13 -0
  192. bmcgo/ipmigen/ctype_defination.py +82 -0
  193. bmcgo/ipmigen/ipmigen.py +309 -0
  194. bmcgo/ipmigen/template/cmd.c.mako +366 -0
  195. bmcgo/ipmigen/template/ipmi.c.mako +25 -0
  196. bmcgo/ipmigen/template/ipmi.h.mako +51 -0
  197. bmcgo/logger.py +176 -0
  198. bmcgo/misc.py +117 -0
  199. bmcgo/target/app.yml +17 -0
  200. bmcgo/target/install_sdk.yml +15 -0
  201. bmcgo/target/personal.yml +53 -0
  202. bmcgo/target/publish.yml +45 -0
  203. bmcgo/tasks/__init__.py +11 -0
  204. bmcgo/tasks/download_buildtools_hm.py +124 -0
  205. bmcgo/tasks/misc.py +15 -0
  206. bmcgo/tasks/task.py +354 -0
  207. bmcgo/tasks/task_build_conan.py +714 -0
  208. bmcgo/tasks/task_build_rootfs_img.py +595 -0
  209. bmcgo/tasks/task_buildgppbin.py +88 -0
  210. bmcgo/tasks/task_buildhpm_ext4.py +82 -0
  211. bmcgo/tasks/task_create_interface_config.py +122 -0
  212. bmcgo/tasks/task_download_buildtools.py +99 -0
  213. bmcgo/tasks/task_download_dependency.py +72 -0
  214. bmcgo/tasks/task_hpm_envir_prepare.py +112 -0
  215. bmcgo/tasks/task_packet_to_supporte.py +87 -0
  216. bmcgo/tasks/task_prepare.py +105 -0
  217. bmcgo/tasks/task_sign_and_pack_hpm.py +42 -0
  218. bmcgo/utils/__init__.py +10 -0
  219. bmcgo/utils/buffer.py +128 -0
  220. bmcgo/utils/combine_json_schemas.py +170 -0
  221. bmcgo/utils/component_post.py +54 -0
  222. bmcgo/utils/component_version_check.py +86 -0
  223. bmcgo/utils/config.py +1067 -0
  224. bmcgo/utils/fetch_component_code.py +232 -0
  225. bmcgo/utils/install_manager.py +61 -0
  226. bmcgo/utils/installations/__init__.py +10 -0
  227. bmcgo/utils/installations/base_installer.py +70 -0
  228. bmcgo/utils/installations/install_consts.py +30 -0
  229. bmcgo/utils/installations/install_plans/bingo.yml +11 -0
  230. bmcgo/utils/installations/install_workflow.py +50 -0
  231. bmcgo/utils/installations/installers/apt_installer.py +177 -0
  232. bmcgo/utils/installations/installers/pip_installer.py +46 -0
  233. bmcgo/utils/installations/version_util.py +100 -0
  234. bmcgo/utils/mapping_config_patch.py +443 -0
  235. bmcgo/utils/perf_analysis.py +114 -0
  236. bmcgo/utils/tools.py +704 -0
  237. bmcgo/worker.py +417 -0
  238. openubmc_bingo-0.5.240.dist-info/METADATA +30 -0
  239. openubmc_bingo-0.5.240.dist-info/RECORD +242 -0
  240. openubmc_bingo-0.5.240.dist-info/WHEEL +5 -0
  241. openubmc_bingo-0.5.240.dist-info/entry_points.txt +2 -0
  242. openubmc_bingo-0.5.240.dist-info/top_level.txt +1 -0
@@ -0,0 +1,381 @@
1
+ #!/usr/bin/env python3
2
+ # encoding=utf-8
3
+ # Copyright (c) 2025 Huawei Technologies Co., Ltd.
4
+ # openUBMC is licensed under Mulan PSL v2.
5
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
6
+ # You may obtain a copy of Mulan PSL v2 at:
7
+ # http://license.coscl.org.cn/MulanPSL2
8
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11
+ # See the Mulan PSL v2 for more details.
12
+ import os
13
+ import argparse
14
+ import tempfile
15
+ import stat
16
+ import shutil
17
+ import re
18
+ import filecmp
19
+ import yaml
20
+ from colorama import Fore, Style
21
+ from git import Repo
22
+ from git import Commit
23
+ from bmcgo.misc import CommandInfo
24
+ from bmcgo.utils.tools import Tools
25
+ from bmcgo.component.build import BuildComp
26
+ from bmcgo import errors
27
+ from bmcgo.bmcgo_config import BmcgoConfig
28
+ from bmcgo import misc
29
+
30
+ tool = Tools("maintain")
31
+ log = tool.log
32
+ command_info: CommandInfo = CommandInfo(
33
+ group="Misc commands",
34
+ name="maintain",
35
+ description=["组件维护,按conan方式生成维护组件构建脚本, 同时维护版本号、patch等"],
36
+ hidden=True
37
+ )
38
+ CONANDATA_SOURCES = "sources"
39
+ CONANDATA_VERSIONS = "versions"
40
+ CONANDATA_PATCHES = "patches"
41
+ PATCH_FILE_KEY = "patch_file"
42
+
43
+
44
+ def if_available(bconfig: BmcgoConfig):
45
+ return bconfig.conan_index is not None
46
+
47
+
48
+ class PatchInfo():
49
+ def __init__(self, commit: Commit):
50
+ self.commit = commit
51
+ log.info("补丁提交信息 =============================>>>>")
52
+ log.info(self.commit.message)
53
+ log.info("补丁提交信息 =============================<<<<")
54
+
55
+ @property
56
+ def author(self):
57
+ return self.commit.author.name
58
+
59
+ @property
60
+ def description(self):
61
+ match = re.search("(【修改描述】(.*))\n", self.commit.message)
62
+ if match:
63
+ return match.group(1)
64
+ lines = self.commit.message.split("\n")
65
+ for line in lines:
66
+ if line.strip() == "":
67
+ continue
68
+ if re.search("merge.*into.*", line):
69
+ continue
70
+ return line.strip()
71
+
72
+ @property
73
+ def merged_by(self):
74
+ match = re.search("Merged-by: (.*)\n", self.commit.message)
75
+ if match:
76
+ return match.group(1)
77
+ raise RuntimeError("无法找到合法的Merged-by合入人信息,请检查待提取的提交节点是否正确配置")
78
+
79
+
80
+ class BmcgoCommand:
81
+ url = None
82
+ tag = None
83
+ revision = None
84
+ next_version = None
85
+ sub_folder = None
86
+ recipe_folder = None
87
+ conan_folder = None
88
+
89
+ def __init__(self, bconfig: BmcgoConfig, *args):
90
+ self.patch_file = []
91
+ self.bconfig = bconfig
92
+ parser = argparse.ArgumentParser(prog="bmcgo maintain", description="BMC组件的维护管理工具", add_help=True,
93
+ formatter_class=argparse.RawTextHelpFormatter)
94
+ parser.add_argument("-cp", "--conan_package", help="指定需要维护的组件版本,示例:component/1.2.3", required=True)
95
+ parser.add_argument("-p", "--patch_file", help="添加patch文件,可指定多个,顺序追加到代码中", action='append')
96
+ parser.add_argument("-b", "--branch", help="用于提取patch的分支,与commit_id配合使用", default="master")
97
+ parser.add_argument("-c", "--commit_id", help="需要生成patch的提交节点,长度不低于8个字符,可指定多个,顺序追加到代码中",
98
+ action='append')
99
+ parser.add_argument("-v", "--version", help="指定需要生成的组件版本号", default=None)
100
+ parser.add_argument("-r", "--remote", default=misc.CONAN_REPO,
101
+ help="conan远程仓,请检查conan remote list查看已配置的conan仓")
102
+ parsed_args = parser.parse_args(*args)
103
+ cp = parsed_args.conan_package
104
+ if (not re.match("^[a-zA-Z0-9_-]+/([1-9][0-9]*|[0-9])\.[0-9]+\.[0-9]+$", cp) and
105
+ not re.match("^[a-zA-Z0-9_-]+/(([1-9][0-9]*|[0-9])\.[0-9]+\.[0-9]+)(-build\.[0-9]+)$", cp) and
106
+ not re.match("^[a-zA-Z0-9_-]+/(([1-9][0-9]*|[0-9])\.[0-9]+\.[0-9]+)(.p[0-9]+)$" + cp)):
107
+ raise errors.BmcGoException("-cp参数错误,不满足格式\"<name>/<version>\"要求")
108
+ self.conan_package = cp
109
+ self.name = self.conan_package.split("/")[0]
110
+ self.base_version = self.conan_package.split("/")[1]
111
+ self.remote = parsed_args.remote
112
+ self.arg_special_version = parsed_args.version
113
+ if parsed_args.patch_file is None:
114
+ parsed_args.patch_file = []
115
+ for patch_file in parsed_args.patch_file:
116
+ if not os.path.isfile(patch_file):
117
+ raise errors.BmcGoException(f"补丁文件 {patch_file} 不存在")
118
+ self.patch_file.append(os.path.realpath(patch_file))
119
+
120
+ # 待提取的提交节点基本信息
121
+ self.patch_commit: dict[str, PatchInfo] = {}
122
+ self.branch = parsed_args.branch
123
+ self.commit_id = parsed_args.commit_id
124
+ if self.commit_id is None:
125
+ self.commit_id = []
126
+ for commit in self.commit_id:
127
+ if re.match(r"^[a-f0-9]{8,40}$", commit) is None:
128
+ raise errors.ConfigException(f"参数错误, --commit_id({commit}) 格式错误")
129
+ self.patch_description = ""
130
+ self.dir = tempfile.TemporaryDirectory(prefix="bmcgo_maint")
131
+ for file in self.patch_file:
132
+ if not os.path.isfile(file):
133
+ raise errors.BmcGoException(f"补丁文件 {file} 不存在")
134
+ log.debug(f"临时文件夹: {self.dir.name}")
135
+
136
+ def run(self):
137
+ self._fetch_conan_info()
138
+ os.chdir(self.dir.name)
139
+ log.info(f"开始克隆 {self.url}")
140
+ repo = Repo.clone_from(self.url, ".")
141
+ repo.git.checkout(self.tag)
142
+ if not os.path.isfile("mds/service.json"):
143
+ raise errors.NotFoundException("文件 mds/service.json 不存在, 可能不是一个有效的组件")
144
+ # 生成conanbase.py和conanfile.yml
145
+ log.info(f"生成 conanfil.py 和conanbase.py")
146
+ bconfig = BmcgoConfig()
147
+ comp = BuildComp(bconfig, ["--maintain"], gen_conanbase=True)
148
+ self.recipe_folder = os.path.join(self.bconfig.conan_index.folder, comp.info.name)
149
+ if not os.path.isdir(self.recipe_folder):
150
+ os.makedirs(self.recipe_folder)
151
+ self._update_next_version()
152
+
153
+ conanfile = os.path.realpath("conanfile.py")
154
+ conanbase = os.path.realpath("conanbase.py")
155
+ if not os.path.isfile(conanfile):
156
+ raise errors.NotFoundException("文件 conanfile.py 不存在, 可能不是一个有效的组件")
157
+ if not os.path.isfile(conanbase):
158
+ raise errors.NotFoundException("文件 conanbase.py 不存在, 可能不是一个有效的组件")
159
+ # 计算recipe目录
160
+ self.sub_folder = self.next_version + ".x"
161
+ while self.sub_folder != ".x":
162
+ self.conan_folder = os.path.join(self.recipe_folder, self.sub_folder)
163
+ # 找到recipe
164
+ if not self._recipe_need_change(conanfile, conanbase):
165
+ break
166
+ self.conan_folder = None
167
+ self.sub_folder = ".".join(self.sub_folder.split(".")[0:-2]) + ".x"
168
+ if not self.conan_folder:
169
+ # 默认是版号前2段 + ".x"
170
+ self.sub_folder = ".".join(self.next_version.split(".")[0:2]) + ".x"
171
+
172
+ self.conan_folder = os.path.join(self.recipe_folder, self.sub_folder)
173
+ if not os.path.isdir(self.conan_folder):
174
+ os.makedirs(self.conan_folder)
175
+
176
+ self._gen_patches(repo)
177
+ if not self._gen_conandata():
178
+ return -1
179
+ self._gen_config()
180
+ shutil.copyfile(conanfile, os.path.join(self.conan_folder, "conanfile.py"))
181
+ shutil.copyfile(conanbase, os.path.join(self.conan_folder, "conanbase.py"))
182
+ log.success(f"生成维护版本 {self.name}/{self.next_version} 成功")
183
+ return 0
184
+
185
+ def _fetch_conan_info(self):
186
+ user = tool.conan_user
187
+ export_path = os.path.join(tool.conan_data, self.conan_package, f"{user}/stable", "export")
188
+ if not os.path.isdir(export_path):
189
+ cmd = f"conan download {self.conan_package}@{user}/stable -r {self.remote} -re"
190
+ tool.run_command(cmd, error_log=f"组件 {self.conan_package} 未找到,请检查网络连接以及该版本是否已发布")
191
+ conanfile = os.path.join(export_path, "conanfile.py")
192
+ conandata = os.path.join(export_path, "conandata.yml")
193
+ if os.path.isfile(conandata):
194
+ log.info(f"从 {conandata} 读取源码tag的url")
195
+ # 尝试从conandata中获取代码仓地址
196
+ with open(conandata, "r") as fp:
197
+ data = yaml.safe_load(fp)
198
+ cfg = data.get("sources", {}).get(self.base_version)
199
+ if cfg is None:
200
+ raise RuntimeError(f"${conandata}不存在组件 {self.conan_package} 配置, 请检查是否正确")
201
+ self.url = cfg.get("url")
202
+ branch = cfg.get("branch")
203
+ if re.match("^refs/tags/[0-9]+\\.[0-9]+\\.[0-9]+$", branch):
204
+ self.tag = branch[len("refs/tags/"):]
205
+ else:
206
+ raise RuntimeError(f"${conandata}的组件 {self.conan_package} 配置错误, 未找到有效的tag")
207
+ else:
208
+ log.info(f"从 {conanfile} 读取源码tag的url")
209
+ self.tag = self.base_version
210
+ with open(conanfile, "r") as fp:
211
+ lines = fp.readlines()
212
+ for idx, line in enumerate(lines):
213
+ if line.find('scm = {"revision":') > 0:
214
+ self.url = re.split(r'["]', lines[idx + 2])[-2]
215
+ break
216
+ else:
217
+ raise RuntimeError("无法找到版本(revision)和地址(url)字段")
218
+
219
+ def _update_next_version(self):
220
+ self.next_version = self.arg_special_version
221
+ if not self.next_version:
222
+ if re.match("^(([1-9][0-9]*|[0-9])\.[0-9]+\.[0-9]+)(-build\.[0-9]+)$", self.base_version):
223
+ temp_version = self.base_version.split(".")
224
+ temp_version[-1] = str(int(temp_version[-1]) + 1)
225
+ self.next_version = ".".join(temp_version)
226
+ else:
227
+ self.next_version = self.base_version.split("-")[0] + "-build.1"
228
+ log.info(f"自动生成的版本号为 {Fore.GREEN}{self.next_version}{Style.RESET_ALL}")
229
+ version = input("请回车确认 或者 输入你期望的版本号(必须以-build.x结束,如1.2.3-build.1): ").strip()
230
+ if version:
231
+ self.next_version = version
232
+ if not self.arg_special_version and "-build." not in self.next_version:
233
+ raise errors.BmcGoException(f"版本号格式必须以-build.x结束,如1.2.3-build.1")
234
+ restr = r"^(([1-9][0-9]*|[0-9])\.[0-9]+\.[0-9]+)(-build\.[1-9][0-9]*)?$"
235
+ match = re.match(restr, self.next_version)
236
+ if not match:
237
+ raise errors.BmcGoException(f"版本号 {self.next_version} 不满足正则表达式 '{restr}' 要求")
238
+ log.info(f"创建组件版本 {Fore.GREEN}{self.next_version}{Style.RESET_ALL}")
239
+
240
+ def _gen_patches(self, repo: Repo):
241
+ # 用户指定patch
242
+ patches_dir = os.path.join(self.conan_folder, "..", CONANDATA_PATCHES)
243
+ if len(self.patch_file) > 0 and not os.path.isdir(patches_dir):
244
+ os.makedirs(patches_dir)
245
+ for file in self.patch_file:
246
+ patch_file = os.path.join(patches_dir, os.path.basename(file))
247
+ if not os.path.isfile(patch_file) or not filecmp.cmp(file, patch_file):
248
+ log.info(f"复制补丁文件 {patch_file}")
249
+ shutil.copyfile(file, patch_file)
250
+
251
+ if len(self.commit_id) == 0:
252
+ return
253
+ # 从代码仓生成patch
254
+ if not os.path.isdir(patches_dir):
255
+ os.makedirs(patches_dir)
256
+
257
+ repo.git.checkout(self.branch)
258
+ for commit_id in self.commit_id:
259
+ found = False
260
+ for commit in repo.iter_commits():
261
+ if commit.hexsha.startswith(commit_id):
262
+ commit_id = commit.hexsha
263
+ found = True
264
+ break
265
+ if not found:
266
+ raise errors.ParameterException(f"无效的提交节点: {commit_id}")
267
+ log.info(f"开始生成补丁文件, 提交节点: {commit_id}")
268
+ patch_info = PatchInfo(commit)
269
+ cmd = f"git format-patch -1 {commit_id} --numbered-files -- ':!mds/service.json' ':!CHANGELOG*'"
270
+ cmd += " ':!ChangeLog*'"
271
+ tool.run_command(cmd)
272
+ patch_id = 0
273
+ while True:
274
+ if patch_id == 0:
275
+ patch_file = os.path.join(patches_dir, commit.hexsha + ".patch")
276
+ else:
277
+ patch_file = os.path.join(patches_dir, commit.hexsha + f"_{patch_id}.patch")
278
+ if not os.path.isfile(patch_file) or filecmp.cmp("1", patch_file):
279
+ break
280
+ log.warning(f"待生成的补丁 与 {patch_file} 不一致,尝试生成新的补丁文件名")
281
+ patch_id += 1
282
+ shutil.copyfile("1", patch_file)
283
+ log.success(f"补丁文件 {patch_file} 创建成功")
284
+ self.patch_file.append(patch_file)
285
+ self.patch_commit[patch_file] = patch_info
286
+
287
+ def _gen_config(self):
288
+ """生成config.yml文件"""
289
+ config_file = os.path.join(self.recipe_folder, "config.yml")
290
+ config = {}
291
+ if os.path.isfile(config_file):
292
+ with open(config_file, "r") as fp:
293
+ config = yaml.safe_load(fp)
294
+ if config.get(CONANDATA_VERSIONS) is None:
295
+ config[CONANDATA_VERSIONS] = {}
296
+ config[CONANDATA_VERSIONS][self.next_version] = {
297
+ "folder": os.path.basename(self.sub_folder)
298
+ }
299
+ with os.fdopen(os.open(config_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
300
+ stat.S_IWUSR | stat.S_IRUSR), 'w') as file_handler:
301
+ yaml.dump(config, file_handler, encoding='utf-8', allow_unicode=True)
302
+
303
+ def _recipe_need_change(self, conanfile, conanbase):
304
+ """检查recipe目录是否需要切换"""
305
+ ori_conanfile = os.path.join(self.conan_folder, "conanfile.py")
306
+ ori_conanbase = os.path.join(self.conan_folder, "conanbase.py")
307
+ # 文件不存在时无需切换
308
+ if not os.path.isfile(ori_conanfile) or not os.path.isfile(ori_conanbase):
309
+ return True
310
+ # 文件完全相同时无需切换
311
+ if filecmp.cmp(ori_conanfile, conanfile) and filecmp.cmp(ori_conanbase, conanbase):
312
+ return False
313
+ # 其它场景需要切换
314
+ return True
315
+
316
+ def _get_prev_patches(self):
317
+ """获取上个版本的补丁列表"""
318
+ config_file = os.path.join(self.recipe_folder, "config.yml")
319
+ if not os.path.isfile(config_file):
320
+ return []
321
+ with open(config_file, "r") as fp:
322
+ config = yaml.safe_load(fp)
323
+ folder = config.get("versions", {}).get(self.base_version, {}).get("folder")
324
+ if folder is None:
325
+ return []
326
+ config_file = os.path.join(self.recipe_folder, folder, "conandata.yml")
327
+ if not os.path.isfile(config_file):
328
+ return []
329
+ with open(config_file, "r") as fp:
330
+ config = yaml.safe_load(fp)
331
+ return config.get("patches", {}).get(self.base_version, [])
332
+
333
+ def _gen_conandata(self):
334
+ """生成conandata.yml文件"""
335
+ config_file = os.path.join(self.conan_folder, "conandata.yml")
336
+ config = {}
337
+ if os.path.isfile(config_file):
338
+ with open(config_file, "r") as fp:
339
+ config = yaml.safe_load(fp)
340
+ if config.get(CONANDATA_SOURCES) is None:
341
+ config[CONANDATA_SOURCES] = {}
342
+ source = {
343
+ "url": self.url,
344
+ "branch": f"refs/tags/{self.tag}",
345
+ "shallow": True
346
+ }
347
+ if config.get(CONANDATA_PATCHES) is None:
348
+ config[CONANDATA_PATCHES] = {}
349
+ patches = config[CONANDATA_PATCHES].get(self.next_version, [])
350
+ if not patches:
351
+ patches = self._get_prev_patches()
352
+ for file in self.patch_file:
353
+ found = False
354
+ for patch in patches:
355
+ if patch.get(PATCH_FILE_KEY, "") == "patches/" + os.path.basename(file):
356
+ found = True
357
+ break
358
+ if found:
359
+ continue
360
+ patch_item = {}
361
+ commit = self.patch_commit.get(file)
362
+ if commit:
363
+ patch_item["description"] = commit.description
364
+ patch_item["author"] = commit.author
365
+ patch_item["merged_by"] = commit.merged_by
366
+ patch_item["commit_id"] = commit.commit.hexsha
367
+ patch_item[PATCH_FILE_KEY] = "patches/" + os.path.basename(file)
368
+ patches.append(patch_item)
369
+ for patch in patches:
370
+ log.success(f"组件 {self.next_version} 包含补丁文件: " + patch.get(PATCH_FILE_KEY))
371
+ log.info(f" description: " + patch.get("description", ""))
372
+ log.info(f" author: " + patch.get("author", ""))
373
+ log.info(f" merged_by: " + patch.get("merged_by", ""))
374
+ log.info(f" commit_id: " + patch.get("commit_id", ""))
375
+ config[CONANDATA_SOURCES][self.next_version] = source
376
+ config[CONANDATA_PATCHES][self.next_version] = patches
377
+ log.info(f"生成 {config_file}")
378
+ with os.fdopen(os.open(config_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
379
+ stat.S_IWUSR | stat.S_IRUSR), 'w') as file_handler:
380
+ yaml.dump(config, file_handler, encoding='utf-8', allow_unicode=True, sort_keys=False)
381
+ return True
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env python3
2
+ # encoding=utf-8
3
+ # 描述:创建组件
4
+ # Copyright (c) 2024 Huawei Technologies Co., Ltd.
5
+ # openUBMC is licensed under Mulan PSL v2.
6
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
7
+ # You may obtain a copy of Mulan PSL v2 at:
8
+ # http://license.coscl.org.cn/MulanPSL2
9
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12
+ # See the Mulan PSL v2 for more details.
13
+ import os
14
+ import sys
15
+ import select
16
+ import argparse
17
+ import shutil
18
+ import subprocess
19
+ from bmcgo.bmcgo_config import BmcgoConfig
20
+ from bmcgo.utils.tools import Tools
21
+ from bmcgo import misc
22
+
23
+ tools = Tools("new")
24
+ log = tools.log
25
+ cwd = os.getcwd()
26
+
27
+ command_info: misc.CommandInfo = misc.CommandInfo(
28
+ group="Misc commands",
29
+ name="new",
30
+ description=["创建组件"],
31
+ hidden=False
32
+ )
33
+
34
+
35
+ def if_available(bconfig: BmcgoConfig):
36
+ return True
37
+
38
+
39
+ _LUA = "lua"
40
+ _APP = "application"
41
+ _DEFAULT = ""
42
+ # 必选项:选项缩写,选项,选项的中文说明
43
+ _REQUIRES = [["n", "name", "组件名"]]
44
+ # 可选项:选项缩写,选项,选项的中文说明,可选值,默认值
45
+ _OPTIONS = [["t", "type", "组件类型", ["application"], "application"], ["l", "language", "组件编程语言", ["lua"], "lua"]]
46
+ # 环境中存放bmcgo自动生成工具相对的目录,组件中存放bmcgo自动生成工具的临时相对目录,模板脚本的相对路径,模板的相对目录
47
+ _TEMPLATES = {
48
+ _LUA : {
49
+ _APP : ['codegen/lua', 'temp/lua_codegen', 'script/template.py', 'templates/new_app']
50
+ }
51
+ }
52
+
53
+
54
+ class BmcgoCommand:
55
+ def __init__(self, bconfig: BmcgoConfig, *args):
56
+ self.bconfig = bconfig
57
+ parser = argparse.ArgumentParser(prog="bingo new", description="创建组件", add_help=True,
58
+ formatter_class=argparse.RawTextHelpFormatter)
59
+ for item in _REQUIRES:
60
+ parser.add_argument(f"-{item[0]}", f"--{item[1]}", help=f"指定{item[2]}", required=True)
61
+ for item in _OPTIONS:
62
+ parser.add_argument(f"-{item[0]}", f"--{item[1]}", help=f"指定{item[2]}, " +
63
+ f"可选值: {', '.join(item[3])}\n默认: {item[4]}")
64
+
65
+ parsed_args, _ = parser.parse_known_args(*args)
66
+ self.name = parsed_args.name
67
+ self.type = parsed_args.type
68
+ self.language = parsed_args.language
69
+ self.path = os.path.join(cwd, self.name)
70
+
71
+ def run(self):
72
+ if os.path.exists(self.path):
73
+ log.error(f"当前目录下已存在{self.name}子目录, 无法创建{self.name}组件")
74
+ return -1
75
+
76
+ if not self._check_options():
77
+ return -1
78
+
79
+ self._ask_options()
80
+
81
+ self._render()
82
+
83
+ return 0
84
+
85
+ def _check_options(self):
86
+ for item in _OPTIONS:
87
+ val = getattr(self, item[1])
88
+ if not val:
89
+ continue
90
+
91
+ if val.lower() not in item[3]:
92
+ log.error(f"无效的{item[2]}: {val}")
93
+ return False
94
+
95
+ setattr(self, item[1], val.lower())
96
+
97
+ return True
98
+
99
+ def _ask_options(self):
100
+ for item in _OPTIONS:
101
+ if not getattr(self, item[1]):
102
+ self._ask_option(item)
103
+
104
+ def _ask_option(self, item):
105
+ option_str = ''
106
+ index = 0
107
+ while index < len(item[3]):
108
+ if index != 0:
109
+ option_str += ', '
110
+ option_str += str(index + 1) + ": " + item[3][index]
111
+ index += 1
112
+
113
+ log.info(f"请指定{item[2]}后回车({option_str}), 不指定则使用默认值{item[4]}")
114
+ while True:
115
+ select_in, _, _ = select.select([sys.stdin], [], [], 10)
116
+ c_item = sys.stdin.readline().strip().lower()
117
+ if c_item == _DEFAULT:
118
+ c_item = item[4]
119
+ elif c_item.isdigit() and (int(c_item) >= 1 and int(c_item) <= len(item[3])):
120
+ c_item = item[3][int(c_item) - 1]
121
+ if select_in is None or c_item not in item[3]:
122
+ log.error(f"不支持的{item[2]}选项, 请重新输入")
123
+ continue
124
+
125
+ setattr(self, item[1], c_item)
126
+ break
127
+
128
+ def _render(self):
129
+ log.info(f"请稍等, 组件生成中...")
130
+ template = _TEMPLATES[self.language][self.type]
131
+ gen_tool_dir = os.path.join(self.name, template[1])
132
+ shutil.rmtree(gen_tool_dir, ignore_errors=True)
133
+ shutil.copytree(f"{os.path.dirname(__file__)}/../{template[0]}", gen_tool_dir)
134
+
135
+ script_file = os.path.join(gen_tool_dir, template[2])
136
+ template_dir = os.path.join(gen_tool_dir, template[3])
137
+
138
+ for root, _, files in os.walk(template_dir):
139
+ rel_dir = os.path.relpath(root, template_dir)
140
+ out_dir = os.path.join(cwd, self.name, rel_dir)
141
+ os.makedirs(out_dir, exist_ok=True)
142
+ for file in files:
143
+ template_path = os.path.join(root, file)
144
+ out_file = file.replace("${project_name}", self.name)
145
+ out_file = out_file[:(len(out_file)-5)]
146
+ if file.endswith('.link'):
147
+ self._link(out_dir, template_path, out_file)
148
+ continue
149
+
150
+ out_path = os.path.join(out_dir, out_file)
151
+ cmd = [
152
+ "python3", script_file, "-n", self.name, "-t", template_path, "-o", out_path
153
+ ]
154
+ subprocess.run(cmd, env=dict(os.environ), check=True)
155
+ cmd = ["chmod", '644', out_path]
156
+ subprocess.run(cmd, env=dict(os.environ), check=True)
157
+ log.success(f"组件已生成到{self.path}目录")
158
+
159
+ def _link(self, out_dir, path, file_name):
160
+ with open(path, "r") as fp:
161
+ src_file = fp.read()
162
+ src_file = src_file.replace("${project_name}", self.name)
163
+ os.chdir(out_dir)
164
+ cmd = ["ln", "-s", src_file, file_name]
165
+ subprocess.run(cmd, env=dict(os.environ), check=True)
166
+ os.chdir(cwd)
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # 描述:检查当前目录下, .yml/.yaml 文件是否符合配置的 schema 规范
4
+ # Copyright (c) 2024 Huawei Technologies Co., Ltd.
5
+ # openUBMC is licensed under Mulan PSL v2.
6
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
7
+ # You may obtain a copy of Mulan PSL v2 at:
8
+ # http://license.coscl.org.cn/MulanPSL2
9
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10
+ # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11
+ # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12
+ # See the Mulan PSL v2 for more details.
13
+ import os
14
+ import json
15
+ import argparse
16
+
17
+ import yaml
18
+ import jsonschema
19
+ from jsonschema import exceptions as jc
20
+
21
+ from bmcgo.logger import Logger
22
+ from bmcgo.bmcgo_config import BmcgoConfig
23
+ from bmcgo import misc
24
+
25
+ log = Logger()
26
+ command_info: misc.CommandInfo = misc.CommandInfo(
27
+ group=misc.GRP_MISC,
28
+ name="validate_yml",
29
+ description=["对指定目录下所有yaml文件或指定yaml文件进行 schema 规范检查"],
30
+ hidden=True
31
+ )
32
+
33
+
34
+ def if_available(_: BmcgoConfig):
35
+ return True
36
+
37
+
38
+ class BmcgoCommand:
39
+ def __init__(self, bconfig: BmcgoConfig, *args):
40
+ """ yaml 文件根据 schema 文件进行规则检查
41
+
42
+ Args:
43
+ bconfig (BmcgoConfig): bmcgo 配置
44
+ """
45
+ self.bconfig = bconfig
46
+ parser = argparse.ArgumentParser(prog="bingo validate_yml", description="Validate yaml files", add_help=True,
47
+ formatter_class=argparse.RawTextHelpFormatter)
48
+ parser.add_argument("-t", "--target", help="目标文件夹或单个yaml文件,默认当前目录", default=".")
49
+
50
+ parsed_args = parser.parse_args(*args)
51
+ self.target = os.path.realpath(parsed_args.target)
52
+
53
+ @staticmethod
54
+ def schema_valid(check_file: str) -> bool:
55
+ """ 有效性校验
56
+
57
+ Args:
58
+ check_file (str): 要校验的文件名称
59
+ """
60
+ schema_file = misc.get_decleared_schema_file(check_file)
61
+ if schema_file == "":
62
+ log.warning(f"文件 {check_file} 没有配置 schema 检查")
63
+ return True
64
+ with open(schema_file, "rb") as fp:
65
+ schema = json.load(fp)
66
+ with open(check_file, "r") as fp:
67
+ check_data = yaml.safe_load(fp)
68
+ log.info("开始校验文件: %s", check_file)
69
+ try:
70
+ jsonschema.validate(check_data, schema)
71
+ log.success("校验成功: %s", check_file)
72
+ return True
73
+ except (jc.ValidationError, jc.SchemaError) as e:
74
+ log.error(f" >>>>>> {check_file} 校验失败 <<<<<<\n{e}")
75
+ return False
76
+
77
+ @staticmethod
78
+ def _is_yml_file(filename):
79
+ if filename.endswith((".yml", ".yaml")):
80
+ return True
81
+ return False
82
+
83
+ def run(self):
84
+ """ 分析参数并启动校验
85
+ """
86
+ check_result = []
87
+
88
+ if os.path.isfile(self.target):
89
+ check_result.append(self.schema_valid(self.target))
90
+ return 0
91
+
92
+ check_result = self._validate_yml_files()
93
+
94
+ if check_result and False in check_result:
95
+ log.error("请仔细阅读报错日志, 日志中会提示哪些是必要属性, 或哪个属性配置错误")
96
+ raise AttributeError(f"所有 .yml/.yaml 文件检查失败, 请仔细检查报错并解决问题项")
97
+ if not check_result:
98
+ log.warning("未找到yml文件")
99
+ return 0
100
+
101
+ def _validate_yml_files(self):
102
+ check_result = []
103
+ for root, _, files in os.walk(self.target):
104
+ for filename in files:
105
+ if not self._is_yml_file(filename):
106
+ continue
107
+ schema_file = os.path.join(root, filename)
108
+ check_result.append(self.schema_valid(schema_file))
109
+ return check_result
110
+
111
+