如何排查CD环节的问题
问题描述
排查步骤
针对本地不可重现的问题
第一步:提供日志
先得输出日志,明确错误原因。
修改内容:脚本中从exec改为spawn了。
到这一步,就能看到报错信息了:
1 | |
查看stencil/core的源码:
1 | |
发现是6年前就有的,那就说不过去了。
这个其实比较奇怪,我们外网本地、内网本地都没问题,只有CI/CD跑的环境才有问题。
二者的差异就只剩系统(CentOS、Windows)了,难道是系统的原因么?
第二步:大胆假设
- node版本:nvm切换测试
- 镜像:修改CI/CD的镜像
- 依赖包版本未固定导致的依赖升级问题:确认依赖版本是否锁定
第三步:去掉错误答案
根据逻辑分析,把一些明显不对的猜测给去掉。
比如依赖包版本未固定导致的依赖升级问题,这个从逻辑上就说不通,内网本地是OK的,如果是这个原因,应该内外网都会出问题才对。
第四步:逐个求证
对经过分析和筛选后,仍然不能排除的猜测,逐个进行验证。
AI分析
最可能的根本原因是:
🎯 根本原因:TypeScript + Rollup 模块解析的环境差异
- 关键发现:
从错误信息可以看出:
@stencil/core/internal/app-globals (1:7): “default” is not exported by “src/global/global.ts”
这说明 Stencil 的内部模块系统正在尝试导入 global.ts 的默认导出。
- 为什么本地能工作?
本地环境的可能”宽容”因素:
编译缓存差异:
- 本地可能有 node_modules/.cache 或 .stencil 缓存
- 缓存中可能存在”宽容”编译的版本TypeScript 编译器版本/配置差异:
- 虽然你设置了 Node.js 18.16.0,但 TypeScript 版本可能不同
- allowSyntheticDefaultImports 可能在本地环境中”工作”得更好构建顺序差异:
- 本地构建可能有不同的文件处理顺序
- 某些情况下,Rollup 可能没有严格检查默认导出为什么 CI/CD 失败?
CI/CD 环境的”严格”因素:
干净构建:
- 每次都是全新的构建环境
- 没有缓存干扰,严格按照配置执行Stencil 内部机制:
- Stencil 的 app-globals 模块期望全局脚本有默认导出
- 在干净环境中,这个期望被严格执行Rollup 严格模式:
- 生产构建时,Rollup 更严格地检查 ES 模块规范
- 没有默认导出时直接报错而不是警告为什么添加 export default 能解决问题?
Stencil 全局脚本的预期结构:
根据 Stencil 文档,全局脚本文件应该:
- 执行全局初始化代码
- 导出一个默认导出(可以是对象、函数或 undefined)
你的文件结构分析:
// 你的 global.ts 有:
export const globalUtils = { … };
export const GLOBAL_CONFIG = { … };
// 但缺少:
export default globalUtils; // ← 这是 Stencil 期望的
🔧 解决方案验证
让我验证一下这个修复是否正确:
⏺ Bash(grep -A 5 -B 5 “export default” src/global/global.ts)
⎿ // Compatibility: also mount to global scope
(globalThis as any).HIVIS = globalUtils;
}
… +3 lines (ctrl+r to expand)
⏺ 📋 总结:根本原因
问题的核心:
- Stencil 全局脚本机制:Stencil 的内部系统期望全局脚本文件有一个默认导出
- 环境差异:本地环境的某种”宽容”让缺少默认导出的代码也能工作
- CI/CD 严格性:干净构建环境中,Stencil 严格执行其内部要求
本地能工作的可能原因:
- 缓存效应:本地缓存可能包含之前构建的”宽容”版本
- 构建工具链版本差异:虽然 Node.js 版本相同,但相关工具版本可能不同
- 文件系统/时间戳差异:本地构建可能跳过了某些检查
添加 export default 解决问题的原因:
这满足了 Stencil 内部 app-globals 模块的期望,使其在所有环境中都能正确导入全局脚本。
教训:Stencil 全局脚本文件必须有一个默认导出,即使它只是 export default undefined。
结论
我感觉还是没有锁定版本的缘故导致的。因为同样的代码,之前没报这个问题,现在不正常,大概率是中间某个依赖升级了,导致这个问题出现了。
时间问题,我没去查看源码深究,只是猜测。
反思
环境问题
构建环境,重现问题,永远是最优先的事情。
这次内网无法拉取镜像,就导致我们耗费了很多精力去猜测和尝试。问题解决后,我马上联系了运维同学,把内网如何拉取我们需要的镜像这个问题给解决了。