GitLab CI/CD学习教程(第四章gitlab-ci.yml)

发布于:2025-03-25 ⋅ 阅读:(40) ⋅ 点赞:(0)

GitLab CI/CD学习教程(第四章gitlab-ci.yml)


🚀从零开始,结合具体场景和示例,让你彻底掌握 GitLab CI/CD 的配置!

icon


1 定义


⭐ 什么是.gitlab-ci.yml

在上一章节中,我们详细讲述了Pipeline的定义,本章节将重点讲解如何对Pipeline进行精细化的控制。

.gitlab-ci.yml 文件是 GitLab CI/CD 管道的配置文件。它以 YAML 格式定义了流水线(Pipeline)的各个阶段(stages)和任务(jobs)。每当你向 GitLab 仓库提交代码时,GitLab 会根据 .gitlab-ci.yml 文件自动执行预定的任务。



2 基础语法

.gitlab-ci.yml 配置文件使用的是 YAML语法,规则十分简单,是一种简洁的数据序列化语言,主要特点是可读性强,并且支持层级结构

  • 🧤 缩进

    空格(不能用 Tab),通常用 2 个空格缩进。

  • 🎎 键值对

    配置项是由键key和值value组成的。例如:stages: [build, test, deploy]

  • 📊 列表

    - 表示列表项

  • ⚙ 多行脚本

    |>(保留换行/折叠换行)

  • 💬 注释

    # 开头的行表示注释,GitLab CI/CD 会忽略这些行。


3 关键配置项

项目 类型 作用 示例
workflow Object 用于控制整个 CI/CD 流水线的行为。
(定义全局规则,比如是否启用流水线、如何调度流水线的执行等)
(通常与rules结合使用)
workflow:
   rules:
       - if: '$CI_COMMIT_TAG #仅当打标签时触发整个流水线
variables 键值对
key-value
定义了在 CI/CD 流水线中使用的环境变量。 variables:
   version: 1.0.0.0
   description: xxx
stages Array 定义了流水线的所有阶段,并指定这些阶段的执行顺序 stages:
   - build
   - test
   - deploy
jobs Object 具体执行的任务,每个任务定义了一个独立的操作。
任务通常包括以下配置项:
  • stage
  • script
job1:
   stage: build
   script:
       - echo “Running job1”
stage String 指定任务属于哪个阶段。
(必须在 stages 中定义)
job1:
   stage: build # 该作业属于build阶段
script Array 或
String
定义任务执行的实际命令。
(比如打印一句话)
script:
   - echo “Running tests…”
before_script Array 或
String
定义在每个任务之前执行的脚本。
(常用于设置公共的执行步骤,安装依赖等)
before_script:
   - $scriptPath = " $env:CI_PROJECT_DIR\test.py"
   if (-not (Test-Path $scriptPath)) {
      Write-Error “错误:Python脚本不存在于 $scriptPath”
      exit 1
   }
   python $scriptPath
after_script Array 或
String
定义在每个任务之后执行的脚本。
(常用于清理操作、记录日志等)
after_script:
   - echo “运行结束”
artifacts Object 用于指定在job执行完成后需要保存的文件或目录。
(这些文件将在后续作业或流水线运行中可用。)
artifacts:
   paths:
       - build/
   expire_in: 30 minute # 30分钟后过期
timeout String 设置作业的超时时间。
(超出这个时间作业会被强制终止。)
job1:
   timeout: 60 minutes
interruptible Boolean 是否允许中断当前作业。
(通常用于节省资源。)
job1:
   interruptible: true
allow_failure Boolean 是否允许任务失败。
(如果设置为 true,即使任务失败,流水线会继续执行)
job1:
   interruptible: true
needs Array 每个阶段内的作业默认是并行执行的,除非使用 needs 显式声明依赖关系。 job1:
   script:
       - eho “Running job1”
job2:
   script:
       - eho “Running job2”
   needs:
       job1
only
except
Array only 定义job应该在哪些分支或事件下执行
except 定义job不应该在哪些情况下执行
(控制任务的触发条件)
job1:
   only:
       - main # main分支才会触发
when Object 定义作业的执行时机。
常用的值包括:
  • on_success(成功时)
  • on_failure(失败时)
  • manual(手动触发)
job1:
   when: manual
rules Array 或
Object
替代 onlyexcept 的更灵活的条件控制方法。
常用选项:
  • if: 用于表达条件判断
  • when: 定义条件成立时作业的执行时机
  • start_in:设置作业的启动延迟时间
rules:
   - if: ‘$ CI_COMMIT_BRANCH’==main
      when: manual
   - if: ‘$CI_COMMIT_TAG’
image String 用于指定一个 Docker 镜像,镜像将在执行作业时被拉取和使用。 image: node:14
services Array 用于定义与作业一起运行的其他 Docker 容器(服务)。
(这些服务通常是数据库、缓存或其他依赖服务。)
services:
   - mysql:5.7

这里需要对onlywhen区别作一个详细的解释。(PS: 建议使用rules,它更强大和灵活)

  • 意图:only 更侧重于指定作业应该在哪种类型的变更(如特定分支或标签)上运行;而 when 则关注于作业在整个管道流程中的执行策略。
  • 灵活性:虽然两者都能影响作业是否执行,但是 when 提供了关于作业执行时机的更多选项,并且可以结合其他条件(例如通过 rules)来实现更为复杂的逻辑。

4 预定义变量

📙 官方文档

预定义变量在流水线执行的三个不同阶段可用:

  • 预流水线:预流水线变量在创建流水线之前可用。这些变量是仅使用 include:rules 来控制在创建流水线时要使用哪些配置文件。
  • 流水线:这些变量在流水线创建时可用。除了预流水线变量外,流水线- 变量还可以用于配置在作业中定义的 rules ,以确定要添加到流水线中的哪些作业。
  • 仅作业:这些变量仅在 runner 选择作业并运行作业时为每个作业可用。

常用的预定义变量: (更多其他变量请查阅官方文档)

🎎 变量 🎨 描述
CI_COMMIT_AUTHOR Name 格式的提交作者。
CI_COMMIT_BEFORE_SHA 出现在分支或标签上的上一个最新提交。在合并请求的流水线中总是 0000000000000000000000000000000000000000。
CI_COMMIT_BRANCH 提交分支名称。在分支流水线中可用,包括默认分支的流水线。在合并请求流水线或标签流水线中不可用。
CI_COMMIT_DESCRIPTION 提交的描述。如果标题短于 100 个字符,则消息没有第一行。
CI_COMMIT_MESSAGE 完整的提交消息。
CI_COMMIT_REF_NAME 为其构建项目的分支或标签名称。
CI_COMMIT_SHORT_SHA CI_COMMIT_SHA 的前八个字符。
CI_COMMIT_TAG 提交标签名称。仅在标签流水线中可用。
CI_COMMIT_TAG_MESSAGE 提交标签消息。仅在标签流水线中可用。
CI_COMMIT_TIMESTAMP ISO 8601 格式的提交时间戳。
CI_COMMIT_TITLE 提交的标题。消息的完整第一行。
CI_CONFIG_PATH CI/CD 配置文件的路径。默认为.gitlab-ci.yml。在正在运行的流水线中只读。
CI_RELEASE_DESCRIPTION 发布的描述。仅在标签流水线上可用。描述长度限制为前 1024 个字符。
CI_JOB_IMAGE 运行作业的 Docker 镜像的名称。
CI_JOB_NAME 作业名称
CI_JOB_STAGE 作业阶段名称。
CI_JOB_STATUS 执行每个 runner 阶段时的作业状态。与 after_script 一起使用。可以是 success、failed 或 canceled。
CI_PIPELINE_SOURCE 流水线是如何触发的。可以是 push、web、schedule、api、external、chat、webide、merge_request_event、external_pull_request_event、parent_pipeline、trigger 或 pipeline 。
CI_PIPELINE_NAME workflow:name 中定义的名称。
CI_PROJECT_ID 当前项目的 ID。该 ID 在实例上的所有项目中都是唯一的。
CI_PROJECT_NAME 项目目录的名称。例如,如果项目 URL 是 gitlab.example.com/group-name/project-1,则 CI_PROJECT_NAME 是 project-1。
CI_PROJECT_NAMESPACE 作业的项目命名空间(用户名或群组名)。
CI_PROJECT_NAMESPACE_ID 作业的项目命名空间 ID。
CI_PROJECT_PATH 包含项目名称的项目命名空间。
CI_PROJECT_ROOT_NAMESPACE 作业的根项目命名空间(用户名或群组名)。例如,如果 CI_PROJECT_NAMESPACE 是 root-group/child-group/grandchild-group,则 CI_PROJECT_ROOT_NAMESPACE 是 root-group。
CI_PROJECT_TITLE Web 界面中显示的人类可读的项目名称。
CI_PROJECT_DESCRIPTION Web 界面中显示的项目描述。
CI_PROJECT_URL 项目的 HTTP(S) 地址。
CI_PROJECT_VISIBILITY 项目可见性。可以是 internal、private 或 public。
CI_REPOSITORY_URL 克隆 Git 仓库的 URL。
GITLAB_USER_EMAIL 启动流水线的用户的电子邮件,除非作业是手动作业。在手动作业中,该值是启动作业的用户的电子邮件。
GITLAB_USER_ID 启动流水线的用户的 ID,除非作业是手动作业。在手动作业中,该值是启动作业的用户的 ID。
GITLAB_USER_LOGIN 启动流水线的用户的用户名,除非作业是手动作业。在手动作业中,该值是启动作业的用户的用户名。
GITLAB_USER_NAME 启动流水线的用户的姓名,除非作业是手动作业。在手动作业中,该值是启动作业的用户的姓名。

5 简单示例

5.1 Vue.js 项目

image: node:18

stages:
  - install
  - build
  - deploy

cache:
  key: $CI_COMMIT_REF_SLUG
  paths:
    - node_modules/

install-deps:
  stage: install
  script:
    - npm ci
  only:
    - main

build-prod:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

deploy-s3:
  stage: deploy
  image: amazon/aws-cli:latest
  script:
    - aws s3 sync dist/ s3://my-bucket/ --delete
  only:
    - main

5.2 Python Django 项目

image: python:3.10

stages:
  - test

services:
  - postgres:13

variables:
  POSTGRES_DB: mydb
  POSTGRES_USER: runner
  POSTGRES_PASSWORD: ""
  DATABASE_URL: "postgres://runner:@postgres:5432/mydb"

test:
  stage: test
  before_script:
    - pip install -r requirements.txt
    - python manage.py migrate
  script:
    - pytest --cov=.
  coverage: '/^TOTAL.+?(\d+\%)$/'

5.3 Qt/C++ 项目(Windows + shell环境)

# 包含共享配置
include:
  - local: '/.ci-templates/variables.yml'  # 共享变量定义

# 定义工作流规则
workflow:
  rules:
    - if: '$CI_COMMIT_TAG'                 # 标签提交触发完整流水线
      variables:
        DEPLOY_ENV: "production"
    - if: '$CI_COMMIT_BRANCH == "main"'    # main分支触发构建、测试、打包
      variables:
        DEPLOY_ENV: "staging"
    - when: manual                         # 允许手动触发

# 全局配置
variables:
  QT_ROOT: "C:\\Qt"
  QIFW_BIN: "C:\\Qt\\Tools\\QtInstallerFramework\\4.6\\bin"
  BUILD_SCRIPT: "scripts/build.py"
  PACKAGE_SCRIPT: "scripts/package.py"
  RELEASE_SCRIPT: "scripts/release.py"

# 阶段定义
stages:
  - prepare
  - build
  - test
  - package
  - release

# 公共before_script
before_script:
  - echo "Running on $CI_RUNNER_DESCRIPTION"
  - python --version
  - pip install -r requirements-ci.txt
  - export ARTIFACTS_DIR="$CI_PROJECT_DIR/artifacts"
  - mkdir -p $ARTIFACTS_DIR

# 公共after_script
after_script:
  - echo "Cleaning temporary files..."
  - rm -rf tmp_build

# 准备阶段
prepare-env:
  stage: prepare
  rules:
    - if: '$DEPLOY_ENV == "production" || $DEPLOY_ENV == "staging"'
  script:
    - python $BUILD_SCRIPT prepare
      --qt-version 5.15.2
      --platform win64
      --output-dir $ARTIFACTS_DIR
  artifacts:
    paths:
      - $ARTIFACTS_DIR/qt_env.bat
    expire_in: 1h

# 并行构建任务
build-windows:
  stage: build
  needs: ["prepare-env"]  # 显式声明依赖
  parallel: 2  # 并行构建两个配置
  rules:
    - if: '$DEPLOY_ENV == "production"'
      variables:
        BUILD_TYPE: "release"
    - if: '$DEPLOY_ENV == "staging"'
      variables:
        BUILD_TYPE: "debug"
  script:
    - call $ARTIFACTS_DIR/qt_env.bat
    - python $BUILD_SCRIPT compile
      --type $BUILD_TYPE
      --jobs 4
      --output $ARTIFACTS_DIR/$BUILD_TYPE
  artifacts:
    paths:
      - $ARTIFACTS_DIR/$BUILD_TYPE/**
    reports:
      dotenv: $ARTIFACTS_DIR/build_info.env

# 测试阶段
run-tests:
  stage: test
  needs:
    - job: build-windows
      artifacts: true
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
  script:
    - python -m pytest tests/ -v --junitxml=test-results.xml
    - python $BUILD_SCRIPT analyze-coverage
      --input build/coverage
      --output $ARTIFACTS_DIR/coverage_report.html
  artifacts:
    paths:
      - test-results.xml
      - $ARTIFACTS_DIR/coverage_report.html
    reports:
      junit: test-results.xml

# 打包阶段
create-installer:
  stage: package
  needs:
    - build-windows
    - run-tests
  rules:
    - if: '$DEPLOY_ENV == "production"'
  script:
    - python $PACKAGE_SCRIPT
      --config installer/windows/config.xml
      --source $ARTIFACTS_DIR/release
      --output $ARTIFACTS_DIR/installer
      --tool-path $QIFW_BIN
  artifacts:
    paths:
      - $ARTIFACTS_DIR/installer/*.exe
    expire_in: 1 week

# 发布阶段
deploy-release:
  stage: release
  needs: ["create-installer"]
  rules:
    - if: '$CI_COMMIT_TAG != null'
  script:
    - python $RELEASE_SCRIPT
      --tag $CI_COMMIT_TAG
      --artifact $ARTIFACTS_DIR/installer/*.exe
      --changelog changelog.md
  environment:
    name: production
    url: https://downloads.example.com

# 安全扫描(动态包含)
include:
  - template: Security/SAST.gitlab-ci.yml

上一篇:《GitLab CI/CD学习教程 第三章Pipeline》
下一篇:《GitLab CI/CD学习教程 第五章高级示例》正在编写中…