如何配置GitLab CI以可靠缓存Cabal构建的Haskell包依赖?
修复GitLab CI中Cabal缓存导致的构建失败问题
问题根源
你遇到的错误是因为GitLab CI缓存的Cabal存储目录(.cabal)出现文件缺失或损坏,比如hedgehog-1.2包的内部模块文件丢失,导致后续构建无法找到依赖模块。这类问题通常由以下原因引发:
- 缓存增量更新时部分文件未正确上传/下载
- 不同构建环境(如GHC版本、Cabal版本)共用同一缓存,引发依赖版本冲突
- 失败的构建更新了缓存,留存了损坏的状态
具体修复方案
1. 优化缓存策略,避免缓存污染
修改GitLab CI的缓存配置,缩小缓存范围并加入环境/依赖标识,确保缓存隔离性:
cabal-build-and-test: cache: key: "v1-cabal-{{ .CI_JOB_IMAGE }}-{{ hashFiles "cabal.project" "cabal.project.freeze" }}" when: "on_success" # 仅成功构建后更新缓存,避免留存损坏状态 paths: - ".cabal/packages" # 仅缓存远程包缓存 - ".cabal/store" # 缓存已编译的依赖产物 script: - | cat >cabal.project.local <<EOF store-dir: $CI_PROJECT_DIR/.cabal/store remote-repo-cache: $CI_PROJECT_DIR/.cabal/packages EOF nix run .#cabal-test
- 缓存Key优化:加入镜像标识和依赖文件哈希,当镜像、
cabal.project或cabal.project.freeze变化时自动生成新缓存,避免版本冲突 - 缓存时机调整:将
when: always改为on_success,只保留成功构建的缓存
2. 添加缓存完整性检查,自动清理损坏缓存
在构建脚本中加入包完整性检测,发现损坏时自动清理缓存:
修改script部分为:
cat >cabal.project.local <<EOF store-dir: $CI_PROJECT_DIR/.cabal/store remote-repo-cache: $CI_PROJECT_DIR/.cabal/packages EOF # 检测损坏的Haskell包,存在则清理缓存 if ghc-pkg check 2>&1 | grep -E "(broken package|missing files)"; then echo "检测到损坏包,清理Cabal缓存..." rm -rf .cabal fi nix run .#cabal-test
3. 优化Cabal构建命令(可选)
调整cabal-test脚本,提前确保依赖完整性:
cabal update hackage.haskell.org # 先单独安装所有依赖,确认完整后再构建项目 cabal build --only-dependencies cabal build cabal run tests
这一步可提前发现依赖问题,避免项目构建中途失败。
内容的提问来源于stack exchange,提问作者Jean-Paul Calderone
相关产品推荐
相关产品推荐

