Skip to content

Commit a0086a3

Browse files
authored
Update public CI to skip on docs-only changes (#4726)
1 parent 430e782 commit a0086a3

File tree

3 files changed

+136
-12
lines changed

3 files changed

+136
-12
lines changed

eng/ci/public-build.yml

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,8 @@ pr:
1414
- release_4.0
1515
- main
1616
- in-proc
17-
paths:
18-
include:
19-
- eng
20-
- src
21-
- test
22-
exclude:
23-
- docs
24-
- '**/*.md'
17+
- feature/*
18+
2519

2620
resources:
2721
repositories:
@@ -52,8 +46,24 @@ extends:
5246
settings:
5347
# PR's from forks do not have sufficient permissions to set tags.
5448
skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }}
49+
5550
stages:
51+
- stage: PreCheck
52+
displayName: 'Pre-check: classify changes'
53+
54+
jobs:
55+
- template: /eng/ci/templates/public/jobs/precheck-docs-only.yml@self
56+
5657
- stage: Build
58+
dependsOn: PreCheck
59+
60+
# This condition ensures that if the build is not a PR (i.e a scheduled or manual build), the stages will always run.
61+
# If it is a PR, the stages will only run if the changes are not "docs-only" changes.
62+
condition: >
63+
or(
64+
ne(variables['Build.Reason'], 'PullRequest'),
65+
ne(dependencies.PreCheck.outputs['classify_changes.detect.DocsOnly'], 'true')
66+
)
5767
5868
jobs:
5969
- ${{ each runtime in split(variables.supportedRuntimes,',') }}:
@@ -63,7 +73,12 @@ extends:
6373
jobNameSuffix: ${{ replace(replace(runtime, '-', ''), '.', '') }}
6474

6575
- stage: UnitTest
66-
dependsOn: ''
76+
dependsOn: PreCheck
77+
condition: >
78+
or(
79+
ne(variables['Build.Reason'], 'PullRequest'),
80+
ne(dependencies.PreCheck.outputs['classify_changes.detect.DocsOnly'], 'true')
81+
)
6782
6883
jobs:
6984
- template: /eng/ci/templates/public/jobs/test-unit-windows.yml@self
@@ -72,19 +87,34 @@ extends:
7287
# Do we want the E2E tests for the public build?
7388
# Might need this at first whilst we work on building out solid unit tests
7489
- stage: E2ETestWindows
75-
dependsOn: ''
90+
dependsOn: PreCheck
91+
condition: >
92+
or(
93+
ne(variables['Build.Reason'], 'PullRequest'),
94+
ne(dependencies.PreCheck.outputs['classify_changes.detect.DocsOnly'], 'true')
95+
)
7696
7797
jobs:
7898
- template: /eng/ci/templates/jobs/test-e2e-windows.yml@self
7999

80100
- stage: E2ETestLinux
81-
dependsOn: ''
101+
dependsOn: PreCheck
102+
condition: >
103+
or(
104+
ne(variables['Build.Reason'], 'PullRequest'),
105+
ne(dependencies.PreCheck.outputs['classify_changes.detect.DocsOnly'], 'true')
106+
)
82107
83108
jobs:
84109
- template: /eng/ci/templates/jobs/test-e2e-linux.yml@self
85110

86111
- stage: E2ETestOSX
87-
dependsOn: ''
112+
dependsOn: PreCheck
113+
condition: >
114+
or(
115+
ne(variables['Build.Reason'], 'PullRequest'),
116+
ne(dependencies.PreCheck.outputs['classify_changes.detect.DocsOnly'], 'true')
117+
)
88118
89119
jobs:
90120
- template: /eng/ci/templates/jobs/test-e2e-osx.yml@self
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# eng/ci/templates/public/jobs/precheck-docs-only.yml
2+
parameters:
3+
- name: scriptPath
4+
type: string
5+
default: eng/scripts/classify-changes.ps1
6+
7+
jobs:
8+
- job: classify_changes
9+
displayName: 'Classify changes (docs-only vs code)'
10+
steps:
11+
- checkout: self
12+
fetchDepth: 0
13+
14+
- task: PowerShell@2
15+
name: detect
16+
displayName: 'Detect docs-only changes'
17+
inputs:
18+
pwsh: true
19+
targetType: filePath
20+
filePath: ${{ parameters.scriptPath }}

eng/scripts/classify-changes.ps1

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# eng/ci/scripts/classify-changes.ps1
2+
3+
# Read from environment variables provided by Azure DevOps
4+
$buildReason = $env:BUILD_REASON
5+
$targetBranch = $env:SYSTEM_PULLREQUEST_TARGETBRANCH
6+
$sourceBranch = $env:SYSTEM_PULLREQUEST_SOURCEBRANCH
7+
8+
Write-Host "BuildReason: $buildReason"
9+
Write-Host "TargetBranch: $targetBranch"
10+
Write-Host "SourceBranch: $sourceBranch"
11+
12+
# Default: not docs-only (for non-PR builds, schedules, etc.)
13+
if ($buildReason -ne "PullRequest") {
14+
Write-Host "Non-PR build, forcing DocsOnly = false"
15+
Write-Host "##vso[task.setvariable variable=DocsOnly;isOutput=true]false"
16+
exit 0
17+
}
18+
19+
if (-not $targetBranch) {
20+
Write-Host "No target branch provided, defaulting DocsOnly = false"
21+
Write-Host "##vso[task.setvariable variable=DocsOnly;isOutput=true]false"
22+
exit 0
23+
}
24+
25+
# Normalize target branch (AzDO usually gives refs/heads/main)
26+
$normalizedTarget = $targetBranch
27+
if ($normalizedTarget.StartsWith("refs/heads/")) {
28+
$normalizedTarget = $normalizedTarget.Substring("refs/heads/".Length)
29+
}
30+
Write-Host "Normalized target branch: $normalizedTarget"
31+
32+
# Fetch that branch
33+
Write-Host "Fetching target branch: origin/$normalizedTarget"
34+
git fetch origin $normalizedTarget --depth=1
35+
36+
# Get changed files between origin/<target> and HEAD
37+
Write-Host "Computing changed files vs origin/$normalizedTarget..."
38+
$changedFiles = git diff --name-only "origin/$normalizedTarget" "HEAD"
39+
40+
if (-not $changedFiles -or $changedFiles.Count -eq 0) {
41+
Write-Host "No changed files detected, treat as non-docs-only"
42+
Write-Host "##vso[task.setvariable variable=DocsOnly;isOutput=true]false"
43+
exit 0
44+
}
45+
46+
Write-Host "Changed files:"
47+
$changedFiles | ForEach-Object { Write-Host " - $_" }
48+
49+
$docsOnly = $true
50+
51+
foreach ($file in $changedFiles) {
52+
$leaf = [System.IO.Path]::GetFileName($file)
53+
$lowerFile = $file.ToLowerInvariant()
54+
55+
# Docs / meta rules:
56+
$isDocsPath = $file.StartsWith("docs/")
57+
$isMarkdown = $lowerFile.EndsWith(".md")
58+
$isVsCodePath = $file.StartsWith(".vscode/")
59+
$isGitHubPath = $file.StartsWith(".github/")
60+
$isLicenseLike = $leaf -in @('LICENSE', 'CODEOWNERS')
61+
62+
$isDocsOrMeta = $isDocsPath -or $isMarkdown -or $isVsCodePath -or $isGitHubPath -or $isLicenseLike
63+
64+
if (-not $isDocsOrMeta) {
65+
Write-Host "Found non-docs/meta file: $file"
66+
$docsOnly = $false
67+
break
68+
}
69+
}
70+
71+
$docsOnlyString = if ($docsOnly) { "true" } else { "false" }
72+
73+
Write-Host "DocsOnly = $docsOnlyString"
74+
Write-Host "##vso[task.setvariable variable=DocsOnly;isOutput=true]$docsOnlyString"

0 commit comments

Comments
 (0)