作业与阶段 #
一、Stage(阶段)概念 #
什么是Stage? #
Stage是Pipeline的逻辑分组,用于组织Job的执行顺序。同一Stage中的Job并行执行,不同Stage按顺序执行。
text
┌─────────────────────────────────────────────────────────┐
│ Pipeline │
├─────────────────────────────────────────────────────────┤
│ │
│ Stage 1: Build │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ build_job_1 │ │ build_job_2 │ (并行执行) │
│ └─────────────┘ └─────────────┘ │
│ ↓ ↓ │
│ Stage 2: Test │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ test_unit │ │ test_e2e │ │ test_integ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ↓ ↓ ↓ │
│ Stage 3: Deploy │
│ ┌─────────────┐ │
│ │ deploy_job │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
定义Stages #
yaml
stages:
- build
- test
- deploy
默认Stages #
如果不定义stages,GitLab使用以下默认值:
yaml
stages:
- build
- test
- deploy
Stage执行规则 #
- 同一Stage中的Job并行执行
- 前一个Stage的所有Job成功后,下一个Stage才开始
- 如果某个Stage中有Job失败,后续Stage不会执行
二、Job(作业)概念 #
什么是Job? #
Job是Pipeline的最小执行单元,定义了具体的执行任务。
yaml
job_name:
stage: test
script:
- echo "Running tests"
- npm test
Job命名规则 #
- 必须是有效的YAML键名
- 每个Job名称必须唯一
- 不能使用GitLab保留关键字
保留关键字:
text
image, services, stages, types, before_script, after_script,
variables, cache, include, true, false, nil
Job基本结构 #
yaml
job_name:
stage: stage_name
script:
- command1
- command2
variables:
VAR: value
only:
- main
三、Job类型 #
1. 普通Job #
yaml
test_job:
stage: test
script:
- npm test
2. 手动Job #
yaml
deploy_production:
stage: deploy
script:
- echo "Deploying..."
when: manual
3. 延迟Job #
yaml
deploy_job:
stage: deploy
script:
- echo "Deploying..."
when: delayed
start_in: 30 minutes
4. 触发Job #
yaml
trigger_downstream:
stage: deploy
trigger:
project: my-group/my-project
branch: main
5. 隐藏Job(模板) #
以.开头的Job不会执行,可作为模板:
yaml
.template:
script:
- echo "Template script"
real_job:
extends: .template
四、Stage执行流程 #
顺序执行 #
yaml
stages:
- build
- test
- deploy
build_job:
stage: build
script: echo "Building..."
test_job:
stage: test
script: echo "Testing..."
deploy_job:
stage: deploy
script: echo "Deploying..."
执行顺序:
text
build_job → test_job → deploy_job
并行执行 #
yaml
stages:
- test
test_unit:
stage: test
script: npm run test:unit
test_integration:
stage: test
script: npm run test:integration
test_e2e:
stage: test
script: npm run test:e2e
执行顺序:
text
test_unit ┐
test_integration ├─ 并行执行
test_e2e ┘
五、needs关键字(DAG) #
什么是DAG? #
DAG(有向无环图)允许Job不按Stage顺序执行,而是按依赖关系执行。
yaml
stages:
- build
- test
- deploy
build_a:
stage: build
script: echo "Build A"
build_b:
stage: build
script: echo "Build B"
test_a:
stage: test
needs: [build_a]
script: echo "Test A"
test_b:
stage: test
needs: [build_b]
script: echo "Test B"
deploy:
stage: deploy
needs: [test_a, test_b]
script: echo "Deploy"
执行图:
text
build_a → test_a ┐
├→ deploy
build_b → test_b ┘
needs与artifacts #
yaml
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
test:
stage: test
needs:
- job: build
artifacts: true
script:
- ls dist/
needs与optional #
yaml
test:
stage: test
needs:
- job: lint
optional: true
script:
- npm test
六、Job控制 #
1. 条件执行 #
使用rules:
yaml
deploy_production:
stage: deploy
script:
- echo "Deploying..."
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
- when: never
使用only/except:
yaml
deploy_production:
stage: deploy
script:
- echo "Deploying..."
only:
- main
2. 失败处理 #
yaml
lint:
stage: test
script:
- npm run lint
allow_failure: true
test:
stage: test
script:
- npm test
3. 重试机制 #
yaml
flaky_test:
stage: test
script:
- npm test
retry:
max: 2
when:
- script_failure
- runner_system_failure
- stuck_or_timeout_failure
4. 超时控制 #
yaml
long_job:
stage: build
script:
- ./long-script.sh
timeout: 2h
5. 并行执行 #
yaml
test:
stage: test
parallel: 5
script:
- echo "Running test $CI_NODE_INDEX of $CI_NODE_TOTAL"
矩阵并行:
yaml
test:
stage: test
parallel:
matrix:
- NODE: [16, 18, 20]
OS: [linux, windows, macos]
image: node:${NODE}
tags:
- ${OS}
script:
- echo "Testing Node ${NODE} on ${OS}"
七、Job产物传递 #
artifacts传递 #
yaml
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
test:
stage: test
dependencies:
- build
script:
- ls dist/
- npm test
dependencies限制 #
yaml
build_a:
stage: build
script: echo "Build A"
artifacts:
paths:
- dist_a/
build_b:
stage: build
script: echo "Build B"
artifacts:
paths:
- dist_b/
test:
stage: test
dependencies:
- build_a
script:
- ls dist_a/
八、Stage和Job最佳实践 #
1. 合理划分Stage #
yaml
stages:
- lint
- build
- test
- security
- deploy
2. 使用模板复用配置 #
yaml
.node_template:
image: node:18
before_script:
- npm ci
cache:
paths:
- node_modules/
lint:
extends: .node_template
stage: lint
script:
- npm run lint
test:
extends: .node_template
stage: test
script:
- npm test
3. 使用needs优化执行 #
yaml
stages:
- lint
- build
- test
lint:
stage: lint
script: npm run lint
build:
stage: build
script: npm run build
test_unit:
stage: test
needs: [build]
script: npm run test:unit
test_integration:
stage: test
needs: [build, lint]
script: npm run test:integration
4. 控制并发 #
yaml
deploy_production:
stage: deploy
resource_group: production
script:
- echo "Deploying..."
5. 环境管理 #
yaml
deploy_staging:
stage: deploy
environment:
name: staging
url: https://staging.example.com
on_stop: stop_staging
script:
- echo "Deploying to staging"
stop_staging:
stage: deploy
environment:
name: staging
action: stop
script:
- echo "Stopping staging"
when: manual
九、完整示例 #
微服务项目 #
yaml
stages:
- lint
- build
- test
- security
- package
- deploy
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
lint:
stage: lint
image: node:18
script:
- npm ci
- npm run lint
allow_failure: true
build:
stage: build
image: node:18
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
test_unit:
stage: test
image: node:18
needs: [build]
script:
- npm ci
- npm run test:unit
coverage: '/Coverage: \d+%/'
test_integration:
stage: test
image: node:18
services:
- postgres:14
needs: [build]
script:
- npm ci
- npm run test:integration
security_scan:
stage: security
image: docker:latest
needs: [build]
script:
- echo "Running security scan..."
allow_failure: true
docker_build:
stage: package
image: docker:latest
services:
- docker:dind
needs: [test_unit, test_integration]
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
deploy_staging:
stage: deploy
image: bitnami/kubectl:latest
needs: [docker_build]
environment:
name: staging
url: https://staging.example.com
script:
- kubectl set image deployment/myapp myapp=$DOCKER_IMAGE
only:
- develop
deploy_production:
stage: deploy
image: bitnami/kubectl:latest
needs: [docker_build, security_scan]
environment:
name: production
url: https://example.com
script:
- kubectl set image deployment/myapp myapp=$DOCKER_IMAGE
only:
- main
when: manual
十、常见问题 #
1. Stage执行顺序不对 #
确保stages定义正确:
yaml
stages:
- build
- test
- deploy
2. Job没有并行执行 #
检查是否在同一个stage:
yaml
stages:
- test
test_unit:
stage: test
test_integration:
stage: test
3. needs找不到artifacts #
确保artifacts正确传递:
yaml
build:
artifacts:
paths:
- dist/
test:
needs:
- job: build
artifacts: true
下一步 #
现在你已经掌握了Jobs和Stages的概念,接下来让我们学习 流水线类型!
最后更新:2026-03-28