生成 GitHub 存储库

Azure DevOps Services

Azure Pipelines 可以自动生成并验证每个拉取请求,并提交到 GitHub 存储库。 本文介绍如何配置 GitHub 与 Azure Pipelines 之间的集成。

如果你不熟悉管道与 GitHub 的集成,请按照创建第一个管道中的步骤进行操作。 返回到本文,详细了解如何配置和自定义 GitHub 与 Azure Pipelines 之间的集成。

组织和用户

GitHub 和 Azure Pipelines 是两个独立的服务,可以很好地集成在一起。 两者都有自己的组织和用户管理。 本部分提供有关如何将组织和用户从 GitHub 复制到 Azure Pipelines 的建议。

组织

GitHub 的结构由包含存储库的组织和用户帐户组成。 请参阅 GitHub 的文档

GitHub organization structureGitHub 组织结构

Azure DevOps 的结构由包含项目组织组成。 请参阅规划组织结构

Azure DevOps organization structureAzure DevOps 组织结构

Azure DevOps 可以通过以下方式反映 GitHub 结构:

  • GitHub 组织或用户帐户的 DevOps 组织
  • GitHub 存储库的 DevOps 项目

GitHub structure mapped to Azure DevOps映射到 Azure DevOps 的 GitHub 结构

若要在 Azure DevOps 中设置相同的结构,请执行以下操作:

  1. 创建以 GitHub 组织或用户帐户命名的 DevOps 组织。 其 URL 类似于 https://dev.azure.com/your-organization
  2. 在 DevOps 组织中,创建以存储库命名的项目。 其 URL 类似于 https://dev.azure.com/your-organization/your-repository
  3. 在 DevOps 项目中,创建以 GitHub 组织及其生成的存储库命名的管道,例如 your-organization.your-repository。 然后,可以明确它们适用于哪些存储库。

按照此模式,GitHub 存储库和 Azure DevOps Projects 将具有匹配的 URL 路径。 例如:

服务 URL
GitHub https://github.com/python/cpython
Azure DevOps https://dev.azure.com/python/cpython

用户

GitHub 用户不会自动获取对 Azure Pipelines 的访问权限。 Azure Pipelines 不知道 GitHub 身份。 因此,无法将 Azure Pipelines 配置为使用其 GitHub 身份和电子邮件地址自动通知用户生成失败或 PR 验证失败。 必须在 Azure Pipelines 中显式创建新用户才能复制 GitHub 用户。 创建新用户后,可以在 Azure DevOps 中为其配置权限,以反映其在 GitHub 中的权限。 还可以使用其 DevOps 身份在 DevOps 中配置通知。

GitHub 组织角色

https://github.com/orgs/your-organization/people 处找到 GitHub 组织成员角色(替换 your-organization)。

https://dev.azure.com/your-organization/_settings/security 处找到 DevOps 组织成员权限(替换 your-organization)。

下面显示了 GitHub 组织中的角色和 Azure DevOps 组织中的等效角色。

GitHub 组织角色 DevOps 组织等效角色
所有者 Project Collection Administrators 的成员
账单管理员 Project Collection Administrators 的成员
成员 Project Collection Valid Users 的成员。 默认情况下,成员组缺少创建新项目的权限。 若要更改权限,请将组的 Create new projects 权限设置为 Allow,或者创建具有所需权限的新组。

GitHub 用户帐户角色

GitHub 用户帐户有一个角色,即帐户的所有权。

https://dev.azure.com/your-organization/_settings/security 处找到 DevOps 组织成员权限(替换 your-organization)。

GitHub 用户帐户角色映射到 DevOps 组织权限,如下所示。

GitHub 用户帐户角色 DevOps 组织等效角色
所有者 Project Collection Administrators 的成员

GitHub 存储库权限

https://github.com/your-organization/your-repository/settings/collaboration 处找到 GitHub 存储库权限(替换 your-organizationyour-repository)。

https://dev.azure.com/your-organization/your-project/_settings/security 处找到 DevOps 项目权限(替换 your-organizationyour-project)。

GitHub 存储库与 Azure DevOps Projects 之间的等效权限如下所示。

GitHub 存储库权限 DevOps 项目等效权限
管理员 Project Collection Administrators 的成员
写入 Project Collection Administrators 的成员
读取 Project Collection Administrators 的成员

如果 GitHub 存储库向团队授予权限,则可以在 Azure DevOps 项目设置的 Teams 部分中创建匹配的团队。 然后,将团队添加到上述安全组,就像用户一样。

特定于管道的权限

若要向用户或团队授予针对 DevOps 项目中特定管道的权限,请执行以下步骤:

  1. 访问项目的“管道”页(例如,https://dev.azure.com/your-organization/your-project/_build)。
  2. 选择要设置特定权限的管道。
  3. 从“...”上下文菜单中,选择“安全性”。
  4. 选择“添加...”以添加特定用户、团队或组并自定义其管道权限。

访问 GitHub 存储库

首先选择 GitHub 存储库,然后在该存储库中选择一个 YAML 文件来创建新管道。 YAML 文件所在的存储库称为 self 存储库。 默认情况下,这是管道生成的存储库。

稍后可以将管道配置为签出不同的存储库或多个存储库。 若要了解如何执行此操作,请参阅多存储库签出

必须向 Azure Pipelines 授予对存储库的访问权限,才能触发其生成并在生成期间提取其代码。

创建管道时,有三种身份验证类型用于授予 Azure Pipelines 对 GitHub 存储库的访问权限。

身份验证类型 管道运行使用的身份 使用 GitHub 检查
1. GitHub 应用 Azure Pipelines 身份
2. OAuth 个人 GitHub 身份
3. 个人访问令牌 (PAT) 个人 GitHub 身份

GitHub 应用身份验证

对于持续集成管道,Azure Pipelines GitHub 应用是建议的身份验证类型。 在 GitHub 帐户或组织中安装 GitHub 应用后,管道将在不使用个人 GitHub 身份的情况下运行。 将使用 Azure Pipelines 身份执行生成和 GitHub 状态更新。 该应用使用 GitHub 检查在 GitHub 中显示生成、测试和代码覆盖率结果。

若要使用 GitHub 应用,请将其安装在 GitHub 组织或者用户帐户中的部分或所有存储库。 可以从应用的主页安装和卸载 GitHub 应用。

安装后,当为存储库创建管道时,GitHub 应用将成为 Azure Pipelines 向 GitHub 进行身份验证的默认方法(而不是 OAuth)。

如果为 GitHub 组织中的所有存储库安装 GitHub 应用,则无需担心 Azure Pipelines 会发送大量电子邮件或代表你自动设置管道。 但是,如果为所有存储库安装了应用,则应用程序使用的令牌将有权访问所有存储库,包括专用存储库。 出于安全原因,建议在组织级别分隔专用和公共存储库。 这意味着仅对没有专用存储库的公共项目拥有专用组织。 如果出于某种原因,需要在同一组织中拥有公共和专用存储库,而不是对所有存储库使用访问权限,而是显式选择应用程序应有权访问的存储库。 这需要更多管理员的工作,但可确保更好的安全管理。

GitHub 中所需的权限

安装 Azure Pipelines GitHub 应用需要你成为 GitHub 组织所有者或存储库管理员。此外,若要为具有持续集成和拉取请求触发器的 GitHub 存储库创建管道,必须配置所需的 GitHub 权限。 否则,创建管道时,存储库将不会显示在存储库列表中。 根据存储库的身份验证类型和所有权,确保配置了适当的访问权限。

  • 如果存储库位于个人 GitHub 帐户中,请在个人 GitHub 帐户中安装 Azure Pipelines GitHub 应用,在 Azure Pipelines 中创建管道时,你将能够列出此存储库。

  • 如果存储库位于其他人的个人 GitHub 帐户中,则其他人必须在其个人 GitHub 帐户中安装 Azure Pipelines GitHub 应用。 必须在存储库设置的“协作者”下将你添加为协作者。 使用通过电子邮件发送给你的链接接受邀请,成为协作者。 完成此操作后,可以为该存储库创建管道。

  • 如果存储库位于你拥有的 GitHub 组织中,请在 GitHub 组织中安装 Azure Pipelines GitHub 应用。 还必须在存储库设置的“协作者和团队”下将你添加为协作者,或者必须添加你的团队。

  • 如果存储库位于其他人拥有的 GitHub 组织中,则 GitHub 组织所有者或存储库管理员必须在组织中安装 Azure Pipelines GitHub 应用。 必须在存储库设置的“协作者和团队”下将你添加为协作者,或者必须添加你的团队。 使用通过电子邮件发送给你的链接接受邀请,成为协作者。

GitHub 应用程序权限

GitHub 应用在安装期间请求会以下权限:

权限 Azure Pipelines 如何使用权限
对代码的写入访问权限 只有在你深思熟虑的情况下,Azure Pipelines 才会通过将 YAML 文件提交到 GitHub 存储库的选定分支来简化管道的创建。
对元数据的读取访问权限 Azure Pipelines 将检索 GitHub 元数据,以在生成的摘要中显示与生成关联的存储库、分支和问题。
对检查的读写访问权限 Azure Pipelines 将读取和写入自己的生成、测试和代码覆盖率结果,这些结果将显示在 GitHub 中。
对拉取请求的读写访问权限 只有在你深思熟虑的情况下,Azure Pipelines 才会通过为提交到 GitHub 存储库选定分支的 YAML 文件创建拉取请求来简化管道的创建。 管道将会检索要在与拉取请求关联的生成摘要中显示的请求元数据。

GitHub 应用安装疑难解答

GitHub 可能会显示如下错误:

You do not have permission to modify this app on your-organization. Please contact an Organization Owner.

这意味着可能已为组织安装了 GitHub 应用。 为组织中的存储库创建管道时,GitHub 应用将自动用于连接到 GitHub。

在多个 Azure DevOps 组织和项目中创建管道

安装 GitHub 应用后,可以在不同的 Azure DevOps 组织和项目中为组织的存储库创建管道。 但是,如果在多个 Azure DevOps 组织中为单个存储库创建管道,GitHub 提交或拉取请求只能自动触发第一个组织的管道。 在辅助 Azure DevOps 组织中,仍可以完成手动或计划生成。

OAuth 身份验证

对于个人 GitHub 帐户中的存储库,OAuth 是最简单的入门身份验证类型。 将代表个人 GitHub 身份执行 GitHub 状态更新。 若要使管道正常工作,存储库访问必须保持活动状态。 某些 GitHub 功能(如检查)不适用于 OAuth,需要 GitHub 应用。

若要使用 OAuth,请在创建管道时选择存储库列表下的“选择其他连接”。 然后,选择“授权”以登录到 GitHub 并通过 OAuth 授权。 OAuth 连接将保存在 Azure DevOps 项目中供以后使用,并在创建的管道中使用。

GitHub 中所需的权限

若要为具有持续集成和拉取请求触发器的 GitHub 存储库创建管道,必须配置所需的 GitHub 权限。 否则,创建管道时,存储库将不会显示在存储库列表中。 根据存储库的身份验证类型和所有权,确保配置了适当的访问权限。

  • 如果存储库位于个人 GitHub 帐户中,则使用个人 GitHub 帐户凭据通过 OAuth 向 GitHub 进行至少一次身份验证。 这可以在 Azure DevOps 项目设置中的“管道”>“服务连接”>“新建服务连接”>“GitHub”>“授权”下完成。 在此处的“权限”下向 Azure Pipelines 授予对你存储库的访问权限。

  • 如果存储库位于其他人的个人 GitHub 帐户中,则其他人必须使用其个人 GitHub 帐户凭据通过 OAuth 向 GitHub 进行至少一次身份验证。 这可以在 Azure DevOps 项目设置中的“管道”>“服务连接”>“新建服务连接”>“GitHub”>“授权”下完成。 其他人必须在此处的“权限”下向 Azure Pipelines 授予对其存储库的访问权限。 必须在存储库设置的“协作者”下将你添加为协作者。 使用通过电子邮件发送给你的链接接受邀请,成为协作者。

  • 如果存储库位于你拥有的 GitHub 组织中,则使用个人 GitHub 帐户凭据通过 OAuth 向 GitHub 进行至少一次身份验证。 这可以在 Azure DevOps 项目设置中的“管道”>“服务连接”>“新建服务连接”>“GitHub”>“授权”下完成。 在此处的“组织访问权限”下向 Azure Pipelines 授予对你组织的访问权限。 必须在存储库设置的“协作者和团队”下将你添加为协作者,或者必须添加你的团队。

  • 如果存储库位于其他人拥有的 GitHub 组织中,则 GitHub 组织所有者必须使用其个人 GitHub 帐户凭据通过 OAuth 向 GitHub 进行至少一次身份验证。 这可以在 Azure DevOps 项目设置中的“管道”>“服务连接”>“新建服务连接”>“GitHub”>“授权”下完成。 组织所有者必须在此处的“组织访问权限”下向 Azure Pipelines 授予对组织的访问权限。 必须在存储库设置的“协作者和团队”下将你添加为协作者,或者必须添加你的团队。 使用通过电子邮件发送给你的链接接受邀请,成为协作者。

撤消 OAuth 访问权限

授权 Azure Pipelines 使用 OAuth 后,若要稍后撤消授权并阻止进一步使用,请访问 GitHub 设置中的 OAuth 应用。 还可以从 Azure DevOps 项目设置中的 GitHub 服务连接列表中将其删除。

个人访问令牌 (PAT) 身份验证

PAT 实际上与 OAuth 相同,但其允许你控制向 Azure Pipelines 授予哪些权限。 将代表你的个人 GitHub 身份执行生成和 GitHub 状态更新。 若要使生成正常工作,你的存储库访问必须保持活动状态。

若要创建 PAT,请访问 GitHub 设置中的个人访问令牌。 必需的权限包括 repoadmin:repo_hookread:useruser:email。 这些权限与使用上述 OAuth 时所需的权限相同。 将生成的 PAT 复制到剪贴板,并将其粘贴到 Azure DevOps 项目设置的新 GitHub 服务连接中。 为了便于将来召回,请以你的 GitHub 用户名命名服务连接。 它将在 Azure DevOps 项目中提供,供以后在创建管道时使用。

GitHub 中所需的权限

若要为具有持续集成和拉取请求触发器的 GitHub 存储库创建管道,必须配置所需的 GitHub 权限。 否则,创建管道时,存储库将不会显示在存储库列表中。 根据存储库的身份验证类型和所有权,确保配置了以下访问权限。

  • 如果存储库位于个人 GitHub 帐户中,PAT 必须在个人访问令牌下具有所需的访问范围:repoadmin:repo_hookread:useruser:email

  • 如果存储库位于其他人的个人 GitHub 帐户中,PAT 必须在个人访问令牌下具有所需的访问范围:repoadmin:repo_hookread:useruser:email。 必须在存储库设置的“协作者”下将你添加为协作者。 使用通过电子邮件发送给你的链接接受邀请,成为协作者。

  • 如果存储库位于你拥有的 GitHub 组织中,PAT 必须在个人访问令牌下具有所需的访问范围:repoadmin:repo_hookread:useruser:email。 必须在存储库设置的“协作者和团队”下将你添加为协作者,或者必须添加你的团队。

  • 如果存储库位于其他人拥有的 GitHub 组织中,PAT 必须在个人访问令牌下具有所需的访问范围:repoadmin:repo_hookread:useruser:email。 必须在存储库设置的“协作者和团队”下将你添加为协作者,或者必须添加你的团队。 使用通过电子邮件发送给你的链接接受邀请,成为协作者。

撤消 PAT 访问权限

授权 Azure Pipelines 使用 PAT 后,若要稍后将其删除并阻止进一步使用,请访问 GitHub 设置中的个人访问令牌。 还可以从 Azure DevOps 项目设置中的 GitHub 服务连接列表中将其删除。

CI 触发器

持续集成 (CI) 触发器会导致管道在将更新推送到指定分支或推送指定的标记时运行。

默认情况下,所有分支上的 YAML 管道都会配置 CI 触发器,除非 Azure DevOps sprint 227 中的“禁用默示的 YAML CI 触发器”已启用。 可以在组织级别或项目级别配置“禁用默示的 YAML CI 触发器”设置。 启用“禁用默示的 YAML CI 触发器”设置后,如果 YAML 管道没有 trigger 部分,则不会启用 YAML 管道的 CI 触发器。 默认情况下,不用启用“禁用默示的 YAML CI 触发器”

分支

可以使用简单的语法控制哪些分支获取 CI 触发器:

trigger:
- main
- releases/*

可以指定分支的全名(例如 main)或通配符(例如 releases/*)。 有关通配符语法的信息,请参阅通配符

注意

不能在触发器中使用变量,因为变量是在运行时评估的(在触发器触发后)。

注意

如果使用模板创作 YAML 文件,则只能在管道的主 YAML 文件中指定触发器。 不能在模板文件中指定触发器。

对于使用 excludebatch 的更复杂的触发器,必须使用完整的语法,如以下示例所示。

# specific branch build
trigger:
  branches:
    include:
    - main
    - releases/*
    exclude:
    - releases/old*

在上面的示例中,如果将更改推送到 main 或推送到任何版本分支,将触发管道。 但是,如果对以 old 开头的版本分支进行更改,则不会触发管道。

如果指定 exclude 子句而不包含 include 子句,则等同于在 include 子句中指定 *

除了在 branches 列表中指定分支名称外,还可以使用以下格式基于标记配置触发器:

trigger:
  branches:
    include:
      - refs/tags/{tagname}
    exclude:
      - refs/tags/{othertagname}

如果未指定任何触发器,并且未启用“禁用默示的 YAML CI 触发器”设置,则默认情况会与你编写以下内容时相同:

trigger:
  branches:
    include:
    - '*'  # must quote since "*" is a YAML reserved character; we want a string

重要

指定触发器时,它将替换默认的隐式触发器,并且只有推送到显式配置为包含的分支才会触发管道。 首先处理包含项,然后从该列表中删除排除项。

批处理 CI 运行

如果有许多团队成员经常上传更改,则可能需要减少启动的运行次数。 如果将 batch 设置为 true,则当管道运行时,系统将等待运行完成,然后启动另一个运行,其中包含尚未生成的所有更改。

# specific branch build with batching
trigger:
  batch: true
  branches:
    include:
    - main

注意

存储库资源触发器不支持 batch

为了阐明此示例,我们假设对 main 的推送 A 导致上述管道运行。 当该管道正在运行时,会向存储库进行额外的推送 BC。 这些更新不会立即启动新的独立运行。 但是,在完成第一次运行后,在该时间点之前的所有推送将一起进行批处理,然后启动新的运行。

注意

如果管道有多个作业和阶段,则通过完成或跳过其所有作业和阶段,第一次运行仍应达到终端状态,然后才能启动第二次运行。 因此,在具有多个阶段或审批的管道中使用此功能时,必须小心谨慎。 如果希望在这种情况下批处理生成,建议将 CI/CD 进程拆分为两个管道 - 一个用于生成(批处理),一个用于部署。

路径

可以指定要包含或排除的文件路径。

# specific path build
trigger:
  branches:
    include:
    - main
    - releases/*
  paths:
    include:
    - docs
    exclude:
    - docs/README.md

指定路径时,如果使用的是 Azure DevOps Server 2019.1 或更低版本,则必须显式指定要触发的分支。 不能触发只有路径筛选器的管道;还必须具有分支筛选器,并且与路径筛选器匹配的已更改文件必须来自与分支筛选器匹配的分支。 如果使用的是 Azure DevOps Server 2020 或更高版本,则可以省略 branches 以结合路径筛选器筛选所有分支。

路径筛选器支持通配符。 例如,可以包含与 src/app/**/myapp* 匹配的所有路径。 指定路径筛选器时,可以使用通配符(***?))。

  • 指定的路径务必是存储库根目录的相对路径。
  • 如果未设置路径筛选器,则默认会隐式包含存储库的根文件夹。
  • 如果排除某个路径,则不能同时包含该路径,除非将其限定为更深一级的文件夹。 例如,如果排除 /tools,则可以包含 /tools/trigger-runs-on-these
  • 路径筛选器的顺序无关紧要。
  • Git 中的路径区分大小写。 请确保使用与真实文件夹相同的大小写。
  • 不能在路径中使用变量,因为变量是在运行时评估的(在触发器触发后)。

Tags

除了按上一部分所述在 branches 列表中指定标记外,还可以直接指定要包含或排除的标记:

# specific tag
trigger:
  tags:
    include:
    - v2.*
    exclude:
    - v2.0

如果未指定任何标记触发器,则默认情况下,标记不会触发管道。

重要

如果结合分支筛选器指定标记,则满足分支筛选器或满足标记筛选器时将触发触发器。 例如,如果推送的标记满足分支筛选器,即使标记筛选器排除了该标记,管道也会触发,因为推送满足分支筛选器。

选择退出 CI

禁用 CI 触发器

可以通过指定 trigger: none 选择完全退出 CI 触发器。

# A pipeline with no CI trigger
trigger: none

重要

将更改推送到分支时,将评估该分支中的 YAML 文件,以确定是否应启动 CI 运行。

跳过单个提交的 CI

还可以告诉 Azure Pipelines 跳过运行推送通常会触发的管道。 仅在消息或属于推送的任何提交的描述中包括 [skip ci],并且 Azure Pipelines 将跳过运行此推送的 CI。 你也可以使用以下任意变体。

  • [skip ci][ci skip]
  • [skip ci][ci skip]
  • [skip ci][ci skip]
  • [skip ci][ci skip]
  • [skip ci][ci skip]
  • ***NO_CI***

在条件中使用触发器类型

常见方案是在管道中运行不同的步骤、作业或阶段,具体取决于启动运行的触发器类型。 可以使用系统变量 Build.Reason 执行此操作。 例如,将以下条件添加到步骤、作业或阶段,以将其从 PR 验证中排除。

condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))

创建新分支时的触发器行为

为同一存储库配置多个管道很常见。 例如,你可能有一个管道用于生成应用的文档,另一个管道用于生成源代码。 可以在其中每个管道中使用适当的分支筛选器和路径筛选器配置 CI 触发器。 例如,你可能希望在将更新推送到 docs 文件夹时触发一个管道,在将更新推送到应用程序代码时触发另一个管道。 在这些情况下,需要了解创建新分支时如何触发管道。

下面是将新分支(与分支筛选器匹配)推送到存储库时的行为:

  • 如果管道具有路径筛选器,则仅当新分支更改了与该路径筛选器匹配的文件时,才会触发该管道。
  • 如果管道没有路径筛选器,则即使新分支中没有更改,也会触发该管道。

通配符

指定分支、标记或路径时,可以使用确切的名称或通配符。 通配符模式允许 * 匹配零个或多个字符并允许 ? 匹配单个字符。

  • 如果在 YAML 管道中使用 * 启动模式,则必须用引号将模式括起来,例如 "*-releases"
  • 对于分支和标记:
    • 通配符可能出现在模式中的任意位置。
  • 对于路径:
    • 在 Azure DevOps Server 2022 及更高版本(包括 Azure DevOps Services)中,通配符可能出现在路径模式中的任何位置,你可以使用 *?
    • 在 Azure DevOps Server 2020 及更低版本中,可以包含 * 作为最后一个字符,但它与单独指定目录名称没有任何不同。 不能在路径筛选器的中间包含 *,并且不能使用 ?
trigger:
  branches:
    include:
    - main
    - releases/*
    - feature/*
    exclude:
    - releases/old*
    - feature/*-working
  paths:
    include:
    - docs/*.md

PR 触发器

每当使用指定目标分支之一打开拉取请求,或对此类拉取请求进行更新时,拉取请求 (PR) 触发器都会导致管道运行。

分支

可以在验证拉取请求时指定目标分支。 例如,若要验证以 mainreleases/* 为目标的拉取请求,可以使用以下 pr 触发器。

pr:
- main
- releases/*

此配置将在第一次创建新的拉取请求时以及每次对拉取请求进行更新之后启动新的运行。

可以指定分支的全名(例如 main)或通配符(例如 releases/*)。

注意

不能在触发器中使用变量,因为变量是在运行时评估的(在触发器触发后)。

注意

如果使用模板创作 YAML 文件,则只能在管道的主 YAML 文件中指定触发器。 不能在模板文件中指定触发器。

GitHub 在创建拉取请求时创建新的引用。 该引用指向合并提交,这是拉取请求的源分支和目标分支之间的合并代码。 PR 验证管道生成此引用指向的提交。 这意味着,用于运行管道的 YAML 文件也是源分支和目标分支之间的合并。 因此,对拉取请求的源分支中的 YAML 文件所做的更改可以覆盖目标分支中 YAML 文件定义的行为。

如果 YAML 文件中未显示任何 pr 触发器,则会自动为所有分支启用拉取请求验证,就像你编写了以下 pr 触发器一样。 当创建任何拉取请求时,以及当提交进入任何活动拉取请求的源分支时,此配置会触发生成。

pr:
  branches:
    include:
    - '*'  # must quote since "*" is a YAML reserved character; we want a string

重要

指定包含分支子集的 pr 触发器时,仅当将更新推送到这些分支时,才会触发管道。

对于需要排除某些分支的更复杂的触发器,必须使用完整的语法,如以下示例所示。 在此示例中,将验证以 mainreleases/* 为目标的拉取请求,并且将排除分支 releases/old*

# specific branch
pr:
  branches:
    include:
    - main
    - releases/*
    exclude:
    - releases/old*

路径

可以指定要包含或排除的文件路径。 例如:

# specific path
pr:
  branches:
    include:
    - main
    - releases/*
  paths:
    include:
    - docs
    exclude:
    - docs/README.md

提示:

  • 当 Azure Pipelines 由于路径排除规则而决定不运行验证生成时,会将中性状态发回 GitHub。 这为 GitHub 提供了一个明确的方向,指示 Azure Pipelines 已完成其处理。 有关详细信息,请参阅跳过生成时将中性状态发布到 GitHub
  • 路径筛选器现在支持通配符
  • 指定的路径务必是存储库根目录的相对路径。
  • 如果未设置路径筛选器,则默认会隐式包含存储库的根文件夹。
  • 如果排除某个路径,则不能同时包含该路径,除非将其限定为更深一级的文件夹。 例如,如果排除 /tools,则可以包含 /tools/trigger-runs-on-these
  • 路径筛选器的顺序无关紧要。
  • Git 中的路径区分大小写。 请确保使用与真实文件夹相同的大小写。
  • 不能在路径中使用变量,因为变量是在运行时评估的(在触发器触发后)。
  • 当 Azure Pipelines 由于路径排除规则而决定不运行验证生成时,会将中性状态发回 GitHub。

多个 PR 更新

可以指定对 PR 的更多更新是否应取消进行中的针对同一 PR 的验证运行。 默认为 true

# auto cancel false
pr:
  autoCancel: false
  branches:
    include:
    - main

草稿 PR 验证

默认情况下,拉取请求触发器对草稿拉取请求和可供审阅的拉取请求触发。 若要禁用草稿拉取请求的拉取请求触发器,请将 drafts 属性设置为 false

pr:
  autoCancel: boolean # indicates whether additional pushes to a PR should cancel in-progress runs for the same PR. Defaults to true
  branches:
    include: [ string ] # branch names which will trigger a build
    exclude: [ string ] # branch names which will not
  paths:
    include: [ string ] # file paths which must match to trigger a build
    exclude: [ string ] # file paths which will not trigger a build
  drafts: boolean # whether to build draft PRs, defaults to true

选择退出 PR 验证

可以通过指定 pr: none 选择完全退出拉取请求验证。

# no PR triggers
pr: none

有关详细信息,请参阅 YAML 架构中的 PR 触发器

注意

如果 pr 触发器未触发,请按照常见问题解答中的疑难解答步骤进行操作。

如果有一个打开的 PR 并将更改推送到其源分支,则多个管道可能会运行:

  • 在 PR 的目标分支上具有 PR 触发器的管道将在合并提交(拉取请求的源分支和目标分支之间的合并代码)上运行,无论是否存在消息或描述中包含 [skip ci](或其任何变体)的已推送提交。
  • 如果没有其消息或说明包含 [skip ci](或其任何变体)的推送提交,则管道由对 PR 的源分支的更改触发。 如果至少有一个推送的提交包含 [skip ci],则管道将不会运行。

最后,在合并 PR 后,如果合并提交的消息或描述不包含 [skip ci](或其任何变体),Azure Pipelines 将运行通过向目标分支进行的推送所触发的 CI 管道。

受保护的分支

可以使用以分支为目标的每个提交或拉取请求运行验证生成,甚至可以在验证生成成功之前阻止拉取请求合并。

若要为 GitHub 存储库配置强制验证生成,你必须是其所有者、具有管理员角色的协作者,或者具有写入角色的 GitHub 组织成员。

  1. 首先,为存储库创建管道,并至少生成一次,以便将其状态发布到 GitHub,从而使 GitHub 知道管道的名称。

  2. 接下来,按照 GitHub 的文档在存储库的设置中配置受保护的分支

    对于状态检查,请在“状态检查”列表中选择管道的名称。

    GitHub pipeline status checkGitHub 管道状态检查

重要

如果管道未在此列表中显示,请确保以下各项:

来自外部源的贡献

如果 GitHub 存储库是开放源代码,则可以将 Azure DevOps 项目设为公开项目,以便任何人都可以查看管道的生成结果、日志和测试结果,而无需登录。 当组织外部的用户为存储库创建分支并提交拉取请求时,他们可以查看自动验证这些拉取请求的生成状态。

如果接受来自外部源的贡献,则在公共项目中使用 Azure Pipelines 时,应注意以下事项。

访问限制

在 Azure DevOps 公共项目中运行管道时,请注意以下访问限制:

  • 机密:默认情况下,与管道关联的机密不可用于分支的拉取请求验证。 请参阅验证分支的贡献
  • 跨项目访问:Azure DevOps 公共项目中的所有管道都使用仅限项目的访问令牌运行。 公共项目中的管道只能访问该项目中的资源(例如,生成项目或测试结果),而不能访问 Azure DevOps 组织的其他项目中的资源。
  • Azure Artifacts 包:如果管道需要访问 Azure Artifacts 中的包,则必须向项目生成服务帐户显式授予访问包源的权限。

分支的贡献

重要

这些设置影响管道的安全性。

创建管道时,会针对存储库分支中的拉取请求自动触发该管道。 可以更改此行为,仔细考虑它对安全性的影响。 若要启用或禁用此行为,请执行以下操作:

  1. 转到 Azure DevOps 项目。 选择“管道”,找到管道,然后选择“编辑”。
  2. 选择“触发器”选项卡。启用拉取请求触发器后,启用或禁用“从此存储库的分支生成拉取请求”复选框。

默认情况下,使用 GitHub 管道时,与生成管道关联的机密不可用于分支的拉取请求生成。 默认情况下,这些机密是使用 GitHub Enterprise Server 管道启用的。 机密包括:

  • 有权访问 GitHub 存储库的安全令牌。
  • 以下项(如果管道使用的话):

若要绕过 GitHub 管道上的此预防措施,请启用“使机密可用于分支生成”复选框。 请注意此设置对安全性的影响。

注意

在允许分支生成访问机密时,Azure Pipelines 默认情况下会对用于分支生成的访问令牌施加限制。 与普通访问令牌相比,它对开放资源的访问权限更加有限。 若要为分支生成授予与常规生成相同的权限,请启用“使分支生成与常规生成具有相同的权限”设置。

有关详细信息,请参阅存储库保护 - 分支

你可以使用“限制来自分支 GitHub 存储库的生成拉取请求”控件,集中定义管道如何基于分支 GitHub 存储库生成 PR。 它在组织和项目级别可用。 你可以选择:

  • 禁用基于分支存储库生成拉取请求
  • 基于分支存储库安全地生成拉取请求
  • 自定义基于分支存储库生成拉取请求的规则

Screenshot of centralized control settings for how pipelines build PRs from forked GitHub repositories.该屏幕截图显示了有关管道如何基于分支 GitHub 存储库生成 PR 的集中控制设置。

Sprint 229 开始,为了提高管道的安全性,Azure Pipelines 不再自动从分叉 GitHub 存储库生成拉取请求。 对于新项目和组织,“限制从分叉 GitHub 存储库生成拉取请求”设置的默认值为“禁用从分叉存储库生成拉取请求”

选择“基于分支存储库安全地生成拉取请求”选项时,所有管道、组织或项目范围都不能向基于分支存储库的 PR 生成提供机密,不能使这些生成具有与普通生成相同的权限,并且必须由 PR 注释触发。 项目仍然可以决定不允许管道生成此类 PR。

选择“自定义”选项时,可以定义如何限制管道设置。 例如,当 PR 属于非团队成员和非参与者时,可以确保所有管道都需要具有注释才能基于分支 GitHub 存储库生成 PR。 但是,你可以选择允许它们向此类生成提供机密。 项目可以决定不允许管道生成此类 PR、安全地生成此类 PR,或者采用比组织级别指定的更严格的设置。

现有组织的该控制已关闭。 从 2023 年 9 月开始,新组织默认启用“基于分支存储库安全地生成拉取请求”

重要的安全注意事项

GitHub 用户可以为存储库创建分支、更改存储库,并创建拉取请求以建议对存储库进行更改。 此拉取请求可能包含要作为触发生成的一部分运行的恶意代码。 此类代码可能会通过以下方式造成损害:

  • 泄露管道中的机密。 若要降低此风险,如果存储库是公共存储库或不受信任的用户可以提交自动触发生成的拉取请求,请不要启用“使机密可用于分支生成”复选框。 默认已禁用此选项。

  • 破坏运行代理的计算机,从其他管道中窃取代码或机密。 若要缓解此问题,请执行以下操作:

    • 使用 Microsoft 托管代理池从分支生成拉取请求。 Microsoft 托管代理计算机在完成生成后会立即删除,因此,如果它们遭到入侵,则不会产生持久的影响。

    • 如果必须使用自托管代理,请不要存储任何机密或执行在同一代理上使用机密的其他生成和发布,除非存储库是专用存储库,并且你信任拉取请求创建者。

注释触发器

存储库协作者可以对拉取请求进行注释以手动运行管道。 下面是一些可能想要执行此操作的常见原因:

  • 在可以查看未知用户的更改之前,你可能不希望自动生成来自未知用户的拉取请求。 你希望其中一个团队成员先查看其代码,然后运行管道。 从分支存储库生成贡献的代码时,这通常用作安全措施。
  • 你可能想要运行可选的测试套件或另一个验证生成。

若要启用注释触发器,必须执行以下两个步骤:

  1. 为管道启用拉取请求触发器,并确保未排除目标分支。
  2. 在 Azure Pipelines Web 门户中,编辑管道并选择“更多操作”、“触发器”。 然后,在“拉取请求验证”下,启用“在生成拉取请求之前,要求提供团队成员的注释”。
    • 选择“所有拉取请求”,以在生成拉取请求之前,要求提供团队成员的注释。 使用此工作流时,团队成员会评审拉取请求,并在拉取请求被认为安全后使用注释触发生成。
    • 选择“仅非团队成员的拉取请求”,以便仅当 PR 来自非团队成员时,才要求提供团队成员的注释。 在此工作流中,团队成员不需要辅助团队成员的评审来触发生成。

通过这两项更改,不会自动触发拉取请求验证生成,除非选择了“仅非团队成员的拉取请求”,并且 PR 来自团队成员。 只有具有“写入”权限的存储库所有者和协作者才能通过使用 /AzurePipelines run/AzurePipelines run <pipeline-name> 对拉取请求进行注释来触发生成。

可以在注释中向 Azure Pipelines 发出以下命令:

命令 结果
/AzurePipelines help 显示所有支持的命令的帮助信息。
/AzurePipelines help <command-name> 显示所有指定的命令的帮助信息。
/AzurePipelines run 运行与此存储库关联的所有管道,其触发器不排除此拉取请求。
/AzurePipelines run <pipeline-name> 运行指定的管道,除非其触发器排除此拉取请求。

注意

为简洁起见,可以使用 /azp(而不是 /AzurePipelines)注释。

重要

仅当管道使用 Azure Pipelines GitHub 应用程序时,这些命令的响应才会显示在拉取请求讨论中。

拉取请求注释触发器疑难解答

如果你有必要的存储库权限,但管道不会由注释触发,请确保你的成员身份在存储库的组织中是公开的,或者直接将自己添加为存储库协作者。 管道无法看到私有组织成员,除非他们是直接协作者或属于直接协作者团队。 可以在此处将 GitHub 组织成员身份从私有更改为公共(将 Your-Organization 替换为你的组织名称):https://github.com/orgs/Your-Organization/people

信息性运行

信息性运行告知 Azure DevOps 无法检索 YAML 管道的源代码。 源代码检索发生在对外部事件(例如,已推送提交)的响应中。 它还发生在对内部触发器的响应中,例如,检查是否发生了代码更改,以及是否启动了计划运行。 源代码检索可能因多种原因而失败,一个常见原因是 git 存储库提供程序限制了请求。 存在信息性运行不一定意味着 Azure DevOps 将运行管道。

信息性运行如以下屏幕截图所示。

Screenshot of an informational pipeline run.信息性管道运行的屏幕截图。

可根据以下属性识别信息性运行:

  • 状态为 Canceled
  • 持续时间为 < 1s
  • 运行名称包含以下文本之一:
    • Could not retrieve file content for {file_path} from repository {repo_name} hosted on {host} using commit {commit_sha}.
    • Could not retrieve content for object {commit_sha} from repository {repo_name} hosted on {host}.
    • Could not retrieve the tree object {tree_sha} from the repository {repo_name} hosted on {host}.
    • Could not find {file_path} from repository {repo_name} hosted on {host} using version {commit_sha}. One of the directories in the path contains too many files or subdirectories.
  • 运行名称通常包含导致 YAML 管道加载失败的 BitBucket/GitHub 错误
  • 无阶段/作业/步骤

详细了解信息性运行

签出

触发管道时,Azure Pipelines 会从 Azure Repos Git 存储库中拉取源代码。 可以控制该行为的各个方面。

注意

在管道中包含签出步骤时,我们将运行以下命令:git -c fetch --force --tags --prune --prune-tags --progress --no-recurse-submodules origin --depth=1。 如果这不能满足你的需求,则可以选择通过 checkout: none 排除内置签出,然后使用脚本任务执行自己的签出。

Git 的首选版本

Windows 代理包含自己的 Git 副本。 如果想要提供自己的 Git 而不是使用包含的副本,请将 System.PreferGitFromPath 设置为 true。 在非 Windows 代理上,此设置始终为 true。

签出路径

如果要签出单个存储库,默认情况下,源代码将签出到名为 s 的目录中。 对于 YAML 管道,可以通过使用 path 指定 checkout 来更改此设置。 指定的路径是 $(Agent.BuildDirectory) 的相对路径。 例如:如果签出路径值为 mycustompath$(Agent.BuildDirectory)C:\agent\_work\1,则源代码将签出到 C:\agent\_work\1\mycustompath 中。

如果使用多个 checkout 步骤并签出多个存储库,并且未使用 path 显式指定文件夹,则每个存储库都放置在以存储库命名的 s 的子文件夹中。 例如,如果签出两个名为 toolscode 的存储库,则源代码将签出到 C:\agent\_work\1\s\toolsC:\agent\_work\1\s\code 中。

请注意,签出路径值不能设置为高于 $(Agent.BuildDirectory) 的任何目录级别,因此 path\..\anotherpath 将会产生有效的签出路径(即 C:\agent\_work\1\anotherpath),但 ..\invalidpath 这样的值则不会产生有效的签出路径(即 C:\agent\_work\invalidpath)。

可以在管道的签出步骤中配置 path 设置。

steps:
- checkout: self  # self represents the repo where the initial Pipelines YAML file was found
  clean: boolean  # whether to fetch clean each time
  fetchDepth: number  # the depth of commits to ask Git to fetch
  lfs: boolean  # whether to download Git-LFS files
  submodules: true | recursive  # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
  path: string  # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
  persistCredentials: boolean  # set to 'true' to leave the OAuth token in the Git config after the initial fetch

子模块

如果要从子模块下载文件,可以在管道的签出步骤中配置 submodules 设置。

steps:
- checkout: self  # self represents the repo where the initial Pipelines YAML file was found
  clean: boolean  # whether to fetch clean each time
  fetchDepth: number  # the depth of commits to ask Git to fetch
  lfs: boolean  # whether to download Git-LFS files
  submodules: true | recursive  # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
  path: string  # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
  persistCredentials: boolean  # set to 'true' to leave the OAuth token in the Git config after the initial fetch

生成管道将签出 Git 子模块,只要它们是:

  • 未经身份验证:一个未经身份验证的公共存储库,无需凭据即可克隆或提取。

  • 已经过身份验证:

    • 包含在与上面指定的 Azure Repos Git 存储库相同的项目中。 代理用于从主存储库获取源的凭据也用于获取子模块的源。

    • 通过使用相对于主存储库的 URL 添加。 例如:

      • 将签出以下代码:git submodule add ../../../FabrikamFiberProject/_git/FabrikamFiber FabrikamFiber

        在此示例中,子模块是指在同一 Azure DevOps 组织中但在不同项目 (FabrikamFiberProject) 中的存储库 (FabrikamFiber)。 代理用于从主存储库获取源的凭据也用于获取子模块的源。 这要求作业访问令牌有权访问第二个项目中的存储库。 如果按上述部分所述限制作业访问令牌,则无法执行此操作。 可以通过 (a) 显式授予对第二个项目中的项目生成服务帐户的访问权限,或者 (b) 使用集合作用域内的访问令牌(而不是整个组织的项目作用域内令牌)来允许作业访问令牌访问第二个项目中的存储库。 有关这些选项及其安全隐患的详细信息,请参阅访问存储库、项目和其他资源

      • 不会签出以下代码:git submodule add https://fabrikam-fiber@dev.azure.com/fabrikam-fiber/FabrikamFiberProject/_git/FabrikamFiber FabrikamFiber

使用 Checkout 子模块选项的替代方法

在某些情况下,无法使用“签出子模块”选项。 你可能会遇到这样一种情况:需要一组不同的凭据才能访问子模块。 例如,如果主存储库和子模块存储库不存储在同一 Azure DevOps 组织中,或者作业访问令牌无权访问其他项目中的存储库,则可能会发生这种情况。

如果无法使用“签出子模块”选项,则可以改用自定义脚本步骤来提取子模块。 首先,获取个人访问令牌 (PAT),并添加前缀 pat:。 接下来,对添加前缀后的字符串进行 base64 编码,以创建基本身份验证令牌。 最后,将此脚本添加到管道:

git -c http.https://<url of submodule repository>.extraheader="AUTHORIZATION: Basic <BASE64_ENCODED_STRING>" submodule update --init --recursive

请务必将“<BASE64_ENCODED_STRING>”替换为 Base64 编码的“pat:token”字符串。

在项目或生成管道中使用机密变量来存储生成的基本身份验证令牌。 使用该变量在上述 Git 命令中填充机密。

注意

问:为什么不能在代理上使用 Git 凭据管理器?答:在专用生成代理上安装的 Git 凭据管理器中存储子模块凭据通常无效,因为每当更新子模块时,凭据管理器可能会提示你重新输入凭据。 当无法进行用户交互时,在自动生成期间,这是不可取的。

同步标记

重要

Azure Repos Git 中支持在 Azure DevOps Server 2022.1 及更高版本中使用同步标记功能。

签出步骤在提取 Git 存储库的内容时使用 --tags 选项。 这会导致服务器提取所有标记以及这些标记所指向的所有对象。 这会增加在管道中运行任务的时间,尤其是在具有大量标记的大型存储库时。 此外,即使启用浅提取选项,签出步骤也会同步标记,因此可能会破坏其用途。 为了减少从 Git 存储库提取或拉取的数据量,Microsoft 添加了一个新签出选项来控制同步标记的行为。 此选项在经典管道和 YAML 管道中都可用。

是否在签出存储库时同步标记可以通过设置 fetchTags 属性在 YAML 中配置,并且通过配置同步标记设置在 UI 中配置。

可以在管道的签出步骤中配置 path 设置。

若要在 YAML 中配置设置,请设置 fetchTags 属性。

steps:
- checkout: self
  fetchTags: true

还可以使用管道设置 UI 中的“同步标记”选项配置此设置。

  1. 编辑 YAML 管道,然后选择“更多操作”、“触发器”。

    Screenshot of more triggers menu.更多触发器菜单的屏幕截图。

  2. 选择“YAML”、“获取源”。

    Screenshot of Get sources.获取源的屏幕截图。

  3. 配置同步标记设置。

    Screenshot of Sync tags setting.同步标记设置的屏幕截图。

注意

如果在 checkout 步骤中显式设置 fetchTags,则该设置优先于管道设置 UI 中配置的设置。

默认行为

  • 对于在 2022 年 9 月发布的 Azure DevOps 冲刺 209 之前创建的现有管道,同步标记的默认值与添加“同步标记”选项之前的现有行为相同,即 true
  • 对于在 Azure DevOps 冲刺版本 209 之后创建的新管道,同步标记的默认值为 false

注意

如果在 checkout 步骤中显式设置 fetchTags,则该设置优先于管道设置 UI 中配置的设置。

浅提取

你可能想要限制要下载多远的历史记录。 这实际上会导致 git fetch --depth=n。 如果存储库很大,此选项可能会提高生成管道的效率。 如果存储库已长期使用并且具有相当大的历史记录,则存储库可能很大。 如果添加并随后删除了大型文件,则它也可能很大。

重要

2022 年 9 月 Azure DevOps 冲刺 209 更新后创建的新管道默认启用了浅提取,并配置了深度为 1。 以前默认不是浅提取。 若要检查管道,请在管道设置 UI 中查看浅提取设置,如以下部分所述。

可以在管道的签出步骤中配置 path 设置。

steps:
- checkout: self  # self represents the repo where the initial Pipelines YAML file was found
  clean: boolean  # whether to fetch clean each time
  fetchDepth: number  # the depth of commits to ask Git to fetch
  lfs: boolean  # whether to download Git-LFS files
  submodules: true | recursive  # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
  path: string  # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
  persistCredentials: boolean  # set to 'true' to leave the OAuth token in the Git config after the initial fetch

还可以通过在管道设置 UI 中设置“浅深度”选项来配置提取深度。

  1. 编辑 YAML 管道,然后选择“更多操作”、“触发器”。

    Screenshot of more triggers menu.更多触发器菜单的屏幕截图。

  2. 选择“YAML”、“获取源”。

    Screenshot of Get sources.获取源的屏幕截图。

  3. 配置浅提取设置。 取消选中“浅提取”以禁用浅提取,或选中框并输入“深度”以启用浅提取。

    Screenshot of options.选项的屏幕截图。

注意

如果在 checkout 步骤中显式设置 fetchTags,则该设置优先于管道设置 UI 中配置的设置。 设置 fetchDepth: 0 将提取所有历史记录,并覆盖“浅提取”设置。

在这些情况下,此选项有助于节省网络和存储资源。 它还可以节省时间。 但它并不是一定会节省时间,原因是,在某些情况下,服务器可能需要花时间计算要为指定深度下载的提交。

注意

启动管道时,要生成的分支将解析为提交 ID。 然后,代理提取分支并签出所需的提交。 分支解析为提交 ID 和代理执行签出之间有一小段时间。 如果分支快速更新,并且你为浅提取设置非常小的值,则当代理尝试签出提交时,提交可能不存在。如果发生这种情况,请增加浅提取深度设置。

不同步源

你可能想要跳过提取新提交。 此选项在需要执行以下操作的情况下非常有用:

  • 使用自己的自定义选项进行 Git 初始化、配置和提取。

  • 使用生成管道仅运行不依赖于版本控制中的代码的自动化(例如,某些脚本)。

可以通过设置 checkout: none 在管道的签出步骤中配置“不同步源”设置。

steps:
- checkout: none  # Don't sync sources

注意

使用此选项时,代理还会跳过运行清理存储库的 Git 命令。

清理生成

在生成运行之前,可以对自托管代理的工作目录执行不同形式的清理。

一般情况下,为了提高自托管代理的性能,请不要清理存储库。 在这种情况下,若要获得最佳性能,请确保同时以增量方式生成,方法是禁用用于生成的任务或工具的任何“清理”选项。

如果你确实需要清理存储库(例如,为了避免上次生成残留的文件造成问题),请使用以下选项。

注意

如果使用 Microsoft 托管代理,则清理无效,因为每次都会获得一个新代理。

可以在管道的签出步骤中配置 path 设置。

steps:
- checkout: self  # self represents the repo where the initial Pipelines YAML file was found
  clean: boolean  # whether to fetch clean each time
  fetchDepth: number  # the depth of commits to ask Git to fetch
  lfs: boolean  # whether to download Git-LFS files
  submodules: true | recursive  # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
  path: string  # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
  persistCredentials: boolean  # set to 'true' to leave the OAuth token in the Git config after the initial fetch

clean 设置为 true 时,生成管道将对 $(Build.SourcesDirectory) 中的任何更改执行撤消操作。 更具体地说,以下 Git 命令在提取源之前执行。

git clean -ffdx
git reset --hard HEAD

有关更多选项,可以配置作业workspace 设置。

jobs:
- job: string  # name of the job, A-Z, a-z, 0-9, and underscore
  ...
  workspace:
    clean: outputs | resources | all # what to clean up before the job runs

这提供了以下清理选项。

  • 输出:与上一签出任务中所述的清理设置相同的操作,加上:删除再重新创建 $(Build.BinariesDirectory)。 请注意,始终在每次生成之前删除再重新创建 $(Build.ArtifactStagingDirectory)$(Common.TestResultsDirectory),而不考虑其中的任何设置。

  • 资源:删除再重新创建 $(Build.SourcesDirectory)。 这会导致为每个生成初始化新的本地 Git 存储库。

  • 全部:删除再重新创建 $(Agent.BuildDirectory)。 这会导致为每个生成初始化新的本地 Git 存储库。

标记源

你可能想要标记源代码文件,使团队能够轻松确定每个文件的哪个版本包含在已完成的生成中。 还可以选择指定是应为所有生成标记源代码,还是仅为成功的生成标记源代码。

当前无法在 YAML 中配置此设置,但可以在经典编辑器中配置此设置。 编辑 YAML 管道时,可以通过从 YAML 编辑器菜单中选择任一触发器来访问经典编辑器。

Configure Git options, YAML.配置 Git 选项“YAML”。

在经典编辑器中,选择“YAML”,选择“获取源”任务,然后在其中配置所需的属性。

From the Classic editor, choose YAML > Get sources.从经典编辑器中,选择“YAML”>“获取源”。

标记格式中,可以使用范围为“全部”的用户定义变量和预定义变量。例如:

$(Build.DefinitionName)_$(Build.DefinitionVersion)_$(Build.BuildId)_$(Build.BuildNumber)_$(My.Variable)

前四个变量是预定义变量。 My.Variable 可以是你在“变量”选项卡上定义的变量。

生成管道使用 Git 标记标记源。

某些生成变量可能会生成不是有效标签的值。 例如,$(Build.RequestedFor)$(Build.DefinitionName) 等变量可以包含空格。 如果值包含空格,则不会创建标记。

生成管道标记源后,带有 Git 引用 refs/tags/{tag} 的项目会自动添加到已完成的生成中。 这为团队提供了额外的可跟踪性,并提供更加用户友好的方式来从生成导航到生成的代码。 标记被视为生成项目,因为它是由生成创建的。 手动或通过保留策略删除生成时,也会删除标记。

预定义变量

生成 GitHub 存储库时,大多数预定义变量都可用于作业。 但是,由于 Azure Pipelines 无法识别在 GitHub 中进行更新的用户的身份,因此以下变量设置为系统身份而不是用户的身份:

  • Build.RequestedFor
  • Build.RequestedForId
  • Build.RequestedForEmail

状态更新

Azure Pipelines 有两种类型的状态会发布回 GitHub - 基本状态和 GitHub 检查运行。 GitHub 检查功能仅适用于 GitHub 应用。

管道状态显示在 GitHub UI 中的不同位置。

  • 对于 PR,它们将显示在“PR 对话”选项卡上。
  • 对于各个提交,当将鼠标悬停在提交时间之后的状态标记上时,它们会显示在存储库的提交选项卡上。

PAT 或 OAuth GitHub 连接

对于使用 PATOAuth GitHub 连接的管道,状态将发布回触发运行的提交/PR。 GitHub 状态 API 用于发布此类更新。 这些状态包含有限的信息:管道状态(失败、成功)、链接回生成管道的 URL,以及状态的简要描述。

PAT 或 OAuth GitHub 连接的状态仅在运行级别发送。 换句话说,可以针对整个运行更新单个状态。 如果运行中有多个作业,则无法针对每个作业发布单独的状态。 但是,多个管道可以将单独的状态发布到同一个提交。

GitHub 检查

对于使用 Azure Pipelines GitHub 应用设置的管道,状态以 GitHub 检查的形式发布回。 GitHub 检查允许发送有关管道状态和测试、代码覆盖率以及错误的详细信息。 可在此处找到 GitHub 检查 API。

对于使用 GitHub 应用的每个管道,将针对整个运行以及该运行中的每个作业发布回检查。

GitHub 允许在 PR/提交的一个或多个检查运行失败时使用三个选项。 可以选择“重新运行”单个检查,重新运行该 PR/提交上的所有失败检查,或重新运行所有检查,无论它们最初是否成功。

GitHub checks rerunGitHub 检查重新运行

单击检查运行名称旁边的“重新运行”链接将导致 Azure Pipelines 重试生成了“检查运行”的运行。 生成的运行将具有相同的运行编号,并且将使用与初始生成相同的源代码、配置和 YAML 文件版本。 仅那些在初始运行中失败的作业和任何相关的下游作业将重新运行。 单击“重新运行所有失败的检查”链接将会有相同的效果。 这与在 Azure Pipelines UI 中单击“重试运行”的行为相同。 单击“重新运行所有检查”将产生新运行,有新运行编号,并且将在配置或 YAML 文件中选取更改。

限制

  • 为了获得最佳性能,建议单个存储库中最多 50 个管道。 为了获得可接受的性能,建议单个存储库中最多 100 个管道。 处理到存储库的推送所需的时间随着该存储库中管道数量的增加而增加。 每当推送到存储库时,Azure Pipelines 都需要加载该存储库中的所有 YAML 管道,以确定是否需要运行其中的任何管道,而加载每个管道会导致性能下降。 除了性能问题之外,单个存储库中有太多管道可能会导致 GitHub 端的限制,因为 Azure Pipelines 可能会在短时间内发出过多的请求。

  • 在管道中使用扩展包含模板会影响 Azure Pipelines 发出 GitHub API 请求的速率,并可能导致 GitHub 端的限制。 在运行管道之前,Azure Pipelines 需要生成完整的 YAML 代码,因此需要提取所有模板文件。

  • Azure Pipelines 最多将存储库中的 2000 个分支加载到 Azure DevOps 门户的下拉列表中,例如为手动和计划生成的默认分支设置选择一个分支窗口,或者在手动运行管道的情况下在选择分支时这样做。

    如果在列表中看不到所需的分支,请在手动和计划生成的默认分支字段中手动键入所需的分支名称。

    如果单击省略号并打开选择分支对话框并关闭它,然后在不从下拉列表中选择有效分支的情况下将其关闭,你可能会在手动和计划生成的默认分支下方看到一些设置需要注意消息和该设置是必需设置消息。 若要解决此问题,请重新打开管道,并直接在手动和计划生成的默认分支字段中输入名称。

常见问题解答

与 GitHub 集成相关的问题分为以下几个类别:

  • 连接类型我不确定使用哪种连接类型将管道连接到 GitHub。
  • 触发器失败将更新推送到存储库时,管道未触发。
  • 签出失败管道被触发,但在签出步骤中失败。
  • 版本错误管道运行,但它使用的并非是预期版本的源/YAML。
  • 缺少状态更新我的 GitHub PR 被阻止,因为 Azure Pipelines 未报告状态更新。

连接类型

若要对触发器进行故障排除,如何知道用于管道的 GitHub 连接类型?

解决触发器问题在很大程度上取决于你在管道中使用的 GitHub 连接类型。 可通过两种方法确定连接类型 - 从 GitHub 中以及从 Azure Pipelines 中。

  • 从 GitHub 中:如果存储库设置为使用 GitHub 应用,则 PR 和提交的状态将为“检查运行”。 如果存储库使用 OAuth 或 PAT 连接设置了 Azure Pipelines,则状态将为“旧”样式的状态。 确定状态是“检查运行”还是简单状态的快速方法是查看 GitHub PR 上的“对话”选项卡。

    • 如果“详细信息”链接重定向到“检查”选项卡,则它是“检查运行”,并且存储库正在使用应用。
    • 如果“详细信息”链接重定向到 Azure DevOps 管道,则状态为“旧样式”状态,并且存储库未使用应用。
  • 从 Azure Pipelines 中:还可以通过在 Azure Pipelines UI 中检查管道来确定连接类型。 打开管道的编辑器。 选择“触发器”以打开管道的经典编辑器。 然后,依次选择“YAML”选项卡和“获取源”步骤。 你会注意到一个横幅“授权使用连接:”,指示用于将管道与 GitHub 集成的服务连接。 服务连接的名称是超链接。 选择它可导航到服务连接属性。 服务连接的属性将指示正在使用的连接类型:

    • Azure Pipelines 应用表示 GitHub 应用连接
    • oauth 表示 OAuth 连接
    • personalaccesstoken 表示 PAT 身份验证

如何将管道切换为使用 GitHub 应用而不是 OAuth?

建议使用 GitHub 应用而不是 OAuth 或 PAT 连接在 GitHub 与 Azure Pipelines 之间集成。 若要切换到 GitHub 应用,请执行以下步骤:

  1. 此处导航,并在存储库的 GitHub 组织中安装应用。
  2. 在安装过程中,你将被重定向到 Azure DevOps,以选择 Azure DevOps 组织和项目。 选择包含要为其使用应用的经典生成管道的组织和项目。 此选项将 GitHub 应用安装与 Azure DevOps 组织相关联。 如果选择不正确,则可以访问此页面以从 GitHub 组织中卸载 GitHub 应用,然后从头开始。
  3. 在显示的下一页中,无需继续创建新管道。
  4. 通过访问“管道”页(例如,https://dev.azure.com/YOUR_ORG_NAME/YOUR_PROJECT_NAME/_build))、选择管道并单击“编辑”来编辑管道。
  5. 如果这是 YAML 管道,请选择“触发器”菜单以打开经典编辑器。
  6. 在管道中选择“获取源”步骤。
  7. 在显示文本“授权使用连接”的绿色栏上,选择“更改”,然后选择与安装应用的 GitHub 组织同名的 GitHub 应用连接。
  8. 在工具栏上,选择“保存并排队”,然后再次选择“保存并排队”。 选择指向已排队的管道运行的链接,以确保成功。
  9. 在 GitHub 存储库中创建(或关闭并重新打开)拉取请求,以验证生成在其“检查”部分中是否已成功排队。

为什么 Azure Pipelines 中没有显示供我选择的 GitHub 存储库?

根据存储库的身份验证类型和所有权,需要特定权限。

创建管道期间选择存储库时,收到错误“存储库 {repo-name} 正在被另一个 Azure DevOps 组织中的 Azure Pipelines GitHub 应用使用”。

这意味着存储库已与其他组织中的管道关联。 此存储库中的 CI 和 PR 事件将不起作用,因为它们将传递到其他组织。 下面是在继续创建管道之前删除到其他组织的映射应采取的步骤。

  1. 在 GitHub 存储库中打开拉取请求,并注释 /azp where。 这将报告回存储库映射到的 Azure DevOps 组织。

  2. 若要更改映射,请从 GitHub 组织中卸载应用,然后再重新安装。 重新安装时,请确保在重定向到 Azure DevOps 时选择正确的组织。

触发器失败

我刚刚创建了一个包含 CI/PR 触发器的新 YAML 管道,但该管道未触发。

按照以下各步骤对失败的触发器进行故障排除:

  • 你的 YAML CI 或 PR 触发器是否被 UI 中的管道设置替代? 编辑管道时,选择“...”,然后选择“触发器”。

    Pipeline settings UI.管道设置 UI。

    针对你的存储库可用的触发器类型(“持续集成”或“拉取请求验证”)选中“从此处替代 YAML 触发器”设置。

    Override YAML trigger from here.从此处覆盖 YAML 触发器。

  • 是否使用 GitHub 应用连接将管道连接到 GitHub? 请参阅连接类型来确定你拥有的连接类型。 如果使用 GitHub 应用连接,请执行以下步骤:

    • GitHub 和 Azure DevOps 之间的映射设置是否正确? 在 GitHub 存储库中打开拉取请求,并注释 /azp where。 这将报告回存储库映射到的 Azure DevOps 组织。

      • 如果没有组织设置为使用应用生成此存储库,请转到 https://github.com/<org_name>/<repo_name>/settings/installations 并完成应用的配置。

      • 如果报告了其他 Azure DevOps 组织,则表示有人已在其他组织中为此存储库建立了管道。 我们目前有一项限制,即只能将 GitHub 存储库映射到单个 DevOps 组织。只能自动触发第一个 Azure DevOps 组织中的管道。 若要更改映射,请从 GitHub 组织中卸载应用,然后再重新安装。 重新安装时,请确保在重定向到 Azure DevOps 时选择正确的组织。

  • 是否使用 OAuth 或 PAT 将管道连接到 GitHub? 请参阅连接类型来确定你拥有的连接类型。 如果使用 GitHub 连接,请执行以下步骤:

    1. OAuth 和 PAT 连接依赖于 Webhook 将更新传送到 Azure Pipelines。 在 GitHub 中,导航到存储库的设置,然后导航到 Webhook。 验证 Webhook 是否存在。 通常应看到三个 Webhook - push、pull_request 和 issue_comment。 如果没有,则必须重新创建服务连接,并更新管道以使用新的服务连接。

    2. 在 GitHub 中选择每个 Webhook,并验证与用户提交对应的有效负载是否存在,以及是否已成功发送到 Azure DevOps。 如果无法将事件传送到 Azure DevOps,你可能会在此处看到错误。

  • 来自 Azure DevOps 的流量可能会受到 GitHub 的限制。 当 Azure Pipelines 收到来自 GitHub 的通知时,它会尝试联系 GitHub 并提取有关存储库和 YAML 文件的详细信息。 如果有包含大量更新和拉取请求的存储库,则此调用可能因此类限制而失败。 在这种情况下,请查看是否可以使用批处理或更严格的路径/分支筛选器来降低生成频率。

  • 管道是否已暂停或禁用? 打开管道的编辑器,然后选择“设置”进行检查。 如果管道已暂停或禁用,则触发器将不起作用。

  • 是否已在正确的分支中更新 YAML 文件? 如果将更新推送到分支,则同一分支中的 YAML 文件将控制 CI 行为。 如果将更新推送到源分支,则因将源分支与目标分支合并而产生的 YAML 文件将控制 PR 行为。 请确保正确分支中的 YAML 文件具有必要的 CI 或 PR 配置。

  • 是否已正确配置触发器? 定义 YAML 触发器时,可以为分支、标记和路径指定 include 和 exclude 子句。 确保 include 子句与提交的详细信息匹配,并且 exclude 子句不会排除它们。 检查触发器的语法,并确保它是正确无误的。

  • 是否在定义触发器或路径时使用了变量? 这不受支持。

  • 是否对 YAML 文件使用了模板? 如果是这样,请确保在主 YAML 文件中定义了触发器。 在模板文件中定义的触发器不受支持。

  • 是否排除了将更改推送到的分支或路径? 通过将更改推送到包含的分支中包含的路径进行测试。 请注意,触发器中的路径区分大小写。 在触发器中指定路径时,请确保使用与真实文件夹相同的大小写。

  • 你刚刚推送了一个新分支吗? 如果是这样,新分支可能不会启动新的运行。 请参阅“创建新分支时的触发器行为”。

我的 CI 或 PR 触发器一直工作正常。 但是,它们现在停止工作了。

首先,完成上一个问题中的故障排除步骤,然后执行以下附加步骤:

  • PR 中是否有合并冲突? 对于未触发管道的 PR,请将其打开并检查它是否具有合并冲突。 解决合并冲突。

  • 是否在处理推送或 PR 事件时遇到延迟? 通常可以通过查看该问题是特定于单个管道,还是适用于项目中所有管道或存储库来验证延迟。 如果对任何存储库的推送或 PR 更新都出现此症状,则可能是在处理更新事件时遇到延迟。 下面是可能发生延迟的一些原因:

    • 我们正在状态页上遇到服务中断。 如果状态页显示问题,则我们的团队必定已开始处理该问题。 请经常查看页面以获取有关该问题的更新。
    • 存储库包含的 YAML 管道过多。 为了获得最佳性能,建议单个存储库中最多 50 个管道。 为了获得可接受的性能,建议单个存储库中最多 100 个管道。 管道越多,处理到该存储库的推送的速度就越慢。 每当推送到存储库时,Azure Pipelines 都需要加载该存储库中的所有 YAML 管道,以确定其中是否有任何一个管道需要运行,并且每个新管道都会造成性能损失。

我不希望用户在更新 YAML 文件时覆盖触发器的分支列表。 如何执行此操作?

有权贡献代码的用户可以更新 YAML 文件并包括/排除其他分支。 因此,用户可以在其 YAML 文件中包含自己的功能或用户分支,并将该更新推送到功能或用户分支。 这可能会导致针对该分支的所有更新触发管道。 如果要阻止此行为,可以执行以下步骤:

  1. 在 Azure Pipelines UI 中编辑管道。
  2. 导航到“触发器”菜单。
  3. 选择“从此处覆盖 YAML 持续集成触发器”。
  4. 指定要为触发器包含或排除的分支。

执行这些步骤时,将忽略 YAML 文件中指定的任何 CI 触发器。

签出失败

在签出步骤期间,我在日志文件中看到以下错误。 如何解决问题?

remote: Repository not found.
fatal: repository <repo> not found

这可能是由 GitHub 中断引起的。 尝试访问 GitHub 中的存储库,并确保能够访问。

版本错误

管道中使用了错误的 YAML 文件版本。 为什么会这样?

  • 对于 CI 触发器,你所推送的分支中的 YAML 文件将受到评估,以了解是否应运行 CI 生成。
  • 对于 PR 触发器,将评估合并 PR 的源分支和目标分支所产生的 YAML 文件,以查看是否应运行 PR 生成。

缺少状态更新

GitHub 中的 PR 被阻止,因为 Azure Pipelines 未更新状态。

这可能是暂时性错误,导致 Azure DevOps 无法与 GitHub 通信。 如果使用 GitHub 应用,请重试签入 GitHub。 或者,对 PR 进行普通更新,以查看是否可以解决问题。