GitLab CI 迁到内置流水线:YAML 怎么改写

简介: 想把 .gitlab-ci.yml 搬到 AngusGit 内置流水线,可以先用「导入 GitLab CI」生成初稿(转换出来还要手改的第一版)。artifacts、rules 和 when 不会映射,deploy 仍会自动跑,分支限制也会丢失,所以要逐项对照、改好之后再创建流水线。

这篇讲怎么把 .gitlab-ci.yml 用 导入 GitLab CI 转成 AngusGit 流水线,以及保存前要改什么。看完你可以对照未映射清单和注意清单,处理转不过去的 artifacts、rules 和 when,补上分支限制,避免部署在没人点击时就自动跑;导入不会替你新建凭证。

AngusGit 的流水线在团队版和企业版中提供,社区版没有 CI/CD 菜单。如果你还没写过 AngusGit 的流水线,建议先看文末参考里的 YAML 入门一文,了解 Job(流水线里的一组步骤)、运行器(Runner,真正执行任务的那台机器)这些基本概念。

导入 GitLab CI:转换之后先看清单,核对完再创建

1. 一份用来转换的 .gitlab-ci.yml

下面这份配置专门用来演示转换,并不是哪个线上仓库正在使用的文件。它分三个阶段:先构建,再测试,最后在 main 分支上手动触发部署。

stages:
  - build
  - test
  - deploy

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=.m2"

build:
  stage: build
  image: maven:3.9-eclipse-temurin-21
  tags: [docker]
  script:
    - mvn -B -DskipTests package
  artifacts:
    paths: [target/*.jar]

test:
  stage: test
  image: maven:3.9-eclipse-temurin-21
  tags: [docker]
  script:
    - mvn -B test
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == "main"'

deploy:
  stage: deploy
  tags: [deploy]
  script:
    - ./deploy.sh $CI_COMMIT_SHORT_SHA
  when: manual
  only: [main]

2. 用控制台导入,先拿到初稿

  1. 打开导入对话框

    进入 CI/CD → 流水线,点 新建流水线。菜单里有 空白创建、根据仓库生成、导入 GitHub Actions、导入 GitLab CI 四项,后两项下面都有一行小字「部分语法自动转换,导入后请校验」。这里选 导入 GitLab CI。

  2. 粘贴内容并转换

    对话框标题是 导入 GitLab CI,说明文字是「子集映射为 AngusCICD YAML。include / 完整 rules / child pipeline 不会展开,请看未映射清单。」也就是说,只有一部分语法会被转换。默认页签是 粘贴 YAML(旁边还有 扫描仓库),输入框的名称是 GitLab CI,提示文字是「粘贴 .gitlab-ci.yml 内容」。把第 1 节的整段 YAML 贴进去,点 转换。

  3. 看两份清单

    转换结果显示在输入框下方,从上到下依次是 未映射(需人工改)、注意、流水线名称,最后是 YAML 编辑器。流水线名称会自动填成 imported-from-gitlab(输入框占位文字是「输入流水线名称」)。

  4. 核对清单后再创建

    从流水线列表打开时,对话框右下角的按钮是 创建流水线;从空白创建页打开同一个对话框时,这个位置是 填入编辑器。如果清单里的问题还没改完,点 取消 即可,仓库里不会留下流水线。

导入 GitLab CI 的转换结果:未映射四条、注意三条,流水线名称是 imported-from-gitlab

转换完成后,对话框中间会滚到两份清单(更上方的粘贴框可能被滚出视野),标题、说明和右下角的 取消、创建流水线 仍在。清单内容如下,四条未映射是:

  • jobs.build.artifacts
  • jobs.test rules/only/except(仅用于推断触发器;完整条件未映射)
  • jobs.deploy rules/only/except(仅用于推断触发器;完整条件未映射)
  • jobs.deploy.when

三条注意是:

  • jobs.deploy 无 image,映射为 NATIVE
  • CI_COMMIT_SHORT_SHA → commitSha(完整 SHA,不是短 SHA)
  • GitLab CI_* 预定义变量已近似改写;其余 CI_* 运行时不会注入

第一条注意里的 NATIVE,和下面初稿里的 DOCKER,是 AngusGit 的两种执行模式:DOCKER 在指定镜像启动的容器里执行命令,NATIVE 直接在运行器所在的机器(宿主机)上执行。转换成功的项不会逐条列出,编辑器里生成的初稿如下:

version: '1'
name: imported-from-gitlab
triggers:
- 'on': push
- 'on': pull_request
env:
  MAVEN_OPTS: -Dmaven.repo.local=.m2
pipeline:
  build:
    runner:
      mode: DOCKER
      image: maven:3.9-eclipse-temurin-21
      labels:
      - docker
    steps:
    - name: script
      run: mvn -B -DskipTests package
  test:
    runner:
      mode: DOCKER
      image: maven:3.9-eclipse-temurin-21
      labels:
      - docker
    steps:
    - name: script
      run: mvn -B test
    needs:
    - build
  deploy:
    runner:
      mode: NATIVE
      labels:
      - deploy
    steps:
    - name: script
      run: ./deploy.sh ${
   {
    commitSha }}
    needs:
    - test

初稿里的 'on' 带引号,是因为 YAML 会把不加引号的 on 当成布尔值,导出时特意加了引号来避开。这是转换后的初稿,保存前还必须处理未映射项。

左边是原配置,右边是转换初稿:deploy 仍会自动跑

3. 对照表:哪些转了,哪些没转

先看能自动转换的部分。其中最需要理解的是 stages:GitLab CI 用阶段来排先后,AngusGit 没有阶段,改为让后一个 Job 用 needs 声明它要等哪个 Job 完成。

导入会自动转过去的:

GitLab CI 初稿里的样子 说明
script 步骤名 script,命令在 run 单行脚本的步骤名就是 script
image runner.mode: DOCKER 加 runner.image 镜像名原样保留,仍是 maven:3.9-eclipse-temurin-21
没写 image runner.mode: NATIVE 例如 deploy,注意里写了「jobs.deploy 无 image,映射为 NATIVE」
tags runner.labels docker、deploy 原样变成标签
variables 流水线级 env MAVEN_OPTS 写在了顶层 env
stages 后一个阶段的 Job 写 needs test 依赖 build,deploy 依赖 test。stages 本身不保留
rules 里的合并请求 触发器多了一条 pull_request 完整的 if 没有写进 Job
allow_failure continue-on-error 这份示例里没有
environment 只保留环境名称 这份示例里没有。有的话,注意会写「只保留名称,无 GitLab environment 保护规则」

接下来是没转过去的部分。下表先列出要点,表后再逐条展开。

这份示例没转过去、保存前要处理的:

你在清单里看到的 初稿实际做了什么 保存前怎么改
jobs.build.artifacts target/*.jar 不会传给后面的 Job 本例可先不改
jobs.test 和 jobs.deploy 的 rules / only 只用来推断触发器,main 没变成 branches 给触发器补上 branches: [main]
jobs.deploy.when 丢掉了 when: manual,deploy 仍在且 needs: [test] 删掉 deploy 另建一条,或加 approval
include、retry、timeout、dependencies、trigger 本例没有,出现时会进未映射清单 见表后说明
  • artifacts(构建产物):这份示例的 test 自己会再跑一遍 mvn test,不读那个 jar,所以两个 Job 可以先保持原样。如果下游脚本要读上一个 Job 生成的文件,就把相关步骤并进同一个 Job,或者先上传到制品库再下载。
  • rules / only:初稿里的 push 和 pull_request 都没有 branches: [main]。不改的话,其他分支也会触发这条流水线,而且 deploy 会跟着运行。
  • when:when: manual 被丢掉后,部署会在每次触发时自动执行。不想自动部署,就把 deploy 从这条流水线里删掉,另建一条用 workflow_dispatch(只能手动运行)触发的流水线,或者给这个 Job 加 approval(审批)。
  • 其他字段:用了 include 的,要先把被引用的片段合并进一份 YAML 再导入;Job 级的 retry、timeout 要改写到步骤上,单位是秒;用 trigger 触发的下游流水线要拆开单独处理。

定时任务也能导入,但 cron 要自己补。 cron 是描述定时规则的表达式。GitLab 的定时规则配置在页面上,不写在 YAML 里。所以,YAML 里如果有 only: schedules,或者 rules 的条件里写了 schedule,导入会加上 on: schedule,同时在未映射里写明「schedule cron 未映射(GitLab 定时在 UI,不在 YAML)」。这时 cron 要你自己补上,格式是五段式,例如 0 2 * * *。第 1 节的示例没有定时,所以初稿里也没有 on: schedule。

4. CI_* 变量要特别检查

GitLab 运行时会自动提供一批以 CI_ 开头的预定义变量,AngusGit 不会注入它们。导入时只会把下表这几个改写成 ${ { }} 表达式,并不会改成环境变量 GIT_COMMIT_SHA:

GitLab 变量 导入后 这份示例
$CI_COMMIT_SHA ${ { commitSha }} 示例脚本里没有
$CI_COMMIT_SHORT_SHA 同样是 ${ { commitSha }},完整 SHA deploy 命令变成 ./deploy.sh ${ { commitSha }}
$CI_COMMIT_BRANCH ${ { branch }} 只在 test 的 rules 里,那条 if 没写进 Job
$CI_PIPELINE_SOURCE ${ { event }} 同样只用来推断出 pull_request
$CI_COMMIT_TAG ${ { ref }} 本例没有,出现时注意写「CI_COMMIT_TAG → ref(近似)」

其中 $CI_COMMIT_SHORT_SHA 最容易出错。注意原文是 CI_COMMIT_SHORT_SHA → commitSha(完整 SHA,不是短 SHA),也就是说,改写后拿到的是完整的提交号。如果你要 8 位短 SHA,就在 shell 里自己截取 $GIT_COMMIT_SHA,不要以为 ${ { commitSha }} 已经是短的。

表外的其他 CI_ 变量,例如 CI_PROJECT_DIR、CI_PIPELINE_ID、CI_REGISTRY,运行时都不会注入。只要原文有变量被改写过、又还留着 CI_ 变量,注意里就会有这一句:「GitLab CI* 预定义变量已近似改写;其余 CI* 运行时不会注入」。自己写的脚本可以改用平台提供的环境变量 GIT_REPO_URL、GIT_BRANCH、GIT_COMMIT_SHA。

还有一类变量要留意:名字以 TOKEN、SECRET、PASSWORD、PASSWD、PRIVATE_KEY、ACCESS_KEY 或 API_KEY 结尾时,导入会把这个名字写进 Job 的 secrets 名单,并在注意里写「$名字 → env.名字,并写入 Job secrets 名单」。这时 AngusGit 里必须先有同名凭证,否则 Job 会失败并提示 Credential not visible or expired。导入不会替你创建凭证,要自己在 CI/CD → 配置 → 凭证 里新建。第 1 节没有这类变量,所以初稿里没有 secrets。

5. 保存前建议改成什么样

这份初稿不能直接保存,因为有两处和原配置的意思相反:一是 only: [main] 没有变成 branches: [main],其他分支也会触发;二是 when: manual 丢了,deploy 仍会在 test 之后自动运行。

建议把它拆成两条流水线。第一条保留构建和测试,并补上分支限制。镜像先沿用转换结果;如果内网拉不到 Docker Hub,再把 maven:3.9-eclipse-temurin-21 换成平台镜像 repo.anguskit.com/docker-public/angus-ci-maven:21。下面是手动改完后的写法,并非导入器直接给出的初稿:

version: "1"
name: imported-from-gitlab
triggers:
  - "on": push
    branches: [main]
  - "on": pull_request
    branches: [main]
env:
  MAVEN_OPTS: "-Dmaven.repo.local=.m2"
pipeline:
  build:
    runner:
      mode: DOCKER
      image: maven:3.9-eclipse-temurin-21
      labels: [docker]
    steps:
      - name: script
        run: mvn -B -DskipTests package
  test:
    needs: [build]
    runner:
      mode: DOCKER
      image: maven:3.9-eclipse-temurin-21
      labels: [docker]
    steps:
      - name: script
        run: mvn -B test

注意 needs 只决定先后顺序,不会把 target/*.jar 传给 test。这里之所以还能分成两个 Job,是因为 test 自己执行 mvn test,用不到那个 jar。如果部署脚本要读这个 jar,就把打包和部署写成同一个 Job 里的两个步骤。

第二条流水线只放部署,并且只允许手动运行。脚本参数里的 ${ { commitSha }} 仍然是完整 SHA。建议写成:

version: "1"
name: deploy
triggers:
  - "on": workflow_dispatch
pipeline:
  deploy:
    runner:
      mode: NATIVE
      labels: [deploy]
    steps:
      - name: script
        run: ./deploy.sh "${
   {
    commitSha }}"

如果希望部署仍然跟在构建后面,但要由指定的人批准后才继续,就给这个 Job 加 approval;已经被丢掉的 when: manual 起不到这个作用。具体做法见文末参考里的流水线审批一文。

6. 真要保存时先验证一次

改完之后,按下面三步把流水线建起来并验证:

  1. 通过运行前检查

    如果对话框是从列表打开的,点 创建流水线;如果是从空白创建页打开的,先点 填入编辑器,再在创建页保存。保存前平台会做运行前检查:通过时页面显示「检查通过,可以保存。」;提示「请先修复错误」时,按提示修改。最常见的原因是 YAML 里还留着 stages、variables 这类 GitLab 字段。

  2. 手动跑一次

    在流水线详情页点 触发,分支 / 标签 填一个测试分支,然后确认 Job 被带 docker 标签的运行器接走。要小心:如果 deploy 还留在同一条流水线里,这次运行就会真的执行部署命令。

  3. 再看自动触发

    手动运行通过后,再发起一个拉取请求,确认 pull_request 能正常触发,并且结果写回了拉取请求页的状态检查(页面上标明流水线是否通过的那一项)。

迁移期间,.gitlab-ci.yml 可以先留在仓库里,AngusGit 不会执行它。等新的流水线稳定运行之后再删除。

常见问题

迁移后最常遇到的情况如下:

你看到的 原因 怎么处理
Job 一直排队 没有在线的运行器同时满足 mode 和 labels 运行器要带 docker 标签,并能跑对应的执行模式
Job 没在容器里,直接跑在宿主机上 原 Job 没有写 image,变成了 NATIVE 补上 runner.mode: DOCKER 和 runner.image
后面的 Job 找不到 target/*.jar artifacts 在未映射里,needs 不传文件 合成一个 Job,或经制品库中转
部署在没人点击时就跑了 when: manual 未映射,Job 仍在流水线里 删掉这个 Job,或改成 workflow_dispatch / approval
非 main 的分支也跑了部署 only: [main] 没有写成 branches 给 push 和 pull_request 加上 branches: [main]
脚本里某个路径或编号是空的 用了没有注入的 CI_* 变量 按第 4 节替换,短 SHA 用 $GIT_COMMIT_SHA 自己截
合并进 main 后没有自动构建 拉取请求页的合并不会触发 on: push,只有 git push 会 用 pull_request 在合并前跑构建和测试

能不能一次导入多个文件?

不能,对话框一次只处理一份 YAML。如果项目用了 include(在一份 YAML 里引用其他 YAML 片段),要先把被引用的文件合并成一份再导入,否则未映射里会写「include(不拉取远程/本地片段,须先展开再导入)」。

转换结果能不能直接用?

这份示例的初稿不能直接用,因为 deploy 会自动运行,分支限制也丢了。先按第 5 节改好这两处,再保存。

小结

把 .gitlab-ci.yml 贴进 导入 GitLab CI 再点 转换,得到的是一份需要人工核对的初稿,本例名为 imported-from-gitlab,其中 script、image、tags、variables、stages 分别转成了步骤、DOCKER 模式、标签、env 和 needs。以第 1 节为例,未映射的是 jobs.build.artifacts、两处 rules/only/except 和 jobs.deploy.when;注意清单则提醒 deploy 变成了 NATIVE,$CI_COMMIT_SHORT_SHA 变成了完整的 ${ { commitSha }}。最要紧的是,when: manual 不会变成手动 Job,only: [main] 也不会变成分支限制,不改的话部署会在其他分支上自动运行。所以要逐项核对、改完再创建流水线,并自己建好需要的凭证,因为导入不会新建凭证。

结论: 导入 GitLab CI 给出的只是转换后的初稿,保存前要处理未映射的 artifacts 和 when,把丢掉的 only: [main] 补成触发器上的 branches: [main],并记住 ${ { commitSha }} 拿到的是完整 SHA,不是短 SHA。

参考文章

相关文章
|
1天前
|
Java 开发工具 git
仓库能推之后:内置流水线 YAML 怎么写
代码推上 AngusGit 之后,想让每次推送都自动构建和测试,就要写一份 .anguscicd.yaml。从一份最小能跑的配置开始,可以弄清文件放在哪、Job 和步骤怎么写、触发器怎么配、令牌怎么安全引用,以及写错时会看到什么提示。
仓库能推之后:内置流水线 YAML 怎么写
|
1天前
|
jenkins 持续交付 开发工具
从 GitLab 迁到 AngusGit:迁移清单、双跑和回滚
团队从 GitLab 整体切到 AngusGit,难的不是推送几个仓库,而是切换那天谁都不丢代码、出了问题能退回去。按准备、首次同步、双跑、切换日、回滚五个阶段,给出每一步要做什么、怎么验收,以及分支保护为什么要放在最后一次同步之后再打开。
从 GitLab 迁到 AngusGit:迁移清单、双跑和回滚
|
2天前
|
开发工具 git
Issue 怎么关联合并请求:写上 Closes #编号,合并后自动关闭
在 AngusGit 里,问题和拉取请求可以连上:在拉取请求的标题或描述里写 Closes #编号,两边页面就互相列出对方,合并后问题自动关闭。文中列出可用的英文关键字、写在标题或描述才算数,以及没有自动关闭时怎么查。
|
16天前
|
缓存 资源调度 运维
npm 私服怎么搭:从安装到配源、scope 和 publish
私有化部署后接 npm:建 HOSTED/PROXY/GROUP,配 .npmrc 与 scope,用最小包跑通 publish/install,并处理 E401、E404、E409。
|
14天前
|
缓存 Java 数据库
AngusRepo 缓存架构设计与实践
制品仓库要同时保住权限、覆盖写和多进程一致。本文说明 AngusRepo 如何划分缓存层次、用版本号表达失效,以及单节点与多实例如何共用同一套模型。
AngusRepo 缓存架构设计与实践
|
16天前
|
供应链 安全 数据挖掘
制品入库怎么拦住漏洞和许可证问题
上传不等于扫过。对接 AngusSecurity 后由平台跑 SCA,Repo 负责策略触发与「未通过时拒绝下载」;给出集成步骤、能力对照、灰度验证与翻车表。
|
Java Maven Docker
一套制品库接入 28 种格式:Maven、Docker、npm、PyPI、Helm 实战指南
在同一套 AngusRepo 服务中,为 Maven、Docker、npm、PyPI 等 10 种格式完成认证、发布和拉取。
一套制品库接入 28 种格式:Maven、Docker、npm、PyPI、Helm 实战指南
|
1天前
|
Java 开发工具 git
导入 GitHub Actions 之后:事件、密钥和 Runner 还要对一遍
把 GitHub Actions 的 workflow 贴进「导入 GitHub Actions」之后,先对照未映射清单和注意清单,核对触发事件、密钥和运行器有没有变。示例转换后的初稿名叫 CI,runs-on 会变成 NATIVE,types 和 Job 超时都不会映射,核对完再创建流水线。
|
2天前
|
安全 Java 网络安全
怎么保护 Git 主分支:先开分支保护,再用合并请求合代码
在 AngusGit 给 main 加一条分支保护规则,禁止直接推送、强推和删除,改动必须经过拉取请求和至少一位评审通过才能合入。管理员豁免、需要最新分支等容易卡住的地方一并说明。
|
2天前
|
缓存 网络安全 开发工具
自建 Git 之后怎么推代码:配 SSH 或 HTTPS,完成第一次 push
AngusGit 装好之后,新建一个空仓库,选 SSH 公钥或访问令牌其中一种认证,把本地项目推上去。端口 2222、令牌当密码、首推被拒等常见报错一并说明。