【问题标题】:How to cache Elixir / Phoenix on CircleCI?如何在 CircleCI 上缓存 Elixir / Phoenix?
【发布时间】:2026-02-07 19:55:01
【问题描述】:

目前我对Elixir项目的CircleCI 2.0缓存策略如下:

  - restore_cache:
      keys:
        - v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
        - v1-mix-cache-{{ .Branch }}
        - v1-mix-cache
        - v1-build-cache-{{ .Branch }}
        - v1-build-cache

  - save_cache:
      key: v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
      paths: deps
  - save_cache:
      key: v1-mix-cache-{{ .Branch }}
      paths: deps
  - save_cache:
      key: v1-mix-cache
      paths: deps
  - save_cache:
      key: v1-build-cache-{{ .Branch }}
      paths: _build
  - save_cache:
      key: v1-build-cache
      paths: _build

但是,它有时会导致如下错误:

===> Compiling certifi

=ERROR REPORT==== 12-Jul-2018::15:37:40 ===
Loading of /home/circleci/project/_build/test/lib/parse_trans/ebin/parse_trans.beam failed: badfile

=ERROR REPORT==== 12-Jul-2018::15:37:40 ===
beam/beam_load.c(1863): Error loading module parse_trans:
  This BEAM file was compiled for a later version of the run-time system than 20.
  To fix this, please recompile this module with an 20 compiler.
  (Use of opcode 162; this emulator supports only up to 159.)

===> Compiling src/certifi.erl failed

有时我们会得到:

 ** (UndefinedFunctionError) function :hackney.request/5 is undefined (module :hackney is not available)

/home/circleci/project/_build/test/lib/hackney/ebin/hackney.beam failed: :badfile

 12:44:02.665 [error] beam/beam_load.c(1863): Error loading module hackney:
   This BEAM file was compiled for a later version of the run-time system than 20.
   To fix this, please recompile this module with an 20 compiler.
   (Use of opcode 162; this emulator supports only up to 159.)

当然,一切都与缓存有关,因为当我们在没有缓存的情况下重新运行构建时,一切都按预期工作。

这种情况并非每次都会发生,但有时会出现不同的错误。

对于Elixir 项目,你们有什么可靠的缓存策略吗?

【问题讨论】:

    标签: continuous-integration elixir phoenix-framework circleci circleci-2.0


    【解决方案1】:

    免责声明:我是 CircleCI 开发者倡导者

    我在这里看到 1 个问题和一个潜在问题。

    首先,您不想为部分键多次保存缓存。通过部分匹配来恢复缓存键。当你保存缓存时,使用一次完整的键名就可以了。恢复缓存会在需要时进行匹配。

    第二,Elixir 是否支持部分缓存?我自己不使用它,所以我还不太了解它。如果没有,您可能只想恢复完整的缓存键,而不是任何部分键。

    我的第一点:

      - restore_cache:
          keys:
            - v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
            - v1-mix-cache-{{ .Branch }}
            - v1-mix-cache
            - v1-build-cache-{{ .Branch }}
            - v1-build-cache
    
      - save_cache:
          key: v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
          paths: deps
      - save_cache:
          key: v1-build-cache-{{ .Branch }}
          paths: _build
    

    我的第二点:

      - restore_cache:
          keys:
            - v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
            - v1-build-cache-{{ .Branch }}
    
      - save_cache:
          key: v1-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
          paths: deps
      - save_cache:
          key: v1-build-cache-{{ .Branch }}
          paths: _build
    

    【讨论】:

    • 我得到的问题还是:10:08:04.821 [error] Loading of /home/circleci/project/_build/test/lib/hackney/ebin/hackney.beam failed: :badfile 10:08:04.822 [error] beam/beam_load.c(1863): Error loading module hackney: This BEAM file was compiled for a later version of the run-time system than 20. To fix this, please recompile this module with an 20 compiler. (Use of opcode 162; this emulator supports only up to 159.)
    • @KamilLelonek 看起来您的缓存包含使用不同版本的 Erlang/OTP 的构建。尝试通过修改密钥的版本号来破坏缓存。
    【解决方案2】:

    解决办法是:

      - restore_cache:
          keys:
            - v{{ .Environment.CACHE_VERSION }}-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
      - restore_cache:
          keys:
            - v{{ .Environment.CACHE_VERSION }}-build-cache-{{ .Branch }}
    
      - save_cache:
          key: v{{ .Environment.CACHE_VERSION }}-mix-cache-{{ .Branch }}-{{ checksum "mix.lock" }}
          paths: deps
      - save_cache:
          key: v{{ .Environment.CACHE_VERSION }}-build-cache-{{ .Branch }}
          paths: _build
    

    【讨论】: