|
39 | 39 | if: github.repository_owner == 'MicrosoftDocs' && contains(github.event.repository.topics, 'build') |
40 | 40 | runs-on: ubuntu-latest |
41 | 41 | steps: |
42 | | - |
| 42 | + - name: Check out repo |
| 43 | + id: checkout-repo |
| 44 | + uses: actions/checkout@v4 |
| 45 | + with: |
| 46 | + ref: ${{ fromJson(inputs.PayloadJson).event.pull_request.head.sha }} |
| 47 | + |
43 | 48 | - name: Create App Token |
44 | 49 | id: app-token |
45 | 50 | uses: actions/create-github-app-token@v1 |
|
76 | 81 |
|
77 | 82 | run: | |
78 | 83 | # Get runspace info |
79 | | - $RepoRoot = $env:RUNNER_WORKSPACE |
| 84 | + $RepoRoot = $env:GITHUB_WORKSPACE |
80 | 85 | $RepoName = $env:GITHUB_REPOSITORY |
81 | 86 | $WorkflowName = $env:GITHUB_WORKFLOW -replace '[\\/:*?"<>|\s]', '_' |
82 | 87 | $WorkflowRunId = $env:GITHUB_RUN_ID |
@@ -175,6 +180,129 @@ jobs: |
175 | 180 |
|
176 | 181 | Write-Host "Repository URL: $RepoUrl" |
177 | 182 |
|
| 183 | + ##################### |
| 184 | + ##################### |
| 185 | + # Convert-DocFxMetadataPatternToRegex |
| 186 | +
|
| 187 | + Function Convert-DocFxMetadataPatternToRegex { |
| 188 | + Param ( |
| 189 | + [string]$Pattern |
| 190 | + ) |
| 191 | +
|
| 192 | + $Clean = ($Pattern -replace '\\', '/') -replace '^\./', '' |
| 193 | + $Regex = [Regex]::Escape($Clean) -replace '/\\\*\\\*/', '/(?:[^/]+/)*' ` |
| 194 | + -replace '/\\\*\\\*$', '/.*' ` |
| 195 | + -replace '\\\*\\\*', '.*' ` |
| 196 | + -replace '\\\*', '[^/]*' ` |
| 197 | + -replace '\\\?', '[^/]' |
| 198 | +
|
| 199 | + # Both absolute (starts with /) and relative patterns should anchor to repo root |
| 200 | + Return $Clean.StartsWith('/') ? "^$($Regex.TrimStart('/'))$" : "^$Regex$" |
| 201 | +
|
| 202 | + } |
| 203 | +
|
| 204 | + ##################### |
| 205 | + ##################### |
| 206 | + # Get-DocFxFileMetadataFromPattern |
| 207 | +
|
| 208 | + Function Get-DocFxFileMetadataFromPattern { |
| 209 | +
|
| 210 | + [CmdletBinding()] |
| 211 | + Param ( |
| 212 | + [object]$PatternTable, |
| 213 | +
|
| 214 | + [Parameter(Mandatory = $true)] |
| 215 | + [string]$FilePath |
| 216 | + ) |
| 217 | +
|
| 218 | + If ($PatternTable -ne $Null) { |
| 219 | + |
| 220 | + If ($PatternTable -isnot [hashtable]) { |
| 221 | +
|
| 222 | + $Ordered = [ordered]@{} |
| 223 | + $PatternTable.PSObject.Properties | ForEach-Object { $Ordered[$_.Name] = $_.Value } |
| 224 | + $PatternTable = $Ordered |
| 225 | +
|
| 226 | + } |
| 227 | +
|
| 228 | + $NormPath = ($FilePath -replace '\\', '/') -replace '^\./', '' |
| 229 | +
|
| 230 | + Foreach ($Pattern in $PatternTable.Keys) { |
| 231 | +
|
| 232 | + If ($NormPath -match (Convert-DocFxMetadataPatternToRegex -Pattern $Pattern)) { |
| 233 | +
|
| 234 | + Return $PatternTable[$Pattern] |
| 235 | +
|
| 236 | + } |
| 237 | +
|
| 238 | + } |
| 239 | +
|
| 240 | + } Else { |
| 241 | +
|
| 242 | + Write-Host "No data for specified attribute found in DocFx fileMetadata config." |
| 243 | +
|
| 244 | + } |
| 245 | +
|
| 246 | + Return $null |
| 247 | +
|
| 248 | + } |
| 249 | +
|
| 250 | + ##################### |
| 251 | + ##################### |
| 252 | + # Get-DocFxConfig |
| 253 | + |
| 254 | + Function Get-DocFxConfig { |
| 255 | + |
| 256 | + [CmdletBinding()] |
| 257 | + Param ( |
| 258 | + [Parameter(Mandatory = $true)] |
| 259 | + [string]$FilePath |
| 260 | + ) |
| 261 | + |
| 262 | + If (-not $RepoRoot) { |
| 263 | + |
| 264 | + Throw 'Repository root could not be determined.' |
| 265 | + |
| 266 | + } |
| 267 | + |
| 268 | + $FullPath = (Resolve-Path -LiteralPath $FilePath -ErrorAction Stop).Path |
| 269 | + $RepoRoot = (Resolve-Path -LiteralPath $RepoRoot -ErrorAction Stop).Path.TrimEnd([IO.Path]::DirectorySeparatorChar, [IO.Path]::AltDirectorySeparatorChar) |
| 270 | + |
| 271 | + # Confirm the file is inside the repo |
| 272 | + If (-not $FullPath.StartsWith($RepoRoot, [StringComparison]::OrdinalIgnoreCase)) { |
| 273 | + |
| 274 | + Throw 'FilePath is not located underneath the repository root.' |
| 275 | + |
| 276 | + } |
| 277 | + |
| 278 | + # Walk up the tree |
| 279 | + $CurrentDir = Split-Path -Path $FullPath -Parent |
| 280 | + |
| 281 | + While ($CurrentDir) { |
| 282 | + |
| 283 | + $Candidate = Join-Path -Path $CurrentDir -ChildPath 'docfx.json' |
| 284 | + |
| 285 | + If (Test-Path -LiteralPath $Candidate -PathType Leaf) { |
| 286 | + |
| 287 | + Write-Host "Getting DocFx config from $Candidate" |
| 288 | + |
| 289 | + Return (Get-Content -LiteralPath $Candidate -Raw) | ConvertFrom-Json -AsHashtable |
| 290 | + } |
| 291 | + |
| 292 | + If ($CurrentDir.TrimEnd([IO.Path]::DirectorySeparatorChar, [IO.Path]::AltDirectorySeparatorChar) -eq $RepoRoot) { |
| 293 | + |
| 294 | + Break |
| 295 | + |
| 296 | + } |
| 297 | + |
| 298 | + # Get the parent of the current folder |
| 299 | + $CurrentDir = Split-Path -Path $CurrentDir -Parent |
| 300 | + |
| 301 | + } |
| 302 | + |
| 303 | + Return $null |
| 304 | + } |
| 305 | + |
178 | 306 | ##################### |
179 | 307 | ##################### |
180 | 308 | # Get-FileMetadata |
@@ -209,32 +337,130 @@ jobs: |
209 | 337 | $FileContentsBase64 = Invoke-RestMethod -Method GET -Uri $File.contents_url -Headers $GitHubHeaders |
210 | 338 | $FileContents = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($FileContentsBase64.content)) |
211 | 339 |
|
212 | | - # Check to see if the file contents contains a string that matches the $AuthorRegex regex pattern. If yes, add value to $Author, if not assign $Null. |
| 340 | + # Retrieve DocFx configuration that applies to current file. Retrieving for each file is inefficient but most PRs only have a few files in them. |
| 341 | + # Pre-processing to be more efficient could actually use more cycles. |
| 342 | + $DocFxConfig = Get-DocFxConfig -FilePath $FileName |
| 343 | + |
| 344 | + # Check to see if the file contents contains a string that matches the $AuthorRegex regex pattern. If yes, add value to $Author, check |
| 345 | + # fileMetadata and globalMetadata in that order in DocFx. If there's a match in either of those, return value. If not, return null. |
213 | 346 | If ($FileContents -match $AuthorRegex) { |
| 347 | + |
214 | 348 | $Author = $Matches[2] |
215 | 349 | $MetadataFound = $True |
| 350 | + |
216 | 351 | Write-Host "Found author $Author." |
| 352 | + |
217 | 353 | } Else { |
218 | | - $Author = $Null |
| 354 | + |
| 355 | + Write-Host "Author not found in article. Checking DocFx fileMetadata for $FileName." |
| 356 | + |
| 357 | + $Author = Get-DocFxFileMetadataFromPattern -PatternTable $DocFxConfig.build.fileMetadata.author -FilePath $FileName |
| 358 | + |
| 359 | + If ($Author -ne $Null) { |
| 360 | + |
| 361 | + Write-Host "Author $Author found in DocFx fileMetadata." |
| 362 | + $MetadataFound = $True |
| 363 | + |
| 364 | + } Else { |
| 365 | + |
| 366 | + $Author = $DocFxConfig.build.globalMetadata.author |
| 367 | + |
| 368 | + If ($Author -ne $Null) { |
| 369 | + |
| 370 | + Write-Host "Author $Author found in DocFx globalMetadata." |
| 371 | + $MetadataFound = $True |
| 372 | + |
| 373 | + } Else { |
| 374 | + |
| 375 | + Write-Host "Author not found in DocFx globalMetadata. Returning null." |
| 376 | + $Author = $Null |
| 377 | + |
| 378 | + } |
| 379 | + |
| 380 | + } |
| 381 | + |
219 | 382 | } |
220 | 383 |
|
221 | | - # Check to see if file contents contains a string that matches the $ServiceRegex regex pattern. If yes, add value to $Service. Then check SubService regex pattern. |
222 | | - # If value isn't matched, assign $Null and don't check SubService. |
223 | | - If ($FileContents -match $ServiceRegex) { |
| 384 | + # Check to see if file contents contains a string that matches the $ServiceRegex regex pattern. If yes, add value to $Service, check |
| 385 | + # fileMetadata and globalMetadata in that order in DocFx. If there's a match in either of those, return value. If not, return null. |
| 386 | + |
| 387 | + If ($FileContents -match $ServiceRegex) { |
| 388 | + |
224 | 389 | $Service = $Matches[2] |
225 | 390 | $MetadataFound = $True |
| 391 | + |
226 | 392 | Write-Host "Found service $Service." |
227 | | - If ($FileContents -match $SubServiceRegex) |
228 | | - { |
229 | | - $SubService = $Matches[2] |
230 | | - $MetadataFound = $True |
231 | | - Write-Host "Found sub service $SubService." |
232 | | - } Else { |
233 | | - $SubService = $Null |
234 | | - } |
| 393 | + |
235 | 394 | } Else { |
236 | | - $Service = $Null |
| 395 | + |
| 396 | + Write-Host "Service not found in article. Checking DocFx fileMetadata for $FileName." |
| 397 | + |
| 398 | + $Service = Get-DocFxFileMetadataFromPattern -PatternTable $DocFxConfig.build.fileMetadata.'ms.service' -FilePath $FileName |
| 399 | + |
| 400 | + If ($Service -ne $Null) { |
| 401 | + |
| 402 | + Write-Host "Service $Service found in DocFx fileMetadata." |
| 403 | + $MetadataFound = $True |
| 404 | + |
| 405 | + |
| 406 | + } Else { |
| 407 | + |
| 408 | + $Service = $DocFxConfig.build.globalMetadata.'ms.service' |
| 409 | + |
| 410 | + If ($Service -ne $Null) { |
| 411 | + |
| 412 | + Write-Host "Service $Service found in DocFx globalMetadata." |
| 413 | + $MetadataFound = $True |
| 414 | + |
| 415 | + } Else { |
| 416 | + |
| 417 | + Write-Host "Service not found in DocFx globalMetadata. Returning null." |
| 418 | + $Service = $Null |
| 419 | + |
| 420 | + } |
| 421 | + |
| 422 | + } |
| 423 | + |
237 | 424 | } |
| 425 | + |
| 426 | + # Check to see if file contents contains a string that matches the $SubServiceRegex regex pattern. If yes, add value to $SubService, check |
| 427 | + # fileMetadata and globalMetadata in that order in DocFx. If there's a match in either of those, return value. If not, return null. |
| 428 | + If ($FileContents -match $SubServiceRegex) { |
| 429 | + |
| 430 | + $SubService = $Matches[2] |
| 431 | + $MetadataFound = $True |
| 432 | + |
| 433 | + Write-Host "Found sub service $SubService." |
| 434 | + |
| 435 | + } Else { |
| 436 | + |
| 437 | + Write-Host "SubService not found in article. Checking DocFx fileMetadata for $FileName." |
| 438 | + |
| 439 | + $SubService = Get-DocFxFileMetadataFromPattern -PatternTable $DocFxConfig.build.fileMetadata.'ms.subservice' -FilePath $FileName |
| 440 | + |
| 441 | + If ($SubService -ne $Null) { |
| 442 | + |
| 443 | + Write-Host "SubService $SubService found in DocFx fileMetadata." |
| 444 | + |
| 445 | + } Else { |
| 446 | + |
| 447 | + $SubService = $DocFxConfig.build.globalMetadata.'ms.subservice' |
| 448 | + |
| 449 | + If ($SubService -ne $Null) { |
| 450 | + |
| 451 | + Write-Host "SubService $SubService found in DocFx globalMetadata." |
| 452 | + |
| 453 | + } Else { |
| 454 | + |
| 455 | + Write-Host "SubService not found in DocFx globalMetadata. Returning null." |
| 456 | + $SubService = $Null |
| 457 | + |
| 458 | + } |
| 459 | + |
| 460 | + } |
| 461 | + |
| 462 | + } |
| 463 | + |
238 | 464 | # Check to see if file contents contains a string that matches the $ProdRegex regex pattern. If yes, add value to $Product. Then check TechnologyRegex regex pattern. |
239 | 465 | # If value isn't matched, assign $Null and don't check Technology. |
240 | 466 | If ($FileContents -match $ProdRegex) { |
@@ -1060,6 +1286,7 @@ jobs: |
1060 | 1286 | } |
1061 | 1287 |
|
1062 | 1288 |
|
| 1289 | + |
1063 | 1290 | ##################### |
1064 | 1291 | ##################### |
1065 | 1292 | # Main |
@@ -1338,3 +1565,4 @@ jobs: |
1338 | 1565 | Write-Host "Event action not ready_for_review, opened, reopened, or synchronize." |
1339 | 1566 |
|
1340 | 1567 | } # PR event and action check |
| 1568 | + |
0 commit comments