基于Node和Yarn的GitHub Actions共享CI工作流问题求助
GitHub Actions共享工作流环境不共享问题解决方案
问题背景
我使用Lerna管理Monorepo,正在从CircleCI迁移至GitHub Actions。单独运行测试、代码检查的Action均正常,但尝试通过共享工作流复用初始化步骤时遇到问题:执行yarn lint和yarn test-ci时,由于后续Job运行在与初始化工作流不同的容器中,Yarn未安装且依赖不存在。
现有配置文件
.github/workflows/ci-setup.yml
name: "[CI] Setup" on: workflow_call jobs: build: name: Setup runs-on: ubuntu-latest steps: - uses: szenius/set-timezone@v1.2 with: timezoneLinux: "Europe/Paris" - uses: actions/checkout@v3 - name: Set Node.js uses: actions/setup-node@v3 with: node-version-file: '.node-version' - name: Setup run: cp packages/mobile/env.sample.json packages/mobile/env.json && cp packages/mobile-pro/env.sample.json packages/mobile-pro/env.json - name: Run install uses: Borales/actions-yarn@v4.2.0 with: cmd: install # will run `yarn install` command
.github/workflows/ci-test.yml
name: "[CI] Test" on: [push] concurrency: group: ci-test-${{ github.ref }} cancel-in-progress: true jobs: setup: uses: ./.github/workflows/ci-setup.yml build: needs: setup name: Test on the monorepo runs-on: ubuntu-latest steps: - name: Test uses: Borales/actions-yarn@v4.2.0 with: cmd: test-ci # will run `yarn test-ci` command
.github/workflows/ci-lint.yml
name: "[CI] Lint" on: [push] concurrency: group: ci-test-${{ github.ref }} cancel-in-progress: true jobs: setup: uses: ./.github/workflows/ci-setup.yml build: needs: setup name: Lint on the monorepo runs-on: ubuntu-latest steps: - name: Lint uses: Borales/actions-yarn@v4.2.0 with: cmd: lint # will run `yarn lint` command
解决方案
方法1:用复合动作(Composite Action)封装初始化步骤
这是最适合你的方案,将初始化步骤封装为自定义复合动作,在同一个Job中调用,确保所有步骤共享同一个Runner容器环境。
- 创建复合动作文件
.github/actions/ci-setup/action.yml:
name: 'CI Setup' runs: using: "composite" steps: - uses: szenius/set-timezone@v1.2 with: timezoneLinux: "Europe/Paris" - uses: actions/checkout@v3 - name: Set Node.js uses: actions/setup-node@v3 with: node-version-file: '.node-version' - name: Setup env files run: cp packages/mobile/env.sample.json packages/mobile/env.json && cp packages/mobile-pro/env.sample.json packages/mobile-pro/env.json shell: bash - name: Install dependencies uses: Borales/actions-yarn@v4.2.0 with: cmd: install
- 修改测试和代码检查工作流,在同一个Job中调用复合动作:
修改后的 .github/workflows/ci-test.yml
name: "[CI] Test" on: [push] concurrency: group: ci-test-${{ github.ref }} cancel-in-progress: true jobs: test: name: Test on the monorepo runs-on: ubuntu-latest steps: - uses: ./.github/actions/ci-setup - name: Run tests uses: Borales/actions-yarn@v4.2.0 with: cmd: test-ci
修改后的 .github/workflows/ci-lint.yml
name: "[CI] Lint" on: [push] concurrency: group: ci-lint-${{ github.ref }} cancel-in-progress: true jobs: lint: name: Lint on the monorepo runs-on: ubuntu-latest steps: - uses: ./.github/actions/ci-setup - name: Run lint uses: Borales/actions-yarn@v4.2.0 with: cmd: lint
方法2:用缓存机制在多Job间复用依赖
如果必须拆分多个独立Job(例如需要并行执行不同任务),可以通过GitHub缓存功能复用依赖,避免重复安装,同时在每个Job中重新执行基础初始化步骤:
以ci-test.yml为例:
name: "[CI] Test" on: [push] concurrency: group: ci-test-${{ github.ref }} cancel-in-progress: true jobs: setup: name: Setup Dependencies runs-on: ubuntu-latest outputs: cache-key: ${{ steps.cache.outputs.cache-primary-key }} steps: - uses: szenius/set-timezone@v1.2 with: timezoneLinux: "Europe/Paris" - uses: actions/checkout@v3 - name: Set Node.js uses: actions/setup-node@v3 with: node-version-file: '.node-version' - name: Setup env files run: cp packages/mobile/env.sample.json packages/mobile/env.json && cp packages/mobile-pro/env.sample.json packages/mobile-pro/env.json - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT shell: bash - name: Cache yarn dependencies id: cache uses: actions/cache@v3 with: path: | ${{ steps.yarn-cache-dir-path.outputs.dir }} node_modules packages/**/node_modules key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - name: Install dependencies if: steps.cache.outputs.cache-hit != 'true' uses: Borales/actions-yarn@v4.2.0 with: cmd: install test: needs: setup name: Test on the monorepo runs-on: ubuntu-latest steps: - uses: szenius/set-timezone@v1.2 with: timezoneLinux: "Europe/Paris" - uses: actions/checkout@v3 - name: Set Node.js uses: actions/setup-node@v3 with: node-version-file: '.node-version' - name: Setup env files run: cp packages/mobile/env.sample.json packages/mobile/env.json && cp packages/mobile-pro/env.sample.json packages/mobile-pro/env.json - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT shell: bash - name: Restore yarn cache uses: actions/cache@v3 with: path: | ${{ steps.yarn-cache-dir-path.outputs.dir }} node_modules packages/**/node_modules key: ${{ needs.setup.outputs.cache-key }} restore-keys: | ${{ runner.os }}-yarn- - name: Run tests uses: Borales/actions-yarn@v4.2.0 with: cmd: test-ci
总结
- 优先选择复合动作方案,既能实现步骤复用,又能保证环境一致性,完全解决你的问题;
- 若必须拆分Job,使用缓存机制可以大幅缩短依赖安装时间,避免重复劳动;
- 独立的setup Job(workflow_call)无法共享容器环境,不适合你的复用需求。
内容的提问来源于stack exchange,提问作者Bambou
相关产品推荐
相关产品推荐

