背景
这一篇是处理GitHub上的ci的报错的
wsl下安装act
wsl 安装docker
bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
docker --version

wsl 安装act
bash
wget https://github.com/nektos/act/releases/download/v0.2.89/act_Linux_x86_64.tar.gz
tar xzf act_Linux_x86_64.tar.gz
sudo mv act /usr/local/bin/act
act --version

打包镜像
新建Dockerfile
bash
# Dockerfile
FROM ubuntu:24.04
# 避免交互式询问
ENV DEBIAN_FRONTEND=noninteractive
# 安装所有系统依赖(从你 workflow 中汇总)
RUN --mount=type=cache,target=/var/cache/apt/archives \
apt-get update && apt-get install -y \
build-essential \
ninja-build \
cmake \
libx11-dev \
libxcb1-dev \
libxkbcommon-dev \
libgl1-mesa-dev \
libglu1-mesa-dev \
libxrender-dev \
libxi-dev \
libxrandr-dev \
libxcursor-dev \
libxinerama-dev \
libfontconfig1-dev \
libfreetype-dev \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
RUN --mount=type=cache,target=/var/cache/apt/archives \
apt-get update && apt-get install -y \
autoconf \
autoconf-archive \
automake \
libtool \
'^libxcb.*-dev' \
libx11-xcb-dev \
libxkbcommon-x11-dev \
libegl1-mesa-dev \
clang-format-18 \
clang-tidy-18 \
cppcheck \
lcov \
clang-18 \
doxygen \
git \
curl \
wget \
curl zip unzip tar \
nodejs \
npm \
&& rm -rf /var/lib/apt/lists/*
RUN --mount=type=cache,target=/var/cache/apt/archives \
apt-get update && apt-get install -y \
sudo \
libwayland-dev \
libxt-dev \
&& rm -rf /var/lib/apt/lists/*
# 3. 克隆并引导 vcpkg(固定在 /opt/vcpkg)
WORKDIR /opt
RUN git clone https://github.com/Microsoft/vcpkg.git && \
./vcpkg/bootstrap-vcpkg.sh
ENV VCPKG_ROOT=/opt/vcpkg
ENV PATH=/opt/vcpkg:$PATH
# 4. 复制项目的 vcpkg.json(并锁定文件,如果有)
# 注意:Dockerfile 必须放在项目根目录,且 vcpkg.json 在同一目录
WORKDIR /workspace
COPY vcpkg.json vcpkg.lock* ./
COPY triplets ./triplets
# 4. 复制预下载的源码包(如果存在)
# 在项目根目录创建 vcpkg-cache 文件夹,放入 *.tar.gz, *.zip 等
COPY vcpkg-cache/downloads/* /opt/vcpkg/downloads/
ENV VCPKG_MAX_CONCURRENCY=2
# 5. 预安装项目依赖(利用 Docker 层缓存)
# 如果 vcpkg.json 未变,此层会复用缓存,极大加速
RUN --mount=type=cache,target=/root/.cache/vcpkg \
--mount=type=cache,target=/opt/vcpkg/buildtrees \
--mount=type=cache,target=/opt/vcpkg/packages \
vcpkg install --triplet x64-linux --overlay-triplets=./triplets --recurse \
&& mkdir -p /opt/vcpkg-cache \
&& cp -r /root/.cache/vcpkg/archives/* /opt/vcpkg-cache/
ENV VCPKG_BINARY_SOURCES=clear;files,/opt/vcpkg-cache,readwrite
ENV CMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake
ENV VCPKG_ROOT=/opt/vcpkg
执行构建命令
bash
docker build --progress=plain -t ghcr.io/xcyxiner/dicomviewer-ci:latest . 2>&1 | tee build.log

发布镜像
bash
echo $GITHUB_TOKEN | docker login ghcr.io -u xcyxiner --password-stdin
# 构建镜像
docker build -t ghcr.io/xcyxiner/dicomviewer-ci:latest .
# 推送
docker push ghcr.io/xcyxiner/dicomviewer-ci:latest
本地镜像抄过10G,没法直接上传。

在ci里编译
yaml
# .github/workflows/build-ci-image.yml
name: Build CI Image
on:
workflow_dispatch: # 手动触发一次就行
permissions:
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile # 你现有的 Dockerfile
push: true
tags: ghcr.io/xcyxiner/dicomviewer-ci:latest

wsl 空间不足
上面的默认是在c盘,c盘空间不够,移动到D盘
lua
wsl --export Ubuntu-24.04 D:\WSL\Ubuntu-24.04.tar
wsl --unregister Ubuntu-24.04
wsl --import Ubuntu-24.04 D:\WSL\Ubuntu D:\WSL\Ubuntu-24.04.tar --version 2
wsl -d Ubuntu-24.04 -u ubuntu


使用本地镜像验证
禁用dev的test

之前有一份了test了,这里就不用重复了
lint
安装codespell
ini
自动修复
cmake -D FORMAT_COMMAND=clang-format-18 -D FIX=YES -P cmake/lint.cmake
cmake -D FORMAT_COMMAND=clang-format-18 -P cmake/lint.cmake
------------------------------------------------
拼写检查
pipx install codespell
cmake -D FIX=YES -P cmake/spell.cmake
cmake -P cmake/spell.cmake

先忽略类库

执行自动修复(拼写以及lint)

ci 中lint使用之前打包的镜像
yaml
container:
image: ghcr.io/xcyxiner/dicomviewer-ci:latest

使用本地的镜像,因为服务器的还没打包成功
ini
act push -j lint --pull=false

执行结果

coverage
ci 添加镜像
yaml
coverage:
needs: [lint]
runs-on: ubuntu-24.04
container:
image: ghcr.io/xcyxiner/dicomviewer-ci:latest
# To enable coverage, delete the last line from the conditional below and
# edit the "<name>" placeholder to your GitHub name.
# If you do not wish to use codecov, then simply delete this job from the
# workflow.
if: github.repository_owner == 'xcyxiner'
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Install LCov
run: sudo apt-get update -q
&& sudo apt-get install lcov -q -y
- name: Configure
run: cmake --preset=ci-coverage
- name: Build
run: cmake --build build/coverage -j 2
- name: Test
working-directory: build/coverage
run: ctest --output-on-failure --no-tests=error -j 2
- name: Process coverage info
run: cmake --build build/coverage -t coverage
- name: Submit to codecov.io
if: env.CODECOV_TOKEN != ''
uses: codecov/codecov-action@v4
with:
file: build/coverage/coverage.info
token: ${{ secrets.CODECOV_TOKEN }}

CMakeList.txt 修改
scss
option(AUTO_TESTING "Enable automatic testing" OFF)
if(AUTO_TESTING)
add_library(dicom_core STATIC
${SRC}
)
target_include_directories(dicom_core PUBLIC
${CMAKE_SOURCE_DIR}/source
)
endif()
if(AUTO_TESTING)
target_link_libraries(dicom_core
PUBLIC
Qt6::Widgets
Qt6::OpenGLWidgets
DCMTK::dcmdata
DCMTK::ofstd
DCMTK::dcmfg
VTK::GUISupportQt
VTK::CommonCore
VTK::CommonDataModel
VTK::FiltersCore
VTK::IOImage
VTK::ImagingColor
VTK::ImagingCore
VTK::ImagingGeneral
VTK::RenderingCore
VTK::RenderingOpenGL2
VTK::RenderingVolumeOpenGL2
VTK::InteractionStyle
VTK::RenderingQt
VTK::DICOM
gdcmDICT
gdcmIOD
gdcmDSED
gdcmCommon
gdcmMSFF
)
endif()
if(UNIX)
if(DEFINED ENV{DCMDICTPATH})
set(DCM_DICT_PATH "$ENV{DCMDICTPATH}")
message(STATUS "Using DCMDICTPATH: ${DCM_DICT_PATH}")
else()
# 2. 在项目源码树中查找 dicom.dic(递归搜索)
file(GLOB_RECURSE DCM_DICT_CANDIDATES
${CMAKE_SOURCE_DIR}/dicom.dic
${CMAKE_SOURCE_DIR}/*/dicom.dic # 可放宽,但 GLOB_RECURSE 本身会递归
)
# 但 GLOB_RECURSE 返回列表,取第一个
list(GET DCM_DICT_CANDIDATES 0 DCM_DICT_PATH)
if(DCM_DICT_PATH)
message(STATUS "Found dicom.dic in source tree: ${DCM_DICT_PATH}")
else()
# 可选:如果环境变量未设置,尝试查找默认路径(避免硬编码)
find_file(DCM_DICT_PATH
NAMES dicom.dic
PATHS /usr/share/dcmtk /usr/local/share/dcmtk /opt/dcmtk/share/dcmtk
)
if(NOT DCM_DICT_PATH)
message(FATAL_ERROR "DCMDICTPATH not set and dicom.dic not found in standard paths.")
endif()
endif()
endif()
if(AUTO_TESTING)
# 为需要 DCMTK 的目标添加宏定义
target_compile_definitions(dicom_core PUBLIC
DCM_DICT_DEFAULT_PATH="${DCM_DICT_PATH}"
)
endif()
# 如果还有其他目标(如 DicomViewer_exe)也编译该文件,同样添加
target_compile_definitions(DicomViewer_exe PRIVATE
DCM_DICT_DEFAULT_PATH="${DCM_DICT_PATH}"
)
endif()
dcmtk的字典只有linux需要,其他的只有测试需要


CMakePresets.json 更新
分别添加linux和Windows对vcpkg的依赖
bash
{
"name": "window-vcpkg",
"hidden": true,
"cacheVariables": {
"DEPLOY_QT_PLUGINS": "ON",
"CMAKE_CXX_CLANG_TIDY": "",
"VCPKG_OVERLAY_TRIPLETS": "${sourceDir}/triplets",
"VCPKG_TARGET_TRIPLET": "x64-windows"
},
"errors": {
"dev": false
}
},
{
"name": "ubuntu-vcpkg",
"hidden": true,
"cacheVariables": {
"AUTO_DEPLOY_FONTS": "ON",
"CMAKE_CXX_CLANG_TIDY": "",
"VCPKG_OVERLAY_TRIPLETS": "${sourceDir}/triplets",
"VCPKG_TARGET_TRIPLET": "x64-linux"
},
"errors": {
"dev": false
}
},

json
{
"name": "dev-mode",
"hidden": true,
"inherits": "cmake-pedantic",
"cacheVariables": {
"DicomViewer_DEVELOPER_MODE": "ON",
"AUTO_TESTING": "ON"
}
},
dev-mode 追加 AUTO_TESTING,自己定义的变量,来生成测试的。
bash
{
"name": "coverage-linux",
"binaryDir": "${sourceDir}/build/coverage",
"inherits": "ci-linux",
"hidden": true,
"cacheVariables": {
"ENABLE_COVERAGE": "ON",
"CMAKE_BUILD_TYPE": "Coverage",
"CMAKE_CXX_FLAGS_COVERAGE": "-Og -g --coverage",
"CMAKE_EXE_LINKER_FLAGS_COVERAGE": "--coverage",
"CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "--coverage"
}
},

coverage.cmake 中还要添加
css
--ignore-errors mismatch --rc geninfo_unexecuted_blocks=1

- "ci-coverage" "ci-sanitize" "ci-ubuntu" 继承 "ubuntu-vcpkg"
- "ci-windows" 继承 "window-vcpkg"

act 测试 coverage
ini
act push -j coverage --pull=false


修复这里的报错,重新运行

sanitize
ini
act push -j sanitize --pull=false


修复报错后继续处理

test
yaml
test:
needs: [lint]
strategy:
matrix:
os: [ubuntu-24.04, windows-2022]
runs-on: ${{ matrix.os }}
container:
${{ matrix.os == 'ubuntu-24.04' && 'ghcr.io/xcyxiner/dicomviewer-ci:latest' || null }}
steps:
- uses: actions/checkout@v4
- name: Setup CMake (Windows)
if: matrix.os == 'windows-2022'
uses: lukka/get-cmake@latest
- name: Setup vcpkg (Windows)
if: matrix.os == 'windows-2022'
shell: pwsh
run: |
git clone https://github.com/Microsoft/vcpkg.git
.\vcpkg\bootstrap-vcpkg.bat
Add-Content -Path $env:GITHUB_ENV -Value "VCPKG_ROOT=$pwd\vcpkg"
Add-Content -Path $env:GITHUB_ENV -Value "CMAKE_TOOLCHAIN_FILE=$pwd\vcpkg\scripts\buildsystems\vcpkg.cmake"
Add-Content -Path $env:GITHUB_PATH -Value "$pwd\vcpkg"
- name: Install static analyzers
if: matrix.os == 'ubuntu-24.04'
run: >-
sudo apt-get install clang-tidy-18 cppcheck -y -q
sudo update-alternatives --install
/usr/bin/clang-tidy clang-tidy
/usr/bin/clang-tidy-18 180
- name: Setup MultiToolTask
if: matrix.os == 'windows-2022'
run: |
Add-Content "$env:GITHUB_ENV" 'UseMultiToolTask=true'
Add-Content "$env:GITHUB_ENV" 'EnforceProcessCountAcrossBuilds=true'
- name: Configure
if: matrix.os == 'ubuntu-24.04'
shell: bash
run: |
os="${{ matrix.os }}"
preset="ci-$(echo "$os" | cut -d'-' -f1)"
cmake --preset="$preset"
- name: Configure
if: matrix.os == 'windows-2022'
shell: pwsh
run: cmake "--preset=ci-$("${{ matrix.os }}".split("-")[0])"
- name: Build
run: cmake --build build --config Release -j 2
- name: Install
run: cmake --install build --config Release --prefix prefix
- name: Test
working-directory: build
run: ctest --output-on-failure --no-tests=error -C Release -j 2
Windows配置vcpkg环境变量,linux还是使用镜像


git commit
