Check out multiple repositories in your pipeline
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020
Pipelines often rely on multiple repositories that contain source, tools, scripts, or other items that you need to build your code. By using multiple checkout
steps in your pipeline, you can fetch and check out other repositories in addition to the one you use to store your YAML pipeline.
Specify multiple repositories
Repositories can be specified as a repository resource, or inline with the checkout
step.
The following repository types are supported.
Azure Repos Git (git
)
- Azure DevOps Server (limited to repositories in the same organization)
- Azure DevOps Services
GitHub (github
)
- Azure DevOps Services
GitHubEnterprise (githubenterprise
)
- Azure DevOps Services
Bitbucket Cloud (bitbucket
)
- Azure DevOps Services
Important
Only Azure Repos Git (git
) repositories in the same organization as the pipeline are supported for multi-repo checkout in Azure DevOps Server.
Note
Azure Pipelines provides Limit job scope settings for Azure Repos Git repositories. To check out Azure Repos Git repositories hosted in another project, Limit job scope must be configured to allow access. For more information, see Limit job authorization scope.
The following combinations of checkout
steps are supported.
No checkout
steps
The default behavior is as if checkout: self
were the first step, and the current repository is checked out.
A single checkout: none
step
No repositories are synced or checked out.
A single checkout: self
step
The current repository is checked out.
A single checkout
step that isn't self
or none
The designated repository is checked out instead of self
.
Multiple checkout
steps
Each designated repository is checked out to a folder named after the repository, unless a different path
is specified in the checkout
step. To check out self
as one of the repositories, use checkout: self
as one of the checkout
steps.
Note
When you check out Azure Repos Git repositories other than the one containing the pipeline, you may be prompted to authorize access to that resource before the pipeline runs for the first time. For more information, see Why am I prompted to authorize resources the first time I try to check out a different repository? in the FAQ section.
Repository resource definition
You must use a repository resource if your repository type requires a service connection or other extended resources field. The following repository types require a service connection.
Repository type | Service connection |
---|---|
Bitbucket Cloud | Bitbucket Cloud |
GitHub | GitHub |
GitHub Enterprise Server | GitHub Enterprise Server |
Azure Repos Git repositories in a different organization than your pipeline | Azure Repos/Team Foundation Server |
You may use a repository resource even if your repository type doesn't require a service connection, for example if you have a repository resource defined already for templates in a different repository.
In the following example, three repositories are declared as repository resources. The Azure Repos Git repository in another organization, GitHub, and Bitbucket Cloud repository resources require service connections, which are specified as the endpoint
for those repository resources. This example has four checkout
steps, which checks out the three repositories declared as repository resources along with the current self
repository that contains the pipeline YAML.
resources:
repositories:
- repository: MyGitHubRepo # The name used to reference this repository in the checkout step
type: github
endpoint: MyGitHubServiceConnection
name: MyGitHubOrgOrUser/MyGitHubRepo
- repository: MyBitbucketRepo
type: bitbucket
endpoint: MyBitbucketServiceConnection
name: MyBitbucketOrgOrUser/MyBitbucketRepo
- repository: MyAzureReposGitRepository # In a different organization
endpoint: MyAzureReposGitServiceConnection
type: git
name: OtherProject/MyAzureReposGitRepo
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
- checkout: MyGitHubRepo
- checkout: MyBitbucketRepo
- checkout: MyAzureReposGitRepository
- script: dir $(Build.SourcesDirectory)
If the self
repository is named CurrentRepo
, the script
command produces the following output: CurrentRepo MyAzureReposGitRepo MyBitbucketRepo MyGitHubRepo
. In this example, the names of the repositories (as specified by the name
property in the repository resource) are used for the folders, because no path
is specified in the checkout step. For more information on repository folder names and locations, see the following Checkout path section.
Inline syntax checkout
If your repository doesn't require a service connection, you can declare it inline with your checkout
step.
Note
Only Azure Repos Git repositories in the same organization can use the inline syntax. Azure Repos Git repositories in a different organization, and other supported repository types require a service connection and must be declared as a repository resource.
steps:
- checkout: self
- checkout: git://MyProject/MyRepo # Azure Repos Git repository in the same organization
Note
In the previous example, the self
checkout repository is specified in order to checkout the source of the repository associated with the pipeline.
If you are using the default Azure Repos Git repository (that has the same name as the project), use the format - checkout: git://MyRepo/MyRepo
.
Checkout path
Unless a path
is specified in the checkout
step, source code is placed in a default directory. This directory is different depending on whether you are checking out a single repository or multiple repositories.
Single repository: If you have a single
checkout
step in your job, or you have no checkout step which is equivalent tocheckout: self
, your source code is checked out into a directory calleds
located as a subfolder of(Agent.BuildDirectory)
. If(Agent.BuildDirectory)
isC:\agent\_work\1
, your code is checked out toC:\agent\_work\1\s
.Multiple repositories: If you have multiple
checkout
steps in your job, your source code is checked out into directories named after the repositories as a subfolder ofs
in(Agent.BuildDirectory)
. If(Agent.BuildDirectory)
isC:\agent\_work\1
and your repositories are namedtools
andcode
, your code is checked out toC:\agent\_work\1\s\tools
andC:\agent\_work\1\s\code
.Note
If no
path
is specified in thecheckout
step, the name of the repository is used for the folder, not therepository
value which is used to reference the repository in thecheckout
step.
If a path
is specified for a checkout
step, that path is used, relative to (Agent.BuildDirectory)
.
Note
If you are using default paths, adding a second repository checkout
step changes the default path of the code for the first repository. For example, the code for a repository named tools
would be checked out to C:\agent\_work\1\s
when tools
is the only repository, but if a second repository is added, tools
would then be checked out to C:\agent\_work\1\s\tools
. If you have any steps that depend on the source code being in the original location, those steps must be updated.
Checking out a specific ref
The default branch is checked out unless you designate a specific ref.
If you are using inline syntax, designate the ref by appending @<ref>
. For example:
- checkout: git://MyProject/MyRepo@features/tools # checks out the features/tools branch
- checkout: git://MyProject/MyRepo@refs/heads/features/tools # also checks out the features/tools branch
- checkout: git://MyProject/MyRepo@refs/tags/MyTag # checks out the commit referenced by MyTag.
When using a repository resource, specify the ref using the ref
property. The following example checks out the features/tools/
branch of the designated repository.
resources:
repositories:
- repository: MyGitHubRepo
type: github
endpoint: MyGitHubServiceConnection
name: MyGitHubOrgOrUser/MyGitHubRepo
ref: features/tools
steps:
- checkout: MyGitHubRepo
The following example uses tags to check out the commit referenced by MyTag
.
resources:
repositories:
- repository: MyGitHubRepo
type: github
endpoint: MyGitHubServiceConnection
name: MyGitHubOrgOrUser/MyGitHubRepo
ref: refs/tags/MyTag
steps:
- checkout: MyGitHubRepo
Triggers
You can trigger a pipeline when an update is pushed to the self
repository or to any of the repositories declared as resources. This is useful, for instance, in the following scenarios:
- You consume a tool or a library from a different repository. You want to run tests for your application whenever the tool or library is updated.
- You keep your YAML file in a separate repository from the application code. You want to trigger the pipeline every time an update is pushed to the application repository.
Important
Repository resource triggers only work for Azure Repos Git repositories in the same organization and when the self
repository type is Azure Repos Git. They do not work for GitHub or Bitbucket repository resources.
batch
is not supported in repository resource triggers.
If you do not specify a trigger
section in a repository resource, then the pipeline won't be triggered by changes to that repository. If you specify a trigger
section, then the behavior for triggering is similar to how CI triggers work for the self repository.
If you specify a trigger
section for multiple repository resources, then a change to any of them will start a new run.
When a pipeline is triggered, Azure Pipelines has to determine the version of the YAML file that should be used and a version for each repository that should be checked out. If a change to the self
repository triggers a pipeline, then the commit that triggered the pipeline is used to determine the version of the YAML file. If a change to any other repository resource triggers the pipeline, then the latest version of YAML from the default branch of self
repository is used.
When an update to one of the repositories triggers a pipeline, then the following variables are set based on triggering repository:
Build.Repository.ID
Build.Repository.Name
Build.Repository.Provider
Build.Repository.Uri
Build.SourceBranch
Build.SourceBranchName
Build.SourceVersion
Build.SourceVersionMessage
For the triggering repository, the commit that triggered the pipeline determines the version of the code that is checked out. For other repositories, the ref
defined in the YAML for that repository resource determines the default version that is checked out.
Consider the following example, where the self
repository contains the YAML file and repositories A
and B
contain additional source code.
trigger:
- main
- feature
resources:
repositories:
- repository: A
type: git
name: MyProject/A
ref: main
trigger:
- main
- repository: B
type: git
name: MyProject/B
ref: release
trigger:
- main
- release
steps:
- checkout: self
- checkout: A
- checkout: B
The following table shows which versions are checked out for each repository by a pipeline using the above YAML file.
Change made to | Pipeline triggered | Version of YAML | Version of self |
Version of A |
Version of B |
---|---|---|---|---|---|
main in self |
Yes | commit from main that triggered the pipeline |
commit from main that triggered the pipeline |
latest from main |
latest from release |
feature in self |
Yes | commit from feature that triggered the pipeline |
commit from feature that triggered the pipeline |
latest from main |
latest from release |
main in A |
Yes | latest from main |
latest from main |
commit from main that triggered the pipeline |
latest from release |
main in B |
Yes | latest from main |
latest from main |
latest from main |
commit from main that triggered the pipeline |
release in B |
Yes | latest from main |
latest from main |
latest from main |
commit from release that triggered the pipeline |
You can also trigger the pipeline when you create or update a pull request in any of the repositories. To do this, declare the repository resources in the YAML files as in the examples above, and configure a branch policy in the repository (Azure Repos only).
Repository details
When you check out multiple repositories, some details about the self
repository are available as variables.
When you use multi-repo triggers, some of those variables have information about the triggering repository instead.
Details about all of the repositories consumed by the job are available as a template context object called resources.repositories
.
For example, to get the ref of a non-self
repository, you could write a pipeline like this:
resources:
repositories:
- repository: other
type: git
name: MyProject/OtherTools
variables:
tools.ref: $[ resources.repositories['other'].ref ]
steps:
- checkout: self
- checkout: other
- bash: |
echo "Tools version: $TOOLS_REF"
FAQ
- Why can't I check out a repository from another project? It used to work.
- Why am I prompted to authorize resources the first time I try to check out a different repository?
Why can't I check out a repository from another project? It used to work.
Azure Pipelines provides a Limit job authorization scope to current project setting, that when enabled, doesn't permit the pipeline to access resources outside of the project that contains the pipeline. This setting can be set at either the organization or project level. If this setting is enabled, you won't be able to check out a repository in another project unless you explicitly grant access. For more information, see Job authorization scope.
Why am I prompted to authorize resources the first time I try to check out a different repository?
When you check out Azure Repos Git repositories other than the one containing the pipeline, you may be prompted to authorize access to that resource before the pipeline runs for the first time. These prompts are displayed on the pipeline run summary page.
Choose View or Authorize resources, and follow the prompts to authorize the resources.
For more information, see Troubleshooting authorization for a YAML pipeline.