Skip to content

ci: Self-built toolchains, git-based versioning, and automated SDK/firmware releases - #14

Merged
qzhhhi merged 3 commits into
mainfrom
dev/ci-build
Jan 19, 2026
Merged

ci: Self-built toolchains, git-based versioning, and automated SDK/firmware releases#14
qzhhhi merged 3 commits into
mainfrom
dev/ci-build

Conversation

@qzhhhi

@qzhhhiqzhhhi commented Jan 19, 2026

Copy link
Copy Markdown
Member

ci(release): Build and publish Docker-packaged artifacts

  • Add release-package.yml to build SDK .deb (multi-arch) + optional source zip, and create a tag-triggered GitHub pre-release with uploaded artifacts
  • Introduce Dockerfile.build_sdk and Dockerfile.build_firmware to package SDK/firmware from qzhhhi/librmcs-ci with versioned outputs
  • Update host/CMakePresets.json with linux-debug/linux-release presets for the packaging builds

build(version): Generate versions from git tags

  • Add .scripts/generate_version to emit semver and Debian-friendly versions via git describe
  • Update host/firmware CMake to derive LIBRMCS_PROJECT_VERSION and expose LIBRMCS_PROJECT_VERSION_STRING
  • Stamp firmware USB product string and align CPack Debian packaging (headers install + versioned file names)

ci(docker): Self-build RISC-V toolchain for CI images

  • Switch Dockerfile to a multi-stage build that compiles riscv-gnu-toolchain from source and reuses it in the ci/develop targets
  • Update docker-image.yml to build/push per-arch digests for librmcs-ci and librmcs-develop, then publish multi-arch manifests

Pull Request 摘要

概述

本 PR 引入 CI/打包、基于 Git 的版本生成、自编译 RISC-V 工具链与多架构镜像发布流程,增加用于生成 SDK/固件的专用 Docker 构建文件,并将版本信息贯穿至固件 USB 描述符与 Debian 打包文件名,支持标签触发的预发布自动化流程。

主要改动

一、版本生成与暴露

  • 新增脚本 .scripts/generate_version:通过 git describe 派生语义化版本与 Debian 友好版本,支持预发布标识(a/b/rc → alpha/beta/rc)、开发版(dev.N.commit)与 dirty 标记,支持 semver / debian 两种输出格式。
  • firmware/CMakeLists.txt:集成版本生成(在未预设时调用 .scripts/generate_version),设置 LIBRMCS_PROJECT_VERSION,并通过编译定义暴露 LIBRMCS_PROJECT_VERSION_STRING(用于固件中的 USB 产品字符串)。
  • host/CMakeLists.txt:项目改名为 librmcs-sdk(从 librmcs),在配置时通过脚本生成 LIBRMCS_PROJECT_VERSION 与 LIBRMCS_DEBIAN_VERSION,并将 LIBRMCS_PROJECT_VERSION_STRING 作为编译定义暴露;更新最低 CMake 版本、语言标准与构建策略;移除 RPM,改为仅使用 DEB 打包,CPack 配置使用生成的版本与构建模式来命名包文件。

二、CI / 打包与发布

  • 新增工作流 .github/workflows/release-package.yml:矩阵化构建多架构 SDK(生成 .deb,按需包含源码 zip)与固件产物,使用 Docker 多阶段构建导出本地产物并上传为 workflow artifacts;当以 tag 推送时创建 GitHub 预发布并附带产物与自动生成的 release notes。
  • 更新 .github/workflows/docker-image.yml:将 CI 镜像与 Develop 镜像区分,按架构构建并导出 digest;在合并阶段下载各架构 digest 并分别创建、推送多架构 manifest 列表;增加构建前的磁盘清理等步骤以支持大型镜像构建。

三、Docker 与工具链

  • 顶层 Dockerfile 改为多阶段:新增 builder 阶段从源码编译 riscv-gnu-toolchain,后续 ci/develop 阶段复用该编译产物(COPY /opt/riscv32-none-elf);提供 develop 阶段作为 ci 的扩展镜像;完善包依赖、工具链路径与 clangd 安装逻辑。
  • 新增 Dockerfile.build_sdk:基于 qzhhhi/librmcs-ci 构建 SDK,注入版本信息(调用脚本生成),可选打包源码,分别以 linux-debug/linux-release 预设产出版本化 .deb 包并导出。
  • 新增 Dockerfile.build_firmware:基于 qzhhhi/librmcs-ci 构建固件,读取生成的版本并将 ELF 产物按版本与构建类型重命名导出(debug/release)。
  • 新增 .dockerignore:减少构建上下文体积,排除常见开发与构建临时文件。

四、固件与源码调整

  • firmware/src/usb/usb_descriptors.hpp:将固定 C 数组替换为 std::array 并扩展缓冲容量,改进字符串长度上限计算,get_string_descriptor 返回 std::array 数据指针;USB 产品字符串改为 "RMCS Board v" + LIBRMCS_PROJECT_VERSION_STRING(由 CMake 注入)。
  • firmware/.clangd:简化配置,移除显式 Compiler 路径设置并调整 Diagnostics.Include 忽略规则。
  • firmware 项目命名:project 改为 librmcs-firmware,设置 C 标准为 C11 并通过编译定义暴露版本字符串。

五、构建预设与安装/打包

  • host/CMakePresets.json:升级 schema(version 4),将原 "linux" 预设重命名为 "linux-debug",并新增 "linux-release" 预设以支持 Release 打包路径。
  • 安装规则与 CPACK:安装头文件路径调整(包含 core/include),CPACK_DEBIAN_PACKAGE_VERSION 基于生成的 LIBRMCS_DEBIAN_VERSION,CPACK_PACKAGE_FILE_NAME 包含项目名、LIBRMCS_PROJECT_VERSION、架构与构建模式;移除 RPM 相关配置。

技术亮点

  • 自编译并复用 RISC-V 工具链以减少重复下载/环境差异。
  • Git 标签驱动的语义化版本与 Debian 版本双格式输出,版本信息链路从脚本 → CMake → 编译定义 → 固件 USB 描述符 → 最终 deb/elf 文件名。
  • 使用 Docker 多阶段与 GitHub Actions matrix 构建实现多架构并行构建、digest 导出与 manifest 合并,实现跨架构发布与自动化预发布流程。

兼容性与注意点

  • 打包流程已切换为仅 DEB,移除 RPM 支持;CI 镜像与 develop 镜像已分离并以 manifest 发布,镜像标签/名称策略有所变化。
  • 版本生成依赖 git describe 的 tag 语义(必须以 v 前缀并符合脚本正则),在不符合时脚本将报错并导致构建失败;构建环境需包含 git 可执行文件。

- Switch Dockerfile to a multi-stage build that compiles riscv-gnu-toolchain from source and reuses it in the ci/develop targets
- Update docker-image.yml to build/push per-arch digests for librmcs-ci and librmcs-develop, then publish multi-arch manifests
- Simplify firmware/.clangd thanks to the stable in-image toolchain layout, and add .dockerignore to trim build context
@coderabbitai

coderabbitaiBot commented Jan 19, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

Walkthrough

本次变更新增并重构了多阶段容器构建与发布管道、引入自动版本生成脚本、添加专用 SDK/固件 构建 Dockerfile,并在固件与主机 CMake 中暴露版本与调整打包流程。

Changes

Cohort / File(s)变更摘要
忽略文件
\.dockerignore
添加忽略规则:.vscode/.cache/build/compile_commands.json.devcontainer/.zsh_history 等。
主 Dockerfile 与镜像分层
\Dockerfile``
引入 buildercidevelop 多阶段构建;在 builder 中编译 riscv 工具链并在后续阶段 COPY;扩展 apt/工具链/clangd、zsh/Oh My Zsh 配置与环境变量。
专用构建镜像
\Dockerfile.build_firmware`, `Dockerfile.build_sdk``
新增两个多阶段 Dockerfile:用于构建并版本化 ELF 固件产物与生成 SDK(源码包与 Debian 包)。
版本生成脚本
\.scripts/generate_version``
新增 Python 脚本:基于 git describe 解析版本、支持 semver/debian 输出、提供 CLI,新增 VersionError 及相关函数。
GitHub Actions:镜像构建
\.github/workflows/docker-image.yml``
重构为区分 CI 与 Develop 的构建/推送流程:释放磁盘、按目标构建并按 digest 导出、上传 artifact、分别创建/推送 CI 与 Develop manifest 列表并检查镜像。
GitHub Actions:发布制件
\.github/workflows/release-package.yml``
新增 release-package 工作流:矩阵化构建(含不同 runner/架构)、条件性生成并上传 SDK/firmware 工件,基于 artifact 创建预发布。
固件 CMake 与版本暴露
\firmware/CMakeLists.txt``
project 改为 librmcs-firmware VERSION 3,若未定义则调用脚本生成 LIBRMCS_PROJECT_VERSION,通过编译定义暴露 LIBRMCS_PROJECT_VERSION_STRING,并设置 C 标准。
固件 USB 描述符
\firmware/src/usb/usb_descriptors.hpp``
uint16_t[64] 改为 std::array<uint16_t,128>,引入 max_size 限制字符串长度,产品字符串使用 LIBRMCS_PROJECT_VERSION_STRING,返回 .data()
固件语言服务配置
\firmware/.clangd``
移除显式 Compiler/sysroot/include-path,调整 Diagnostics.Includes.IgnoreHeader 模式为 firmware/bsp/hpm_sdk/soc/.*
主机构建与打包
\host/CMakeLists.txt`, `host/CMakePresets.json``
项目重命名为 librmcs-sdk、CMake 最低版本提升到 3.28、启用 C++23/C11、加入版本与 Debian 打包(移除 RPM)、新增 BUILD_STATIC_LIBRMCS 选项;Presets schema 升级并新增 linux-release 预设。

Sequence Diagram(s)

sequenceDiagram
participant GH as GitHub Actions
participant WF as docker-image.yml
participant Buildx as Docker Buildx
participant Registry as Container Registry
participant Artifacts as Artifact Storage
GH->>WF: 触发(push/merge)
WF->>WF: Free disk space
WF->>Buildx: Build & push CI (target=ci, platforms, push-by-digest)
Buildx->>Registry: 推送 CI 镜像层
Buildx-->>WF: 输出 CI digest
WF->>Artifacts: 上传 CI digest artifact
WF->>Buildx: Build & push Develop (target=develop, push-by-digest)
Buildx->>Registry: 推送 Develop 镜像层
Buildx-->>WF: 输出 Develop digest
WF->>Artifacts: 上传 Develop digest artifact
WF->>Artifacts: 下载 CI digest -> ci/
WF->>Artifacts: 下载 Develop digest -> develop/
WF->>Buildx: Create CI manifest list (ci/)
Buildx->>Registry: 推送 CI manifest list
WF->>Buildx: Create Develop manifest list (develop/)
Buildx->>Registry: 推送 Develop manifest list
WF->>Buildx: Inspect final CI & Develop images
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 我是一只忙碌的小兔子,蹦进新流水线,

镜像分层像胡萝卜堆,版本跳跃像小步伐,
SDK 与固件并肩跑,工件飘向云端城,
CI 唱着歌,Release 点着灯,快乐在构建间闪烁。

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passed标题准确总结了PR的主要变化:自建工具链、基于git的版本管理和自动化SDK/固件发布。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Dockerfile (2)

84-90: ARM GNU工具链下载缺少完整性校验

当前代码直接下载并解压 ARM GNU工具链,缺少完整性校验会产生供应链风险。ARM 官方在 Arm Developer 下载页面提供 .sha256asc 校验文件,建议引入 SHA256 校验并在校验失败时中止构建。

校验实现示例
+ARG ARM_GNU_TOOLCHAIN_SHA256
RUN VERSION=15.2.rel1 \
&& wget https://developer.arm.com/-/media/Files/downloads/gnu/${VERSION}/binrel/arm-gnu-toolchain-${VERSION}-${TARGETARCH_UNAME}-arm-none-eabi.tar.xz \
-O arm-gnu-toolchain.tar.xz \
+ && echo "${ARM_GNU_TOOLCHAIN_SHA256} arm-gnu-toolchain.tar.xz" | sha256sum -c - \
&& tar -xvf arm-gnu-toolchain.tar.xz -C /opt/ \

27-77: Dockerfile ${VAR/old/new} 替换依赖 BuildKit,在常规构建中可能不工作

ARG TARGETARCH_UNAME=${TARGETARCH/amd64/x86_64} 这种参数展开语法需要启用 BuildKit(如 docker buildxDOCKER_BUILDKIT=1),以及声明正确的 frontend(如 # syntax=docker/dockerfile:1)。如果构建环境未启用 BuildKit,变量会解析为空或被当作字面值,导致后续路径失效。

为提高可移植性和兼容性,建议在 RUN 中用显式的 case 映射替代:

🛠️ 修正示例
-ARG TARGETARCH_UNAME=${TARGETARCH/amd64/x86_64}-ARG TARGETARCH_UNAME=${TARGETARCH_UNAME/arm64/aarch64}+ARG TARGETARCH_UNAME
...
-RUN apt-get update \+RUN case "$TARGETARCH" in \+ amd64) TARGETARCH_UNAME=x86_64 ;; \+ arm64) TARGETARCH_UNAME=aarch64 ;; \+ *) echo "Unsupported TARGETARCH=$TARGETARCH" >&2; exit 1 ;; \+ esac \+ && apt-get update \
🤖 Fix all issues with AI agents
In @.scripts/generate_version:
- Line 1: The shebang in .scripts/generate_version is using an incorrect
hardcoded path (/bin/python3); update the script's shebang line so it uses the
environment lookup (/usr/bin/env python3) to ensure portability across
distributions — edit the first line of .scripts/generate_version to replace the
current shebang with the env-based one.
- Around line 71-80: The function format_version mutates the input release list
by doing release[-1] += 1 which causes side effects if the caller reuses the
same version tuple; to fix, do not modify release in place — make a shallow copy
(e.g., release_copy = list(release) or similar), increment the last element on
that copy, and use the copy when building trailing/version strings (update
references to release in format_version to use the copied list instead of
mutating the original release variable).
🧹 Nitpick comments (2)
.github/workflows/docker-image.yml (1)

37-51: 建议将 Free disk space 步骤提前到 Buildx 之前

该动作会清理 Docker 镜像/缓存,放在 Buildx 初始化后可能影响 builder 与缓存命中;建议先清理再 setup Buildx。

🔧 调整顺序示例
- - name: Set up Docker Buildx- uses: docker/setup-buildx-action@v3-- - name: Free disk space- uses: BRAINSia/free-disk-space@v2- with:- tool-cache: false- mandb: true- android: true- dotnet: true- haskell: true- large-packages: true- docker-images: true- swap-storage: false+ - name: Free disk space+ uses: BRAINSia/free-disk-space@v2+ with:+ tool-cache: false+ mandb: true+ android: true+ dotnet: true+ haskell: true+ large-packages: true+ docker-images: true+ swap-storage: false++ - name: Set up Docker Buildx+ uses: docker/setup-buildx-action@v3
Dockerfile (1)

16-21: 建议固定 riscv-gnu-toolchain 版本并核对 GCC 15.1 要求

当前直接拉取最新 HEAD 会导致构建不可复现,且工具链版本可能漂移。建议通过 tag/commit 固定版本,并在需要时显式校验 GCC 版本。

♻️ 固定版本示例
+ARG RISCV_GNU_TOOLCHAIN_REF=<pin>-RUN git clone --depth 1 https://github.com/riscv-collab/riscv-gnu-toolchain \+RUN git clone https://github.com/riscv-collab/riscv-gnu-toolchain \
&& cd /src/riscv-gnu-toolchain \
+ && git checkout "${RISCV_GNU_TOOLCHAIN_REF}" \
&& git submodule update --init --depth 1 binutils newlib gcc gdb \
Based on learnings, 固件构建要求 GCC 15.1,请确认所固定的提交满足该要求。

Comment thread.scripts/generate_version Outdated
Comment thread.scripts/generate_version
- Add .scripts/generate_version to emit semver and Debian-friendly versions via git describe
- Update host/firmware CMake to derive LIBRMCS_PROJECT_VERSION and expose LIBRMCS_PROJECT_VERSION_STRING
- Stamp firmware USB product string and align CPack Debian packaging (headers install + versioned file names)
- Add release-package.yml to build SDK .deb (multi-arch) + optional source zip, and create a tag-triggered GitHub pre-release with uploaded artifacts
- Introduce Dockerfile.build_sdk and Dockerfile.build_firmware to package SDK/firmware from qzhhhi/librmcs-ci with versioned outputs
- Update host/CMakePresets.json with linux-debug/linux-release presets for the packaging builds
@qzhhhi
qzhhhi merged commit bca155a into mainJan 19, 2026
3 of 4 checks passed
@github-project-automationgithub-project-automationBot moved this from Todo to Done in RMCS Slave SDKJan 19, 2026
@qzhhhi
qzhhhi deleted the dev/ci-build branch January 19, 2026 04:20
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant

@qzhhhi