已合并
[feature]:devcontainer机制打样仓合入,pre-commit机制调整 #65
孟广欣创建于 8月4日
[feature]:devcontainer机制打样仓合入,pre-commit机制调整 #65
已合并
孟广欣创建于 8月4日
6 个文件变更+311-110
@@ -1,4 +1,4 @@
1-# Dev Container 快速入门指南1+# Dev Container 快速指南
2 2 
3> **真正开箱即用**:零手动配置!**首次 2 分钟** 全自动构建,**后续 10 秒** 极速开工。3> **真正开箱即用**:零手动配置!**首次 2 分钟** 全自动构建,**后续 10 秒** 极速开工。
4 4 
@@ -11,43 +11,9 @@
11| **远程服务器(推荐)** | [VS Code](https://code.visualstudio.com/) + `Dev Containers` + `Remote - SSH` 插件 | Linux 服务器已启用 Docker 服务 | 高性能计算、释放本地资源 |11| **远程服务器(推荐)** | [VS Code](https://code.visualstudio.com/) + `Dev Containers` + `Remote - SSH` 插件 | Linux 服务器已启用 Docker 服务 | 高性能计算、释放本地资源 |
12| **本地 PC** | [VS Code](https://code.visualstudio.com/) + `Dev Containers` 插件 | [Docker Desktop](https://www.docker.com/products/docker-desktop/)(Linux 模式) | 单机离线开发 |12| **本地 PC** | [VS Code](https://code.visualstudio.com/) + `Dev Containers` 插件 | [Docker Desktop](https://www.docker.com/products/docker-desktop/)(Linux 模式) | 单机离线开发 |
13 13 
14-> ⚠️ *注意:默认配置启用了 Host 网络模式及高权限,请务必在可信环境中使用。*14+> ⚠️ **安全提示**:默认配置启用了 Host 网络模式及高权限,请务必在可信环境中使用。
15 15 
16-## 🚀 3 步闪电开工16+### 可选:配置 SSH 免密登录(仅远程服务器方案,10 秒完成)
17- 
18-1. **打开项目**:在 VS Code 中打开本项目代码目录。
19-2. **加载容器**:点击右下角弹出的 **`Reopen in Container`** 提示(或通过 `F1` 执行同名命令)。
20-3. **进入开发**:待容器环境自动初始化完成后,即可直接进行编码、编译、单元测试及调试。
21- 
22-## 🔨 编译与单元测试
23- 
24-环境就绪后,通过 VS Code 菜单栏 **`Terminal`** > **`Run Task`** 即可调用预设的自动化任务:
25- 
26-| 任务名称 | 功能说明 |
27-| :--- | :--- |
28-| `Build: Release Mode` | 构建 Release 版本,产物输出至 `artifacts` 目录 |
29-| `Build: Debug Mode` | 构建 Debug 版本(仅 C++ 项目支持,Python 项目请忽略) |
30-| `Test: Run Unit Tests` | 执行全量单元测试 |
31-| `Clean: All Workspace` | 清理工作区内的所有构建缓存与临时文件 |
32- 
33-> *也可直接在终端执行 `python3 build.py` 命令,其功能与上述任务一致。*
34- 
35-## ⏱️ 自动化流程与耗时说明
36- 
37-启动 Dev Container 后,系统将**全自动完成以下环境配置**
38- 
39-| 阶段 | 自动化任务 | 首次耗时 | 后续启动 | 体验 |
40-|:--------------|:---------------------------------| :--- | :--- | :--- |
41-| **1. 环境拉取** | 拉取预置镜像并部署 VS Code Server | ~1 分钟 | 3 秒 | 全程无感 |
42-| **2. 身份与挂载** | 挂载代码目录(`/workspace`)并同步 Git 权限 | ~10 秒 | 3 秒 | 全程无感 |
43-| **3. 工具链加载** | 并行安装 Python 插件及 Clangd 等开发工具 | ~20 秒 | 3 秒 | 开箱即用 |
44-| **总计** | **零人工干预·全自动就绪** | **⏱️ ~2 分钟** | **⚡ ~10 秒** | **一次配置,持续高效** |
45- 
46-> **镜像说明**:因 MindStudio 镜像制作流程复杂且耗时,本方案**内置预构建镜像**。若需了解镜像细节,可参考 [《MindStudio 统一构建镜像制作指南》](https://gitcode.com/Ascend/msot/blob/master/docs/zh/common/docker_image_build_guide.md)。
47- 
48-## 💡 效率优化与故障恢复
49- 
50-### 1. 配置 SSH 免密登录(10 秒完成)
51 17 
52为避免频繁输入密码,可在 Windows PowerShell 中粘贴执行以下脚本,按提示操作即可自动完成配置:18为避免频繁输入密码,可在 Windows PowerShell 中粘贴执行以下脚本,按提示操作即可自动完成配置:
53 19 
@@ -73,7 +39,38 @@ Get-Content $pubKeyPath | ssh "${user}@${ip}" "mkdir -p ~/.ssh && chmod 700 ~/.s
73Write-Host "公钥上传完成,免密登录配置成功!" -ForegroundColor Green39Write-Host "公钥上传完成,免密登录配置成功!" -ForegroundColor Green
74```40```
75 41 
76-### 2. 毁坏无忧:一键复原环境42+## 🚀 3 步闪电开工
43+ 
44+1. **打开项目**:在 VS Code 中打开本项目代码目录。
45+2. **加载容器**:点击右下角弹出的 **`Reopen in Container`** 提示(或通过 `F1` 执行同名命令)。
46+3. **进入开发**:待容器环境初始化完成(弹出的日志打印“READY”时),即可直接进行编码、编译、单元测试、调试及合入。
47+ 
48+## ⏱️ 自动化流程与耗时说明
49+ 
50+启动 Dev Container 后,系统将**全自动完成以下环境配置**,期间无需任何人工干预:
51+ 
52+| 阶段 | 自动化任务 | 首次耗时 | 后续启动 | 体验 |
53+|:--------------|:---------------------------------| :--- | :--- | :--- |
54+| **1. 环境拉取** | 拉取预置镜像并部署 VS Code Server | ~1 分钟 | 3 秒 | 全程无感 |
55+| **2. 身份与挂载** | 挂载代码目录(`/workspace`)并同步 Git 权限 | ~10 秒 | 3 秒 | 全程无感 |
56+| **3. 工具链加载** | 并行安装 Python 插件及 Clangd 等开发工具 | ~20 秒 | 3 秒 | 开箱即用 |
57+| **总计** | **零人工干预·全自动就绪** | **⏱️ ~2 分钟** | **⚡ ~10 秒** | **一次配置,持续高效** |
58+ 
59+> **镜像说明**:因 MindStudio 镜像制作流程复杂且耗时,本方案**内置预构建镜像**。若需了解镜像细节,可参考 [《MindStudio 统一构建镜像制作指南》](https://gitcode.com/Ascend/msot/blob/master/docs/zh/common/docker_image_build_guide.md)。
60+ 
61+## 🔨 编译与单元测试
62+ 
63+环境就绪后,通过 VS Code 菜单栏 **`Terminal`** > **`Run Task`** 即可调用预设的自动化任务:
64+ 
65+| 任务名称 | 功能说明 |
66+| :--- | :--- |
67+| `Build: Release Mode` | 构建 Release 版本,产物输出至 `artifacts` 目录 |
68+| `Test: Run Unit Tests` | 执行全量单元测试 |
69+| `Clean: All Workspace` | 清理工作区内的所有构建缓存与临时文件 |
70+ 
71+> *也可直接在终端执行 `python3 build.py [test]` 命令,其功能与上述 Build/Test 任务一致。*
72+ 
73+## ♻️ 环境复原:毁坏无忧
77 74 
78若开发过程中容器环境搞乱或损坏,无需重新搭建:只需按 `F1` 键选择 **Dev Containers: Rebuild Container**,即可瞬间获得一个全新的纯净环境!75若开发过程中容器环境搞乱或损坏,无需重新搭建:只需按 `F1` 键选择 **Dev Containers: Rebuild Container**,即可瞬间获得一个全新的纯净环境!
79 76 
@@ -104,12 +101,7 @@ VS Code 远程开发依赖 SSH 端口转发。若服务端 `sshd_config` 限制
104 - 在远程服务器执行:`rm -rf ~/.vscode-server`101 - 在远程服务器执行:`rm -rf ~/.vscode-server`
105 - 重新发起连接,VS Code 将自动重新部署匹配的 Server 组件。102 - 重新发起连接,VS Code 将自动重新部署匹配的 Server 组件。
106 103 
107-### 2. 代码提交响应缓慢或反馈104+### 2. 修改 `.vscode/settings.json` 后 `git pull` 冲突且法更新
108- 
109-**原因分析**
110-项目默认启用 `pre-commit` 钩子。首次提交时需下载并初始化检查工具,耗时约 30~60 秒。后续提交将直接执行检查,响应通常为秒级。
111- 
112-### 3. 修改 `.vscode/settings.json` 后 `git pull` 冲突且无法更新?
113 105 
114**原因分析**106**原因分析**
115为支持个性化配置,该文件被标记为 `skip-worktree`,本地修改不会显示在 `git status` 中。当远端同步更新该文件时,Git 会拒绝覆盖本地内容以防止丢失。107为支持个性化配置,该文件被标记为 `skip-worktree`,本地修改不会显示在 `git status` 中。当远端同步更新该文件时,Git 会拒绝覆盖本地内容以防止丢失。
@@ -16,7 +16,7 @@
16 16 
17{17{
18 "name": "mskl",18 "name": "mskl",
19- "image": "swr.cn-north-4.myhuaweicloud.com/mindstudio-image/mindstudio-build:26.1.0-0701",19+ "image": "swr.cn-north-4.myhuaweicloud.com/mindstudio-image/mindstudio-build:26.2.0-0801",
20 20 
21 // 镜像 WORKDIR 即 /workspace;z_cache.sh 通过设备号探测 /workspace 是否为21 // 镜像 WORKDIR 即 /workspace;z_cache.sh 通过设备号探测 /workspace 是否为
22 // 独立挂载点,命中后自动把 ccache/uv 缓存放到 /workspace/.cache 下,22 // 独立挂载点,命中后自动把 ccache/uv 缓存放到 /workspace/.cache 下,
@@ -55,7 +55,11 @@
55 55 
56 // uv 缓存持久化:将宿主机 ~/.cache/uv bind mount 到容器内。56 // uv 缓存持久化:将宿主机 ~/.cache/uv bind mount 到容器内。
57 // 配合下方 UV_CACHE_DIR 环境变量,uv 安装/构建缓存不受容器重建影响。57 // 配合下方 UV_CACHE_DIR 环境变量,uv 安装/构建缓存不受容器重建影响。
58- "source=${localEnv:HOME}/.cache/uv,target=/home/mindstudio/.cache/uv,type=bind"58+ "source=${localEnv:HOME}/.cache/uv,target=/home/mindstudio/.cache/uv,type=bind",
59+ 
60+ // pre-commit Hook 环境持久化:使用 Docker named volume 保存首次初始化结果,
61+ // 容器重建后直接复用,无需再次下载仓库和创建各 Hook 的运行环境。
62+ "source=pre-commit-cache,target=/home/mindstudio/.cache/pre-commit,type=volume"
59 ],63 ],
60 "containerEnv": {64 "containerEnv": {
61 // ctr_in.py 进入 mindstudio-build 容器时注入,保证 profile.d 启用 gcc1165 // ctr_in.py 进入 mindstudio-build 容器时注入,保证 profile.d 启用 gcc11
@@ -65,7 +69,11 @@
65 // /usr/local/nodejs,非 root 用户没有写权限,因此把全局 npm 包放到用户目录。69 // /usr/local/nodejs,非 root 用户没有写权限,因此把全局 npm 包放到用户目录。
66 "NPM_CONFIG_PREFIX": "/home/mindstudio/.local",70 "NPM_CONFIG_PREFIX": "/home/mindstudio/.local",
67 // 配合上方 mounts 中宿主机 uv 缓存目录挂载,固化 uv 包安装缓存路径。71 // 配合上方 mounts 中宿主机 uv 缓存目录挂载,固化 uv 包安装缓存路径。
68- "UV_CACHE_DIR": "/home/mindstudio/.cache/uv"72+ "UV_CACHE_DIR": "/home/mindstudio/.cache/uv",
73+ 
74+ // 显式对齐上方 named volume 的挂载目标,确保后台预热和 Git Hook 执行时
75+ // 始终复用同一份 pre-commit 环境缓存。
76+ "PRE_COMMIT_HOME": "/home/mindstudio/.cache/pre-commit"
69 },77 },
70 "remoteEnv": {78 "remoteEnv": {
71 // VS Code Server 及其扩展进程不一定读取 shell 启动文件,显式补充用户命令目录。79 // VS Code Server 及其扩展进程不一定读取 shell 启动文件,显式补充用户命令目录。
@@ -53,7 +53,7 @@ else
53 : > "$SCRIPT_DIR/.host-gitconfig"53 : > "$SCRIPT_DIR/.host-gitconfig"
54fi54fi
55 55 
56-# ---- 准备 uv 缓存挂载源 ----56+# ---- 准备缓存挂载源 ----
57# devcontainer.json 将该目录 bind mount 到 /home/mindstudio/.cache/uv。57# devcontainer.json 将该目录 bind mount 到 /home/mindstudio/.cache/uv。
58# bind mount 的 source 必须在 docker create 前存在;initializeCommand 以宿主58# bind mount 的 source 必须在 docker create 前存在;initializeCommand 以宿主
59# 当前用户执行,因此新建目录天然归当前用户所有。59# 当前用户执行,因此新建目录天然归当前用户所有。
@@ -31,16 +31,18 @@
31# 能够感知到这些工具链的存在。31# 能够感知到这些工具链的存在。
32#32#
33# 执行顺序(按依赖关系排列):33# 执行顺序(按依赖关系排列):
34-# 1. fix_cache_ownership - 修复 z_cache.sh 创建缓存目录权限34+# 1. configure_yum_mirror - 切换至 HTTP 协议华为云 openEuler 软件源
35-# 2. fix_file_watcher_limit - 提升 inotify max_user_watches 至 52428835+# 2. fix_cache_ownership - 修复 z_cache.sh 创建的缓存目录权限
36-# 3. configure_user_bin - 建立用户级命令目录,重映射 npm prefix36+# 3. fix_file_watcher_limit - 提升 inotify max_user_watches 至 524288
37-# 4. configure_python311 - 在 shell 启动文件中启Python 3.1137+# 4. configure_user_bin - 建立户级命令目录,重映射 npm prefix
38-# 5. sync_git_identity - 从宿主同步 Git 用户名和邮箱38+# 5. ensure_shared_bin_path - 补齐 root 用户的共享命令路径
39-# 6. append_dev_hint_once - .bash_profile 追加常开发命令提示39+# 6. configure_python311 - shell 启动文件中启 Python 3.11
40-# 7. install_pre_commit_hook - 自动安装 pre-commit Git Hook40+# 7. sync_git_identity - 从宿主同步 Git 用户名和邮箱
41-# 8. install_gitleaks - OBS 下载 gitleaks 二进制(pre-commit 依赖)41+# 8. append_dev_hint_once - .bash_profile 追加常用开发命令提示
42-# 9. ignore_vscode_settings - 隔离个人化 VS Code settings 修改42+# 9. install_pre_commit_hook - 自动安装 pre-commit Git Hook
43-# 10. install_git_safe_pull_alias - 安装可处理 skip-worktree 文件的拉取命令43+# 10. warmup_pre_commit_async - 后台预创建 pre-commit Hook 环境
44+# 11. ignore_vscode_settings - 隔离个人化 VS Code settings 修改
45+# 12. install_git_safe_pull_alias - 安装可处理 skip-worktree 文件的拉取命令
44#46#
45# =============================================================================47# =============================================================================
46 48 
@@ -62,6 +64,106 @@ warn() {
62 printf '[post-create] warning: %s\n' "$*" >&264 printf '[post-create] warning: %s\n' "$*" >&2
63}65}
64 66 
67+# 以统一格式执行并展示初始化步骤。即使某一步失败也继续后续流程,避免单项
68+# 非关键配置阻止开发者进入容器;耗时用于识别初始化过程中的慢步骤。
69+run_step() {
70+ local step_number="$1"
71+ local total_steps="$2"
72+ local step_title="$3"
73+ local step_function="$4"
74+ local step_label
75+ local exit_code
76+ local started_at=$SECONDS
77+ local elapsed
78+ 
79+ printf -v step_label '%02d/%02d' "$step_number" "$total_steps"
80+ printf '\n'
81+ log "------------------------------------------------------------------------"
82+ log "[STEP $step_label] START | $step_title"
83+ 
84+ if "$step_function"; then
85+ elapsed=$((SECONDS - started_at))
86+ log "[STEP $step_label] DONE | $step_title (${elapsed}s)"
87+ else
88+ exit_code=$?
89+ elapsed=$((SECONDS - started_at))
90+ warn "[STEP $step_label] FAILED | $step_title (${elapsed}s, exit: $exit_code)"
91+ fi
92+ 
93+ # run_step 自身始终成功,确保某一步失败后仍执行剩余初始化任务。
94+ return 0
95+}
96+ 
97+# =============================================================================
98+# configure_yum_mirror —— 配置华为云 openEuler 软件源
99+# =============================================================================
100+#
101+# 背景与问题:
102+# 基础镜像默认使用 https://repo.openeuler.org,部分开发网络访问该地址较慢。
103+# 华为云 openEuler 镜像站提供相同的仓库目录结构,可直接保留当前发行版、
104+# 仓库分区和 $basearch 路径,仅替换站点前缀。
105+#
106+# 解决方案:
107+# 将 openEuler 官方源及 HTTPS 华为云源统一替换为:
108+# http://mirrors.huaweicloud.com/openeuler
109+# 修改前保留一次原始 repo 文件备份;仅在配置发生变化时清理 dnf/yum 元数据。
110+# 本地 file:// GPG Key 配置保持不变,软件包签名校验仍然启用。
111+configure_yum_mirror() {
112+ local repo_dir="/etc/yum.repos.d"
113+ local mirror_base="http://mirrors.huaweicloud.com/openeuler"
114+ local repo_files=("$repo_dir"/*.repo)
115+ local repo_file
116+ local backup_file
117+ local changed=0
118+ 
119+ if [ ! -e "${repo_files[0]}" ]; then
120+ warn "no yum repo files found in $repo_dir; skipping mirror configuration"
121+ return 0
122+ fi
123+ 
124+ for repo_file in "${repo_files[@]}"; do
125+ if ! grep -Eq 'https?://repo\.openeuler\.org|https://mirrors\.huaweicloud\.com/openeuler|https?://repo\.huaweicloud\.com/openeuler' "$repo_file"; then
126+ continue
127+ fi
128+ 
129+ backup_file="${repo_file}.post-create.bak"
130+ if [ ! -e "$backup_file" ]; then
131+ sudo cp -a "$repo_file" "$backup_file" || {
132+ warn "failed to back up yum repo file: $repo_file"
133+ return 1
134+ }
135+ fi
136+ 
137+ sudo sed -E -i \
138+ -e "s#https?://repo\.openeuler\.org#${mirror_base}#g" \
139+ -e "s#https://mirrors\.huaweicloud\.com/openeuler#${mirror_base}#g" \
140+ -e "s#https?://repo\.huaweicloud\.com/openeuler#${mirror_base}#g" \
141+ "$repo_file" || {
142+ warn "failed to update yum repo file: $repo_file"
143+ return 1
144+ }
145+ changed=1
146+ done
147+ 
148+ if ! grep -Eq '^[[:space:]]*baseurl=http://mirrors\.huaweicloud\.com/openeuler/' "${repo_files[@]}"; then
149+ warn "Huawei Cloud yum mirror was not found in active repo configuration"
150+ return 1
151+ fi
152+ 
153+ if [ "$changed" -eq 1 ]; then
154+ if command -v dnf >/dev/null 2>&1; then
155+ sudo dnf clean all >/dev/null 2>&1 || warn "failed to clean dnf metadata"
156+ elif command -v yum >/dev/null 2>&1; then
157+ sudo yum clean all >/dev/null 2>&1 || warn "failed to clean yum metadata"
158+ fi
159+ log "yum mirror changed to $mirror_base"
160+ else
161+ log "yum mirror already uses $mirror_base"
162+ fi
163+ 
164+ log "configure_yum_mirror succeeded"
165+}
166+ 
65# append_path_once:167# append_path_once:
66# 幂等地将 $HOME/.local/bin 放到指定 shell 启动文件的 PATH 前端。168# 幂等地将 $HOME/.local/bin 放到指定 shell 启动文件的 PATH 前端。
67# 解决非 root 用户(mindstudio)无法写入 /usr/local/nodejs 等系统级目录的问题。169# 解决非 root 用户(mindstudio)无法写入 /usr/local/nodejs 等系统级目录的问题。
@@ -339,6 +441,83 @@ install_pre_commit_hook() {
339 log "install_pre_commit_hook succeeded"441 log "install_pre_commit_hook succeeded"
340}442}
341 443 
444+# =============================================================================
445+# warmup_pre_commit_async —— 后台预创建 pre-commit Hook 环境
446+# =============================================================================
447+#
448+# 背景与问题:
449+# pre-commit 首次运行时需要下载 Hook 仓库并创建各自的运行环境,耗时较长。
450+# 如果等到开发者第一次提交时才执行,会明显阻塞提交流程。
451+#
452+# 解决方案:
453+# pre-commit Hook 安装完成后,在后台执行 `pre-commit install-hooks`,并与
454+# 后续 clangd 安装等初始化任务并行。该命令只准备 Hook 环境,不执行检查,
455+# 也不会修改工作区文件。后台进程的标准输入、输出和错误均与
456+# postCreateCommand 分离,避免阻塞容器初始化完成。
457+#
458+# 资源与并发控制:
459+# 1. 使用 nice 和 ionice 降低 CPU、磁盘调度优先级,减少对交互操作的影响。
460+# 2. flock 可用时持有非阻塞锁,防止脚本重复执行后同时启动多个预热任务。
461+# 3. 详细结果写入缓存目录中的日志,预热失败不影响容器正常使用。
462+warmup_pre_commit_async() {
463+ if ! command -v pre-commit >/dev/null 2>&1; then
464+ warn "pre-commit is not available; skipping async warmup"
465+ return 0
466+ fi
467+ 
468+ local repo_root
469+ repo_root=$(git rev-parse --show-toplevel 2>/dev/null || true)
470+ if [ -z "$repo_root" ]; then
471+ warn "workspace is not a Git repository; skipping async warmup"
472+ return 0
473+ fi
474+ 
475+ if [ ! -f "$repo_root/.pre-commit-config.yaml" ]; then
476+ warn "pre-commit config is not available; skipping async warmup"
477+ return 0
478+ fi
479+ 
480+ local warmup_dir="$HOME/.cache"
481+ local log_file="$warmup_dir/pre-commit-warmup.log"
482+ local lock_file="$warmup_dir/pre-commit-warmup.lock"
483+ mkdir -p "$warmup_dir"
484+ 
485+ (
486+ # 忽略启动 shell 结束时可能发送的 HUP,并断开所有终端输入输出。
487+ trap '' HUP
488+ cd "$repo_root" || exit 0
489+ 
490+ if command -v flock >/dev/null 2>&1; then
491+ exec 9>"$lock_file"
492+ if ! flock -n 9; then
493+ log "pre-commit environment warmup is already running"
494+ exit 0
495+ fi
496+ fi
497+ 
498+ # ionice 调整失败时继续运行;nice 在常规 Linux 环境中始终可用。
499+ if command -v ionice >/dev/null 2>&1; then
500+ ionice -c 3 -p "$$" 2>/dev/null || true
501+ fi
502+ 
503+ # 确保 $HOME/.local/bin 在 PATH 前端,使用与用户交互式 shell
504+ # 一致的 pre-commit 二进制(Python 3.11),避免版本不匹配导致
505+ # 预热环境与用户实际使用的 Python 版本不一致而重新下载。
506+ export PATH="$HOME/.local/bin:$PATH"
507+ 
508+ log "pre-commit environment warmup started"
509+ if nice -n 10 pre-commit install-hooks; then
510+ log "pre-commit environment warmup succeeded"
511+ else
512+ warn "pre-commit environment warmup failed"
513+ fi
514+ ) </dev/null >>"$log_file" 2>&1 &
515+ 
516+ local warmup_pid
517+ warmup_pid=$!
518+ log "pre-commit environment warmup started in background (pid: $warmup_pid, log: $log_file)"
519+}
520+ 
342# =============================================================================521# =============================================================================
343# fix_cache_ownership —— 修复缓存目录权限522# fix_cache_ownership —— 修复缓存目录权限
344# =============================================================================523# =============================================================================
@@ -477,6 +656,7 @@ fix_file_watcher_limit() {
477 656 
478 warn "failed to increase inotify max_user_watches; VS Code file watching may not work correctly"657 warn "failed to increase inotify max_user_watches; VS Code file watching may not work correctly"
479}658}
659+ 
480# =============================================================================660# =============================================================================
481# ignore_vscode_settings —— 隔离个人化 VS Code Settings 修改661# ignore_vscode_settings —— 隔离个人化 VS Code Settings 修改
482# =============================================================================662# =============================================================================
@@ -548,46 +728,33 @@ install_git_safe_pull_alias() {
548 log "install_git_safe_pull_alias succeeded"728 log "install_git_safe_pull_alias succeeded"
549}729}
550 730 
551-# =============================================================================731+# 输出醒目的完成标识,便于开发者在 Dev Containers 启动日志中快速确认状态。
552-# install_gitleaks —— Gitleaks 秘密扫描二进制下载732+print_ready_banner() {
553-# =============================================================================733+ local green=$'\033[1;32m'
554-#734+ local reset=$'\033[0m'
555-# 背景与问题:
556-# pre-commit 配置中的 gitleaks-offline-scan hook 执行 `./gitleaks protect`,
557-# 期望仓库根目录存在 gitleaks 二进制文件。如果缺失,git commit 时
558-# pre-commit hook 会因 "Executable ./gitleaks not found" 而失败。
559-#
560-# 解决方案:
561-# 从华为 OBS 镜像站下载预编译的 gitleaks 二进制到 /workspace/gitleaks,
562-# 确保 devcontainer 创建后立即可用,无需开发者手工下载。
563-#
564-# 降级策略:
565-# wget 下载失败时只告警,不阻塞容器创建。
566-# 开发者仍可手工下载或使用 git commit --no-verify 绕过。
567-install_gitleaks() {
568- local target="/workspace/gitleaks"
569- local base_url="https://inst.obs.cn-north-4.myhuaweicloud.com/env/mirror"
570- local arch=""
571- local url=""
572 735 
573- # 根据 CPU 架构选择对应的二进制目录736+ cat <<EOF
574- case "$(uname -m)" in
575- x86_64) arch="x86_64" ;;
576- aarch64) arch="aarch64" ;;
577- *) arch="x86_64" ;; # 默认回退到 x86_64
578- esac
579- url="${base_url}/${arch}/gitleaks"
580 737 
581- log "downloading gitleaks (${arch}) from OBS..."738++------------------------------------------------------------------------------+
582- if wget --no-host-directories -c --no-check-certificate \739+| |
583- -O "$target" "$url" 2>/dev/null; then740+|${green} ____ _____ _ ______ __ ${reset}|
584- chmod +x "$target"741+|${green} | _ \| ____| / \ | _ \ \ / / ${reset}|
585- log "gitleaks installed successfully: $($target --version 2>/dev/null || echo 'version unknown')"742+|${green} | |_) | _| / _ \ | | | \ V / ${reset}|
586- else743+|${green} | _ <| |___ / ___ \| |_| || | ${reset}|
587- warn "failed to download gitleaks (${arch}) from OBS; git commit may fail on pre-commit hook"744+|${green} |_| \_\_____/_/ \_\____/ |_| ${reset}|
588- warn "URL attempted: ${url}"745+| |
589- rm -f "$target"746+| +------------------------------------------------------------------------+ |
590- fi747+| | DEV CONTAINER STATUS: ${green}READY${reset} | |
748+| +------------------------------------------------------------------------+ |
749+| |
750+| ENVIRONMENT ${green}READY${reset} FOR DEVELOPMENT |
751+| WORKSPACE /workspace |
752+| |
753+| Initialization complete. Start coding, building, and shipping. |
754+| |
755++------------------------------------------------------------------------------+
756+ 
757+EOF
591}758}
592 759 
593# =============================================================================760# =============================================================================
@@ -595,20 +762,23 @@ install_gitleaks() {
595# =============================================================================762# =============================================================================
596#763#
597# 按依赖顺序执行:先修复目录权限,再写用户配置,最后安装 Git 辅助能力。764# 按依赖顺序执行:先修复目录权限,再写用户配置,最后安装 Git 辅助能力。
598-# 各模块尽量自行降级并输出 warning,非关键项失败不阻止容器启动。765+# run_step 为每一步输出序号、状态和耗时,非关键项失败不阻止容器启动。
599 766 
600-log "post-create setup started"767+total_steps=14
768+log "Dev Container initialization started ($total_steps steps)"
601 769 
602-fix_cache_ownership770+run_step 1 "$total_steps" "Configure Huawei Cloud yum mirror" configure_yum_mirror
603-fix_file_watcher_limit771+run_step 2 "$total_steps" "Fix cache directory ownership" fix_cache_ownership
604-configure_user_bin772+run_step 3 "$total_steps" "Configure file watcher limit" fix_file_watcher_limit
605-ensure_shared_bin_path773+run_step 4 "$total_steps" "Configure user command paths" configure_user_bin
606-configure_python311774+run_step 5 "$total_steps" "Configure shared command paths" ensure_shared_bin_path
607-sync_git_identity775+run_step 6 "$total_steps" "Configure Python 3.11" configure_python311
608-append_dev_hint_once776+run_step 7 "$total_steps" "Synchronize Git identity" sync_git_identity
609-install_pre_commit_hook777+run_step 8 "$total_steps" "Install developer shell hints" append_dev_hint_once
610-install_gitleaks778+run_step 9 "$total_steps" "Install pre-commit Git Hook" install_pre_commit_hook
611-ignore_vscode_settings779+run_step 10 "$total_steps" "Start pre-commit environment warmup" warmup_pre_commit_async
612-install_git_safe_pull_alias780+run_step 11 "$total_steps" "Configure workspace Git settings" ignore_vscode_settings
781+run_step 12 "$total_steps" "Install Git safe-pull command" install_git_safe_pull_alias
613 782 
614log "post-create setup finished"783log "post-create setup finished"
784+print_ready_banner
@@ -91,7 +91,7 @@ repos:
91 hooks:91 hooks:
92 - id: gitleaks-offline-scan92 - id: gitleaks-offline-scan
93 name: Gitleaks Secret Scan(Local Binary)93 name: Gitleaks Secret Scan(Local Binary)
94- entry: ./gitleaks94+ entry: gitleaks
atomgit-bot
atomgit-botatomgit-bot8月4日

🟡 Medium Priority

此行将 gitleaks hook 的 entry 从 ./gitleaks(仓库根目录的本地二进制文件)改为 gitleaks(依赖系统 PATH 查找)。

然而,.devcontainer/post-create.sh 中的 install_gitleaks 函数(第 567-591 行)仍将 gitleaks 二进制文件下载到 /workspace/gitleaks,其注释(第 556-558 行)明确指出这是为了满足 ./gitleaks 配置。该函数的设计与旧的 ./gitleaks 入口绑定——它将二进制文件放在仓库根目录,该目录通常不在 PATH 中。

失效模式:在 devcontainer 内,post-create.sh 运行后,gitleaks 位于 /workspace/gitleaks,但新的 entry gitleaks 会在 PATH 中查找。由于 /workspace 通常不在 PATH 中,pre-commit hook 会因 "Executable gitleaks not found" 而失败。即使新镜像 26.2.0-0801 恰好预装了 gitleaks,install_gitleaks 函数仍会进行冗余下载,且其注释现已产生误导。

建议:使 pre-commit entry 与 install_gitleaks 的行为保持一致。两种方案可选:(a) 将 entry 恢复为 ./gitleaks 以匹配现有的 install_gitleaks 逻辑;或 (b) 更新 install_gitleaks,将二进制文件安装到 PATH 中的某个目录(如 $HOME/.local/bin/gitleaks,因为 configure_user_bin 已确保该目录在 PATH 中),并将 entry 保持为 gitleaks。若新镜像已预装 gitleaks,方案 (b) 更佳——同时移除 install_gitleaks 函数中冗余的下载步骤。

likedislike
不准确?
孟广欣
孟广欣
8月5日 评论:
95 language: system95 language: system
96 pass_filenames: true96 pass_filenames: true
97 args:97 args:
@@ -0,0 +1,31 @@
1+#!/usr/bin/env bash
2+# =============================================================================
3+# clang-tidy wrapper — checks compile_commands.json before running clang-tidy
4+# =============================================================================
5+set -euo pipefail
6+ 
7+BUILD_DIRS=("build")
8+ 
9+for dir in "${BUILD_DIRS[@]}"; do
10+ if [[ -f "${dir}/compile_commands.json" ]]; then
11+ break
12+ fi
13+done
14+ 
15+if [[ ! -f "${dir}/compile_commands.json" ]]; then
16+ cat >&2 <<'EOF'
17+=======================================================================
18+ ERROR: compile_commands.json NOT FOUND
19+-----------------------------------------------------------------------
20+ clang-tidy requires a compilation database to work.
21+ Run this command to generate compile_commands.json:
22+ 
23+ python3 build.py
24+ 
25+ This will generate compile_commands.json under the build/ directory.
26+=======================================================================
27+EOF
28+ exit 1
29+fi
30+ 
31+exec clang-tidy "$@"