You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitHub Actions更新yarn.lock后构建失败的原因及解决方法

问题描述

使用如下GitHub Actions流程:
GitHub Actions流程
当Dependabot更新yarn.lock后构建失败,错误信息如下:

Run yarn build
Usage Error: The project in /home/runner/work/na-lab-client/na-lab-client/package.json doesn't seem to have been installed - running an install there might help

$ yarn run [--inspect] [--inspect-brk] [-T,--top-level] [-B,--binaries-only] <scriptName> ...
Error: Process completed with exit code 1.

疑问

  1. 该错误为何发生?
  2. 如何解决该错误?

尝试情况:

不使用依赖缓存时,Build任务自行安装依赖即可运行成功;部署环境中构建也能成功。


我的ci.yml代码如下:

name: CI

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

env:
  CACHED_DEPENDENCY_PATHS: ${{ github.workspace }}/.yarn/unplugged
  CACHED_BUILD_PATHS: ${{ github.workspace }}/.next
  BUILD_CACHE_KEY: ${{ github.sha }}
  DEFAULT_NODE_VERSION: '16'

jobs:
  job_install_dependencies:
    name: Install Dependencies
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Check out current commit (${{ github.sha }})
        uses: actions/checkout@v3
      - name: Set up Node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.DEFAULT_NODE_VERSION }}

      - name: Compute dependency cache key
        id: compute_lockfile_hash
        run: echo "::set-output name=hash::${{ hashFiles('yarn.lock') }}"

      - name: Check dependency cache
        uses: actions/cache@v3
        id: cache_dependencies
        with:
          path: ${{ env.CACHED_DEPENDENCY_PATHS }}
          key: ${{ steps.compute_lockfile_hash.outputs.hash }}

      - name: Install dependencies
        if: steps.cache_dependencies.outputs.cache-hit == ''
        run: yarn install --immutable
    outputs:
      dependency_cache_key: ${{ steps.compute_lockfile_hash.outputs.hash }}

  job_build:
    name: Build
    needs: [job_install_dependencies]
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Check out current commit (${{ github.sha }})
        uses: actions/checkout@v3

      - name: Set up Node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.DEFAULT_NODE_VERSION }}

      - name: Check dependency cache
        uses: actions/cache@v3
        with:
          path: ${{ env.CACHED_DEPENDENCY_PATHS }}
          key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}

      - name: Check build cache
        uses: actions/cache@v3
        id: cache_built_packages
        with:
          path: ${{ env.CACHED_BUILD_PATHS }}
          key: ${{ env.BUILD_CACHE_KEY }}

      - name: Build
        if: steps.cache_built_packages.outputs.cache-hit == ''
        run: yarn build

    outputs:
      dependency_cache_key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}

  job_codechecks:
    if: github.event_name != 'push'
    runs-on: ubuntu-latest
    name: Run codechecks
    needs: [job_install_dependencies]

    steps:
      - name: Check out current commit (${{ github.sha }})
        uses: actions/checkout@v3
      - name: Set up Node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.DEFAULT_NODE_VERSION }}

      - name: Check dependency cache
        uses: actions/cache@v3
        with:
          path: ${{ env.CACHED_DEPENDENCY_PATHS }}
          key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}

      - name: Run codechecks
        run: yarn codechecks
        env:
          CC_SECRET: ${{ secrets.CC_SECRET }}

  job_continuous_integration:
    runs-on: ubuntu-latest
    name: Check test & lint
    needs: [job_install_dependencies]

    steps:
      - name: Check out current commit (${{ github.sha }})
        uses: actions/checkout@v3
      - name: Set up Node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.DEFAULT_NODE_VERSION }}

      - name: Check dependency cache
        uses: actions/cache@v3
        with:
          path: ${{ env.CACHED_DEPENDENCY_PATHS }}
          key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}

      - name: Check Lint
        if: github.event_name != 'push'
        run: yarn lint

      - name: Check Stylelint
        if: github.event_name != 'push'
        run: yarn lint:style

      - name: Check Unit Test
        if: github.event_name != 'push'
        run: yarn test

  job_codecov_test_coverage:
    name: Set codecov unit test coverage
    runs-on: ubuntu-latest
    needs: [job_install_dependencies]
    steps:
      - name: Check out current commit (${{ github.sha }})
        uses: actions/checkout@v3

      - name: Set up Node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.DEFAULT_NODE_VERSION }}

      - name: Check dependency cache
        uses: actions/cache@v3
        with:
          path: ${{ env.CACHED_DEPENDENCY_PATHS }}
          key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}

      - name: Create Unit Test Coverage
        run: yarn test:coverage

      - name: Set unit test coverage
        uses: codecov/codecov-action@v3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          fail_ci_if_error: true

  job_e2e_test:
    timeout-minutes: 60
    name: Check e2e test
    runs-on: ubuntu-latest
    needs: [job_install_dependencies]
    steps:
      - name: Check out current commit (${{ github.sha }})
        uses: actions/checkout@v3

      - name: Set up Node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.DEFAULT_NODE_VERSION }}

      - name: Check dependency cache
        uses: actions/cache@v3
        with:
          path: ${{ env.CACHED_DEPENDENCY_PATHS }}
          key: ${{ needs.job_install_dependencies.outputs.dependency_cache_key }}

      - name: Install Playwright Browsers
        run: yarn playwright install --with-deps

      - name: Run Playwright tests
        run: yarn test:e2e

      - name: Report playwright tests
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

  job_nextjs_bundle_analysis:
    name: Nextjs bundle analysis
    runs-on: ubuntu-latest
    needs: [job_build]
    steps:
      - name: Check out current commit (${{ github.sha }})
        uses: actions/checkout@v3

      - name: Set up Node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ env.DEFAULT_NODE_VERSION }}

      - name: Check dependency cache
        uses: actions/cache@v3
        with:
          path: ${{ env.CACHED_DEPENDENCY_PATHS }}
          key: ${{ needs.job_build.outputs.dependency_cache_key }}

      - name: Check build cache
        uses: actions/cache@v3
        with:
          path: ${{ env.CACHED_BUILD_PATHS }}
          key: ${{ env.BUILD_CACHE_KEY }}

      - name: Analyze bundle sizes
        uses: transferwise/actions-next-bundle-analyzer@master
        with:
          workflow-id: ci.yml
          base-branch: main
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

问题解答

问题1:错误原因

  1. 缓存路径不完整:当前仅缓存.yarn/unplugged目录,但使用--immutable的Yarn Berry(Yarn 3+)运行yarn build需要.yarn/cache、.yarn/install-state.gz、.pnp.cjs等关键文件,这些文件缺失会让Yarn判定依赖未完成安装。
  2. 跨Job缓存一致性问题:job_install_dependencies安装依赖后,未缓存全部必要文件,导致后续job_build拉取缓存后缺少依赖安装状态标记,Yarn无法识别依赖已就绪。
  3. Dependabot更新后缓存未触发正确安装:虽然job_install_dependencies会在缓存未命中时执行安装,但缓存路径不全导致即使缓存命中,依赖状态也不完整,后续Job无法正常使用。

问题2:解决方法

方案1:修正缓存路径,包含Yarn Berry全部关键文件

更新环境变量CACHED_DEPENDENCY_PATHS,覆盖所有Yarn运行必需的依赖相关文件/目录:

env:
  CACHED_DEPENDENCY_PATHS: |
    ${{ github.workspace }}/.yarn/cache
    ${{ github.workspace }}/.yarn/unplugged
    ${{ github.workspace }}/.yarn/install-state.gz
    ${{ github.workspace }}/.pnp.cjs

所有使用依赖缓存的Job(job_install_dependencies、job_build等)均使用该更新后的路径。

方案2:在Build Job中添加依赖校验步骤

即使缓存命中,也执行yarn install --immutable校验依赖状态,该命令会快速验证依赖完整性,缺失则自动补充,不重复下载已存在的依赖:
在job_build的Check dependency cache步骤后添加:

- name: Ensure dependencies are installed
  run: yarn install --immutable

方案3:优化缓存Key生成逻辑(可选)

将yarn.lock和.yarnrc.yml(若存在)的哈希共同作为缓存Key,避免因Yarn配置变更导致缓存不匹配:

- name: Compute dependency cache key
  id: compute_lockfile_hash
  run: echo "::set-output name=hash::${{ hashFiles('yarn.lock', '.yarnrc.yml') }}"

方案4:移除跨Job缓存,每个Job自行处理依赖(简单直接)

如果跨Job缓存维护成本过高,可删除job_install_dependencies,在每个需要依赖的Job中直接执行yarn install --immutable,虽增加少量执行时间,但能彻底避免缓存一致性问题。


内容的提问来源于stack exchange,提问作者Hyesung Oh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:57:42