GitLab CI:我们一直在等待的最新版本中的6个功能



在无所不在的CI / CD时代,我们面临着各种各样的相关工具,包括CI系统。但是,是GitLab对我们来说是最接近的,真正的“本地人”。他在整个行业中获得了显着的知名度*。该产品的开发人员并没有落后于对其使用的日益增长的兴趣,因此定期用新版本使开发人员和DevOps工程师社区感到高兴。


GitLab存储库月份和标签聚合

主动开发带来许多新的有趣功能时就是GitLab的情况。如果对于潜在用户来说,这只是选择工具的因素之一,对于现有用户来说,情况是这样的:如果您在上个月未更新GitLab安装,那么很可能错过了一些有趣的东西。包括定期出现的安全更新。

关于最重要的-即我们的DevOps工程师和客户的要求-最新版本的GitLab社区版本中的创新,并将在本文中进行讨论。

* 5 , «GitLab», : «, GitHub?». — , Google Trends 5- «gitlab» . «» , . , , «» .

№1: needs


  • job'.
  • GitLab: 12.2.
  • .

dependencies-这就是您需要的吗?也许,我们不是谁提出分配这个指令的错误唯一的......这是需要列出以前的工作时,器物,其中将需要。这是工件,而不是依赖于先前任务的性能。

假设在某个阶段发生了一些不需要执行的工作,但是由于某种原因,就没有可能或只是希望将它们带到另一个阶段(懒惰是进步的动力,但不会被带走)。

情况:



如您所见,stage Deploy包含用于展开生产和阶段以及作业Selenium测试的按钮由于某种原因未执行。很简单:他等到上一阶段的所有作业都成功完成为止。但是,在同一个管道的框架中,我们不需要立即部署阶段来运行测试(它早些时候就被抽出了,不在标签内)。该怎么办?然后,前来救援的需求

我们只列出了运行测试所需的先前工作:

  needs:
    - To production (Cluster 1)
    - To production (Cluster 2)

...我们得到一个作业,该作业仅在执行列出的作业后自动调用:



方便吗?但是一旦我期望该指令可以像这样工作dependencies...

2号:扩展



厌倦了阅读卷.gitlab-ci.yaml?缺少代码重用原理?然后,您已经尝试过并且可能成功地将您.gitlab-ci.yaml的状态设置为如下所示:

.base_deploy: &base_deploy
  stage: deploy
  script:
    - my_deploy_command.sh
  variables:
    CLUSTER: "default-cluster"
    MY_VAR: "10"

Deploy Test:
  <<: *base_deploy
  environment:
    url: test.example.com
    name: test

Deploy Production:
  <<: *base_deploy
  environment:
    url: production.example.com
    name: production
  variables:
    CLUSTER: "prod-cluster"
    MY_VAR: "10"

听起来不错吗?但是,如果您仔细观察,就会有什么吸引您的目光……为什么我们不仅要改变生产方式variables.CLUSTER,而且还要重新生产variables.MY_VAR=10?这个变量应该取自base_deploy吗?事实证明,它不应该这样做:YAML起作用,以便重新定义从锚接收到内容,它不会扩展匹配字段内容,而是会替换它。因此,我们不得不在匹配的段落中列出我们已经知道的变量。

是的,“扩展”是正确的词:这正是所涉及的功能。Extends它们不仅使我们能够像锚一样重写字段,还可以对其进行智能合并:

.base_deploy: 
  stage: deploy
  script:
    - my_deploy_command.sh
  variables:
    CLUSTER: "default-cluster"
    MY_VAR: "10"

Deploy Production:
  extends: .base_deploy
  environment:
    url: production.example.com
    name: production
  variables:
    CLUSTER: "prod-cluster"

在最后的作业Deploy Production中,这里将有一个MY_VAR具有默认值的变量和一个被覆盖的变量CLUSTER

看来这真是一件小事,但请想象一下:您有一个base_deploy和20个电路部署相似。它们需要传递给其他人clusterenvironment.name同时保留一组特定的变量或其他匹配的字段...这种小小的愉悦感使我们能够将开发电路集的部署描述减少2-3倍。

第三名:包括



.gitlab-ci.yaml它看起来仍然像是20种语言的真空吸尘器的折叠式说明(您只懂其中一种),当您需要处理它的其中一个部分而又不面对途中遇到的未知工作时,是否很难?

长期的编程朋友将为您提供帮助include

stages:
  - test
  - build
  - deploy

variables:
  VAR_FOR_ALL: 42

include:
  - local: .gitlab/ci/test.yml
  - local: .gitlab/ci/build.yml
  - local: .gitlab/ci/deploy-base.yml
  - local: .gitlab/ci/deploy-production.yml

那些。现在,我们正在大胆地编辑生产环境中的部署,而测试人员正在忙于修改他们的文件,而我们甚至可能没有看过。另外,这有助于避免合并冲突:了解别人的代码并不总是很有趣。

但是,如果我们知道前后20个项目的流程,该如何解释每个工作的逻辑呢?这将如何帮助我们?对于那些对代码重用有所启发的人以及所有拥有许多类似项目的人,您可以:


十二个具有不同代码但类型相同的项目,但部署方式相同-轻松且无需在所有存储库中保持最新的CI!本文还提供了

一个实际使用的示例include

第4:只有/裁判除外


  • 全面的条件,包括变量和文件更改。
  • 由于这是一个完整的功能家族,因此某些部分开始出现在GitLab 10.0中,而其他部分(例如changes开始出现在11.4中。
  • docs.gitlab.com/ce/ci/yaml/#onlyexcept-advanced

在我看来,有时候这不是听我们的管道,而是我们。一支优秀的管理工具中only/ except-现在集成。这是什么意思?

在最简单(也许最愉快)的情况下,跳过阶段:

Tests:
  only:
    - master
  except:
    refs:
    - schedules
    - triggers
    variables:
    - $CI_COMMIT_MESSAGE =~ /skip tests/

在示例作业中,它仅在主节点的一个分支上运行,但不能由计划或触发器触发(GitLab共享API调用和触发器,尽管本质上是相同的API)。如果提交消息中有跳过测试密码,则作业将不会执行例如,README.md项目或文档中的错字得到修复-为什么要等待测试结果?

“嘿,2020年在外面!” 为什么每次更改文档时我都应该向铁盒解释没有必要运行测试?” 确实:only:changes它允许您仅在某些目录中更改文件时运行测试。例如:

  only:
    refs:
      - master
      - merge_requests
    changes:
      - "front/**/*"
      - "jest.config.js"
      - "package.json"

而对于反向动作-即 不要跑-是的except:changes

第5条:规则



该指令与之前的指令非常相似only:*,但是有一个重要的区别:它允许您控制参数when例如,如果您不想完全消除开始工作的可能性。您可以简单地保留该按钮,如果需要,可以独立调用该按钮,而无需启动新管道或进行提交。

#6:环境:auto_stop_in



我们在本文发表之前就已经了解了这种机会,并且还没有足够的时间在实践中进行尝试,但这绝对是“同一件事”,在几个项目中都是如此。

您可以在GitLab环境中指定参数on_stop-当您要动态创建和删除环境(例如到每个分支)时,该参数非常有用。on_stop例如,当MR的合并在主分支中或MR关闭时(甚至仅通过单击按钮),将执行标记为k的作业,由于该原因,不必要的环境会被自动删除。

如果不是出于人为因素,一切都是方便,合乎逻辑的,并且可以正常工作。许多开发人员不是通过单击GitLab中的按钮来合并MR,而是通过本地合并git merge。您可以理解它们:方便!但是在这种情况下,逻辑on_stop它行不通,我们已经积累了被遗忘的环境...这是期待已久的方便之处auto_stop_in

奖励:机会不足时的临时小屋


尽管有所有(以及许多其他)GitLab所需的新功能,但遗憾的是,有时无法在当前可用功能的框架内描述完成工作的条件。

GitLab并不完美,但是它提供了构建梦想管道的基本工具……如果您准备超越普通的DSL,而陷入脚本世界。以下是根据我们的经验提供的一些解决方案,这些解决方案决不假装在意识形态上是正确的或推荐的,但在没有内置API功能的情况下,将提供更多解决方案以演示不同的可能性。

解决方法1:一键启动两个作业


script:
  - > 
    export CI_PROD_CL1_JOB_ID=`curl -s -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs" | \
      jq '[.[] | select(.name == "Deploy (Cluster 1)")][0] | .id'`
  - > 
    export CI_PROD_CL2_JOB_ID=`curl -s -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs" | \
      jq '[.[] | select(.name == "Deploy (Cluster 2)")][0] | .id'`
  - > 
    curl -s --request POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/jobs/$CI_PROD_CL1_JOB_ID/play"
  - > 
    curl -s --request POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/jobs/$CI_PROD_CL2_JOB_ID/play"

而且,如果您确实想这样做,为什么不呢?

解决方法2:更改了图像内部rubocop的MR rb文件中的传输


Rubocop:
  stage: test
  allow_failure: false
  script:
    ...
    - export VARFILE=$(mktemp)
    - export MASTERCOMMIT=$(git merge-base origin/master HEAD)
    - echo -ne 'CHANGED_FILES=' > ${VARFILE}
    - if [ $(git --no-pager diff --name-only ${MASTERCOMMIT} | grep '.rb$' | wc -w |awk '{print $1}') -gt 0 ]; then
        git --no-pager diff --name-only ${MASTERCOMMIT} | grep '.rb$' |tr '\n' ' ' >> ${VARFILE} ;
      fi
    - if [ $(wc -w ${VARFILE} | awk '{print $1}') -gt 1 ]; then
        werf --stages-storage :local run rails-dev --docker-options="--rm --user app --env-file=${VARFILE}" -- bash -c /scripts/rubocop.sh ;
      fi
    - rm ${VARFILE}

里面没有图像.git,所以我不得不出去检查已更改的文件。

注意:这不是非常标准的情况,并且是拼命尝试满足该问题的许多条件的情况,对此的描述不包括在本文的范围内。

解决方法#3:推出时触发从其他存储库启动作业


  before_script:
    - |
      echo '### Trigger review: infra'
      curl -s -X POST \
        -F "token=$REVIEW_TOKEN_INFRA" \
        -F "ref=master" \
        -F "variables[REVIEW_NS]=$CI_ENVIRONMENT_SLUG" \
        -F "variables[ACTION]=auto_review_start" \
        https://gitlab.example.com/api/v4/projects/${INFRA_PROJECT_ID}/trigger/pipeline

看起来,这种简单而必要的事情(在微服务领域)正在将另一个微服务作为依赖项部署到新创建的电路中。但这不是必需的,因此不需要API调用和已经熟悉的功能(如上所述):

  only:
    refs:
    - triggers
    variables:
    - $ACTION == "auto_review_start"

笔记:

  • 类似于示例1,触发器上的作业被设计为将变量传递给API。通过传递的作业名称在API上实现此操作更合乎逻辑。
  • 是的,该功能是在商业(EE)版本的GitLab中提供的,但我们不考虑它。

结论


GitLab努力跟上趋势,逐步实现DevOps社区所需要的令人愉悦的功能。它们非常易于使用,当基本功能不够用时,可以随时使用脚本进行扩展。而且,如果我们发现它在支持方面并不那么优雅,便捷……则有必要等待新版本的GitLab或帮助我们做出贡献的项目

聚苯乙烯


另请参阅我们的博客:


All Articles