Skip to content

Commit 75baba3

Browse files
committed
Merge branch 'automerge-azdo'
2 parents e1a938d + b45a287 commit 75baba3

File tree

3 files changed

+250
-0
lines changed

3 files changed

+250
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<#
2+
.SYNOPSIS
3+
Returns the name of the well-known branch in the Library.Template repository upon which HEAD is based.
4+
#>
5+
[CmdletBinding(SupportsShouldProcess = $true)]
6+
Param(
7+
[switch]$ErrorIfNotRelated
8+
)
9+
10+
# This list should be sorted in order of decreasing specificity.
11+
$branchMarkers = @(
12+
@{ commit = 'fd0a7b25ccf030bbd16880cca6efe009d5b1fffc'; branch = 'microbuild' };
13+
@{ commit = '05f49ce799c1f9cc696d53eea89699d80f59f833'; branch = 'main' };
14+
)
15+
16+
foreach ($entry in $branchMarkers) {
17+
if (git rev-list HEAD | Select-String -Pattern $entry.commit) {
18+
return $entry.branch
19+
}
20+
}
21+
22+
if ($ErrorIfNotRelated) {
23+
Write-Error "Library.Template has not been previously merged with this repo. Please review https://github.com/AArnott/Library.Template/tree/main?tab=readme-ov-file#readme for instructions."
24+
exit 1
25+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# This pipeline schedules regular merges of Library.Template into a repo that is based on it.
2+
# Only Azure Repos are supported. GitHub support comes via a GitHub Actions workflow.
3+
4+
trigger: none
5+
pr: none
6+
schedules:
7+
- cron: "0 3 * * Mon" # Sun @ 8 or 9 PM Mountain Time (depending on DST)
8+
displayName: Weekly trigger
9+
branches:
10+
include:
11+
- main
12+
always: true
13+
14+
parameters:
15+
- name: AutoComplete
16+
displayName: Auto-complete pull request
17+
type: boolean
18+
default: false
19+
20+
stages:
21+
- stage: Merge
22+
jobs:
23+
- job: merge
24+
pool:
25+
vmImage: ubuntu-latest
26+
steps:
27+
- checkout: self
28+
fetchDepth: 0
29+
clean: true
30+
- pwsh: |
31+
$LibTemplateBranch = & ./azure-pipelines/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated
32+
if ($LASTEXITCODE -ne 0) {
33+
exit $LASTEXITCODE
34+
}
35+
36+
git fetch https://github.com/aarnott/Library.Template $LibTemplateBranch
37+
if ($LASTEXITCODE -ne 0) {
38+
exit $LASTEXITCODE
39+
}
40+
$LibTemplateCommit = git rev-parse FETCH_HEAD
41+
42+
if ((git rev-list FETCH_HEAD ^HEAD --count) -eq 0) {
43+
Write-Host "There are no Library.Template updates to merge."
44+
exit 0
45+
}
46+
47+
$UpdateBranchName = 'auto/libtemplateUpdate'
48+
git -c http.extraheader="AUTHORIZATION: bearer $(System.AccessToken)" push origin -f FETCH_HEAD:refs/heads/$UpdateBranchName
49+
50+
Write-Host "Creating pull request"
51+
$contentType = 'application/json';
52+
$headers = @{ Authorization = 'Bearer $(System.AccessToken)' };
53+
$rawRequest = @{
54+
sourceRefName = "refs/heads/$UpdateBranchName";
55+
targetRefName = "refs/heads/main";
56+
title = 'Merge latest Library.Template';
57+
description = "This merges the latest features and fixes from [Library.Template's $LibTemplateBranch branch](https://github.com/AArnott/Library.Template/tree/$LibTemplateBranch).";
58+
}
59+
$request = ConvertTo-Json $rawRequest
60+
61+
$prApiBaseUri = '$(System.TeamFoundationCollectionUri)/$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/pullrequests'
62+
$prCreationUri = $prApiBaseUri + "?api-version=6.0"
63+
Write-Host "POST $prCreationUri"
64+
Write-Host $request
65+
66+
$prCreationResult = Invoke-RestMethod -uri $prCreationUri -method POST -Headers $headers -ContentType $contentType -Body $request
67+
$prUrl = "$($prCreationResult.repository.webUrl)/pullrequest/$($prCreationResult.pullRequestId)"
68+
Write-Host "Pull request: $prUrl"
69+
$prApiBaseUri += "/$($prCreationResult.pullRequestId)"
70+
71+
$SummaryPath = Join-Path '$(Agent.TempDirectory)' 'summary.md'
72+
Set-Content -Path $SummaryPath -Value "[Insertion pull request]($prUrl)"
73+
Write-Host "##vso[task.uploadsummary]$SummaryPath"
74+
75+
# Tag the PR
76+
$tagUri = "$prApiBaseUri/labels?api-version=7.0"
77+
$rawRequest = @{
78+
name = 'auto-template-merge';
79+
}
80+
$request = ConvertTo-Json $rawRequest
81+
Invoke-RestMethod -uri $tagUri -method POST -Headers $headers -ContentType $contentType -Body $request | Out-Null
82+
83+
# Add properties to the PR that we can programatically parse later.
84+
Function Set-PRProperties($properties) {
85+
$rawRequest = $properties.GetEnumerator() |% {
86+
@{
87+
op = 'add'
88+
path = "/$($_.key)"
89+
from = $null
90+
value = $_.value
91+
}
92+
}
93+
$request = ConvertTo-Json $rawRequest
94+
$setPrPropertyUri = "$prApiBaseUri/properties?api-version=7.0"
95+
Write-Debug "$request"
96+
$setPrPropertyResult = Invoke-RestMethod -uri $setPrPropertyUri -method PATCH -Headers $headers -ContentType 'application/json-patch+json' -Body $request -StatusCodeVariable setPrPropertyStatus -SkipHttpErrorCheck
97+
if ($setPrPropertyStatus -ne 200) {
98+
Write-Host "##vso[task.logissue type=warning]Failed to set pull request properties. Result: $setPrPropertyStatus. $($setPrPropertyResult.message)"
99+
}
100+
}
101+
Write-Host "Setting pull request properties"
102+
Set-PRProperties @{
103+
'AutomatedMerge.SourceBranch' = $LibTemplateBranch
104+
'AutomatedMerge.SourceCommit' = $LibTemplateCommit
105+
}
106+
107+
# Add an *active* PR comment to warn users to *merge* the pull request instead of squash it.
108+
$request = ConvertTo-Json @{
109+
comments = @(
110+
@{
111+
parentCommentId = 0
112+
content = "Do **not** squash this pull request when completing it. You must *merge* it."
113+
commentType = 'system'
114+
}
115+
)
116+
status = 'active'
117+
}
118+
$result = Invoke-RestMethod -uri "$prApiBaseUri/threads?api-version=7.1" -method POST -Headers $headers -ContentType $contentType -Body $request -StatusCodeVariable addCommentStatus -SkipHttpErrorCheck
119+
if ($addCommentStatus -ne 200) {
120+
Write-Host "##vso[task.logissue type=warning]Failed to post comment on pull request. Result: $addCommentStatus. $($result.message)"
121+
}
122+
123+
# Set auto-complete on the PR
124+
if ('${{ parameters.AutoComplete }}' -eq 'True') {
125+
Write-Host "Setting auto-complete"
126+
$mergeMessage = "Merged PR $($prCreationResult.pullRequestId): " + $commitMessage
127+
$rawRequest = @{
128+
autoCompleteSetBy = @{
129+
id = $prCreationResult.createdBy.id
130+
};
131+
completionOptions = @{
132+
deleteSourceBranch = $true;
133+
mergeCommitMessage = $mergeMessage;
134+
mergeStrategy = 'noFastForward';
135+
};
136+
}
137+
$request = ConvertTo-Json $rawRequest
138+
Write-Host $request
139+
$uri = "$($prApiBaseUri)?api-version=6.0"
140+
$result = Invoke-RestMethod -uri $uri -method PATCH -Headers $headers -ContentType $contentType -Body $request -StatusCodeVariable autoCompleteStatus -SkipHttpErrorCheck
141+
if ($autoCompleteStatus -ne 200) {
142+
Write-Host "##vso[task.logissue type=warning]Failed to set auto-complete on pull request. Result: $autoCompleteStatus. $($result.message)"
143+
}
144+
}
145+
146+
displayName: Create pull request

tools/MergeFrom-Template.ps1

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
2+
<#
3+
.SYNOPSIS
4+
Merges the latest changes from Library.Template into HEAD of this repo.
5+
.PARAMETER LocalBranch
6+
The name of the local branch to create at HEAD and use to merge into from Library.Template.
7+
#>
8+
[CmdletBinding(SupportsShouldProcess = $true)]
9+
Param(
10+
[string]$LocalBranch = "dev/$($env:USERNAME)/libtemplateUpdate"
11+
)
12+
13+
Function Spawn-Tool($command, $commandArgs, $workingDirectory, $allowFailures) {
14+
if ($workingDirectory) {
15+
Push-Location $workingDirectory
16+
}
17+
try {
18+
if ($env:TF_BUILD) {
19+
Write-Host "$pwd >"
20+
Write-Host "##[command]$command $commandArgs"
21+
}
22+
else {
23+
Write-Host "$command $commandArgs" -ForegroundColor Yellow
24+
}
25+
if ($commandArgs) {
26+
& $command @commandArgs
27+
} else {
28+
Invoke-Expression $command
29+
}
30+
if ((!$allowFailures) -and ($LASTEXITCODE -ne 0)) { exit $LASTEXITCODE }
31+
}
32+
finally {
33+
if ($workingDirectory) {
34+
Pop-Location
35+
}
36+
}
37+
}
38+
39+
$remoteBranch = & $PSScriptRoot\..\azure-pipelines\Get-LibTemplateBasis.ps1 -ErrorIfNotRelated
40+
if ($LASTEXITCODE -ne 0) {
41+
exit $LASTEXITCODE
42+
}
43+
44+
$LibTemplateUrl = 'https://github.com/aarnott/Library.Template'
45+
Spawn-Tool 'git' ('fetch', $LibTemplateUrl, $remoteBranch)
46+
$SourceCommit = git rev-parse FETCH_HEAD
47+
$BaseBranch = Spawn-Tool 'git' ('branch', '--show-current')
48+
$SourceCommitUrl = "$LibTemplateUrl/commit/$SourceCommit"
49+
50+
# To reduce the odds of merge conflicts at this stage, we always move HEAD to the last successful merge.
51+
$basis = Spawn-Tool 'git' ('rev-parse', 'HEAD') # TODO: consider improving this later
52+
53+
Write-Host "Merging the $remoteBranch branch of Library.Template ($SourceCommit) into local repo $basis" -ForegroundColor Green
54+
55+
Spawn-Tool 'git' ('checkout', '-b', $LocalBranch, $basis) $null $true
56+
if ($LASTEXITCODE -eq 128) {
57+
Spawn-Tool 'git' ('checkout', $LocalBranch)
58+
Spawn-Tool 'git' ('merge', $basis)
59+
}
60+
61+
Spawn-Tool 'git' ('merge', 'FETCH_HEAD', '--no-ff', '-m', "Merge the $remoteBranch branch from $LibTemplateUrl`n`nSpecifically, this merges [$SourceCommit from that repo]($SourceCommitUrl).")
62+
if ($LASTEXITCODE -eq 1) {
63+
Write-Error "Merge conflict detected. Manual resolution required."
64+
exit 1
65+
}
66+
elseif ($LASTEXITCODE -ne 0) {
67+
Write-Error "Merge failed with exit code $LASTEXITCODE."
68+
exit $LASTEXITCODE
69+
}
70+
71+
$result = New-Object PSObject -Property @{
72+
BaseBranch = $BaseBranch # The original branch that was checked out when the script ran.
73+
LocalBranch = $LocalBranch # The name of the local branch that was created before the merge.
74+
SourceCommit = $SourceCommit # The commit from Library.Template that was merged in.
75+
SourceBranch = $remoteBranch # The branch from Library.Template that was merged in.
76+
}
77+
78+
Write-Host $result
79+
Write-Output $result

0 commit comments

Comments
 (0)