* Add downgrade report feature.
This commit is contained in:
Executable
+145
@@ -0,0 +1,145 @@
|
||||
pipeline {
|
||||
agent {
|
||||
kubernetes {
|
||||
inheritFrom "xuanim"
|
||||
yamlFile 'misc/ci/normal.yaml'
|
||||
}
|
||||
}
|
||||
|
||||
options {
|
||||
skipDefaultCheckout()
|
||||
}
|
||||
|
||||
environment {
|
||||
TZ="Asia/Shanghai"
|
||||
|
||||
ZENTAO_RELEASE_PATH = "${WORKSPACE}/release"
|
||||
XUANXUAN_SRC_PATH = "${WORKSPACE}/xuansrc"
|
||||
SRC_ZDOO_PATH = "${WORKSPACE}/zdoo"
|
||||
SRC_ZDOOEXT_PATH = "${WORKSPACE}/zdooext"
|
||||
SRC_ZENTAOEXT_PATH = "${WORKSPACE}/zentaoext"
|
||||
|
||||
// set to blank for auto-detect from ci.json
|
||||
DOWNGRADE_ENABLED = "false"
|
||||
DOWNGRADE_VERSIONS = "7.2,7.1,7.0,5.4"
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
stage("Test Code") {
|
||||
|
||||
agent {
|
||||
kubernetes {
|
||||
inheritFrom "zentao-package build-docker xuanim"
|
||||
yamlFile 'misc/ci/basic-build.yaml'
|
||||
}
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("Pull") {
|
||||
steps {
|
||||
checkout scm
|
||||
script {
|
||||
env.XUANVERSION = sh(returnStdout: true,script: 'jq -r .pkg.xuanxuan.gitVersion < ci.json').trim()
|
||||
env.ZENTAOEXT_VERSION = sh(returnStdout: true,script: 'jq -r .pkg.zentaoext.gitVersion < ci.json').trim()
|
||||
env.ZENTAOEXT_GIT_REPO = sh(returnStdout: true,script: 'jq -r .pkg.zentaoext.gitRepo < ci.json').trim()
|
||||
env.ZDOO_VERSION = sh(returnStdout: true,script: 'jq -r .pkg.zdoo.gitVersion < ci.json').trim()
|
||||
env.ZDOOEXT_VERSION = sh(returnStdout: true,script: 'jq -r .pkg.zdooext.gitVersion < ci.json').trim()
|
||||
}
|
||||
|
||||
dir('xuansrc') {
|
||||
checkout scmGit(branches: [[name: "${env.XUANVERSION}"]],
|
||||
userRemoteConfigs: [[credentialsId: 'git-zcorp-cc-jenkins-bot-http', url: 'https://git.zcorp.cc/easycorp/xuanxuan.git']]
|
||||
)
|
||||
}
|
||||
|
||||
dir('zdoo') {
|
||||
checkout scmGit(branches: [[name: "${env.ZDOO_VERSION}"]],
|
||||
extensions: [cloneOption(depth: 2, noTags: false, reference: '', shallow: true)],
|
||||
userRemoteConfigs: [[credentialsId: 'git-zcorp-cc-jenkins-bot-http', url: 'https://git.zcorp.cc/easycorp/zdoo.git']]
|
||||
)
|
||||
}
|
||||
|
||||
dir('zdooext') {
|
||||
checkout scmGit(branches: [[name: "${env.ZDOOEXT_VERSION}"]],
|
||||
extensions: [cloneOption(depth: 2, noTags: false, reference: '', shallow: true)],
|
||||
userRemoteConfigs: [[credentialsId: 'git-zcorp-cc-jenkins-bot-http', url: 'https://git.zcorp.cc/easycorp/zdooext.git']]
|
||||
)
|
||||
}
|
||||
|
||||
dir('zentaoext') {
|
||||
checkout scmGit(branches: [[name: "${env.ZENTAOEXT_VERSION}"]],
|
||||
extensions: [cloneOption(depth: 2, noTags: false, reference: '', shallow: true)],
|
||||
userRemoteConfigs: [[credentialsId: 'git-zcorp-cc-jenkins-bot-http', url: "${env.ZENTAOEXT_GIT_REPO}"]]
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
stage("Setup Global Env") {
|
||||
steps {
|
||||
script {
|
||||
def ximUsers = sh(returnStdout: true,script: 'jq -r .notice.users < ci.json').trim()
|
||||
env.XIM_USERS = "qishiyao"
|
||||
// env.XIM_GROUPS = sh(returnStdout: true,script: 'jq -r .notice.groups < ci.json').trim()
|
||||
|
||||
env.PMS_VERSION = sh(returnStdout: true, script: 'cat ${SRC_ZENTAOEXT_PATH}/VERSION').trim()
|
||||
env.BIZ_VERSION = sh(returnStdout: true, script: 'cat ${SRC_ZENTAOEXT_PATH}/BIZVERSION').trim()
|
||||
env.MAX_VERSION = sh(returnStdout: true, script: 'cat ${SRC_ZENTAOEXT_PATH}/MAXVERSION').trim()
|
||||
env.IPD_VERSION = sh(returnStdout: true, script: 'cat ${SRC_ZENTAOEXT_PATH}/IPDVERSION').trim()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
stage("Downgrade") {
|
||||
stages {
|
||||
stage("make Package") {
|
||||
steps {
|
||||
withCredentials([gitUsernamePassword(credentialsId: 'git-zcorp-cc-jenkins-bot-http',gitToolName: 'git-tool')]) {
|
||||
container('package') {
|
||||
sh 'mkdir ${ZENTAO_RELEASE_PATH} && chown 1000:1000 ${ZENTAO_RELEASE_PATH}'
|
||||
sh 'git config --global pull.ff only'
|
||||
sh 'pwd && ls -l && make ciCommon'
|
||||
sh 'ls -l ${ZENTAO_RELEASE_PATH}'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
stage("test downgrade") {
|
||||
steps {
|
||||
container('package') {
|
||||
sh 'unzip -q ZenTaoPMS.${PMS_VERSION}.zip'
|
||||
sh 'ls -l zentaopms'
|
||||
sh './misc/downgrade.sh -p "$DOWNGRADE_VERSIONS" -r zentaopms -i -s -o "$ZENTAO_RELEASE_PATH" framework lib module/*'
|
||||
}
|
||||
|
||||
publishHTML([
|
||||
allowMissing: true,
|
||||
alwaysLinkToLastBuild: false,
|
||||
keepAll: true,
|
||||
reportDir: env.ZENTAO_RELEASE_PATH,
|
||||
reportFiles: 'downgradeReport.html',
|
||||
reportName: 'DowngradeReport'
|
||||
])
|
||||
|
||||
container('xuanimbot') {
|
||||
sh 'git config --global --add safe.directory $(pwd)'
|
||||
sh 'test -f $ZENTAO_RELEASE_PATH/downgradeReport.html || echo "No syntax found" && /usr/local/bin/xuanimbot --title "`echo -n 6ZmN57qn5aSx6LSl | base64 --decode`" --url "${RUN_DISPLAY_URL}" --content "[PHP Syntax Report]($BUILD_URL/DowngradeReport/)" --debug --custom '
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // End Downgrade
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>PHP Syntax Errors</title>
|
||||
<style>
|
||||
/* Custom styles */
|
||||
.container {
|
||||
padding: 20px;
|
||||
}
|
||||
.page-content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>PHP Syntax Errors</h1>
|
||||
<div id="navMenu"></div>
|
||||
<div class="page-content">
|
||||
<div id="tableContainer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const jsonData =
|
||||
;
|
||||
|
||||
const navMenu = document.getElementById("navMenu");
|
||||
const tableContainer = document.getElementById("tableContainer");
|
||||
|
||||
// Create navigation buttons
|
||||
for (const version in jsonData.versions) {
|
||||
const button = document.createElement("button");
|
||||
button.textContent = version;
|
||||
button.addEventListener("click", () => renderTable(version));
|
||||
navMenu.appendChild(button);
|
||||
}
|
||||
|
||||
// Render table based on version
|
||||
const renderTable = (version) => {
|
||||
const data = jsonData.versions[version];
|
||||
const tableData = [];
|
||||
|
||||
for (let i = 0; i < data.length; i += 2) {
|
||||
const fileName = data[i];
|
||||
const errorDetails = data[i + 1];
|
||||
tableData.push({ fileName, errorDetails });
|
||||
}
|
||||
|
||||
const table = document.createElement("table");
|
||||
const thead = document.createElement("thead");
|
||||
const tbody = document.createElement("tbody");
|
||||
|
||||
const headerRow = document.createElement("tr");
|
||||
const fileNameHeader = document.createElement("th");
|
||||
fileNameHeader.textContent = "File Name";
|
||||
const errorDetailsHeader = document.createElement("th");
|
||||
errorDetailsHeader.textContent = "Error Details";
|
||||
|
||||
headerRow.appendChild(fileNameHeader);
|
||||
headerRow.appendChild(errorDetailsHeader);
|
||||
thead.appendChild(headerRow);
|
||||
|
||||
tableData.forEach((item) => {
|
||||
const row = document.createElement("tr");
|
||||
const fileNameCell = document.createElement("td");
|
||||
fileNameCell.textContent = item.fileName;
|
||||
const errorDetailsCell = document.createElement("td");
|
||||
errorDetailsCell.textContent = item.errorDetails;
|
||||
|
||||
row.appendChild(fileNameCell);
|
||||
row.appendChild(errorDetailsCell);
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
|
||||
table.appendChild(thead);
|
||||
table.appendChild(tbody);
|
||||
|
||||
// Clear previous table
|
||||
tableContainer.innerHTML = "";
|
||||
// Append new table
|
||||
tableContainer.appendChild(table);
|
||||
|
||||
// Update active button
|
||||
const buttons = navMenu.getElementsByTagName("button");
|
||||
for (const button of buttons) {
|
||||
button.classList.remove("active");
|
||||
}
|
||||
Array.from(buttons).forEach((button) => {
|
||||
if (button.textContent === version) {
|
||||
button.classList.add("active");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Initialize the page
|
||||
const initialVersion = Object.keys(jsonData.versions)[0];
|
||||
renderTable(initialVersion);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+84
-28
@@ -7,6 +7,7 @@ statisticSyntax="false"
|
||||
codeRootDir=$PWD
|
||||
composerDir="$(dirname "$(realpath "$0")")"
|
||||
outputDir="$PWD/tmp"
|
||||
reportHtmlFile="$PWD/misc/downgrade-report-tpl.html"
|
||||
|
||||
helper() {
|
||||
cat << EOF
|
||||
@@ -48,6 +49,7 @@ while getopts "isr:p:o:" opt; do
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
statisticDataFile="$outputDir/statistic.data.json"
|
||||
|
||||
if [ "$#" -eq 0 ];then
|
||||
echo "need at least one file or directory"
|
||||
@@ -65,7 +67,6 @@ done
|
||||
# 结束命令行参数处理
|
||||
|
||||
excludeRegexList=(
|
||||
module/holiday/ext/
|
||||
lib/purifier/HTMLPurifier.autoload-legacy.php
|
||||
lib/sqlparser/vendor/
|
||||
)
|
||||
@@ -195,8 +196,7 @@ ensureSyntaxPassed() {
|
||||
echo "downgrade failed"
|
||||
echo "md5 compare (before:$beforeMD5) (after:$afterMD5)"
|
||||
if [[ "$statisticSyntax" == "true" ]];then
|
||||
outputFile="${outputDir}/syntax-error-${phpVersion}.log"
|
||||
syntaxCheck "$phpVersion" "$phpFilePath" >> "$outputFile" || echo "record file $phpFilePath"
|
||||
syntaxAddErrRecord "$phpVersion" "$phpFilePath"
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
@@ -292,39 +292,95 @@ DownGrade() {
|
||||
echo
|
||||
}
|
||||
|
||||
# 设置脚本启动时间
|
||||
startPointTime=$(date +'%Y-%m-%d %H:%M:%S')
|
||||
syntaxInitReport() {
|
||||
echo '{"versions": {}}' > "$statisticDataFile"
|
||||
}
|
||||
|
||||
# 执行 composer 组件安装
|
||||
if [ "$installRector" = "true" ];then
|
||||
lastDir=$PWD
|
||||
cd "$composerDir" || exit 1
|
||||
syntaxAddErrRecord() {
|
||||
phpVersion="$1"
|
||||
phpFilePath="$2"
|
||||
|
||||
phpCli=$(which php"${phpVersion}")
|
||||
listKey=".versions[\"$phpVersion\"]"
|
||||
|
||||
fileName=$(echo "$phpFilePath"| sed "s|${codeRootDir}/||")
|
||||
|
||||
composer config -g repo.packagist composer https://mirrors.cloud.tencent.com/composer/
|
||||
composer install
|
||||
lastDir=$PWD
|
||||
cd "$codeRootDir" || exit 1
|
||||
|
||||
cd "$lastDir" || exit 1
|
||||
fi
|
||||
set +e
|
||||
errMsg=$($phpCli -l "$fileName" | jq -Rs '.')
|
||||
set -e
|
||||
|
||||
# 检查 -p 参数, 执行多版本降级或是单版本降级
|
||||
if [[ "$phpVer" =~ ^.*, ]];then
|
||||
IFS=',' read -r -a verList <<< "$phpVer"
|
||||
for v in "${verList[@]}"
|
||||
cd "$lastDir"
|
||||
|
||||
jq "$listKey += [\"$fileName\", $errMsg]" "$statisticDataFile" > "$statisticDataFile.tmp"
|
||||
mv "$statisticDataFile.tmp" "$statisticDataFile"
|
||||
}
|
||||
|
||||
preProcess() {
|
||||
# 初始化语法错误记录
|
||||
if [[ "$statisticSyntax" == "true" ]];then
|
||||
syntaxInitReport
|
||||
fi
|
||||
|
||||
# 执行 composer 组件安装
|
||||
if [ "$installRector" = "true" ];then
|
||||
lastDir=$PWD
|
||||
cd "$composerDir" || exit 1
|
||||
|
||||
composer config -g repo.packagist composer https://mirrors.cloud.tencent.com/composer/
|
||||
composer install
|
||||
|
||||
cd "$lastDir" || exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
process() {
|
||||
# 设置脚本启动时间
|
||||
startPointTime=$(date +'%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 检查 -p 参数, 执行多版本降级或是单版本降级
|
||||
if [[ "$phpVer" =~ ^.*, ]];then
|
||||
IFS=',' read -r -a verList <<< "$phpVer"
|
||||
for v in "${verList[@]}"
|
||||
do
|
||||
existsPHPCli "$v" || (echo "php${v} is not found, abort."; exit 3)
|
||||
done
|
||||
|
||||
for v in "${verList[@]}"
|
||||
do
|
||||
DownGrade "$v" "$startPointTime" "${downGradeDirs[@]}"
|
||||
done
|
||||
else
|
||||
existsPHPCli "$phpVer" || (echo "php${phpVer} is not found, abort."; exit 3)
|
||||
DownGrade "$phpVer" "$startPointTime" "${downGradeDirs[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
postProcess() {
|
||||
if [[ "$statisticSyntax" == "true" ]];then
|
||||
foundSyntaxErr="false"
|
||||
for ver in $(jq -r '.versions | keys[]' "$statisticDataFile")
|
||||
do
|
||||
existsPHPCli "$v" || (echo "php${v} is not found, abort."; exit 3)
|
||||
count=$(jq -r ".versions[\"$ver\"] | length" < "$statisticDataFile")
|
||||
if [[ "$count" -gt 0 && "$foundSyntaxErr" != "true" ]];then
|
||||
foundSyntaxErr=true
|
||||
fi
|
||||
done
|
||||
|
||||
for v in "${verList[@]}"
|
||||
do
|
||||
DownGrade "$v" "$startPointTime" "${downGradeDirs[@]}"
|
||||
done
|
||||
else
|
||||
existsPHPCli "$phpVer" || (echo "php${phpVer} is not found, abort."; exit 3)
|
||||
DownGrade "$phpVer" "$startPointTime" "${downGradeDirs[@]}"
|
||||
fi
|
||||
|
||||
if [[ "$foundSyntaxErr" == "true" ]];then
|
||||
reportInsertLine=$(grep -n 'const jsonData' "$reportHtmlFile" | cut -d: -f1)
|
||||
jq -c . "$statisticDataFile" | sed "${reportInsertLine}r /dev/stdin" "$reportHtmlFile" > "$outputDir/downgradeReport.html"
|
||||
fi
|
||||
fi
|
||||
cat "$statisticDataFile"
|
||||
}
|
||||
|
||||
preProcess
|
||||
process
|
||||
postProcess
|
||||
|
||||
# syntaxCheck "$phpVer" /code/module/pipeline/model.php
|
||||
# downGradeDir "$phpVer" "${downGradeDirs[@]}"
|
||||
# archiveChangedFiles "$t" "$codeRootDir"
|
||||
# archiveChangedFiles "$t" "$codeRootDir"
|
||||
Reference in New Issue
Block a user