什么是 CircleCi 管道?它们可以用来触发带有参数的作业吗?

Kri*_*fer 1 continuous-integration pipeline circleci

pipeline文档比较分散,如何使用circle ci语言中的概念有点难以理解?另外,管道和管道变量的意义是什么?

以下文档很有用,但还不足以让我弄清楚它们的实际工作原理:

Kri*_*fer 5

TLDR 答案;

pipelines在 Circle ci 中,本质上是触发器 - 触发特定存储库/分支/标签的所有工作流程,包括当 Circleci 从推送/合并等自动触发时。

管道变量显然是需要在 config.yml 中声明和默认值的变量。它们的值显然只能在通过 2.0 API 触发“管道”时设置。

通过 2.0 API [github] 触发的示例:(注意:需要个人 [而非项目] 令牌)

curl -u ${CIRCLECI_TOKEN}: -X POST --header "Content-Type: application/json" -d '{
  "branch": "feat",
  "parameters": {
    "image-tag": "4.8.2"
  }
}' https://circleci.com/api/v2/project/gh/<org>/<repo>/pipeline
Run Code Online (Sandbox Code Playgroud)

长答案

如果您和我一样,您可能会认为pipelineCI 中的这个词是一个作业层次结构,作业之间具有依赖关系,并且能够将数据从一个步骤传递到下一个步骤。这个功能存在于circle ci中,并且相当强大(除了传递数据有点尴尬),但它被称为workflow. 因此,留下了圆圈 ci 与“管道”意味着什么的问题,在尝试触发它并查看文档的不同部分之后,我的结论是它可能应该被称为“触发”或“工作流程执行”或其他名称。它本质上描述了给定分支/标签中所有工作流程的触发,包括何时通过推送/合并自动触发。

您无法使用管道来触发带参数的作业,甚至根本无法触发作业,除非您首先将每个此类作业包装在管道中并设置条件方案以不运行其他工作流程。

为什么还要去那里?

说实话,我仍然不确定这是否值得,但基本上是以下因素驱动我们:

  • 不要停留在旧技术上(很快就会被抛弃)
  • Orbs - 一种非常好的 DRY 管道方法,仅适用于 2.1 配置

问题?

用例 1:本质上,我们有一个作业需要在 3 个不同的存储库中部署后运行,我们不是在 3 个位置复制粘贴和维护代码,而是将该作业放在第 4 个存储库中,并使用 Circleci API 1.1,通过以下命令触发它来自不同存储库的输入参数。在 2.0 Circleci 配置中工作得很好。在circle ci引入回归不再支持使用参数触发作业后,在2.1配置中也是不可能实现的。

用例 2:在其他一些情况下,通过参数触发非常有用,例如:正在进行的作业需要 2 小时,并且您不想等待测试管道中的某些内容。

用例 3:作业 2 失败,您需要修复它,然后才能使用作业 1 的输出手动重新运行它。

为简单起见,让我们看一下 2 个作业的工作流程:

+-------+      +-------+
| Job 1 |  ->  | Job 2 |
+-------+      +-------+
Run Code Online (Sandbox Code Playgroud)

我们希望能够:

  • 将变量从作业 1 传递到作业 2
  • 通过API执行作业2,向作业传递参数

在 Circleci API 1.1 中,将参数传递给作业(通过 API)很简单,它们会自动转换为环境变量。简单的。

启用“管道”并在 2.1 配置中似乎没有一种优雅的方法来实现这一点。尽管球体的存在和在 1 个存储库中保持完整的工作流程(至少用例 1)在一定程度上缓解了这一问题。然而,使用 2.1 管道有一种臃肿且古怪的方法,可以归结为(下面的 POC 示例):

  • 确保有一个管道参数允许所有“正常”工作流程不运行。
  • 添加管道参数,用于按需触发作业2
  • 添加管道参数作为您需要传递给作业 2 的实际参数。
  • 创建一个作业 3,它采用管道参数并将它们作为环境变量传递给作业 2。
  • 创建一个工作流,在设置按需变量后运行作业 3,然后运行作业 2

尴尬的?哦是的。我只能猜测,circle ci 在引入管道变量时考虑了其他一些用例,因为这不太方便。

结论

我仍然无法真正弄清楚你“应该”如何使用管道变量。也许官方文档将来会对此有更清晰的说明。

我确实看到了对管道变量的需求,它们可能非常强大,但它们的局限性会导致一些尴尬,至少对于我们的用例来说是这样。我发现以下限制是最烦人的:

  • (我认为)无法在作业 1 中设置管道变量,并从作业 2 访问它。
  • (我认为)无法在作业定义中设置管道变量。
  • 变量必须是预定义的。
  • 无法选择性地只运行一个工作流程
  • 无法有选择地只运行一项工作

用于运行 job2 的 config.yml 工作示例 POC,使用 job1 的输出或按需将参数发送到自定义管道、自定义工作流程和临时 job3:

version: 2.1

# Pipeline parameters
parameters:
  workflow_ondemand:
    type: boolean
    default: false
  workflow_job2_ondemand:
    type: boolean
    default: false
  workflow_job2_param1_version:
    type: string
    default: "invalid version"

workflows:
  version: 2

  normal-workflow:
    unless: << pipeline.parameters.workflow_ondemand >>
    jobs:
      - job1
      - job2:
          requires: [job1]
  workflow-job2-ondemand:
    when: << pipeline.parameters.workflow_job2_ondemand >>
    jobs:
      - job3
      - job2:
          requires: [job3]

# Trigger with:
#
# curl -u ${CIRCLECI_TOKEN}: -X POST --header "Content-Type: application/json" -d '{
#                             "branch": "feat",
#                             "parameters": {
#                                "workflow_ondemand": true,
#                                "workflow_job2_ondemand": true,
#                                "workflow_job2_param1_version": "version1"
#                              }
# }' https://circleci.com/api/v2/project/gh/<org>/<repo>/pipeline

jobs:
  job1:
    docker:
      - image: circleci/node:latest
    steps:
      - run:
          name: Fake build and generate random version number
          command: |
            echo export VERSION=$((1 + RANDOM % 100)) >> /tmp/.env
            source /tmp/.env
            echo "Version in job1: ${VERSION}"
      - persist_to_workspace:
          root: /tmp/
          paths: ['.env']

  job2:
    docker:
      - image: circleci/node:latest
    steps:
      - attach_workspace:
          at: /tmp
      - run:
          name: "Load and print version from previous step"
          command: |
            source /tmp/.env
            echo "Version in job2: ${VERSION}"

  job3:
    docker:
      - image: circleci/node:latest
    environment:
      VERSION: << pipeline.parameters.workflow_job2_param1_version >>
    steps:
      - run:
          name: "Save parameter value to .env"
          command: |
            echo export VERSION=${VERSION} >> /tmp/.env
            echo "Version in job3: ${VERSION}"
      - persist_to_workspace:
          root: /tmp/
          paths: ['.env']
Run Code Online (Sandbox Code Playgroud)