-
-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathupdater.ps1
218 lines (177 loc) · 8.19 KB
/
updater.ps1
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# example calls:
# .\updater.ps1 -orgName "rajbos-actions" -userName "xxx" -PAT $env:GitHubPAT
param (
[string] $orgName,
[string] $userName,
[string] $PAT,
[string] $issuesRepository
)
# example parameters:
#$repoUrl = "https://api.github.com/repos/rajbos-actions/test-repo"
#$orgName = "rajbos-actions"
# pull in central calls library
. $PSScriptRoot\github-calls.ps1
. $PSScriptRoot\library.ps1
# placeholder to enable testing locally
$testingLocally = $false
function FindRepoOrigin {
param (
[string] $repoUrl,
[string] $userName,
[string] $PAT
)
$info = CallWebRequest -url $repoUrl -userName $userName -PAT $PAT
if ($false -eq $info.fork) {
Write-Error "The repo with url [$repoUrl] is not a fork"
throw
}
Write-Host "Forks default branch = [$($info.parent.default_branch)] [$($info.parent.branches_url)] with last push [$($info.pushed_at)]"
Write-Host "Found parent [$($info.parent.html_url)] of repo [$repoUrl], last push was on [$($info.parent.pushed_at)]"
$defaultBranch = $info.parent.default_branch
$parentDefaultBranchUrl = $info.parent.branches_url -replace "{/branch}", "/$($defaultBranch)"
Write-Host "Branches url for default branch: " $parentDefaultBranchUrl
$branchLastCommitDate = GetBranchInfo -PAT $PAT -parent $info.parent.full_name -branchName $defaultBranch
if ($info.pushed_at -lt $branchLastCommitDate) {
Write-Host "There are new updates on the parent available on the default branch [$defaultBranch], last commit date: [$branchLastCommitDate]"
}
# build the compare url
$compareUrl = "https://github.com/$($info.full_name)/compare/$defaultBranch..$($info.parent.owner.login):$defaultBranch"
Write-Host "You can compare the default branches using this link: $compareUrl"
return [PSCustomObject]@{
parentUrl = $info.parent.html_url
parentArchived = $info.parent.archived
defaultBranch = $defaultBranch
lastPushRepo = $info.pushed_at
lastPushParent = $branchLastCommitDate
updateAvailable = ($info.pushed_at -lt $branchLastCommitDate)
compareUrl = $compareUrl
}
}
function GetParentHasUpdatesAvailable {
param (
[string] $repoUrl,
[string] $userName,
[string] $PAT
)
$parent = FindRepoOrigin -repoUrl $repoUrl -userName $userName -PAT $PAT
if ($null -ne $parent) {
Write-Host "The repo is forked and the fork is from [$($parent.parentUrl)]"
return $parent.updateAvailable
}
return $false
}
function CheckAllReposInOrg {
param (
[string] $orgName,
[string] $userName,
[string] $PAT,
[string] $issuesRepository
)
Write-Host "Running a check on all repositories inside of organization [$orgName] with user [$userName] and a PAT that has length [$($PAT.Length)]"
$repos = FindAllRepos -orgName $orgName -userName $userName -PAT $PAT
# create hastable
$reposWithUpdates = @()
foreach ($repo in $repos) {
if ($repo.fork -and !$repo.archived -and !$repo.disabled) {
Write-Host "Checking repository [$($repo.full_name)]"
$repoInfo = FindRepoOrigin -repoUrl $repo.url -userName $userName -PAT $PAT
if ($repoInfo.updateAvailable -or $repoInfo.parentArchived) {
Write-Host "Found new updates in the parent repository [$($repoInfo.parentUrl)], compare the changes with [$($repoInfo.compareUrl)]"
$repoData = [PSCustomObject]@{
repoName = $repo.full_name
parentArchived = $repoInfo.parentArchived
parentUrl = $repoInfo.parentUrl
compareUrl = $repoInfo.compareUrl
}
$reposWithUpdates += $repoData
}
else {
Write-Host "No updates available from parent"
}
}
else {
Write-Host "Skipping repository [$($repo.full_name)] since it is not a fork or has been archived or is disabled"
}
}
Write-Host "Found [$($reposWithUpdates.Count)] forks with available updates"
if ($null -ne $env:GITHUB_STEP_SUMMARY) {
Write-Output "Found [$($reposWithUpdates.Count)] forks with available updates" >> $env:GITHUB_STEP_SUMMARY
}
return $reposWithUpdates
}
function CreateIssueFor {
param (
[object] $repoInfo,
[string] $issuesRepositoryName,
[object] $existingIssues,
[string] $PAT,
[string] $userName
)
#Write-Host "- repoName $($repoInfo.repoName)"
#Write-Host "- parentUrl $($repoInfo.parentUrl)"
#Write-Host "- compareUrl $($repoInfo.compareUrl)"
$labels = ""
if ($repoInfo.parentArchived) {
$issueTitle = "Parent repository for [$($repoInfo.repoName)] is archived"
$body = "The parent repository for **[$($repoInfo.repoName)](https://github.com/$($repoInfo.repoName))** is archived. `r`n### Important!`r`nConsider revisiting the usage and find alternatives.`r`nLeave this issue open or it will be recreated."
$labels = "parent-archived"
} else {
$body = "The parent repository for **[$($repoInfo.repoName)](https://github.com/$($repoInfo.repoName))** has updates available. `r`n### Important!`r`nClick on this [compare link]($($repoInfo.compareUrl)) to check the incoming changes before updating the fork. `r`n `r`n### To update the fork`r`nAdd the label **update-fork** to this issue to update the fork automatically."
$issueTitle = "Parent repository for [$($repoInfo.repoName)] has updates available"
$labels = "update-available"
}
$existingIssueForRepo = $existingIssues | Where-Object {$_.title -eq $issueTitle}
if ($null -eq $existingIssueForRepo) {
CreateNewIssueForRepo -repoInfo $repo -issuesRepositoryName $issuesRepository -title $issueTitle -body $body -PAT $PAT -userName $userName -labels $labels
}
else {
# the issue already exists. Doesn't make sense to update the existing issue
# If we need to, we can send in a PATCH to the same url while adding an 'issue_number' parameter to the body
Write-Host "Issue with title [$issueTitle] already exists"
}
}
function CreateIssuesForReposWithUpdates {
param(
[object] $reposWithUpdates,
[string] $issuesRepository,
[string] $PAT,
[string] $userName
)
# load existing issues in the issues repo
# https://api.github.com/repos/{owner}/{repo}/issues
$url = "https://api.github.com/repos/$issuesRepository/issues"
$existingIssues = CallWebRequest -url $url -userName $userName -PAT $PAT
Write-Host "Found $($existingIssues.Count) existing issues in issues repository [$issuesRepository]"
foreach ($repo in $reposWithUpdates) {
CreateIssueFor -repoInfo $repo -issuesRepository $issuesRepository -existingIssues $existingIssues -PAT $PAT -userName $userName
}
}
function TestLocally {
param (
[string] $orgName,
[string] $userName,
[string] $PAT,
[string] $issuesRepository
)
$env:reposWithUpdates = $null
# load the repos with updates if we don't have them available yet
if($null -eq $env:reposWithUpdates) {
$env:reposWithUpdates = (CheckAllReposInOrg -orgName $orgName -userName $userName -PAT $PAT -issuesRepository $issuesRepository) | ConvertTo-Json
}
if ($env:reposWithUpdates.Count -gt 0) {
CreateIssuesForReposWithUpdates ($env:reposWithUpdates | ConvertFrom-Json) -issuesRepository $issuesRepository -userName $userName -PAT $PAT
}
}
# uncomment to test locally
#$orgName = "rajbos"; $userName = "xxx"; $PAT = $env:GitHubPAT; $testingLocally = $true; $issuesRepository = "rajbos/github-fork-updater"
if ($testingLocally) {
TestLocally -orgName $orgName -userName $userName -PAT $PAT -issuesRepository $issuesRepository
}
else {
# production flow:
$reposWithUpdates = CheckAllReposInOrg -orgName $orgName -userName $userName -PAT $PAT -issuesRepository $issuesRepository
if ($reposWithUpdates.Count -gt 0) {
CreateIssuesForReposWithUpdates $reposWithUpdates -issuesRepository $issuesRepository -userName $userName -PAT $PAT
}
return $reposWithUpdates
}