name: check Workflow on: workflow_call: inputs: image_name: required: true type: string default: ubuntu image_tag: required: false type: string default: latest jobs: check: runs-on: amd64 container: image: ${{ inputs.image_name }}:${{ inputs.image_tag }} steps: - name: Checkout code uses: actions/checkout@v4 env: https_proxy: ${{ secrets.https_proxy }} http_proxy: ${{ secrets.http_proxy }} with: ref: ${{ github.event.pull_request.head.sha }} - name: Get short sha id: slug run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT - name: generate cppcheck.sh run: | echo "generate /tmp/cppcheck.sh ..." cat << EOF >/tmp/cppcheck.sh #!/bin/bash echo "Running check.sh" default_ignore=( "build/" ".*_test.cc" \${CPPCHECK_IGNORE[@]} ) echo "default_ignore is : \${default_ignore[@]}" # 构造忽略参数 ignore_args="" for ignore in \${default_ignore[@]}; do # 判断是否为目录 if [ -d "\$ignore" ]; then ignore_args="-i\$ignore \$ignore_args" else files=\$(find . ! -path '*/build/*' -regex "\$ignore" -type f) for file in \$files; do ignore_args="-i\$file \$ignore_args" done fi done # 如果当前目录下没有cc或者cpp或者cxx或者c文件,则直接退出,不需要进行cppcheck检查 if [ -z "\$(find . -name "*.cc" -o -name "*.cpp" -o -name "*.cxx" -o -name "*.c")" ]; then echo "no cc or cpp or cxx files, not need to cppcheck" exit 0 fi echo "check cmd is :" echo "cppcheck . --enable=warning,style,performance,portability,missingInclude --xml \$ignore_args" cppcheck . --enable=warning,style,performance,portability,missingInclude --xml \$ignore_args 2>/tmp/cppcheck.xml # 如果cppcheck检查出错,直接退出 if [ \$? -ne 0 ]; then echo "cppcheck failed" exit -1 fi echo "github.sha is : ${{ github.sha }}" echo "short_sha is : ${{ steps.slug.outputs.sha8 }}" # 生成报告并提交到指定http文件服务器上 if [ -n "${{secrets.CPPCHECK_REPORT_POST_URL}}" ]; then check_report_dir=${{ github.repository }}/${{ github.ref_name }}/${{ steps.slug.outputs.sha8 }} mkdir -p \$check_report_dir echo "github.repository_owner is : ${{ github.repository_owner }}" echo "github.repository.name is : ${{ github.repository }}" echo "github.ref_name is : ${{ github.ref_name }}" echo "steps.slug.outputs.sha8 is : ${{ steps.slug.outputs.sha8 }}" echo "check_report_dir is : \$check_report_dir" cppcheck-htmlreport --file=/tmp/cppcheck.xml --title=CSA --report-dir=\$check_report_dir --source-dir=./ echo "check_report_dir is : \$check_report_dir" # zip 压缩 \$check_report_dir zip -r \${{ steps.slug.outputs.sha8 }}.zip \$check_report_dir curl -F file=@${{ steps.slug.outputs.sha8 }}.zip -F unzip=true \${{secrets.CPPCHECK_REPORT_POST_URL}} # 判断推送是否成功 if [ \$? -ne 0 ]; then echo "cppcheck report push failed" exit -1 fi # 删除临时文件 rm -rf \$check_report_dir rm -rf \${{ steps.slug.outputs.sha8 }}.zip # 打印报告地址 # echo "cppcheck report url: ${{secrets.CPPCHECK_REPORT_POST_URL}}/\$check_report_dir/index.html" echo -e "\\033[1;35m cppcheck report url: ${{secrets.CPPCHECK_REPORT_URL}}/\$check_report_dir/index.html \\033[0m" fi EOF - name: generate cppcheck_analyze.py run: | echo "generate /tmp/cppcheck_analyze.py ..." cat << EOF >/tmp/cppcheck_analyze.py #!/usr/bin/env python3 import os import sys import xml.dom.minidom as minidom #cppcheck 所有的错误类型的严重性 severityList=['information', 'performance', 'style', 'portability', 'warning', 'error'] informationSeverityCount = 0 performanceSeverityCount = 0 styleSeverityCount = 0 portabilitySeverityCount = 0 warningSeverityCount = 0 errorSeverityCount = 0 # 如果 /tmp/cppcheck.xml 文件不存在,则直接退出 if not os.path.exists('/tmp/cppcheck.xml'): print("/tmp/cppcheck.xml not exists") sys.exit(0) # 打开cppcheck输出文件 with open('/tmp/cppcheck.xml', 'r') as file: # 解析XML文件 dom = minidom.parse(file) # 获取所有的error元素 errors = dom.getElementsByTagName('error') for error in errors: # 分别统计每种严重性的错误数 for i in range(len(severityList)): if error.getAttribute('severity') == severityList[i]: if i == 0: informationSeverityCount += 1 elif i == 1: performanceSeverityCount += 1 elif i == 2: styleSeverityCount += 1 elif i == 3: portabilitySeverityCount += 1 elif i == 4: warningSeverityCount += 1 elif i == 5: # 如果是syntaxError则不计入errorSeverityCount if error.getAttribute('id') == 'syntaxError': continue # 如果是internalAstError则不计入errorSeverityCount if error.getAttribute('id') == 'internalAstError': continue # 如果是internalAstError则不计入errorSeverityCount if error.getAttribute('id') == 'unknownMacro': continue # 如 果msg中包含"Syntax"则不计入errorSeverityCount if error.getAttribute('msg').find("Syntax") != -1: continue errorSeverityCount += 1 print(error.getAttribute('msg')) # 打印结果 # print(severityList) print("informationSeverityCount: ", informationSeverityCount) print("performanceSeverityCount: ", performanceSeverityCount) print("styleSeverityCount: ", styleSeverityCount) print("portabilitySeverityCount: ", portabilitySeverityCount) print("warningSeverityCount: ", warningSeverityCount) print("errorSeverityCount: ", errorSeverityCount) # 获取环境变量,如果超过阈值则返回-1,否则返回0 # 获取环境变量 informationSeverityMax = os.environ.get('INFORMATION_SEVERITY_MAX') performanceSeverityMax = os.environ.get('PERFORMANCE_SEVERITY_MAX') styleSeverityMax = os.environ.get('STYLE_SEVERITY_MAX') portabilitySeverityMax = os.environ.get('PORTABILITY_SEVERITY_MAX') warningSeverityMax = os.environ.get('WARNING_SEVERITY_MAX') errorSeverityMax = os.environ.get('ERROR_SEVERITY_MAX') # 如果环境变量不存在则不做处理 if informationSeverityMax != None: if informationSeverityCount >= int(informationSeverityMax): print("informationSeverityCount[{}] >= informationSeverityMax[{}]".format(informationSeverityCount, informationSeverityMax)) sys.exit(-1) if performanceSeverityMax != None: if performanceSeverityCount >= int(performanceSeverityMax): print("performanceSeverityCount[{}] >= performanceSeverityMax[{}]".format(performanceSeverityCount, performanceSeverityMax)) sys.exit(-1) if styleSeverityMax != None: if styleSeverityCount >= int(styleSeverityMax): print("styleSeverityCount[{}] >= styleSeverityMax[{}]".format(styleSeverityCount, styleSeverityMax)) sys.exit(-1) if portabilitySeverityMax != None: if portabilitySeverityCount >= int(portabilitySeverityMax): print("portabilitySeverityCount[{}] >= portabilitySeverityMax[{}]".format(portabilitySeverityCount, portabilitySeverityMax)) sys.exit(-1) if warningSeverityMax != None: if warningSeverityCount >= int(warningSeverityMax): print("warningSeverityCount[{}] >= warningSeverityMax[{}]".format(warningSeverityCount, warningSeverityMax)) sys.exit(-1) if errorSeverityMax != None: if errorSeverityCount >= int(errorSeverityMax): print("errorSeverityCount[{}] >= errorSeverityMax[{}]".format(errorSeverityCount, errorSeverityMax)) sys.exit(-1) EOF - name: run cppcheck run: | chmod +x /tmp/cppcheck.sh chmod +x /tmp/cppcheck_analyze.py /tmp/cppcheck.sh /tmp/cppcheck_analyze.py - name: run format run: | ./format.sh git config --global --add safe.directory '*' git status if [ -n "$(git status --porcelain)" ]; then echo "check ${{ github.ref_name }} failed" exit 1 fi