问题描述
在使用Gitlab CI时,有一个需求是希望能够从阶段A传递信息到阶段B,以便可以动态更改阶段B。
具体要求如下:
– 用户有一个阶段(A),在该阶段中验证terraform计划并检查是否会销毁资源。
– 用户有另一个阶段(B),应用terraform计划,如果阶段A检测到将要销毁资源,则希望手动触发阶段B。
– 当没有资源被销毁时,terraform应用阶段(B)应自动运行。
用户想知道如何将阶段A的信息传递到阶段B。
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
在Gitlab CI中,无法在rules
子句中使用dotenv
变量的原因是,rules
在流水线开始执行之前就会进行评估。
如果你有一个类似以下的rules
子句:
rules:
- if: $CI_COMMIT_TAG === 'v1.0.0'
when: never
- when: always
Gitlab CI将执行以下检查:
1. 流水线是否为Tag Pipeline
(通过CI_PIPELINE_SOURCE
变量判断)?如果不是,则CI_COMMIT_TAG
不存在,因此该子句不存在,只有when:always
规则。将该任务添加到流水线中。
2. 如果流水线是一个标签流水线,是否tag === 'v1.0.0'
?如果是,则使用when:never
。不将该任务添加到流水线中。
3. 标签流水线且标签不等于v1.0.0
,使用when:never
并将该任务添加到流水线中。
所有这些操作都发生在流水线处于created
状态之前,因此它不能依赖于在流水线开始运行后创建的变量。
了解了这一点,我将如下解决问题的方法:
将阶段B的任务标记为手动任务,就像它已经是的那样,但是当你想要自动运行它时,从阶段A的任务中调用Gitlab Jobs API来运行阶段B的任务。
这将使用一些API调用:
1. 首先,我们需要获取特定流水线的任务:
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_IID/jobs?scope=manual"
这将返回流水线中所有manual
任务。如果你有多个任务,可以通过查看响应中的stage
和name
的值来获取正确的任务。以下是文档中的示例:
[
{
"commit": {
"author_email": "admin@example.com",
"author_name": "Administrator",
"created_at": "2015-12-24T16:51:14.000+01:00",
"id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"message": "Test the CI integration.",
"short_id": "0ff3ae19",
"title": "Test the CI integration."
},
"coverage": null,
"allow_failure": false,
"created_at": "2015-12-24T15:51:21.727Z",
"started_at": "2015-12-24T17:54:24.729Z",
"finished_at": "2015-12-24T17:54:24.921Z",
"duration": 0.192,
"queued_duration": 0.023,
"artifacts_expire_at": "2016-01-23T17:54:24.921Z",
"tag_list": [
"docker runner", "ubuntu18"
],
"id": 6,
"name": "rspec:other",
"pipeline": {
"id": 6,
"project_id": 1,
"ref": "main",
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
"status": "pending"
},
"ref": "main",
"artifacts": [],
"runner": null,
"stage": "test",
"status": "failed",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
"id": 1,
"name": "Administrator",
"username": "root",
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
"created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
"location": null,
"public_email": "",
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": "",
"organization": ""
}
}
]
- 一旦我们有了任务ID,我们可以调用Play Job API来运行阶段B的任务:
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/$ID_OF_STAGE_B_JOB/play"
注意:我们不想在Play Job API中使用预定义变量$CI_JOB_ID
,因为那将是阶段A任务的ID,而不是阶段B任务的ID。
以下是有关Pipeline Jobs API和Play Job API的更多信息和查询参数。