CI: Add GitHub Actions to test on multiple platforms (amd64, arm64, msvc) (#22)
feat: 添加 AIMRT github action Key features of this workflow: Runs automated tests on the mentioned platforms using matrix strategy in GitHub Actions. Ensures that the code compiles and runs correctly on each platform. The workflow is automatically triggered whenever the "ci ready" label is applied to a pull request or a new release is published, ensuring thorough testing and validation at critical stages of the development process. --------- Co-authored-by: yuguanlin <yuguanlin@agibot.com>
This commit is contained in:
parent
7d5fe68319
commit
7e4a55c39d
138
.github/workflows/Main.yml
vendored
Normal file
138
.github/workflows/Main.yml
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
name: CI/CD Workflow
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
branches:
|
||||
- '*'
|
||||
types: [labeled]
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
if: github.event.label.name == 'ci ready' || github.event_name == 'release'
|
||||
uses: ./.github/workflows/cppcheck.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/gitlab-ci
|
||||
image_tag: latest
|
||||
secrets: inherit
|
||||
|
||||
test_gcc11_amd64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-gcc11-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: amd64
|
||||
test_report: true
|
||||
secrets: inherit
|
||||
needs: [check]
|
||||
|
||||
test_gcc11_arm64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-arm64-gcc11-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: arm64
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
test_msvc:
|
||||
uses: ./.github/workflows/test-msvc-workflow.yml
|
||||
with:
|
||||
run_platform: msvc
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
test_gcc12_amd64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-gcc12-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: amd64
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
test_gcc13_amd64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-gcc13-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: amd64
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
test_clang15_amd64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-clang15-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: amd64
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
test_clang16_amd64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-clang16-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: amd64
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
test_clang17_amd64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-clang17-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: amd64
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
test_clang18_amd64:
|
||||
uses: ./.github/workflows/test-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-clang18-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: amd64
|
||||
secrets: inherit
|
||||
needs: [test_gcc11_amd64]
|
||||
|
||||
|
||||
build_x86:
|
||||
uses: ./.github/workflows/build-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-amd64-gcc11-ubuntu22_04
|
||||
image_tag: v20240927
|
||||
run_platform: amd64
|
||||
secrets: inherit
|
||||
needs: [test_msvc, test_gcc11_arm64, test_gcc12_amd64, test_gcc13_amd64, test_clang15_amd64, test_clang16_amd64, test_clang17_amd64, test_clang18_amd64]
|
||||
|
||||
build_arm64:
|
||||
uses: ./.github/workflows/build-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/aimrt_ci-arm64-gcc11-ubuntu22_04
|
||||
image_tag: latest
|
||||
run_platform: arm64
|
||||
secrets: inherit
|
||||
needs: [test_msvc, test_gcc11_arm64, test_gcc12_amd64, test_gcc13_amd64, test_clang15_amd64, test_clang16_amd64, test_clang17_amd64, test_clang18_amd64]
|
||||
|
||||
build_msvc:
|
||||
uses: ./.github/workflows/build-msvc-workflow.yml
|
||||
with:
|
||||
run_platform: msvc
|
||||
secrets: inherit
|
||||
needs: [test_msvc, test_gcc11_arm64, test_gcc12_amd64, test_gcc13_amd64, test_clang15_amd64, test_clang16_amd64, test_clang17_amd64, test_clang18_amd64]
|
||||
|
||||
|
||||
release:
|
||||
uses: ./.github/workflows/release-workflow.yml
|
||||
with:
|
||||
image_name: registry.agibot.com/agibot-tech/gitlab-ci
|
||||
image_tag: latest
|
||||
secrets: inherit
|
||||
if: |
|
||||
github.event_name == 'release' ||
|
||||
startsWith(github.ref, 'refs/tags/release') ||
|
||||
startsWith(github.ref, 'refs/tags/v') ||
|
||||
startsWith(github.ref, 'refs/heads/release')
|
||||
needs: [build_x86, build_arm64, build_msvc]
|
79
.github/workflows/build-msvc-workflow.yml
vendored
Normal file
79
.github/workflows/build-msvc-workflow.yml
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
name: build Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
run_platform:
|
||||
required: false
|
||||
type: string
|
||||
default: msvc
|
||||
secrets:
|
||||
BUILD_CMD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ inputs.run_platform }}
|
||||
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: Setup Visual Studio Developer Command Prompt
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
|
||||
- name: Install Chocolatey
|
||||
run: |
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
|
||||
if (Test-Path "C:\ProgramData\chocolatey\bin\choco.exe") {
|
||||
Write-Host "Chocolatey is installed."
|
||||
} else {
|
||||
Write-Host "Chocolatey installation failed."
|
||||
}
|
||||
$env:Path += ";C:\ProgramData\chocolatey\bin"
|
||||
[Environment]::SetEnvironmentVariable("Path", $env:Path, "Machine")
|
||||
env:
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
|
||||
- name: Install Python using Chocolatey
|
||||
run: |
|
||||
$chocoPath = "C:\ProgramData\chocolatey"
|
||||
$env:Path += ";$chocoPath\bin"
|
||||
[Environment]::SetEnvironmentVariable("Path", $env:Path, "Machine")
|
||||
|
||||
# 使用完整路径执行 choco 命令
|
||||
& "$chocoPath\bin\choco.exe" install python --version=3.11.0 -y
|
||||
|
||||
env:
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
|
||||
|
||||
- name: Run build stage
|
||||
shell: powershell
|
||||
run: |
|
||||
python --version
|
||||
${{ secrets.BUILD_CMD_MSVC}}
|
||||
if ($LASTEXITCODE -eq 1) {
|
||||
Write-Host "build failed"
|
||||
exit 1
|
||||
} else {
|
||||
Write-Host "build succeeded"
|
||||
}
|
||||
|
||||
- name: upload build artifact
|
||||
if: github.action
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: build_artifact
|
||||
path: |
|
||||
${{vars.WHL_ARTIFACTS_DIR}}
|
||||
retention-days: 3
|
||||
|
68
.github/workflows/build-workflow.yml
vendored
Normal file
68
.github/workflows/build-workflow.yml
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
name: build Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
image_name:
|
||||
required: true
|
||||
type: string
|
||||
default: ubuntu
|
||||
image_tag:
|
||||
required: false
|
||||
type: string
|
||||
default: latest
|
||||
run_platform:
|
||||
required: false
|
||||
type: string
|
||||
default: amd64
|
||||
secrets:
|
||||
TEST_CMD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ inputs.run_platform }}
|
||||
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: Run build stage
|
||||
env:
|
||||
https_proxy: ""
|
||||
http_proxy: ""
|
||||
no_proxy: "*"
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -d "./build" ]; then
|
||||
ls -lah ./build
|
||||
fi
|
||||
|
||||
echo "removing CMakeCache.txt"
|
||||
rm -rf ./build/CMakeCache.txt
|
||||
|
||||
source /opt/ros/humble/setup.bash
|
||||
eval "${{ secrets.BUILD_CMD}}"
|
||||
|
||||
echo "ls -lah ${{vars.PROJECT_ARTIFACTS_DIR}}"
|
||||
ls -lah ${{vars.PROJECT_ARTIFACTS_DIR}}
|
||||
|
||||
echo "ls -lah ${{vars.WHL_ARTIFACTS_DIR}}"
|
||||
ls -lah ${{vars.WHL_ARTIFACTS_DIR}}
|
||||
|
||||
- name: upload build artifact
|
||||
if: github.action
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: build_artifact
|
||||
path: |
|
||||
${{vars.WHL_ARTIFACTS_DIR}}
|
||||
retention-days: 3
|
||||
|
246
.github/workflows/cppcheck.yml
vendored
Normal file
246
.github/workflows/cppcheck.yml
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
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
|
||||
|
90
.github/workflows/release-workflow.yml
vendored
Normal file
90
.github/workflows/release-workflow.yml
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
name: deploy Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
image_name:
|
||||
required: true
|
||||
type: string
|
||||
default: ubuntu
|
||||
image_tag:
|
||||
required: false
|
||||
type: string
|
||||
default: latest
|
||||
run_platform:
|
||||
required: false
|
||||
type: string
|
||||
default: amd64
|
||||
secrets:
|
||||
TEST_CMD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ${{ inputs.run_platform }}
|
||||
container:
|
||||
image: ${{ inputs.image_name }}:${{ inputs.image_tag }}
|
||||
|
||||
steps:
|
||||
- name: download build artifact
|
||||
uses: actions/download-artifact@v3
|
||||
env:
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
with:
|
||||
name: build_artifact
|
||||
path: |
|
||||
${{vars.WHL_ARTIFACTS_DIR}}
|
||||
|
||||
|
||||
- name: Get short sha
|
||||
id: slug
|
||||
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up release information
|
||||
id: release_info
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=$(echo ${{ github.ref_name }} | sed 's/^v//')
|
||||
echo "RELEASE_NAME=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
echo "RELEASE_DIR=${{ github.repository }}/${{ github.ref_name }}/${{ github.sha }}" >> $GITHUB_OUTPUT
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: Upload wheel packages
|
||||
shell: bash
|
||||
id: whl_upload
|
||||
run: |
|
||||
set -x
|
||||
ls -lah ${{ vars.WHL_ARTIFACTS_DIR }}
|
||||
echo ${{ vars.WHL_ARTIFACTS_DIR }}
|
||||
echo "${{ secrets.ARTIFACTS_URL }}/${{ steps.release_info.outputs.VERSION }}"
|
||||
|
||||
find "${{ vars.WHL_ARTIFACTS_DIR }}" -name "*.whl" -exec curl -F "file=@{}" "${{ secrets.ARTIFACTS_WHL_URL }}/${{ steps.release_info.outputs.VERSION }}" \;
|
||||
echo "上传 whl 包成功"
|
||||
|
||||
|
||||
- name: 上传Release 产物
|
||||
uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
GITHUB_TOKEN: ${{ secrets.PATOKEN }}
|
||||
with:
|
||||
name: ${{ github.ref_name }}
|
||||
files: |
|
||||
${{ vars.WHL_ARTIFACTS_DIR }}/*.whl
|
||||
|
||||
- name: 显示 report 文件
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "${{secrets.CPPCHECK_REPORT_POST_URL}}" ]; then
|
||||
check_report_dir=${{ github.repository }}/${{ github.ref_name }}/${{ steps.slug.outputs.sha8 }}
|
||||
echo "cppcheck report url: ${{secrets.CPPCHECK_REPORT_URL}}/$check_report_dir/index.html"
|
||||
fi
|
||||
if [ -n "${{secrets.TEST_COVERAGE_REPORT_POST_URL}}" ]; then
|
||||
test_coverage_dir=${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ github.ref_name }}/${{ steps.slug.outputs.sha8 }}
|
||||
echo "test coverage report url: ${{secrets.TEST_COVERAGE_REPORT_URL}}/$test_coverage_dir/index.html"
|
||||
fi
|
||||
|
||||
|
71
.github/workflows/test-msvc-workflow.yml
vendored
Normal file
71
.github/workflows/test-msvc-workflow.yml
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
name: test Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
run_platform:
|
||||
required: false
|
||||
type: string
|
||||
default: msvc
|
||||
secrets:
|
||||
BUILD_CMD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ inputs.run_platform }}
|
||||
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: Setup Visual Studio Developer Command Prompt
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
|
||||
- name: Install Chocolatey
|
||||
run: |
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
|
||||
if (Test-Path "C:\ProgramData\chocolatey\bin\choco.exe") {
|
||||
Write-Host "Chocolatey is installed."
|
||||
} else {
|
||||
Write-Host "Chocolatey installation failed."
|
||||
}
|
||||
$env:Path += ";C:\ProgramData\chocolatey\bin"
|
||||
[Environment]::SetEnvironmentVariable("Path", $env:Path, "Machine")
|
||||
env:
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
|
||||
- name: Install Python using Chocolatey
|
||||
run: |
|
||||
$chocoPath = "C:\ProgramData\chocolatey"
|
||||
$env:Path += ";$chocoPath\bin"
|
||||
[Environment]::SetEnvironmentVariable("Path", $env:Path, "Machine")
|
||||
|
||||
# 使用完整路径执行 choco 命令
|
||||
& "$chocoPath\bin\choco.exe" install python --version=3.11.0 -y
|
||||
|
||||
env:
|
||||
https_proxy: ${{ secrets.https_proxy }}
|
||||
http_proxy: ${{ secrets.http_proxy }}
|
||||
|
||||
|
||||
- name: Run test stage
|
||||
shell: powershell
|
||||
run: |
|
||||
python --version
|
||||
${{ secrets.TEST_CMD_MSVC}}
|
||||
if ($LASTEXITCODE -eq 1) {
|
||||
Write-Host "test failed"
|
||||
exit 1
|
||||
} else {
|
||||
Write-Host "test succeeded"
|
||||
}
|
||||
|
||||
|
203
.github/workflows/test-workflow.yml
vendored
Normal file
203
.github/workflows/test-workflow.yml
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
name: test Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
image_name:
|
||||
required: true
|
||||
type: string
|
||||
default: ubuntu
|
||||
image_tag:
|
||||
required: false
|
||||
type: string
|
||||
default: latest
|
||||
run_platform:
|
||||
required: false
|
||||
type: string
|
||||
default: amd64
|
||||
test_report:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
secrets:
|
||||
TEST_CMD:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ inputs.run_platform }}
|
||||
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 test_coverage.sh
|
||||
if: inputs.test_report == true
|
||||
run: |
|
||||
echo "generate /tmp/test_coverage.sh ..."
|
||||
|
||||
cat << EOF >/tmp/test_coverage.sh
|
||||
#!/bin/bash
|
||||
|
||||
# 生成报告并提交到指定http文件服务器上
|
||||
if [ -z "${{ secrets.TEST_COVERAGE_REPORT_POST_URL }}" ]; then
|
||||
echo "TEST_COVERAGE_REPORT_POST_URL is empty, not generate test coverage report"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ret=0
|
||||
|
||||
# 创建一个\$workdir文件夹,用于存放所有的.gcda文件
|
||||
workdir='/tmp/gtest_report'
|
||||
|
||||
rm \$workdir -rf
|
||||
|
||||
mkdir -p \$workdir
|
||||
|
||||
default_ignore=(
|
||||
"_test.cc"
|
||||
"_test.c"
|
||||
"_test.cpp"
|
||||
"*/build/_deps/*"
|
||||
)
|
||||
|
||||
default_test_cov_ignore=(
|
||||
"*/include/*"
|
||||
"*/build/_deps/*"
|
||||
\${TEST_COVERAGE_IGNORE[@]}
|
||||
)
|
||||
|
||||
# 查找同时存在 *.gcda 和 *.gcno 文件的文件
|
||||
gcda_files=\$(find ./build -type f -name "*.gcda")
|
||||
for gcda_file in \$gcda_files; do
|
||||
# 如果匹配了 \$default_ignore 中的文件,则跳过
|
||||
for ignore in \${default_ignore[@]}; do
|
||||
# 使用正则表达式匹配
|
||||
if [[ \$gcda_file =~ \$ignore ]]; then
|
||||
echo "ignore \$gcda_file"
|
||||
continue 2
|
||||
fi
|
||||
done
|
||||
|
||||
gcno_file="\${gcda_file%.gcda}.gcno"
|
||||
if [ -f "\$gcno_file" ]; then
|
||||
cp "\$gcda_file" "\$workdir"
|
||||
cp "\$gcno_file" "\$workdir"
|
||||
fi
|
||||
done
|
||||
|
||||
cd \$workdir
|
||||
|
||||
# 如果当前目录下没有gcda文件,则直接退出,不需要进行测试覆盖率检查
|
||||
if [ -z "\$(find . -name "*.gcda")" ]; then
|
||||
echo "no gcda files, not need to test coverage"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 使用 gcov 来生成覆盖率数据
|
||||
gcov *.gcno >/dev/null 2>&1
|
||||
|
||||
# 生成报告
|
||||
lcov -c -d . -o coverage.info >/dev/null 2>&1
|
||||
|
||||
# 过滤掉不需要的信息
|
||||
|
||||
for ignore in \${default_test_cov_ignore[@]}; do
|
||||
lcov --remove coverage.info "\$ignore" -o coverage.info >/dev/null 2>&1
|
||||
done
|
||||
|
||||
# 列出测试覆盖率
|
||||
lcov -l coverage.info
|
||||
|
||||
# 判断整体覆盖率是否达标
|
||||
test_coverage=\$(lcov -l coverage.info | grep "Total:" | sed 's/|/| /g' | awk '{print \$2}' | awk -F '%' '{print \$1}')
|
||||
# if error to get test_coverage
|
||||
if [ -z "\$test_coverage" ];
|
||||
then
|
||||
echo "no test coverage, skip"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 生成html报告
|
||||
|
||||
|
||||
test_coverage_dir=${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ github.ref_name }}/${{ steps.slug.outputs.sha8 }}
|
||||
mkdir -p \$test_coverage_dir
|
||||
|
||||
genhtml coverage.info -o \$test_coverage_dir >/dev/null 2>&1
|
||||
|
||||
# zip 压缩 \$test_coverage_dir
|
||||
zip -r ${{ steps.slug.outputs.sha8 }}.zip \$test_coverage_dir
|
||||
|
||||
# 生成报告并提交到指定http文件服务器上
|
||||
curl -F file=@\${{ steps.slug.outputs.sha8 }}.zip -F unzip=true \${{secrets.TEST_COVERAGE_REPORT_POST_URL}}
|
||||
|
||||
# 判断推送是否成功
|
||||
if [ \$? -ne 0 ]; then
|
||||
echo "test report push failed ..."
|
||||
ret=1
|
||||
fi
|
||||
|
||||
# 如果 TEST_COVERAGE_THRESHOLD 变量为空,则默认为 0
|
||||
if [ -z "\$TEST_COVERAGE_THRESHOLD" ]; then
|
||||
TEST_COVERAGE_THRESHOLD=0
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "test coverage: \$test_coverage"
|
||||
|
||||
# 将TEST_COVERAGE_THRESHOLD转换为数字,防止出现字符串比较的情况
|
||||
test_coverage_threshold=\$(echo \$TEST_COVERAGE_THRESHOLD | tr -d '"')
|
||||
|
||||
#比较两个数的大小,一个是小数,一个是整数
|
||||
if [ \$(echo "\$test_coverage >= \$test_coverage_threshold" | bc) -eq 1 ]; then
|
||||
echo "test coverage is greater than \$test_coverage_threshold"
|
||||
else
|
||||
echo "test coverage is less than \$test_coverage_threshold"
|
||||
ret=1
|
||||
fi
|
||||
|
||||
# 删除临时文件
|
||||
rm -rf \$test_coverage_dir
|
||||
rm -rf ${{ steps.slug.outputs.sha8 }}.zip
|
||||
|
||||
# 打印报告地址
|
||||
echo -e "\\033[1;35m test coverage report url: ${{secrets.TEST_COVERAGE_REPORT_URL}}/\$test_coverage_dir/index.html \\033[0m"
|
||||
|
||||
exit \$ret
|
||||
|
||||
EOF
|
||||
|
||||
- name: Run test stage
|
||||
shell: bash
|
||||
env:
|
||||
https_proxy: ""
|
||||
http_proxy: ""
|
||||
no_proxy: "*"
|
||||
run: |
|
||||
echo "runnint test in workflow_call"
|
||||
source /opt/ros/humble/setup.bash
|
||||
echo "${{ secrets.TEST_CMD}}"
|
||||
eval "${{ secrets.TEST_CMD}}"
|
||||
|
||||
- name: authorize test_coverage.sh
|
||||
if: inputs.test_report == true
|
||||
env:
|
||||
https_proxy: ""
|
||||
http_proxy: ""
|
||||
no_proxy: "*"
|
||||
run: |
|
||||
chmod +x /tmp/test_coverage.sh
|
||||
echo "test_coverage.sh is authorized"
|
||||
bash /tmp/test_coverage.sh
|
2
build.sh
2
build.sh
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# exit on error and print each command
|
||||
set -ex
|
||||
set -e
|
||||
|
||||
cmake -B build \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
|
Loading…
x
Reference in New Issue
Block a user