116 lines
7.3 KiB
Markdown
Raw Normal View History

# Dependency auto-update
Buildtools provides tooling for automatically updating a repository's dependencies (project.json, msbuild .props, and arbitrary versions in files). Combined with [Maestro][Maestro], this allows a flow where one repository finishes an official build, and all repositories that depend on that repository get an automatically generated pull request from a bot GitHub account.
As of writing, the Repo API Compose commands are not implemented yet. This document describes auto-update in a pre-Repo-API world.
## Parts of auto-update flow
The [versions repo (dotnet/versions)][dotnet/versions] stores information about the last official build of each orchestrated repository in text files.
[Maestro][Maestro] detects changes to files in GitHub and kicks off tasks depending on the file that changed, according to [subscriptions.json][subscriptions]. For dependency auto-update, the relevent files are the build-info files in dotnet/versions.
VSTS builds are used to execute the auto-update pull request generation task. The naming scheme for these build definitions for CoreFX, CoreCLR, and WCF is `Maestro-<Project>GeneralExecutor`.
[VersionTools][VersionTools] is a library that can update and verify dependencies, commit and push changes, and make pull requests. The main BuildTools package includes "wrapper" targets/tasks that run this library, and the library's DLL.
## Auto-update in action
For example, the flow that updated upgrade PR [coreclr/pull/7472](https://github.com/dotnet/coreclr/pull/7472) with CoreFX master beta-24604-02:
1. The official build writes its output data to the dotnet/versions [build-info/dotnet/corefx/master](https://github.com/dotnet/versions/tree/0e83ecde3e99f5c13b9532e3b06003b85b83f435/build-info/dotnet/corefx/master).
1. Latest.txt stores the prerelease specifier for all packages published.
2. Latest_Packages.txt stores the full id and version identifier for each package published.
2. [Maestro][Maestro] detects the build-info commit and the subscription triggers [Maestro-CoreCLRGeneralExecutor #359499](https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_build/index?buildId=359499).
3. The VSTS build runs `/t:UpdateDependenciesAndSubmitPullRequest /p:GitHubUser=dotnet-bot /p:GitHubEmail=dotnet-bot@microsoft.com /p:GitHubAuthToken=******** /p:ProjectRepoOwner=dotnet /p:ProjectRepoName=coreclr /p:ProjectRepoBranch=master /p:NotifyGitHubUsers=dotnet/coreclr-contrib`.
1. The latest build-info Latest_Packages.txt is downloaded and used to update project.jsons and msbuild files.
2. The build searches for an auto-update PR that already exists for the branch and finds [coreclr/pull/7472](https://github.com/dotnet/coreclr/pull/7472).
3. Auto-update PRs are reused when possible, so changes are committed and pushed (`--force`) to the branch for PR 7472.
4. The build updates the title of PR 7472 to indicate the update that took place. If no auto-update PR had existed to update, it would create a fresh PR instead.
4. CI runs, and when it's green, project maintainers can merge the auto-update PR when convenient.
## Subscription
A subscription is simply the path that [Maestro][Maestro] should listen to, and what build to run when it detects a change. These are defined in [subscriptions.json][subscriptions]. For example, a subscription to create auto-update PRs in WCF for the latest CoreFX build, (comments mine):
```
{
"path": "https://github.com/dotnet/versions/blob/master/build-info/dotnet/corefx/master/Latest.txt",
"handlers": [
{
// The build definition to run, a key to a dict elsewhere in subscriptions.json.
"maestroAction": "wcf-general",
// A delay after the change is detected to allow published artifacts to propagate.
"maestroDelay": "00:10:00",
// A queue-time variable sent to the build definition. No special Maestro handling.
// The definition runs the named script with the args given in the "Arguments" variable.
"ScriptFileName": "build-managed.cmd",
// Maestro concatenates the list of arguments and passes them at queue time as a string.
"Arguments": [
"--",
"/t:UpdateDependenciesAndSubmitPullRequest",
"/p:GitHubUser=dotnet-bot",
"/p:GitHubEmail=dotnet-bot@microsoft.com",
"/p:GitHubAuthToken=`$(`$Secrets['DotNetBotGitHubPassword'])",
"/p:ProjectRepoOwner=dotnet",
"/p:ProjectRepoName=wcf",
"/p:ProjectRepoBranch=master",
"/p:NotifyGitHubUsers=dotnet/wcf-contrib",
"/verbosity:Normal"
]
}
]
}
```
([Link to subscription in context.](https://github.com/dotnet/versions/blob/0e83ecde3e99f5c13b9532e3b06003b85b83f435/Maestro/subscriptions.json#L146-L163))
`wcf-general` is [defined as](https://github.com/dotnet/versions/blob/0e83ecde3e99f5c13b9532e3b06003b85b83f435/Maestro/subscriptions.json#L51-L56) this, pointing to the definition that should be queued:
```
"wcf-general": {
"vsoInstance": "devdiv.visualstudio.com",
"vsoProject": "DevDiv",
"buildDefinitionId": 4226
}
```
### MSBuild arguments
* `/t:UpdateDependenciesAndSubmitPullRequest`: the target that invokes [VersionTools][VersionTools].
* `/p:GitHubUser=dotnet-bot`: the fork owner and committer name.
* `/p:GitHubEmail=dotnet-bot@microsoft.com`: committer email.
* `/p:GitHubAuthToken=`$(`$Secrets['DotNetBotGitHubPassword'])`: fork owner token. The build definition has this as a secret variable, and the PowerShell in this string finds the secret's value and passes it to msbuild.
* `/p:ProjectRepoOwner=dotnet`: the owner of the repo to submit the PR to.
* `/p:ProjectRepoName=wcf`: the name of the repo to submit the PR to.
* `/p:ProjectRepoBranch=master`: the base branch to PR against.
* `/p:NotifyGitHubUsers=dotnet/wcf-contrib`: a user/group to `@`-mention in the PR description. In theory a semicolon-delimited list, but the layers of JSON and PowerShell escaping make it difficult so subscriptions have only specified a single user/group so far.
## dependencies.props
For an in-depth look at `dependencies.props`, which stores the current dependencies and configures auto-update's specific behavior for a repository, read [annotated-dependency-props.md](annotated-dependency-props.md).
# Adding or removing a subscription
In general, submit a PR for changes to [subscriptions.json][subscriptions].
When adding a subscription to a new branch, if there isn't an existing "non-master" subscription to examine as an example, note that the `vsoSourceBranch` property (sibling of `maestroAction` and `maestroDelay`) tells Maestro which branch to run the GeneralExecutor on.
When adding an entirely new project, a new build definition is also needed. Look at the `Maestro-*GeneralExecutor` definitions as examples and, if possible, clone an existing one and change the repository pointer in VSTS. Add a corresponding entry to the `actions` object in subscriptions.json.
To remove a subscription, delete the entry in the `handlers` array.
When changing subscriptions.json, match the existing comment style as best as possible, because it makes searching the file more consistent.
[Maestro]: https://github.com/dotnet/versions/tree/master/Maestro
[dotnet/versions]: https://github.com/dotnet/versions
[subscriptions]: https://github.com/dotnet/versions/blob/master/Maestro/subscriptions.json
[VersionTools]: https://github.com/dotnet/buildtools/tree/094e239b8c1e7f1495abf8c7dc96c71e56bf6c96/src/Microsoft.DotNet.VersionTools