原创 鲜正权 / 叫叫技能团队

现阶段开发人员的作业流程,编写代码、提交、构建、发布。这个过程往往还需求手动履行,简单犯错且很Low,本文将带领我们手摸手完结GitlabCI 自动构建发布,从此高大上~

gitlab-ci 从0到1

一、为什么选择Gitlab CI?

现在市面上的 CI/CD 东西有许多,如 **Jenkins****CircleCI****Bamboo** 等,而本文将讲选取 Gitlab CI/CD 进行叙述。
其间原因有下:

  • 大部分开发团队都会选择内部建立 Gitalb 作为代码仓库,而 Gitlab CI/CD 内置在 Gitlab 中,不需求额外安装。
  • Gitlab CI/CD 的功用丰厚,足以应对大部分devops场景。
  • 其间流水线的功用,概念简单,开发者上手门槛低。

二、概念

在运用 Gitlab CI/CD 之前,咱们需求先了解一些概念,这能够帮咱们更简单了解整个 Gitlab CI/CD 运转流程。

1. 流水线(Pipelines)

Gitlab 把在项目中触发的一系列 CI/CD 使命合称 **流水线**。 一般开发者会把 CI/CD 中的使命按逻辑划分为比如测试,构建,部署等。而这些使命会按次序一个接着一个履行,如同工业流水线一般。

gitlab-ci 从0到1

gitlab-ci 从0到1

2. 使命(Jobs)

使命是组成流水线的基本要素,是流水线中具体的某个作业。开发者能够自行描绘这些使命的内容与履行方法。

gitlab-ci 从0到1

3. 环境变量(Variables)

环境变量不是 CI/CD 的必要部分,但在某些场景下能够完结一些特别需求。官方自有大局环境变量。

gitlab-ci 从0到1

一旦装备之后,在流水线就能够直接运用变量的信息。因此一般被用作需求保密信息的记载,如账号密码等。 除此之外,还能够以文件形式保存,但要注意的是当用文件作为变量时,在流水线运用时变量代表的不再是文字内容,而是文件的途径。

4. Runner

ci 需求装备了 runner 之后,才干运用。

gitlab-ci 从0到1

三、运用(.gitlab-ci.yml)

GitlabCI就是经过编写 .gitlab-ci.yml文件来完结。悉数的关键字参考官网文档,本文仅仅举例平常常用的部分。

# 界说阶段
stages:
	- build
	- deploy
# 界说作业 job
# 名字随意整,只要不整成关键字
job1:
	stage: build
	script: echo "hello world"
job2:
	stage: deploy
	script: 
  	- echo "hello world"
  	- echo "Q:闪钢斩,第三下能够吹风击飞敌人"

大局关键字

阶段 stages

用于界说包括作业组的阶段。在作业(Job)中运用 stage 以将作业装备为在特定阶段运转。
假如 stages未在 .gitlab-ci.yml 文件中界说,则默认管道(Pipelines)阶段为:

  • .pre
  • build
  • test
  • deploy
  • .post

项目的 stages次序 界说了作业的履行次序:

  • 同一阶段的作业并行运转。
  • 下一阶段的作业在前一阶段的作业成功完结后运转。

假如管道仅包括 .pre.post阶段中的作业,则它不会运转。在不同的阶段有必要至少有一份其他作业。.pre.post阶段可用于所需的管道装备 ,以界说有必要在项目管道作业之前或之后运转的合规性作业。

比如:

stages:
	- build
	- test
	- deploy

在这个比如中:

  1. 一切 stagebuild 的 作业(Job)都会履行。
  2. 一切 build都履行成功,则开端履行 stagetest的一切作业。
  3. 一切 test都履行成功,则开端履行 stagedeploy的一切作业。
  4. 一切 deploy都履行成功,则管道(Pipeline)标记为 passed

其间,假如有任何一个作业(Job)履行失利,整个管道(Pipeline)都将被标记为 failed,而且一切后续阶段都不会履行。当前阶段的Job不会停止并继续履行

其他信息

  • 假如作业未指定 stage则会为该 Job 分配 test阶段。
  • 假如界说了一个 stage 但没有Job运用它,则该阶段在管道中不行见。

Jobs 关键字

阶段 stage

stage用于指定 Job 在哪个阶段运转。同一阶段的Job能够并行履行。
假如 stage未界说,则Job默认运用test阶段。

stages:
  - build
  - test
  - deploy
job1:
  stage: build
  script:
    - echo "这是一个履行的job,因为该job的stage是 build"
job2:
  stage: test
  script:
    - echo "该job需求等候上个job履行完结才干履行"
job3:
  script:
    - echo "我和上面那个job相同的,都是 test 阶段履行".
job4:
  stage: deploy
  script:
    - echo "我是现在最终履行的,需求等 test 阶段履行完了才履行。"
first-job:
  stage: .pre # 敲黑板,我不受stages次序约束,我就是第一个跑
  script:
    - echo "不论咋地,我在一切stages之前履行"
last-job:
  stage: .post # 敲黑板,我不受stages次序约束,我就是最终一个跑
  script:
    - echo "不论咋地,我在一切stages之后履行"

script

指定该Job履行啥。

before_script、after_script

script相同,都是该 Job 需求履行的具体内容。 before_script是在履行 script履行履行的,after_script则是在之后。

stages:
  - build
  - test
  - deploy
job1:
  stage: build
  before_script:
    - echo "我在script之前履行"
  script:
    - echo "这是一个履行的job,因为该job的stage是 build"
job2:
  stage: test
  script:
    - echo "该job需求等候上个job履行完结才干履行"
  after_script:
    - echo "我在script之前履行"
job4:
  stage: deploy
  script:
    - echo "我是现在最终履行的,需求等 test 阶段履行完了才履行。"

needs

needs用于乱序履行Job,运用之后能够忽略 stages的次序运转其他Job。多个阶段的作业能够同时运转。详细介绍
语法:

  • 数组,[] 空数组用于将作业设置为在创建管道后当即发动。
  • 一系列的Job
linux:build:
  stage: build
  script: echo "Building linux..."
mac:build:
  stage: build
  script: echo "Building mac..."
lint:
  stage: test
  needs: []
  script: echo "Linting..."
linux:rspec:
  stage: test
  needs: ["linux:build"]
  script: echo "linux:build履行完结之后履行,不受mac:build影响"
mac:rspec:
  stage: test
  needs: ["mac:build"]
  script: echo "mac:build履行完结之后履行,不受linux:build影响"
production:
  stage: deploy
  script: echo "Running production..."
  environment: production

rules

运用rules来完结何时履行Job。
rules可用的规矩有:

  • if句子为 真时履行。
  • changes:用于查看特定文件的更改来指定何时履行。
  • exists:仓库中存在某些文件时履行。
  • allow_failure:允许 Job 失利而不停止管道。优先级 > Job的allow_failure。
  • variables:为当前条件界说变量。
  • when:同下方 when

能够将多个规矩组合在一起,以进行复杂的规矩匹配。

rules:if

  • 假如 if句子为 true,则将Job增加到管道中。
  • 假如 if句子为 true,但是 when: never,则不会将Job增加到管道中。
  • 假如没有任何 iftrue,则不会增加Job到管道中。
  • =~!~ 右边的表达式会被认定为 正则表达式。
job1:
  script: "echo Hello, Rules 1!"
  rules:
  	## 只要在代码 merge 到 master 分支时才会履行。
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      when: always
job2:
  script: "echo Hello, Rules 2!"
  rules:
  	## 只要在代码 commit 到 dev 分支时才会履行。
    - if: '$CI_COMMIT_BRANCH == "dev"'
      when: always
      variables:
        VAR_1: "变量1" # 界说变量
job3:
  script: "echo Hello, Rules 3!"
  rules:
  	## 只要在代码 commit tag 时才会履行。
		- if: '$CI_COMMIT_TAG != null'
      when: always
job4:
  script: "echo Hello, Rules 4!"
  rules:
		## 只要在仓库目录下存在 package.json 文件时才会履行。
    - exists:
      - package.json
job5:
	script: "echo Hello, Rules 5!"
	rules:
		# tag 为 t.x.x 或 v.x.x 时,才会履行
  	- if: '$CI_COMMIT_TAG =~ /^[t|v]\d+\.\d+\.\d+$/'
    	when: manual

when

用于制造Job运转条件,假如没有指定,则默以为 on_success
可选值:

  • on_success (默认):当之前阶段一切Job都成功时履行,或许该Job有 allow_failure : true
  • manual:手动触发。
  • always:不论其他阶段的Job状态,都能够履行。
  • on_failure:之前阶段的Job至少有一个失利才履行。
  • delayed:指定延迟时间。
  • never:不运转该Job。只能在 rules中或许 workflow:rules运用。
stages:
  - build
  - cleanup_build
  - test
  - deploy
  - cleanup
build_job:
  stage: build
  script:
    - make build
cleanup_build_job:
  stage: cleanup_build
  script:
    - cleanup build when failed
  when: on_failure
test_job:
  stage: test
  script:
    - make test
deploy_job:
  stage: deploy
  script:
    - make deploy
  when: manual
  environment: production
cleanup_job:
  stage: cleanup
  script:
    - cleanup after jobs
  when: always

tags

指定该Job运转在哪个服务器。来源是注册runner时指定的runner标签。

job:
	tags:
  	- frontend
job2:
	tags:
  	- alicloud
  	- nodejs

四、方针

最终方针:完结一个业务流程上面的 .gitlab-ci.yml

# 固定的 stages
stages:
    - check
    - dev
    - fat
    - uat
    - pro
# 代码lint阶段的Job
check:
    stage: check # 指定 stage 为 check
    script:
        - "xxxx script"
    # 履行方法: 默认 on_success
    only: # 当兼并代码时
        - merge_requests
    tags:
        - tag
dev:
    stage: dev
    script:
        - "xxxx script"
    rules:
    	- if: '$CI_COMMIT_TAG =~ /^[t|v]\d+\.\d+\.\d+$/'
      	when: manual
    tags:
        - tag
fat:
    stage: fat
    script:
        - "xxxx script"
    rules:
    	- if: '$CI_COMMIT_TAG =~ /^[t|v]\d+\.\d+\.\d+$/'
      	when: manual
    tags:
        - tag
uat:
    stage: uat
    script:
        - "xxxx script"
    rules:
    	- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
      	when: manual
    tags:
        - tag
pro:
    stage: pro
    script:
        - "xxxx script"
    rules:
    	- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
      	when: manual
    tags:
        - tag

五、结束

到现在,信任我们都应该已经完全会gitlabCI了,这玩意儿其实很简单,但还是有几点需求注意:

  • stages 不声明会有默认值,声明之后就只会用生命的stage
  • Job 称号没有限制
  • Job 需求指定 stage
  • rules: if 句子有必要是 ” 单引号包裹,if 需求跟 when
  • tags 在Job中有必要,否则不会履行Job
  • ci 验证:
    gitlab-ci 从0到1

输入自己的ci内容,点击验证就能够了

gitlab-ci 从0到1

参考文献

  • .gitlab-ci.yml keyword reference | GitLab