学习有条件的CircleCI流水线执行

636 阅读11分钟

本教程包括:

  1. 什么是条件式以及如何在CI/CD管线中使用它们
  2. 为什么你可能想在管道中使用条件式
  3. 如何使用条件执行来设置管道配置

持续集成和持续部署(CI/CD)的DevOps实践改善了软件交付。CI/CD平台监控和自动化应用开发过程,确保更好的应用,更快。CI/CD管道构建代码,运行测试,并部署已通过所有自动化检查的生产就绪版本的应用程序。

由于不断需要确保流程的完整性,开发团队可能希望根据前一个工作的结果来执行管道工作。本教程将告诉你关于条件管道以及如何根据你指定的条件在CI/CD工作流中选择性地执行作业。我将解释如何设置管道,如何为其执行设置条件,以及job A 的失败如何影响job B 的执行并对管道的结果作出贡献。

前提条件

完成本教程需要以下条件。

  • 在您的系统上安装Node.js
  • 一个CircleCI账户
  • 一个GitHub账户
  • 对CircleCI管道的工作原理有所了解

有了这些先决条件,你就可以开始学习本教程了。

了解有条件的管道执行

大多数管道是由多个步骤组成的,必须在软件的最终版本交付之前完成。你可以根据你指定的一个条件或一组条件跳过一个或多个管道阶段。

为了有效,流水线应该有明确定义的步骤,在进入下一步之前必须进行验证。下面是一个有四个作业的流水线的例子。

  • lint check
  • code build
  • testing
  • deployment

每个工作都依赖于前一个工作的验证,或成功运行。如果你想部署一个已经通过所有测试的应用程序,你已经为你的CI/CD管道创建了一个条件。也就是说,在执行部署步骤之前,代码和构建步骤必须通过。

为了让你更好地理解条件管道的执行,我创建了一个三步管道的图例。

Conditional pipeline execution

有三条流水线,每条都有三个作业。在第一条流水线中,所有作业都被验证,流水线成功了。然而,在第二条流水线中,第一个作业通过了,触发了构建和测试,但第二步的失败阻止了部署作业。该管道失败了。

管道3与其他的不同之处在于,如果第一个作业失败,进程会立即停止。

设置一个API,在测试执行前运行lint

本教程的这一部分将展示失效的lint是如何导致管道失败的。

确保你的代码有正确的格式化和提示,为运行测试和构建打下良好的基础。一项工作的失败,(例如,如果你的代码没有正确地加皮特)应该阻止触发构建和测试阶段。管道将不符合条件,并将失败,这是预料之中的事。

我已经建立了一个API,供你在本教程中使用。你所需要做的就是克隆仓库。

git clone https://github.com/CIRCLECI-GWP/conditional-pipeline-execution-demo.git

这个命令将项目克隆到你的本地机器上,放到一个叫做conditional-pipeline-execution-demo 的目录中。这应该是你当前工作目录中你克隆版本库的地方。完成后,运行下面的命令。

注意。 为了在CircleCI上运行管道,我建议你创建一个Mongo Atlas账户,并根据克隆版本库的README.md 中提供的说明进行设置。

改变目录。

cd  conditional-pipeline-execution-demo

安装必要的依赖项。

npm install

安装完成后,使用此命令启动服务器。

npm  start

本教程的API现在正在你的本地机器上运行。你可以通过访问http://localhost:3000/ 来测试它。

好消息:这个API已经被正确地配置了PrettierESLint。lint和Prettier的配置是在package.json 文件中处理的。一些测试也已经写好了。

接下来,确保版本库的格式遵循配置的Prettier准则。运行下面的命令来启动lint和格式化检查。

npm run format:check # checks if formatting guidelines are followed

用Prettier格式化所有文件。

npm run format:write # Writes onto formatted files applying the eslint and prettier rules

Lint代码。

npm run lint:check # checks if code is linted

Formatting and linting commands

现在,你已经验证了格式化和刷新是按预期进行的,你可以配置CircleCI管道,包括在满足条件时选择性地执行管道。

CircleCI配置文件设置

在你的API的根目录下建立一个.circleci 目录。在它里面,创建一个名为config.yml 的空文件,并添加这个。

# CircleCI configuration file

version: 2.1
workflows:
   lint-build-test:
       jobs:
           - lint-code
           - build-and-test:
                 requires:
                     - lint-code
jobs:
   lint-code:
       docker:
           - image: cimg/node:16.13.2
       steps:
           - checkout
           - run:
                name: update npm
                command: 'sudo npm install -g npm'

           - restore_cache:
                key: dependency-cache-{{ checksum "package-lock.json" }}

           - run:
                name: install dependencies
                command: sudo npm install

           - save_cache:
                key: dependency-cache-{{ checksum "package-lock.json" }}
                paths:
                    - ./node_modules

           - run:
                 name: lint check
                 command: npm run format:check

    build-and-test:
        docker:
            - image: cimg/node:16.13.2
        steps:
            - checkout
            - run:
                    name: update npm
                    command: 'sudo npm install -g npm'

            - restore_cache:
                    key: dependency-cache-{{ checksum "package-lock.json" }}

            - run:
                    name: install dependencies
                    command: sudo npm install

            - save_cache:
                key: dependency-cache-{{ checksum "package-lock.json" }}
                paths:
                        - ./node_modules

            - run:
                    name: run tests
                    command: npm test

这个config.yml 文件有一个工作流,有两个工作:lint-codebuild-and-test

注意在工作流定义中使用了requires 键,指定lint-codebuild-and-test 工作成功执行的必要条件。这意味着,只有当第一个作业成功时,第二个作业才会被执行。当第一个作业失败时,进程会自动停止,所以这里设置了一个条件。Lint检查必须通过,我们的流水线才能成功构建和测试代码。

按照工作流程,我们将定义实际的工作。两个作业的第一步是指示CircleCI使用node docker镜像。然后,他们将更新node包管理器,并使用npm 来安装所需的依赖。两项工作的最后一步是执行这三个动作。lint,check, 和test 。该配置还使用restore_cachesave_cache 步骤来缓存依赖关系,然后恢复它们。这些步骤大大减少了执行流水线的时间。

推送代码到GitHub

注意: 如果你克隆了仓库,那么变化已经存在于仓库中,因此这是一个可选的步骤。如果你使用的是不同的仓库,并且使用相同的配置,你将需要把修改推送到该仓库。

保存你的工作,提交,并推送更改到GitHub仓库。在CircleCI仪表板的项目部分,点击仓库名称旁边的设置项目

Select project on CircleCI

当你被提示时,使用main ,这是我们的默认分支。然后点击Set Up Project开始在CircleCI上运行该项目。

Setting up a project on CircleCI

CircleCI仪表盘将显示这次构建失败,这和预期的一样。这完美地将我们引入了本教程的下一节,即管道的有条件执行。

管道的有条件执行

我们的构建失败是因为我们故意引入的lint问题。为了使管道有效,你需要能够在一组条件未得到满足时停止它。你应该能够在测试失败时终止部署,或者在本例中,当项目的linting失败时终止部署。

  • 管道中的lint check ,显示了一个步骤的失败是如何连带到管道的其他部分的。npm run format:check CircleCI跳过了运行我们的测试,因为它在执行lint-code 工作中的package.json 文件的命令时遇到了失败。成功完成该工作是the build-test 工作的一个要求。
  • format:check 命令运行prettier --list-different . 命令,该命令验证所有文件是否使用了 Prettier 配置。如果它发现不符合配置的文件,它会抛出一个异常。当遇到不符合配置的文件时,在CI上抛出异常,流水线就会失败。

Failing lint check

由于lint失败,管道的故意失败,意味着你现在可以验证,如果一个步骤在运行不是并行运行时失败,后续步骤将不会执行,管道将失败。在这种情况下,我们已经在这个代码片段的配置中明确声明了这一点。

# congig.yml line 6, 7, and 8
- build-and-test:
    requires:
      - lint-code

Failing lint check

这就是了--你已经配置了一条流水线,只在满足特定条件时运行特定的作业。你也可以编写并行的管道,每个管道都有不同的条件集。CircleCI可以很容易地解释这一点,并正确执行你的管道。

高级条件执行

在本节中,我将提供更多关于设置管道的细节,以便根据条件运行或不运行。本节涵盖了。

  • 保持一个工作流程的手动批准
  • 使用 "当 "和 "或 "逻辑语句

保持一个工作流程的手动批准

我们可以配置工作流,使其在进入下一项工作之前需要手动批准。任何有回购推送权限的人都可以通过点击批准按钮来批准一个搁置的工作流,这将恢复工作流。

我们已经设置了一个工作流。你可以通过在作业列表中添加一个键为type: approval 的作业来修改它。

workflows:
  lint-build-test:
    jobs:
      - lint-code
      - hold:
          type: approval
          requires:
            - lint-code

      - build-and-test:
          requires:
            - hold

这段代码在工作流中添加了一个新的工作,名为holdtype: approval 是一个键值对,它将使工作流处于暂停状态。在现实世界中,你可以出于QA或部署经理的批准或手动防止意外部署的目的而搁置一个管道。使用requires 键在hold 工作中设置一个条件,当lint-code 成功时运行它。在hold 作业被批准后,任何需要它的后续作业都会运行。然后用户可以手动继续构建和测试工作。

将这些修改提交到GitHub。在CircleCI仪表板上,第一个作业执行,然后搁置并等待批准。

Hold executing pipeline

点击仪表盘上的On Hold标签,进入下一步,其中包括工作流程的可视化表示。点击保留框,然后在弹出的窗口中批准该工作。

Approved job

一旦作业被批准,工作流程就会恢复,随后的作业就可以运行。

使用逻辑语句来控制管道的执行

除了使用requires 关键字来定义工作流条件外,你还可以将when 子句与逻辑语句结合使用。当逻辑语句在when 子句中使用时,它们会解析为一个truefalse 的值。在这个例子中,你将修改你以前的工作流程,只有当你修改一个暂存分支或一个主分支时才执行它。请做此代码块中所示的修改。

workflows:
  lint-build-test:
    when:
      or:
        - equal: [main, << pipeline.git.branch >>]
        - equal: [staging, << pipeline.git.branch >>]
    jobs:
      - lint-code
      - hold:
          type: approval
          requires:
            - lint-code
      - build-and-test:
          requires:
            - hold

whenor 子句设置了一个条件,阻止工作流lint_build_test 的运行,除非该工作流是在分支stagingmain

现在,如果你在任何其他分支上运行,工作流将无法执行。

Approved job

通过这些标志,你可以提供诸如 "只能在发布分支上进行发布 "或 "必须只从主分支上进行部署 "的规则,以避免意外的预生产部署。

验证成功的构建

现在你知道了如何编写条件管道,以及条件是如何影响管道结果的,现在是时候修复linting问题并将代码推送到GitHub。当修改完成后,你的管道会成功执行,lint-codebuild-and-test 工作都会成功执行。

Successful execution

Voila!你的流水线现在是绿色的。它运行lint-check管道,然后继续构建和测试代码。在这种庆祝的模式下,是时候结束本教程了。

总结

在本教程中,你了解了条件管道以及如何构建它们。你在CircleCI管道中执行了一个作业,其条件是第一个作业必须在执行第二个作业之前通过。你甚至尝试了几个更高级的概念:保持一个工作流和使用whenor 语句。你有第一手的经验,知道一个作业的失败会导致一个级联的失败,从而关闭整个管道。你还学会了如何通过内置的CircleCI功能来执行控制。而且你能够观察到你的条件管道的成功执行。我希望你喜欢这个教程,并发现它很有用。直到下一次,继续学习!