Skip to content

Commit 2338f5f

Browse files
committed
Merge branch 'shixin-ZCF-1365' into 'feature-5.5.12-zns'
<fix>[rest]: improve markdown validation error reporting See merge request zstackio/zstack!9529
2 parents d261b05 + 6db0908 commit 2338f5f

1 file changed

Lines changed: 97 additions & 78 deletions

File tree

rest/src/main/resources/scripts/RestDocumentationGenerator.groovy

Lines changed: 97 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -787,81 +787,91 @@ class RestDocumentationGenerator implements DocumentGenerator {
787787
return globalConfigMarkDown
788788
}
789789

790-
Boolean isConsistent(GlobalConfigMarkDown md, GlobalConfig globalConfig) {
791-
if (md == null || globalConfig == null) {
792-
return false
793-
}
790+
List<String> isConsistent(GlobalConfigMarkDown md, GlobalConfig globalConfig) {
791+
if (md == null) {
792+
return ["GlobalConfigMarkDown is null"]
793+
}
794+
if (globalConfig == null) {
795+
return ["GlobalConfig is null"]
796+
}
794797
String mdPath =
795798
PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(),
796799
"globalconfig"), md.globalConfig.category, md.globalConfig.name) + ".md"
797800
List<String> classes = new ArrayList<>()
798801
initializer.bindResources.get(globalConfig.getIdentity()).each { classes.add(it.getName()) }
799802
List<String> newClasses = classes.sort()
800803
String validatorString = initializer.validatorMap.get(globalConfig.getIdentity())
801-
Boolean flag = true
802-
if (md.globalConfig.name != globalConfig.name) {
803-
logger.info("name of ${mdPath} is not latest")
804-
flag = false
805-
}
806-
if (md.globalConfig.defaultValue != globalConfig.defaultValue) {
807-
logger.info("defaultValue of ${mdPath} is not latest")
808-
flag = false
809-
}
810-
if (StringUtils.trimToEmpty(md.globalConfig.description) != StringUtils.trimToEmpty(globalConfig.description)) {
811-
logger.info("desc of ${mdPath} is not latest")
812-
flag = false
813-
}
814-
if (md.globalConfig.type != globalConfig.type) {
815-
if (globalConfig.type != null) {
816-
logger.info("type of ${mdPath} is not latest")
817-
flag = false
818-
}
819-
}
820-
if (md.globalConfig.category != globalConfig.category) {
821-
logger.info("category of ${mdPath} is not latest")
822-
flag = false
823-
}
824-
List<String> oldClasses = md.globalConfig.resources.sort()
825-
if (oldClasses != newClasses) {
826-
logger.info("classes of ${mdPath} is not latest")
827-
flag = false
828-
}
804+
List<String> mismatches = []
805+
if (md.globalConfig.name != globalConfig.name) {
806+
logger.info("name of ${mdPath} is not latest")
807+
mismatches.add("name mismatch in ${mdPath}: markdown='${md.globalConfig.name}', current='${globalConfig.name}'")
808+
}
809+
if (md.globalConfig.defaultValue != globalConfig.defaultValue) {
810+
logger.info("defaultValue of ${mdPath} is not latest")
811+
mismatches.add("defaultValue mismatch in ${mdPath}: markdown='${md.globalConfig.defaultValue}', current='${globalConfig.defaultValue}'")
812+
}
813+
if (StringUtils.trimToEmpty(md.globalConfig.description) != StringUtils.trimToEmpty(globalConfig.description)) {
814+
logger.info("desc of ${mdPath} is not latest")
815+
mismatches.add("description mismatch in ${mdPath}: markdown='${StringUtils.trimToEmpty(md.globalConfig.description)}', current='${StringUtils.trimToEmpty(globalConfig.description)}'")
816+
}
817+
if (md.globalConfig.type != globalConfig.type) {
818+
if (globalConfig.type != null) {
819+
logger.info("type of ${mdPath} is not latest")
820+
mismatches.add("type mismatch in ${mdPath}: markdown='${md.globalConfig.type}', current='${globalConfig.type}'")
821+
}
822+
}
823+
if (md.globalConfig.category != globalConfig.category) {
824+
logger.info("category of ${mdPath} is not latest")
825+
mismatches.add("category mismatch in ${mdPath}: markdown='${md.globalConfig.category}', current='${globalConfig.category}'")
826+
}
827+
List<String> oldClasses = md.globalConfig.resources.sort()
828+
if (oldClasses != newClasses) {
829+
logger.info("classes of ${mdPath} is not latest")
830+
mismatches.add("resources mismatch in ${mdPath}: markdown='${oldClasses}', current='${newClasses}'")
831+
}
829832

830833
if (md.globalConfig.valueRange != (validatorString)) {
831834
boolean useBooleanValidator = (globalConfig.type == "java.lang.Boolean"
832835
&& md.globalConfig.valueRange == "{true, false}")
833-
if (validatorString != null || !useBooleanValidator) {
834-
logger.info("valueRange of ${mdPath} is not latest")
835-
logger.info("valueRange = ${md.globalConfig.valueRange} validatorString = ${validatorString}")
836-
flag = false
837-
}
838-
}
839-
return flag
840-
}
836+
if (validatorString != null || !useBooleanValidator) {
837+
logger.info("valueRange of ${mdPath} is not latest")
838+
logger.info("valueRange = ${md.globalConfig.valueRange} validatorString = ${validatorString}")
839+
mismatches.add("valueRange mismatch in ${mdPath}: markdown='${md.globalConfig.valueRange}', current='${validatorString}'")
840+
}
841+
}
842+
return mismatches
843+
}
841844

842845
void checkMD(String mdPath, GlobalConfig globalConfig) {
843846
String result = ShellUtils.runAndReturn(
844847
"grep '${PLACEHOLDER}' ${mdPath}").stdout.replaceAll("\n", "")
845-
if (!result.empty) {
846-
throw new CloudRuntimeException("Placeholders are detected in ${mdPath}, please replace them by content.")
847-
}
848-
GlobalConfigMarkDown markDown = getExistGlobalConfigMarkDown(mdPath)
849-
if (markDown.desc_CN.isEmpty()
850-
|| markDown.name_CN.isEmpty()
851-
|| markDown.valueRangeRemark.isEmpty()
852-
|| markDown.defaultValueRemark.isEmpty()
853-
|| markDown.resourcesGranularitiesRemark.isEmpty()
854-
|| markDown.additionalRemark.isEmpty()
855-
|| markDown.backgroundInformation.isEmpty()
856-
|| markDown.isUIExposed.isEmpty()
857-
|| markDown.isCLIExposed.isEmpty()
858-
) {
859-
throw new CloudRuntimeException("The necessary information of ${mdPath} is missing, please complete the information before submission.")
860-
}
861-
if (!isConsistent(markDown, globalConfig)) {
862-
throw new CloudRuntimeException("${mdPath} is not match with its definition, please use Repair mode to correct it.")
863-
}
864-
}
848+
if (!result.empty) {
849+
throw new CloudRuntimeException("Placeholders detected in ${mdPath}; please replace them with actual content.")
850+
}
851+
GlobalConfigMarkDown markDown = getExistGlobalConfigMarkDown(mdPath)
852+
List<String> missingFields = []
853+
if (markDown.desc_CN.isEmpty()) missingFields.add("desc_CN")
854+
if (markDown.name_CN.isEmpty()) missingFields.add("name_CN")
855+
if (markDown.valueRangeRemark.isEmpty()) missingFields.add("valueRangeRemark")
856+
if (markDown.defaultValueRemark.isEmpty()) missingFields.add("defaultValueRemark")
857+
if (markDown.resourcesGranularitiesRemark.isEmpty()) missingFields.add("resourcesGranularitiesRemark")
858+
if (markDown.additionalRemark.isEmpty()) missingFields.add("additionalRemark")
859+
if (markDown.backgroundInformation.isEmpty()) missingFields.add("backgroundInformation")
860+
if (markDown.isUIExposed.isEmpty()) missingFields.add("isUIExposed")
861+
if (markDown.isCLIExposed.isEmpty()) missingFields.add("isCLIExposed")
862+
List<String> inconsistencies = isConsistent(markDown, globalConfig)
863+
if (!missingFields.isEmpty() || !inconsistencies.isEmpty()) {
864+
StringBuilder sb = new StringBuilder("Validation failed for ${mdPath}:\n")
865+
if (!missingFields.isEmpty()) {
866+
sb.append("Missing required fields: ${missingFields}\n")
867+
}
868+
if (!inconsistencies.isEmpty()) {
869+
sb.append("Inconsistent fields:\n")
870+
inconsistencies.each { sb.append("- ${it}\n") }
871+
}
872+
throw new CloudRuntimeException(sb.toString())
873+
}
874+
}
865875

866876
class ElaborationMarkDown {
867877
private def table = ["|编号|描述|原因|操作建议|更多|"]
@@ -2815,23 +2825,32 @@ ${additionalRemark}
28152825
return System.getProperty("ignoreError") != null
28162826
}
28172827

2818-
void testGlobalConfigTemplateAndMarkDown() {
2819-
Map<String, GlobalConfig> allConfigs = initializer.configs
2820-
allConfigs.each {
2821-
String newPath =
2822-
PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(),
2823-
"globalconfig"), it.value.category, it.value.name) + DEPRECATED + ".md"
2824-
if (new File(newPath).exists()) {
2828+
void testGlobalConfigTemplateAndMarkDown() {
2829+
Map<String, GlobalConfig> allConfigs = initializer.configs
2830+
List<String> allErrors = []
2831+
allConfigs.each {
2832+
String newPath =
2833+
PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(),
2834+
"globalconfig"), it.value.category, it.value.name) + DEPRECATED + ".md"
2835+
if (new File(newPath).exists()) {
28252836
return
28262837
}
2827-
String mdPath =
2828-
PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(),
2829-
"globalconfig"), it.value.category, it.value.name) + ".md"
2830-
File mdFile = new File(mdPath)
2831-
if (!mdFile.exists()) {
2832-
throw new CloudRuntimeException("Not found the document markdown of the global config ${it.value.name} , please generate it first.")
2833-
}
2834-
checkMD(mdPath, it.value)
2835-
}
2836-
}
2837-
}
2838+
String mdPath =
2839+
PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(),
2840+
"globalconfig"), it.value.category, it.value.name) + ".md"
2841+
File mdFile = new File(mdPath)
2842+
if (!mdFile.exists()) {
2843+
allErrors.add("Global config markdown not found: ${mdPath}")
2844+
return
2845+
}
2846+
try {
2847+
checkMD(mdPath, it.value)
2848+
} catch (CloudRuntimeException e) {
2849+
allErrors.add(e.message)
2850+
}
2851+
}
2852+
if (!allErrors.isEmpty()) {
2853+
throw new CloudRuntimeException(allErrors.join("\n\n"))
2854+
}
2855+
}
2856+
}

0 commit comments

Comments
 (0)