CI/CD 管道中的并行性,如 GitHub 操作

Parallelism in CI/CD Pipelines like GitHub Actions

你好,感谢你阅读我的问题,这是我的第一个问题。

我使用 CI/CD 管道已经一年了,我认为它们对于开发网站和其他东西来说非常好而且方便。但在过去的几个月里,我在创建快速、高效和智能的管道时遇到了越来越多的问题,而无需安装冗余依赖项或类似的东西。所以我想使用尽可能少的计算资源,同时仍然有快速构建。我想并行化步骤并在另一个最后步骤中使用它们的工件。例如以下 GitHub 操作工作流程:

我使用此工作流程的目标是构建一个 VueJS 单页应用程序并将其部署到 IBM Cloud。为此,我需要安装 npm 依赖项并构建 Vue 应用程序,还需要安装 IBM Cloud CLI。完成这两个步骤后,应将构建的应用程序推送到 IBM Cloud。

我可以像这样简单地 运行 所有步骤:

name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v2
      - name: Use Node.js 10.X
        uses: actions/setup-node@v1
        with:
          node-version: '10.x'
      - name: Cache Node Modules
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          # npm cache files are stored in `~/.npm` on Linux/macOS
          path: ~/.npm
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-
      - name: Install Dependencies
        run: npm ci
      - name: Build Page
        run: npm run build
      - name: Install IBM Cloud CLI
        run: curl -fsSL https://clis.cloud.ibm.com/install/linux | sh
        shell: bash
      - name: Install Cloud Foundry CLI
        run: ibmcloud cf install
        shell: bash
      - name: Authenticate with IBM Cloud CLI
        run: ibmcloud login --apikey "${{ secrets.IBM_CLOUD_API_KEY }}" --no-region -g Default
        shell: bash
      - name: Target a Cloud Foundry org and space
        run: ibmcloud target --cf-api "${{ secrets.IBM_CLOUD_CF_API }}" -o "${{ secrets.IBM_CLOUD_CF_ORG }}" -s "${{ secrets.IBM_CLOUD_CF_SPACE }}"
        shell: bash
      - name: Deploy to Cloud Foundry
        run: ibmcloud cf push
        shell: bash

但在我看来这是非常丑陋的,可以改进。所以我试图将工作分成 3 个部分:构建、预部署和部署。构建作业安装并构建 Vue 应用程序。 Predeploy 作业安装 IBM CLI。这两个工作不相互依赖,因此可以并行化。但最后一项工作部署取决于两者,因此我向其添加了 needs: [build, predeploy] 值。所以我有以下工作流程来存档:

### This will not work!
name: Deploy
    on:
      push:
        branches: [main]
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout Code
            uses: actions/checkout@v2
          - name: Use Node.js 10.X
            uses: actions/setup-node@v1
            with:
              node-version: '10.x'
          - name: Cache Node Modules
            uses: actions/cache@v2
            env:
              cache-name: cache-node-modules
            with:
              # npm cache files are stored in `~/.npm` on Linux/macOS
              path: ~/.npm
              key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
              restore-keys: |
                ${{ runner.os }}-build-${{ env.cache-name }}-
                ${{ runner.os }}-build-
                ${{ runner.os }}-
          - name: Install Dependencies
            run: npm ci
          - name: Build Page
            run: npm run build
      predeploy:
        runs-on: ubuntu-latest
        defaults:
          run:
            shell: bash
        steps:
          - name: Install IBM Cloud CLI
            run: curl -fsSL https://clis.cloud.ibm.com/install/linux | sh
          - name: Install Cloud Foundry CLI
            run: ibmcloud cf install
          - name: Authenticate with IBM Cloud CLI
            run: ibmcloud login --apikey "${{ secrets.IBM_CLOUD_API_KEY }}" --no-region -g Default
          - name: Target a Cloud Foundry org and space
            run: ibmcloud target --cf-api "${{ secrets.IBM_CLOUD_CF_API }}" -o "${{ secrets.IBM_CLOUD_CF_ORG }}" -s "${{ secrets.IBM_CLOUD_CF_SPACE }}"
      deploy:
        needs: [build, predeploy]
        runs-on: ubuntu-latest
        steps:
          - name: Deploy to Cloud Foundry
            # Error: 'ibmcloud: command not found'
            run: ibmcloud cf push
            shell: bash

在 GUI 上看起来像:

[![GUI 上我的 GitHub 工作流程][1]][1]

但是这个工作流程会出错,因为最后一个作业与其他作业不共享相同的环境。我知道我可以使用 GitHub Actions 的 up/download Artifact 功能,但在我看来这会占用大量资源。但我不想为我的管道使用大量资源,我不需要很多不同的虚拟环境或构建矩阵。 (我知道它们对于大型项目非常有用,但对于我的小网站来说它们似乎有点矫枉过正)

所以这是我的最后两个问题:

为什么 CI/CD 中的并行性通常很复杂而不是直截了当?

如何在没有冗余执行的情况下通过并行改进我当前的管道?

我很高兴收到每条有用的建议或 link。谢谢你。 :) [1]: https://i.stack.imgur.com/qEqLs.png

我认为您原来的工作流程已经非常高效了。正如您提到的,不同的作业在不同的 运行 人员上执行,有时工作流之间 synchronization/logic 的额外复杂性和工作量超过了并行性的好处。在你的情况下,我认为并行 运行 你的工作没有多大意义。

对于您的第一个问题,我认为这不是 CI/CD 管道特有的问题。我在这里有点超出范围,但是您在任何并行工作的代码中都有类似的问题,或者事实上在任何地方并行完成的任何一般工作中都有类似的问题。作为工厂、团队、代码、CI 管道,一旦工作被拆分,就会有某种机制来管理工作分配并跟踪其进度。这将使它变得更加复杂。 为什么 GH 工作流程看起来不如其他系统那么简单似乎是一个更好的问题,我认为它已经存在了多长时间。这是对 github 的最新补充,随着新功能的逐步添加,它变得越来越容易使用。

关于您的工作流程的其他优化,如果不需要,我建议尽量避免每次工作流程 运行 重做相同的工作。您已经使用 npm 的缓存操作执行此操作。但是,例如,您可以构建一个 docker 图像,甚至更好的操作,其中包含您的 IBM CLI,并完全删除预部署阶段。只需拥有:

name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v2
      - name: Use Node.js 10.X
        uses: actions/setup-node@v1
        with:
          node-version: '10.x'
      - name: Cache Node Modules
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          # npm cache files are stored in `~/.npm` on Linux/macOS
          path: ~/.npm
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-
      - name: Install Dependencies
        run: npm ci
      - name: Build Page
        run: npm run build
      - name: Deploy to Cloud Foundry
        uses: my-action:v1
        with:
          api-key: ${{ secrets.IBM_CLOUD_API_KEY }}
          cf-api: ${{ secrets.IBM_CLOUD_CF_API }}
          cf-org: ${{ secrets.IBM_CLOUD_CF_ORG }}
          cf-space: ${{ secrets.IBM_CLOUD_CF_SPACE }}