从 Azure DevOps 迁移到 GitLab 的完整指南

本指南详细介绍了如何从 Azure DevOps 迁移到 GitLab,涵盖规划、执行及后续步骤。内容包括迁移源代码、流水线、工作项等资产,对比不同迁移工具,并提供实战示例与术语对照,助力企业实现平滑、高效的 DevSecOps 平台迁移。

指南:从 Azure DevOps 迁移到 GitLab

将工作从 Azure DevOps 迁移到 GitLab 看似是一项艰巨的任务,但采用正确的方法和工具,它可以成为一个顺畅高效的过程。本指南将引导您完成成功迁移项目、仓库和流水线所需的步骤。

概述

GitLab 提供 Congregate(由 GitLab 专业服务团队维护)和内置的 Git 仓库导入功能,用于从 Azure DevOps 迁移项目。这些选项支持逐个仓库或批量迁移,并保留 Git 提交历史、分支和标签。借助 Congregate 和专业服务工具,我们还支持额外的资产,如 Wiki、工作项、CI/CD 变量、容器镜像、软件包、流水线等(参见功能矩阵)。使用本指南来规划和执行您的迁移,并完成迁移后的后续任务。

从 ADO 迁移到 GitLab 的企业通常遵循多阶段方法:

  1. 使用 Congregate 或 GitLab 的内置仓库迁移功能将仓库从 ADO 迁移到 GitLab。
  2. 将流水线从 Azure Pipelines 迁移到 GitLab CI/CD。

高层级迁移阶段:

  • 迁移阶段:迁移源代码 | 保持贡献和历史格式 | 迁移工作项并映射到 GitLab | 计划和跟踪工作
  • 先决条件:设置身份提供商 (IdP) 并供应用户 | 设置运行器和第三方集成 | 用户赋能和变更管理
  • 迁移后步骤:创建或转换 ADO 流水线到 GitLab CI | 迁移其他资产(如包和容器镜像)| 引入安全性和 SDLC 改进

规划您的迁移

要规划迁移,请思考以下问题:

  • 我们需要多快完成迁移?
  • 我们是否了解需要迁移哪些内容?
  • 谁来执行迁移?
  • 我们在 GitLab 中想要什么样的组织结构?
  • 是否有任何需要考量的约束、限制或陷阱?

确定您的时间表,因为它将在很大程度上决定您的迁移方法。确定熟悉 ADO 和 GitLab 平台的负责人或团队(例如早期采用者),以帮助推动采用并提供指导。

清点您需要迁移的内容:

  • 仓库、拉取请求和贡献者的数量
  • 工作项和流水线的数量及复杂程度
  • 仓库大小和依赖关系
  • 关键集成和运行器要求(具有特定功能的代理池)

使用 GitLab 专业服务的评估工具来生成整个 Azure DevOps 组织的完整清单,包括仓库、PR 数量、贡献者列表、流水线数量、工作项、CI/CD 变量等。如果您正在与 GitLab 专业服务团队合作,请将此报告分享给您的参与经理或技术架构师,以帮助规划迁移。

迁移时间主要受拉取请求数量、仓库大小和贡献量(例如 PR 中的评论、工作项等)的影响。例如,1000 个 PR 很少、贡献者有限的小型仓库可以比包含数万个 PR 和数千名贡献者的较少数量的仓库迁移得快得多。使用您的库存数据来估计工作量,并在进行生产迁移之前规划试运行。

将清单与您的期望时间线进行比较,并决定是一次性迁移所有仓库还是分批迁移。如果团队无法同时迁移,请进行分批和错峰迁移以配合团队时间表。例如,在专业服务项目中,我们将迁移组织成 200-300 个项目为一波,以管理复杂性并遵守 GitLab 和 ADO 的 API 速率限制。

GitLab 的内置仓库导入器逐个迁移 Git 仓库(提交、分支和标签)。Congregate 旨在尽可能保留拉取请求(在 GitLab 中称为合并请求)、评论和相关元数据;而简单的内置仓库导入仅专注于 Git 数据(历史记录、分支和标签)。

通常需要单独迁移或手动重新创建的项:

  • Azure Pipelines - 创建等效的 GitLab CI/CD 流水线(可参考 CI/CD YAML 和/或 CI/CD 组件)。或者,考虑使用 Congregate 中提供的基于 AI 的流水线转换。

  • 制品、容器镜像 (ACR) - 迁移到 GitLab Package Registry 或 Container Registry。

  • 服务钩子和外部集成 - 在 GitLab 中重新创建。

  • ADO 和 GitLab 的权限模型不同;请审查并规划权限映射,而不是假设精确保留。

审查每种工具(Congregate 与内置导入)将迁移的内容,并选择适合您需求的工具。列出任何必须手动迁移或重新创建的数据或集成。

谁来运行迁移?

迁移通常由 GitLab 组所有者或实例管理员运行,或者由被授予目标组/项目必要权限的指定迁移人员运行。Congregate 和 GitLab 导入 API 都需要 Azure DevOps 和 GitLab 的有效身份验证令牌。

  • 决定是由组所有者/管理员执行迁移,还是授予特定团队/人员委派的访问权限。
  • 确保迁移人员已正确配置具有所选迁移工具所需范围(例如,api/read_repository 范围以及任何工具特定要求)的个人访问令牌(Azure DevOps 和 GitLab)。
  • 使用小型试点迁移测试令牌和权限。
  • 注意:Congregate 利用基于文件的导入功能进行 ADO 迁移,并且需要实例管理员权限才能运行(请参阅我们的文档)。如果您要迁移到 GitLab.com,请考虑联系专业服务。有关更多信息,请参阅专业服务完整目录。非管理员帐户无法保留贡献归属!

我们在 GitLab 中想要什么样的组织结构?

虽然可以将 ADO 结构直接映射到 GitLab 结构,但建议在迁移过程中进行合理化并简化结构。考虑团队将如何在 GitLab 中工作,并设计结构以促进协作和访问管理。

以下是将 ADO 结构映射到 GitLab 结构的一种思路:

  • Azure DevOps 组织 -> GitLab 顶级群组
  • Azure DevOps 项目 -> GitLab 子组(可选)
  • Azure DevOps 仓库 -> GitLab 项目

推荐方法:

  • 将每个 ADO 组织映射到一个 GitLab 组(或一小部分组),而不是映射到许多小群组。避免为每个 ADO 团队项目创建 GitLab 组。利用迁移作为机会来合理化您的 GitLab 结构。
  • 使用子组和项目级权限对相关仓库进行分组。
  • 通过使用 GitLab 群组和组成员资格(群组和子群组)来管理对项目集的访问,而不是为每个团队项目使用一个群组。
  • 审查 GitLab 权限,并考虑使用 SAML 群组链接为您的 GitLab 实例(或 GitLab.com 命名空间)实现企业 RBAC 模型。

ADO 看板和工作项:迁移状态

了解工作项如何从 ADO 迁移到 GitLab Plan(议题、史诗和看板)非常重要。

  • ADO 史诗和功能变为 GitLab Epics。

  • 大多数标准字段会被保留;当受支持时,选定的自定义字段可以迁移。

  • 到拉取请求的链接转换为合并请求链接,以保持开发可追溯性。

分批指导:

  • 如果您需要分批运行迁移,请使用新的群组/子组结构来定义批次(例如,按 ADO 组织或产品领域)。
  • 使用库存报告来驱动批次选择,并在扩展之前通过试点迁移测试每个批次。

流水线迁移

Congregate 最近引入了将多阶段 YAML 流水线从 Azure DevOps 转换为 GitLab CI/CD 的 AI 驱动转换。这种自动转换最适合简单、单文件的流水线,旨在提供一个可用的起点,而不是一个生产就绪的 .gitlab-ci.yml 文件。该工具会生成功能上等效的 GitLab 流水线,然后您可以根据特定需求进行细化和优化。

  • 自动将 Azure Pipelines YAML 转换为 .gitlab-ci.yml 格式。
  • 最适合简单直接的、单文件的流水线配置。
  • 提供一个加速迁移的模板,而不是最终的生产产物。
  • 对于复杂场景、自定义任务或企业需求,需要进行审查和调整。
  • 不支持 Azure DevOps 经典发布流水线——请先将这些转换为多阶段 YAML。
  • 仓库所有者应在初始转换后,查阅 GitLab CI/CD 文档以进一步优化和增强其流水线。

转换后的流水线示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# azure-pipelines.yml
trigger:
  - main
variables:
  imageName: myapp
stages:
  - stage: Build
    jobs:
      - job: Build
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - checkout: self
          - task: Docker@2
            displayName: Build Docker image
            inputs:
              command: build
              repository: $(imageName)
              Dockerfile: '**/Dockerfile'
              tags: |
                $(Build.BuildId)
  - stage: Test
    jobs:
      - job: Test
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - checkout: self
          # 示例:在容器内运行测试
          - script: |
              docker run --rm $(imageName):$(Build.BuildId) npm test
            displayName: Run tests
  - stage: Push
    jobs:
      - job: Push
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - checkout: self
          - task: Docker@2
            displayName: Login to ACR
            inputs:
              command: login
              containerRegistry: '<your-acr-service-connection>'
          - task: Docker@2
            displayName: Push image to ACR
            inputs:
              command: push
              repository: $(imageName)
              tags: |
                $(Build.BuildId)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# .gitlab-ci.yml
variables:
  imageName: myapp
stages:
  - build
  - test
  - push
build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $imageName:$CI_PIPELINE_ID -f $(find . -name Dockerfile) .
  only:
    - main
test:
  stage: test
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker run --rm $imageName:$CI_PIPELINE_ID npm test
  only:
    - main
push:
  stage: push
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker tag $imageName:$CI_PIPELINE_ID $CI_REGISTRY/$CI_PROJECT_PATH/$imageName:$CI_PIPELINE_ID
    - docker push $CI_REGISTRY/$CI_PROJECT_PATH/$imageName:$CI_PIPELINE_ID
  only:
    - main

最终清单

  • 决定时间线和分批策略。
  • 生成仓库、PR 和贡献者的完整清单。
  • 根据范围(PR 和元数据 vs. 仅 Git 数据)选择 Congregate 或内置导入。
  • 决定谁将运行迁移,并确保令牌/权限已配置。
  • 确定必须单独迁移的资产(流水线、工作项、制品和钩子),并规划这些工作。
  • 运行试点迁移,验证结果,然后根据您的计划进行扩展。

运行迁移

在规划之后,分阶段执行迁移,从试运行开始。试运行有助于尽早发现组织特有的问题,并让您在投入生产前测量持续时间、验证结果并微调方法。

试运行验证内容

  • 给定的仓库和相关资产是否迁移成功(历史记录、分支、标签;如果使用 Congregate,还包括 MR/评论)
  • 目标是否立即可用(权限、运行器、CI/CD 变量、集成)
  • 每个批次所需的时间,以便设定时间表和利益相关者的期望

停机指导

  • GitLab 的内置 Git 导入和 Congregate 本质上不需要停机。
  • 对于生产批次,在 ADO 中冻结更改(分支保护或只读),以避免在迁移过程中错过提交、PR 更新或创建的工作项。
  • 试运行不需要冻结,可以随时运行。

分批指导

  • 连续运行试运行批次以缩短总用时;让团队异步验证结果。
  • 使用您规划的群组/子群组结构来定义批次,并遵守 API 速率限制。

推荐步骤

  1. 为试运行在 GitLab 中创建一个测试目的地:
    • GitLab.com:创建一个专用的群组/命名空间(例如,my-org-sandbox
    • 自托管:创建一个顶级群组,如果需要,可以使用单独的测试实例
  2. 准备身份验证:
    • 具有所需范围的 Azure DevOps PAT。
    • 具有 apiread_repository 范围的 GitLab 个人访问令牌(Congregate 使用的基于文件的导入还需要管理员访问权限)。
  3. 运行试迁移:
    • 仅仓库:使用 GitLab 的内置导入(Repo by URL)
    • 仓库 + PR/MR 及其他资产:使用 Congregate
  4. 试运行后跟进:
    • 验证仓库历史记录、分支、标签;合并请求(如果已迁移)、议题/史诗(如果已迁移)、标签和关系。
    • 检查权限/角色、受保护分支、所需批准、运行器/标签、变量/密钥、集成/Webhook。
    • 验证流水线(.gitlab-ci.yml)或转换后的流水线(如果适用)。
  5. 请用户验证功能性和数据保真度。
  6. 解决试运行中发现的问题并更新您的操作手册。
  7. 网络和安全性:
    • 如果您的目标使用 IP 允许列表,请添加迁移主机和任何必需运行器/集成的 IP 地址,以便导入能够成功。
  8. 分批运行生产迁移:
    • 在每个批次期间,在 ADO 中强制执行更改冻结。
    • 监控进度和日志;如果遇到速率限制,请重试或调整批次大小。
  9. 可选:完成后删除沙盒群组或将其归档。

GitLab 和 Azure DevOps 术语对照表

GitLab Azure DevOps 相似之处与主要差异
群组 组织 顶级命名空间、成员资格、策略。ADO 组织包含项目;GitLab 群组包含子群组和项目。
群组或子群组 项目 逻辑容器、权限边界。ADO 项目包含许多仓库;GitLab 群组/子群组组织许多项目。
项目 (包含一个 Git 仓库) 仓库 (在一个项目内) Git 历史记录、分支、标签。在 GitLab 中,“项目”是仓库加上议题、CI/CD、Wiki 等。一个项目对应一个仓库。
合并请求 (MR) 拉取请求 (PR) 代码审查、讨论、批准。MR 规则包括批准、必需的流水线、代码所有者。
受保护分支、MR 批准规则、状态检查 分支策略 强制执行审查和检查。GitLab 结合了分支保护 + 批准规则 + 必需的状态检查。
GitLab CI/CD Azure Pipelines YAML 流水线、阶段/作业、日志。ADO 还有经典的 UI 流水线;GitLab 以 .gitlab-ci.yml 为中心。
.gitlab-ci.yml azure-pipelines.yml 定义阶段/作业/触发器。语法/功能不同;需要映射作业、变量、制品和触发器。
运行器 (共享/特定) 代理 / 代理池 在机器/容器上执行作业。通过需求 (ADO) 与标签 (GitLab) 来定位。注册/范围不同。
CI/CD 变量 (项目/群组/实例)、受保护/屏蔽 流水线变量、变量组、库 将配置/密钥传递给作业。GitLab 支持群组继承和屏蔽/保护标志。
集成、CI/CD 变量、部署密钥 服务连接 到服务/云的外部身份验证。映射到集成或变量;云特定助手可用。
环境和部署 (受保护环境) 环境 (带批准) 跟踪部署目标/历史。在 GitLab 中通过受保护环境和手动作业进行批准。
发布 (标签 + 注释) 发布 (经典或流水线) 版本化的注释/制品。GitLab Release 与标签关联;部署单独跟踪。
作业制品 流水线制品 持久化作业输出。每个作业或项目可配置保留/过期时间。
包注册中心 (NuGet/npm/Maven/PyPI/Composer 等) Azure Artifacts (NuGet/npm/Maven 等) 包托管。身份验证/命名空间不同;按包类型迁移。
GitLab 容器注册中心 Azure 容器注册中心 (ACR) 或其他 OCI 镜像。GitLab 提供每个项目/群组的注册中心。
议题看板 看板 按列可视化工作。GitLab 看板由标签驱动;每个项目/群组可以有多个看板。
议题 (类型/标签)、史诗 工作项 (用户故事/Bug/任务) 跟踪工作单元。将 ADO 类型/字段映射到标签/自定义字段;史诗在群组级别。
史诗、父子议题 史诗/功能 工作的层次结构。架构不同;使用史诗 + 议题关系。
里程碑和迭代 迭代路径 时间盒。GitLab 迭代(群组功能)或每个项目/群组的里程碑。
标签 (范围标签) 区域路径 分类/所有权。用范围标签替换分层区域。
项目/群组 Wiki 项目 Wiki Markdown wiki。两者均基于仓库;布局/身份验证略有不同。
通过 CI 生成的测试报告、需求/测试管理、集成 测试计划/案例/运行 QA 证据/可追溯性。与 ADO 测试计划没有 1:1 对应关系;通常使用 CI 报告 + 议题/需求。
角色 (所有者/维护者/开发者/报告者/访客) + 自定义角色 访问级别 + 细粒度权限 控制读/写/管理。模型不同;利用群组继承和受保护资源。
Webhook 服务钩子 事件驱动的集成。事件名称/载荷不同;需要重新配置端点。
高级搜索 代码搜索 全文仓库搜索。自托管 GitLab 可能需要 Elasticsearch/OpenSearch 来获得高级功能。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计