模板与继承 #

一、模板复用概述 #

GitLab CI提供了多种模板复用机制,帮助减少配置重复,提高可维护性。

text
┌─────────────────────────────────────────────────────────────┐
│                    模板复用机制                              │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  include (引入)              extends (继承)                  │
│  ┌─────────────────┐        ┌─────────────────┐            │
│  │ • 引入外部文件   │        │ • 继承Job配置   │            │
│  │ • local/remote  │        │ • 多层继承      │            │
│  │ • project/template│       │ • 覆盖配置      │            │
│  └─────────────────┘        └─────────────────┘            │
│                                                              │
│  YAML锚点 (&/*)              隐藏Job (.)                     │
│  ┌─────────────────┐        ┌─────────────────┐            │
│  │ • 定义锚点      │        │ • 定义模板      │            │
│  │ • 引用锚点      │        │ • 不执行        │            │
│  │ • YAML原生语法  │        │ • 配合extends   │            │
│  └─────────────────┘        └─────────────────┘            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

二、include引入 #

1. local(本地文件) #

引入同一项目中的文件:

yaml
include:
  - local: '/templates/.gitlab-ci-template.yml'

目录结构:

text
project/
├── .gitlab-ci.yml
└── templates/
    └── .gitlab-ci-template.yml

2. project(其他项目) #

引入其他项目的配置:

yaml
include:
  - project: 'my-group/my-project'
    ref: main
    file: '/templates/.gitlab-ci-template.yml'

多文件引入:

yaml
include:
  - project: 'my-group/my-project'
    ref: main
    files:
      - '/templates/build.yml'
      - '/templates/deploy.yml'

3. remote(远程文件) #

引入远程URL的配置:

yaml
include:
  - remote: 'https://example.com/.gitlab-ci-template.yml'

4. template(官方模板) #

引入GitLab官方模板:

yaml
include:
  - template: Auto-DevOps.gitlab-ci.yml
  - template: Jobs/Code-Quality.gitlab-ci.yml
  - template: Jobs/SAST.gitlab-ci.yml

5. 组合引入 #

yaml
include:
  - local: '/templates/build.yml'
  - project: 'my-group/shared-templates'
    ref: v1.0
    file: '/deploy.yml'
  - template: Jobs/Code-Quality.gitlab-ci.yml

6. 条件引入 #

yaml
include:
  - local: '/templates/production.yml'
    rules:
      - if: $CI_COMMIT_BRANCH == "main"
  - local: '/templates/staging.yml'
    rules:
      - if: $CI_COMMIT_BRANCH == "develop"

三、extends继承 #

基本用法 #

yaml
.build_template:
  image: node:18
  script:
    - npm run build

build_staging:
  extends: .build_template
  environment: staging

build_production:
  extends: .build_template
  environment: production

多层继承 #

yaml
.base_template:
  image: node:18
  before_script:
    - npm install

.build_template:
  extends: .base_template
  script:
    - npm run build

build_staging:
  extends: .build_template
  environment: staging

多重继承 #

yaml
.test_template:
  script:
    - npm test

.lint_template:
  script:
    - npm run lint

test_and_lint:
  extends:
    - .test_template
    - .lint_template

覆盖配置 #

yaml
.deploy_template:
  script:
    - echo "Deploying..."
  only:
    - main

deploy_staging:
  extends: .deploy_template
  script:
    - echo "Deploying to staging..."
  only:
    - develop

合并配置 #

yaml
.base_template:
  variables:
    APP_NAME: myapp
    ENV: production

deploy:
  extends: .base_template
  variables:
    REGION: us-east-1

最终变量:

yaml
variables:
  APP_NAME: myapp
  ENV: production
  REGION: us-east-1

四、隐藏Job(模板) #

定义隐藏Job #

.开头的Job不会执行:

yaml
.template:
  image: node:18
  script:
    - npm test

配合extends使用 #

yaml
.node_template:
  image: node:18
  before_script:
    - npm ci
  cache:
    paths:
      - node_modules/

test:
  extends: .node_template
  script:
    - npm test

build:
  extends: .node_template
  script:
    - npm run build

五、YAML锚点 #

定义锚点 #

yaml
.node_config: &node_config
  image: node:18
  before_script:
    - npm ci

引用锚点 #

yaml
.node_config: &node_config
  image: node:18
  before_script:
    - npm ci

test:
  <<: *node_config
  script:
    - npm test

build:
  <<: *node_config
  script:
    - npm run build

锚点与extends对比 #

特性 锚点 extends
语法 YAML原生 GitLab扩展
可读性 较差 较好
灵活性 有限
多继承 不支持 支持

六、组合使用 #

include + extends #

yaml
include:
  - local: '/templates/node.yml'

test:
  extends: .node_template
  script:
    - npm test

templates/node.yml:

yaml
.node_template:
  image: node:18
  before_script:
    - npm ci

锚点 + extends #

yaml
.node_config: &node_config
  image: node:18
  before_script:
    - npm ci

.node_template:
  <<: *node_config
  cache:
    paths:
      - node_modules/

test:
  extends: .node_template
  script:
    - npm test

七、模板组织 #

目录结构 #

text
project/
├── .gitlab-ci.yml
└── .gitlab/
    ├── templates/
    │   ├── node.yml
    │   ├── docker.yml
    │   └── deploy.yml
    └── jobs/
        ├── test.yml
        └── build.yml

主配置文件 #

yaml
include:
  - local: '/.gitlab/templates/node.yml'
  - local: '/.gitlab/templates/docker.yml'
  - local: '/.gitlab/jobs/test.yml'
  - local: '/.gitlab/jobs/build.yml'

模板文件 #

yaml
.node_template:
  image: node:18
  cache:
    paths:
      - node_modules/
  before_script:
    - npm ci

八、最佳实践 #

1. 分层设计 #

yaml
.base_template:
  image: alpine:latest

.node_template:
  extends: .base_template
  image: node:18

.test_template:
  extends: .node_template
  script:
    - npm test

2. 命名规范 #

yaml
.node_template:
  ...

.docker_template:
  ...

.deploy_template:
  ...

3. 使用include分离关注点 #

yaml
include:
  - local: '/.gitlab/jobs/test.yml'
  - local: '/.gitlab/jobs/build.yml'
  - local: '/.gitlab/jobs/deploy.yml'

4. 使用变量简化配置 #

yaml
variables:
  NODE_VERSION: "18"

.node_template:
  image: node:${NODE_VERSION}

5. 文档化模板 #

yaml
.node_template:
  image: node:18
  before_script:
    - npm ci
  cache:
    paths:
      - node_modules/

九、完整示例 #

项目结构 #

text
project/
├── .gitlab-ci.yml
└── .gitlab/
    ├── templates/
    │   ├── node.yml
    │   └── docker.yml
    └── jobs/
        ├── test.yml
        ├── build.yml
        └── deploy.yml

主配置 #

yaml
stages:
  - test
  - build
  - deploy

include:
  - local: '/.gitlab/templates/node.yml'
  - local: '/.gitlab/templates/docker.yml'
  - local: '/.gitlab/jobs/test.yml'
  - local: '/.gitlab/jobs/build.yml'
  - local: '/.gitlab/jobs/deploy.yml'

模板文件 #

yaml
.node_template:
  image: node:18
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
  before_script:
    - npm ci

.docker_template:
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

Job文件 #

yaml
test:
  extends: .node_template
  stage: test
  script:
    - npm test
  artifacts:
    reports:
      junit: test-results/*.xml

build:
  extends: .node_template
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

docker_build:
  extends: .docker_template
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main

deploy_staging:
  extends: .docker_template
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  environment:
    name: staging
  only:
    - develop

deploy_production:
  extends: .docker_template
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  environment:
    name: production
  only:
    - main
  when: manual

下一步 #

现在你已经掌握了模板与继承,接下来让我们学习 安全与权限

最后更新:2026-03-28