Skip to content

Commit c7ba3da

Browse files
authored
Work around license scan timeout by scanning source-build-assets serially (#20899)
1 parent ee6eb88 commit c7ba3da

3 files changed

Lines changed: 36 additions & 9 deletions

File tree

src/SourceBuild/content/eng/pipelines/vmr-license-scan.yml

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ extends:
3737
containers:
3838
licenseScanContainer:
3939
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net8.0-source-build-test-amd64
40-
options: '--memory=12g'
4140
pool:
4241
name: NetCore1ESPool-Svc-Internal
4342
image: build.azurelinux.3.amd64
@@ -69,20 +68,37 @@ extends:
6968
local name="$1"
7069
local repoPath="$2"
7170
local scanIgnorePatterns="${3:-}"
71+
local scanProcessCount="${4:-}"
7272
if [ ! -z "$matrix" ]; then
7373
matrix="$matrix,"
7474
fi
75-
matrix="$matrix \"$name\": { \"repoPath\": \"$repoPath\", \"scanIgnorePatterns\": \"$scanIgnorePatterns\" }"
75+
matrix="$matrix \"$name\": { \"repoPath\": \"$repoPath\", \"scanIgnorePatterns\": \"$scanIgnorePatterns\", \"scanProcessCount\": \"$scanProcessCount\" }"
7676
}
7777
7878
# Repos whose src/ subdirectories should be scanned as separate jobs.
7979
# The repo root is also scanned with --ignore to skip subdirectories covered by sub-scans.
8080
splitRepos="source-build-assets"
8181
82+
# Repos that should scan with a reduced number of scancode processes. This is
83+
# independent of splitRepos. Their large, text-heavy content deadlocks scancode's
84+
# multiprocessing pool at the end of a scan, so they are scanned serially (0 disables
85+
# multiprocessing). Other repos use the test's default. Flows through the matrix.
86+
serialScanRepos="source-build-assets"
87+
serialScanProcessCount=0
88+
89+
# Returns the scancode --processes value for a repo, or empty to use the test's default.
90+
getScanProcessCount() {
91+
local repoName="$1"
92+
if echo "$serialScanRepos" | grep -qw "$repoName"; then
93+
echo "$serialScanProcessCount"
94+
fi
95+
}
96+
8297
# If the repo name is provided, only scan that repo.
8398
if [ ! -z "$specificRepoName" ]; then
8499
repoName="$specificRepoName"
85100
dir="$vmrSrcDir/$specificRepoName"
101+
scanProcessCount=$(getScanProcessCount "$repoName")
86102
87103
if echo "$splitRepos" | grep -qw "$repoName"; then
88104
ignorePatterns=""
@@ -94,17 +110,18 @@ extends:
94110
ignorePatterns="$ignorePatterns "
95111
fi
96112
ignorePatterns="$ignorePatterns$subdirName"
97-
addMatrixEntry "${repoName}_${subdirName}" "$subdir"
113+
addMatrixEntry "${repoName}_${subdirName}" "$subdir" "" "$scanProcessCount"
98114
fi
99115
done
100-
addMatrixEntry "$repoName" "$dir" "$ignorePatterns"
116+
addMatrixEntry "$repoName" "$dir" "$ignorePatterns" "$scanProcessCount"
101117
else
102-
addMatrixEntry "$repoName" "$dir"
118+
addMatrixEntry "$repoName" "$dir" "" "$scanProcessCount"
103119
fi
104120
else
105121
for dir in "$vmrSrcDir"/*/
106122
do
107123
repoName=$(basename "$dir")
124+
scanProcessCount=$(getScanProcessCount "$repoName")
108125
109126
if echo "$splitRepos" | grep -qw "$repoName"; then
110127
# Root scan: skip subdirectories that are covered by sub-scans
@@ -119,12 +136,12 @@ extends:
119136
ignorePatterns="$ignorePatterns "
120137
fi
121138
ignorePatterns="$ignorePatterns$subdirName"
122-
addMatrixEntry "${repoName}_${subdirName}" "$subdir"
139+
addMatrixEntry "${repoName}_${subdirName}" "$subdir" "" "$scanProcessCount"
123140
fi
124141
done
125-
addMatrixEntry "$repoName" "$dir" "$ignorePatterns"
142+
addMatrixEntry "$repoName" "$dir" "$ignorePatterns" "$scanProcessCount"
126143
else
127-
addMatrixEntry "$repoName" "$dir"
144+
addMatrixEntry "$repoName" "$dir" "" "$scanProcessCount"
128145
fi
129146
done
130147
fi
@@ -166,6 +183,7 @@ extends:
166183
-clp:v=m
167184
-e SMOKE_TESTS_LICENSE_SCAN_PATH=$(repoPath)
168185
-e "SMOKE_TESTS_LICENSE_SCAN_IGNORE_PATTERNS=$(scanIgnorePatterns)"
186+
-e SMOKE_TESTS_LICENSE_SCAN_PROCESS_COUNT=$(scanProcessCount)
169187
-e SMOKE_TESTS_RUNNING_IN_CI=true
170188
-e SMOKE_TESTS_WARN_LICENSE_SCAN_DIFFS=false
171189
-e SMOKE_TESTS_TARGET_RID=linux-x64

src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ internal static class Config
2424
public const string RunningInCIEnv = "SMOKE_TESTS_RUNNING_IN_CI";
2525
public const string LicenseScanPathEnv = "SMOKE_TESTS_LICENSE_SCAN_PATH";
2626
public const string LicenseScanIgnorePatternsEnv = "SMOKE_TESTS_LICENSE_SCAN_IGNORE_PATTERNS";
27+
public const string LicenseScanProcessCountEnv = "SMOKE_TESTS_LICENSE_SCAN_PROCESS_COUNT";
2728

2829
public static string DotNetDirectory { get; } =
2930
Environment.GetEnvironmentVariable(DotNetDirectoryEnv) ?? Path.Combine(Directory.GetCurrentDirectory(), ".dotnet");
@@ -49,4 +50,6 @@ internal static class Config
4950

5051
public static string? LicenseScanPath { get; } = Environment.GetEnvironmentVariable(LicenseScanPathEnv);
5152
public static string? LicenseScanIgnorePatterns { get; } = Environment.GetEnvironmentVariable(LicenseScanIgnorePatternsEnv);
53+
public static int? LicenseScanProcessCount { get; } =
54+
int.TryParse(Environment.GetEnvironmentVariable(LicenseScanProcessCountEnv), out int processCount) ? processCount : null;
5255
}

src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/LicenseScanTests.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ public void ScanForLicenses()
167167
// Indicates how long until a timeout occurs for scanning a given file
168168
const int FileScanTimeoutSeconds = 1800;
169169

170+
// Number of parallel processes scancode should use. Large, text-heavy repos can
171+
// deadlock scancode's multiprocessing pool at the end of a scan, so the pipeline
172+
// scans them serially by passing 0. Default to 4 when not specified by the pipeline.
173+
const int DefaultProcessCount = 4;
174+
int processCount = Config.LicenseScanProcessCount ?? DefaultProcessCount;
175+
170176
string scancodeResultsPath = Path.Combine(LogsDirectory, "scancode-results.json");
171177

172178
// Combine default and additional ignore patterns
@@ -182,7 +188,7 @@ public void ScanForLicenses()
182188
string ignoreOptions = string.Join(" ", allIgnorePatterns.Select(pattern => $"--ignore {pattern}"));
183189
ExecuteHelper.ExecuteProcessValidateExitCode(
184190
"scancode",
185-
$"--license --processes 4 --timeout {FileScanTimeoutSeconds} --strip-root --only-findings {ignoreOptions} --json-pp {scancodeResultsPath} {Config.LicenseScanPath}",
191+
$"--license --processes {processCount} --timeout {FileScanTimeoutSeconds} --strip-root --only-findings {ignoreOptions} --json-pp {scancodeResultsPath} {Config.LicenseScanPath}",
186192
OutputHelper);
187193

188194
JsonDocument doc = JsonDocument.Parse(File.ReadAllText(scancodeResultsPath));

0 commit comments

Comments
 (0)