Merge branch 'main' into darc-main-d813792c-eeee-4e40-9f7c-567a78c653dd

This commit is contained in:
Igor Velikorossov 2023-10-13 15:37:20 +11:00 committed by GitHub
commit 6fdab0d5b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 924 additions and 54 deletions

22
eng/install-scancode.sh Normal file
View file

@ -0,0 +1,22 @@
#!/bin/bash
set -euo pipefail
# https://scancode-toolkit.readthedocs.io/en/latest/getting-started/install.html#installation-as-a-library-via-pip
pyEnvPath="/tmp/scancode-env"
python3 -m venv $pyEnvPath
source $pyEnvPath/bin/activate
pip install scancode-toolkit
deactivate
# Setup a script which executes scancode in the virtual environment
cat > /usr/local/bin/scancode << EOF
#!/bin/bash
set -euo pipefail
source $pyEnvPath/bin/activate
scancode "\$@"
deactivate
EOF
chmod +x /usr/local/bin/scancode

View file

@ -0,0 +1,137 @@
# Pipeline documentation at https://github.com/dotnet/dotnet/blob/main/docs/license-scanning.md
schedules:
- cron: "0 7 * * 1-5"
displayName: Run on weekdays at 7am UTC
branches:
include:
- main
- release/*
pr: none
trigger: none
parameters:
# Provides a way to scan a specific repo. If not provided, all repos of the VMR will be scanned.
- name: specificRepoName
type: string
displayName: "Specific repo name to scan (e.g. runtime, sdk). If empty, scans all repos of the VMR."
default: " " # Set it to an empty string to allow it be an optional parameter
variables:
installerRoot: '$(Build.SourcesDirectory)/src/installer'
jobs:
- job: Setup
pool:
name: NetCore1ESPool-Svc-Internal
demands: ImageOverride -equals 1es-ubuntu-2004
steps:
- script: |
vmrSrcDir="$(Build.SourcesDirectory)/src"
# Builds an Azure DevOps matrix definition. Each entry in the matrix is a path,
# allowing a job to be run for each src repo.
matrix=""
# Trim leading/trailing spaces from the repo name
specificRepoName=$(echo "${{ parameters.specificRepoName }}" | awk '{$1=$1};1')
# If the repo name is provided, only scan that repo.
if [ ! -z "$specificRepoName" ]; then
matrix="\"$specificRepoName\": { \"repoPath\": \"$vmrSrcDir/$specificRepoName\" }"
else
for dir in $vmrSrcDir/*/
do
if [ ! -z "$matrix" ]; then
matrix="$matrix,"
fi
repoName=$(basename $dir)
matrix="$matrix \"$repoName\": { \"repoPath\": \"$dir\" }"
done
fi
matrix="{ $matrix }"
echo "##vso[task.setvariable variable=matrix;isOutput=true]$matrix"
name: GetMatrix
displayName: Get Matrix
- job: LicenseScan
dependsOn: Setup
pool:
name: NetCore1ESPool-Svc-Internal
demands: ImageOverride -equals 1es-ubuntu-2004
timeoutInMinutes: 420
strategy:
matrix: $[ dependencies.Setup.outputs['GetMatrix.matrix'] ]
steps:
- script: $(Build.SourcesDirectory)/prep.sh --no-artifacts --no-bootstrap --no-prebuilts
displayName: 'Install .NET SDK'
- task: PipAuthenticate@1
displayName: 'Pip Authenticate'
inputs:
artifactFeeds: public/dotnet-public-pypi
onlyAddExtraIndex: false
- script: $(installerRoot)/eng/install-scancode.sh
displayName: Install Scancode
- script: >
$(Build.SourcesDirectory)/.dotnet/dotnet test
$(Build.SourcesDirectory)/test/Microsoft.DotNet.SourceBuild.SmokeTests/Microsoft.DotNet.SourceBuild.SmokeTests.csproj
--filter "FullyQualifiedName=Microsoft.DotNet.SourceBuild.SmokeTests.LicenseScanTests.ScanForLicenses"
--logger:'trx;LogFileName=$(Agent.JobName)_LicenseScan.trx'
--logger:'console;verbosity=detailed'
-c Release
-bl:$(Build.SourcesDirectory)/artifacts/log/Debug/BuildTests_$(date +"%m%d%H%M%S").binlog
-flp:LogFile=$(Build.SourcesDirectory)/artifacts/logs/BuildTests_$(date +"%m%d%H%M%S").log
-clp:v=m
-e SMOKE_TESTS_LICENSE_SCAN_PATH=$(repoPath)
-e SMOKE_TESTS_RUNNING_IN_CI=true
-e SMOKE_TESTS_WARN_LICENSE_SCAN_DIFFS=false
-e SMOKE_TESTS_TARGET_RID=linux-x64
-e SMOKE_TESTS_PORTABLE_RID=linux-x64
displayName: Run Tests
workingDirectory: $(Build.SourcesDirectory)
- script: |
set -x
targetFolder=$(Build.StagingDirectory)/BuildLogs/
mkdir -p ${targetFolder}
cd "$(Build.SourcesDirectory)"
find artifacts/ -type f -name "BuildTests*.binlog" -exec cp {} --parents -t ${targetFolder} \;
find artifacts/ -type f -name "BuildTests*.log" -exec cp {} --parents -t ${targetFolder} \;
echo "Updated:"
find test/ -type f -name "Updated*.json"
find test/ -type f -name "Updated*.json" -exec cp {} --parents -t ${targetFolder} \;
echo "Results:"
find test/ -type f -name "scancode-results*.json"
find test/ -type f -name "scancode-results*.json" -exec cp {} --parents -t ${targetFolder} \;
echo "All:"
ls -R test/
echo "BuildLogs:"
ls -R ${targetFolder}
displayName: Prepare BuildLogs staging directory
continueOnError: true
condition: succeededOrFailed()
- publish: '$(Build.StagingDirectory)/BuildLogs'
artifact: $(Agent.JobName)_BuildLogs_Attempt$(System.JobAttempt)
displayName: Publish BuildLogs
continueOnError: true
condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: Publish Test Results
condition: succeededOrFailed()
continueOnError: true
inputs:
testRunner: vSTest
testResultsFiles: '*.trx'
searchFolder: $(Build.SourcesDirectory)/test/Microsoft.DotNet.SourceBuild.SmokeTests/TestResults
mergeTestResults: true
publishRunAttachments: true
testRunTitle: $(Agent.JobName)

View file

@ -0,0 +1,24 @@
# License Scanning
The VMR is regularly scanned for license references to ensure that only open-source license are used where relevant.
License scanning pipline: https://dev.azure.com/dnceng/internal/_build?definitionId=1301 (internal only)
License scanning test: https://github.com/dotnet/dotnet/blob/main/test/Microsoft.DotNet.SourceBuild.SmokeTests/LicenseScanTests.cs
By default, running the pipeline will scan all repos within the VMR which takes several hours to run.
The pipeline can be triggered manually to target a specific repo within the VMR by setting the `specificRepoName` parameter.
This value should be the name of the repo within the VMR (i.e. a name of a directory within https://github.com/dotnet/dotnet/tree/main/src).
To test source modifications intended to resolve a license issue, apply the change in an internal branch of the VMR.
Run this pipeline, targeting your branch, and set the `specificRepoName` parameter to the name of the repo containing the change.
The output of the pipeline is a set of test results and logs.
The logs are published as an artifact and can be found at test/Microsoft.DotNet/SourceBuild.SmokeTests/bin/Release/netX.0/logs.
It consists of the following:
* `UpdatedLicenses.<repo-name>.json`: This is the output of that gets compared to the stored baseline.
If they're the same, the test passes; if not, it fails. By comparing this file to the baseline, one can determine which new license
references have been introduced.
If everything is deemed to be acceptable, the developer can either update the allowed licenses, update the exclusions file, update the
baseline, or any combination.
* `scancode-results.json`: This is the raw output that comes from scancode. This file is useful for diagnostic purposes because it tells you
the exact line number of where a license has been detected in a file.

View file

@ -41,12 +41,12 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests
Assert.Null(message);
}
public static void CompareBaselineContents(string baselineFileName, string actualContents, ITestOutputHelper outputHelper, bool warnOnDiffs = false)
public static void CompareBaselineContents(string baselineFileName, string actualContents, ITestOutputHelper outputHelper, bool warnOnDiffs = false, string baselineSubDir = "")
{
string actualFilePath = Path.Combine(DotNetHelper.LogsDirectory, $"Updated{baselineFileName}");
string actualFilePath = Path.Combine(TestBase.LogsDirectory, $"Updated{baselineFileName}");
File.WriteAllText(actualFilePath, actualContents);
CompareFiles(GetBaselineFilePath(baselineFileName), actualFilePath, outputHelper, warnOnDiffs);
CompareFiles(GetBaselineFilePath(baselineFileName, baselineSubDir), actualFilePath, outputHelper, warnOnDiffs);
}
public static void CompareFiles(string expectedFilePath, string actualFilePath, ITestOutputHelper outputHelper, bool warnOnDiffs = false)
@ -87,7 +87,8 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests
public static string GetAssetsDirectory() => Path.Combine(Directory.GetCurrentDirectory(), "assets");
public static string GetBaselineFilePath(string baselineFileName) => Path.Combine(GetAssetsDirectory(), "baselines", baselineFileName);
public static string GetBaselineFilePath(string baselineFileName, string baselineSubDir = "") =>
Path.Combine(GetAssetsDirectory(), "baselines", baselineSubDir, baselineFileName);
public static string RemoveRids(string diff, bool isPortable = false) =>
isPortable ? diff.Replace(Config.PortableRid, "portable-rid") : diff.Replace(Config.TargetRid, "banana-rid");

View file

@ -15,7 +15,7 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests;
/// <see cref="WebScenarioTests"/> for related web scenarios.
/// They are encapsulated in a separate testclass so that they can be run in parallel.
/// </summary>
public class BasicScenarioTests : SmokeTests
public class BasicScenarioTests : SdkTests
{
public BasicScenarioTests(ITestOutputHelper outputHelper) : base(outputHelper) { }

View file

@ -21,7 +21,9 @@ internal static class Config
public const string SourceBuiltArtifactsPathEnv = "SMOKE_TESTS_SOURCEBUILT_ARTIFACTS_PATH";
public const string TargetRidEnv = "SMOKE_TESTS_TARGET_RID";
public const string WarnSdkContentDiffsEnv = "SMOKE_TESTS_WARN_SDK_CONTENT_DIFFS";
public const string WarnLicenseScanDiffsEnv = "SMOKE_TESTS_WARN_LICENSE_SCAN_DIFFS";
public const string RunningInCIEnv = "SMOKE_TESTS_RUNNING_IN_CI";
public const string LicenseScanPathEnv = "SMOKE_TESTS_LICENSE_SCAN_PATH";
public static string DotNetDirectory { get; } =
Environment.GetEnvironmentVariable(DotNetDirectoryEnv) ?? Path.Combine(Directory.GetCurrentDirectory(), ".dotnet");
@ -32,15 +34,18 @@ internal static class Config
public static string? PrereqsPath { get; } = Environment.GetEnvironmentVariable(PrereqsPathEnv);
public static string? CustomPackagesPath { get; } = Environment.GetEnvironmentVariable(CustomPackagesPathEnv);
public static string? SdkTarballPath { get; } = Environment.GetEnvironmentVariable(SdkTarballPathEnv);
public static string SourceBuiltArtifactsPath { get; } = Environment.GetEnvironmentVariable(SourceBuiltArtifactsPathEnv) ??
throw new InvalidOperationException($"'{Config.SourceBuiltArtifactsPathEnv}' must be specified");
public static string? SourceBuiltArtifactsPath { get; } = Environment.GetEnvironmentVariable(SourceBuiltArtifactsPathEnv);
public static string TargetRid { get; } = Environment.GetEnvironmentVariable(TargetRidEnv) ??
throw new InvalidOperationException($"'{Config.TargetRidEnv}' must be specified");
public static string TargetArchitecture { get; } = TargetRid.Split('-')[1];
public static bool WarnOnSdkContentDiffs { get; } =
bool.TryParse(Environment.GetEnvironmentVariable(WarnSdkContentDiffsEnv), out bool warnOnSdkContentDiffs) && warnOnSdkContentDiffs;
public static bool WarnOnLicenseScanDiffs { get; } =
bool.TryParse(Environment.GetEnvironmentVariable(WarnLicenseScanDiffsEnv), out bool warnOnLicenseScanDiffs) && warnOnLicenseScanDiffs;
// Indicates whether the tests are being run in the context of a CI pipeline
public static bool RunningInCI { get; } =
bool.TryParse(Environment.GetEnvironmentVariable(RunningInCIEnv), out bool runningInCI) && runningInCI;
public static string? LicenseScanPath { get; } = Environment.GetEnvironmentVariable(LicenseScanPathEnv);
}

View file

@ -12,7 +12,7 @@ using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
public class DebugTests : SmokeTests
public class DebugTests : SdkTests
{
private record ScanResult(string FileName, bool HasDebugInfo, bool HasDebugAbbrevs, bool HasFileSymbols, bool HasGnuDebugLink);

View file

@ -8,7 +8,7 @@ using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
public class DotNetFormatTests : SmokeTests
public class DotNetFormatTests : SdkTests
{
private const string TestFileName = "FormatTest.cs";
private const string UnformattedFileName = "FormatTestUnformatted.cs";

View file

@ -3,14 +3,12 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
@ -21,7 +19,6 @@ internal class DotNetHelper
private static readonly object s_lockObj = new();
public static string DotNetPath { get; } = Path.Combine(Config.DotNetDirectory, "dotnet");
public static string LogsDirectory { get; } = Path.Combine(Directory.GetCurrentDirectory(), "logs");
public static string PackagesDirectory { get; } = Path.Combine(Directory.GetCurrentDirectory(), "packages");
public static string ProjectsDirectory { get; } = Path.Combine(Directory.GetCurrentDirectory(), $"projects-{DateTime.Now:yyyyMMddHHmmssffff}");
@ -56,11 +53,6 @@ internal class DotNetHelper
{
Directory.CreateDirectory(PackagesDirectory);
}
if (!Directory.Exists(LogsDirectory))
{
Directory.CreateDirectory(LogsDirectory);
}
}
}
@ -265,7 +257,7 @@ internal class DotNetHelper
fileName += $"-{differentiator}";
}
return $"/bl:{Path.Combine(LogsDirectory, $"{fileName}.binlog")}";
return $"/bl:{Path.Combine(TestBase.LogsDirectory, $"{fileName}.binlog")}";
}
private static bool DetermineIsMonoRuntime(string dotnetRoot)

View file

@ -9,7 +9,7 @@ using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
public class DotNetWatchTests : SmokeTests
public class DotNetWatchTests : SdkTests
{
public DotNetWatchTests(ITestOutputHelper outputHelper) : base(outputHelper) { }

View file

@ -0,0 +1,291 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
/// <summary>
/// Scans the VMR for licenses and compares them to a baseline. This ensures that only open-source licenses are used for relevant files.
/// </summary>
/// <remarks>
/// Each sub-repo of the VMR is scanned separately because of the amount of time it takes.
/// When scanning is run, the test provides a list of files for the scanner to ignore. These include binary file types. It also includes
/// .il/.ildump file types which are massive, causing the scanner to choke and don't include license references anyway.
/// Once the scanner returns the results, a filtering process occurs. First, any detected license that is in the allowed list of licenses
/// is filtered out. The test defines a list of such licenses that all represent open-source licenses. Next, a license exclusions file is
/// applied to the filtering. This file contains a set of paths for which certain detected licenses are to be ignored. Such a path can be
/// defined to ignore all detected licenses or specific ones. These exclusions are useful for ignoring false positives where the scanning
/// tool has detected something in the file that makes it think it's a license reference when that's not actually the intent. Other cases
/// that are excluded are when the license is meant as configuration or test data and not actually applying to the code. These exclusions
/// further filter down the set of the detected licenses for each file. Everything that's left at this point is reported. It gets compared
/// to a baseline file (which is defined for each sub-repo). If the filtered results differ from what's defined in the baseline, the test fails.
///
/// Rules for determining how to resolve a detected license:
/// 1. If it's an allowed open-source license, add it to the list of allowed licenses in LicenseScanTests.cs.
/// 2. If the file shouldn't be scanned as a general rule because of its file type (e.g. image file), add it to the list of excluded file types in LicenseScanTests.cs.
/// 3. Add it to LicenseExclusions.txt if the referenced license is one of the following:
/// a. Not applicable (e.g. test data)
/// b. False positive
/// 4. If the license is not allowed for open-souce, the license needs to be fixed. Everything else should go in the baseline file.
/// </remarks>
public class LicenseScanTests : TestBase
{
private const string BaselineSubDir = "licenses";
private static readonly string[] s_allowedLicenseExpressions = new string[]
{
"apache-1.1", // https://opensource.org/license/apache-1-1/
"apache-2.0", // https://opensource.org/license/apache-2-0/
"apache-2.0 WITH apple-runtime-library-exception", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/apple-runtime-library-exception.LICENSE
"apache-2.0 WITH llvm-exception", // https://foundation.llvm.org/relicensing/LICENSE.txt
"apsl-2.0", // https://opensource.org/license/apsl-2-0-php/
"boost-1.0", // https://opensource.org/license/bsl-1-0/
"bsd-new", // https://opensource.org/license/BSD-3-clause/
"bsd-original", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bsd-original.LICENSE
"bsd-original-uc", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bsd-original-uc.LICENSE
"bsd-simplified", // https://opensource.org/license/bsd-2-clause/
"bytemark", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bytemark.LICENSE
"bzip2-libbzip-2010", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/bzip2-libbzip-2010.LICENSE
"cc0-1.0", // https://creativecommons.org/publicdomain/zero/1.0/legalcode
"cc-by-3.0", // https://creativecommons.org/licenses/by/3.0/legalcode
"cc-by-sa-3.0", // https://creativecommons.org/licenses/by-sa/3.0/legalcode
"cc-by-sa-4.0", // https://creativecommons.org/licenses/by-sa/4.0/legalcode
"cc-pd", // https://creativecommons.org/publicdomain/mark/1.0/
"epl-1.0", // https://opensource.org/license/epl-1-0/
"generic-cla", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/generic-cla.LICENSE
"gpl-1.0-plus", // https://opensource.org/license/gpl-1-0/
"gpl-2.0", // https://opensource.org/license/gpl-2-0/
"ietf", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/ietf.LICENSE
"gpl-2.0-plus WITH autoconf-simple-exception-2.0", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/rules/gpl-2.0-plus_with_autoconf-simple-exception-2.0_8.RULE
"gpl-2.0 WITH gcc-linking-exception-2.0", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/rules/gpl-2.0_with_gcc-linking-exception-2.0_6.RULE
"isc", // https://opensource.org/license/isc-license-txt/
"iso-8879", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/iso-8879.LICENSE
"lgpl-2.0-plus", // https://opensource.org/license/lgpl-2-0/
"lgpl-2.1", // https://opensource.org/license/lgpl-2-1/
"lgpl-2.1-plus", // https://opensource.org/license/lgpl-2-1/
"mit", // https://opensource.org/license/mit/
"mit-addition", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/mit-addition.LICENSE
"ms-patent-promise", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/ms-patent-promise.LICENSE
"ms-lpl", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/ms-lpl.LICENSE
"ms-pl", // https://opensource.org/license/ms-pl-html/
"ms-rl", // https://opensource.org/license/ms-rl-html/
"newton-king-cla", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/newton-king-cla.LICENSE
"ngpl", // https://opensource.org/license/nethack-php/
"object-form-exception-to-mit", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/object-form-exception-to-mit.LICENSE
"ofl-1.1", // https://opensource.org/license/ofl-1-1/
"osf-1990", // https://fedoraproject.org/wiki/Licensing:MIT?rd=Licensing/MIT#HP_Variant
"public-domain", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/public-domain.LICENSE
"public-domain-disclaimer", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/public-domain-disclaimer.LICENSE
"python", // https://opensource.org/license/python-2-0/
"rpl-1.5", // https://opensource.org/license/rpl-1-5/
"sax-pd", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/sax-pd.LICENSE
"unicode", // https://opensource.org/license/unicode-inc-license-agreement-data-files-and-software/
"unicode-mappings", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/unicode-mappings.LICENSE
"uoi-ncsa", // https://opensource.org/license/uoi-ncsa-php/
"w3c-software-19980720", // https://opensource.org/license/w3c/
"w3c-software-doc-20150513", // https://opensource.org/license/w3c/
"warranty-disclaimer", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/warranty-disclaimer.LICENSE
"x11", // https://github.com/nexB/scancode-toolkit/blob/develop/src/licensedcode/data/licenses/x11.LICENSE
"zlib" // https://opensource.org/license/zlib/
};
private static readonly string[] s_ignoredFilePatterns = new string[]
{
"*.bin",
"*.bmp",
"*.bson",
"*.db",
"*.dic",
"*.eot",
"*.gif",
"*.ico",
"*.jpg",
"*.il",
"*.ildump",
"*.lss",
"*.nlp",
"*.otf",
"*.pdf",
"*.pfx",
"*.png",
"*.snk",
"*.ttf",
"*.vsd",
"*.vsdx",
"*.winmd",
"*.woff",
"*.woff2",
"*.xlsx",
};
private readonly string _targetRepo;
public LicenseScanTests(ITestOutputHelper outputHelper) : base(outputHelper)
{
Assert.NotNull(Config.LicenseScanPath);
_targetRepo = new DirectoryInfo(Config.LicenseScanPath).Name;
}
[SkippableFact(Config.LicenseScanPathEnv, skipOnNullOrWhiteSpaceEnv: true)]
public void ScanForLicenses()
{
Assert.NotNull(Config.LicenseScanPath);
string OriginalScancodeResultsPath = Path.Combine(LogsDirectory, "scancode-results-original.json");
string FilteredScancodeResultsPath = Path.Combine(LogsDirectory, "scancode-results-filtered.json");
// Scancode Doc: https://scancode-toolkit.readthedocs.io/en/latest/index.html
string ignoreOptions = string.Join(" ", s_ignoredFilePatterns.Select(pattern => $"--ignore {pattern}"));
ExecuteHelper.ExecuteProcessValidateExitCode(
"scancode",
$"--license --strip-root --only-findings {ignoreOptions} --json-pp {OriginalScancodeResultsPath} {Config.LicenseScanPath}",
OutputHelper);
JsonDocument doc = JsonDocument.Parse(File.ReadAllText(OriginalScancodeResultsPath));
ScancodeResults? scancodeResults = doc.Deserialize<ScancodeResults>();
Assert.NotNull(scancodeResults);
FilterFiles(scancodeResults);
JsonSerializerOptions options = new()
{
WriteIndented = true
};
string json = JsonSerializer.Serialize(scancodeResults, options);
File.WriteAllText(FilteredScancodeResultsPath, json);
string baselineName = $"Licenses.{_targetRepo}.json";
string baselinePath = BaselineHelper.GetBaselineFilePath(baselineName, BaselineSubDir);
if (!File.Exists(baselinePath))
{
Assert.Fail($"No license baseline file exists for repo '{_targetRepo}'. Expected file: {baselinePath}");
}
BaselineHelper.CompareBaselineContents(baselineName, json, OutputHelper, Config.WarnOnLicenseScanDiffs, BaselineSubDir);
}
private LicenseExclusion ParseLicenseExclusion(string rawExclusion)
{
string[] parts = rawExclusion.Split('|', StringSplitOptions.RemoveEmptyEntries);
Match repoNameMatch = Regex.Match(parts[0], @"(?<=src/)[^/]+");
Assert.True(repoNameMatch.Success);
// The path in the exclusion file is rooted from the VMR. But the path in the scancode results is rooted from the
// target repo within the VMR. So we need to strip off the beginning part of the path.
Match restOfPathMatch = Regex.Match(parts[0], @"(?<=src/[^/]+/).*");
string path = restOfPathMatch.Value;
if (parts.Length == 0 || parts.Length > 2)
{
throw new Exception($"Invalid license exclusion: '{rawExclusion}'");
}
if (parts.Length > 1)
{
string[] licenseExpressions = parts[1].Split(',', StringSplitOptions.RemoveEmptyEntries);
return new LicenseExclusion(repoNameMatch.Value, path, licenseExpressions);
}
else
{
return new LicenseExclusion(repoNameMatch.Value, path, Enumerable.Empty<string>());
}
}
private void FilterFiles(ScancodeResults scancodeResults)
{
IEnumerable<string> rawExclusions = Utilities.ParseExclusionsFile("LicenseExclusions.txt");
IEnumerable<LicenseExclusion> exclusions = rawExclusions
.Select(exclusion => ParseLicenseExclusion(exclusion))
.Where(exclusion => exclusion.Repo == _targetRepo)
.ToList();
// This will filter out files that we don't want to include in the baseline.
// Filtering can happen in two ways:
// 1. There are a set of allowed license expressions that apply to all files. If a file has a match on one of those licenses,
// that license will not be considered.
// 2. The LicenseExclusions.txt file contains a list of files and the licenses that should be excluded from those files.
// Once the license expression filtering has been applied, if a file has any licenses left, it will be included in the baseline.
// In that case, the baseline will list all of the licenses for that file, even if some were originally excluded during this processing.
// In other words, the baseline will be fully representative of the licenses that apply to the files that are listed there.
for (int i = scancodeResults.Files.Count - 1; i >= 0; i--)
{
ScancodeFileResult file = scancodeResults.Files[i];
// A license expression can be a logical expression, e.g. "(MIT OR Apache-2.0)"
// For our purposes, we just care about the license involved, not the semantics of the expression.
// Parse out all the expression syntax to just get the license names.
string[] licenses = file.LicenseExpression?
.Replace("(", string.Empty)
.Replace(")", string.Empty)
.Replace(" AND ", ",")
.Replace(" OR ", ",")
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(license => license.Trim())
.ToArray()
?? Array.Empty<string>();
// First check whether the file's licenses can all be matched with allowed expressions
IEnumerable<string> disallowedLicenses = licenses
.Where(license => !s_allowedLicenseExpressions.Contains(license, StringComparer.OrdinalIgnoreCase));
if (!disallowedLicenses.Any())
{
scancodeResults.Files.Remove(file);
}
else
{
// There are some licenses that are not allowed. Now check whether the file is excluded.
IEnumerable<LicenseExclusion> matchingExclusions =
Utilities.GetMatchingFileExclusions(file.Path, exclusions, exclusion => exclusion.Path);
IEnumerable<string> excludedLicenses = matchingExclusions.SelectMany(exclusion => exclusion.LicenseExpressions);
// If no licenses are explicitly specified, it means they're all excluded.
if (matchingExclusions.Any() && !excludedLicenses.Any())
{
scancodeResults.Files.Remove(file);
}
else
{
IEnumerable<string> remainingLicenses = disallowedLicenses.Except(excludedLicenses);
if (!remainingLicenses.Any())
{
scancodeResults.Files.Remove(file);
}
}
}
}
}
private record LicenseExclusion(string Repo, string Path, IEnumerable<string> LicenseExpressions);
private class ScancodeResults
{
[JsonPropertyName("files")]
public List<ScancodeFileResult> Files { get; set; } = new();
}
private class ScancodeFileResult
{
[JsonPropertyName("path")]
public string Path { get; set; } = string.Empty;
[JsonPropertyName("detected_license_expression")]
public string? LicenseExpression { get; set; }
}
}

View file

@ -16,7 +16,7 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests;
/// <summary>
/// OmniSharp tests to ensure it works with a source-built sdk.
/// </summary>
public class OmniSharpTests : SmokeTests
public class OmniSharpTests : SdkTests
{
// Update version as new releases become available: https://github.com/OmniSharp/omnisharp-roslyn/releases
private const string OmniSharpReleaseVersion = "1.39.8";

View file

@ -9,7 +9,7 @@ using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests
{
public class PoisonTests : SmokeTests
public class PoisonTests : SdkTests
{
public PoisonTests(ITestOutputHelper outputHelper) : base(outputHelper) { }

View file

@ -17,7 +17,7 @@ using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
[Trait("Category", "SdkContent")]
public class SdkContentTests : SmokeTests
public class SdkContentTests : SdkTests
{
private const string MsftSdkType = "msft";
private const string SourceBuildSdkType = "sb";
@ -98,7 +98,7 @@ public class SdkContentTests : SmokeTests
if (sbVersion is not null &&
msftVersion is not null &&
sbVersion >= msftVersion &&
IsFileExcluded(assemblyPath, assemblyVersionDiffFilters))
Utilities.IsFileExcluded(assemblyPath, assemblyVersionDiffFilters))
{
sbSdkAssemblyVersions.Remove(assemblyPath);
msftSdkAssemblyVersions.Remove(assemblyPath);
@ -182,7 +182,7 @@ public class SdkContentTests : SmokeTests
string relativePath = Path.GetRelativePath(sbSdkPath, file);
string normalizedPath = BaselineHelper.RemoveVersions(relativePath);
if (!IsFileExcluded(normalizedPath, exclusionFilters))
if (!Utilities.IsFileExcluded(normalizedPath, exclusionFilters))
{
sbSdkAssemblyVersions.Add(normalizedPath, GetVersion(assemblyName));
}
@ -208,32 +208,13 @@ public class SdkContentTests : SmokeTests
}
private static IEnumerable<string> RemoveExclusions(IEnumerable<string> files, IEnumerable<string> exclusions) =>
files.Where(item => !IsFileExcluded(item, exclusions));
private static bool IsFileExcluded(string filePath, IEnumerable<string> exclusions) =>
exclusions.Any(p => FileSystemName.MatchesSimpleExpression(p, filePath));
files.Where(item => !Utilities.IsFileExcluded(item, exclusions));
private static IEnumerable<string> GetSdkDiffExclusionFilters(string sdkType) =>
ParseExclusionsFile("SdkFileDiffExclusions.txt", sdkType);
Utilities.ParseExclusionsFile("SdkFileDiffExclusions.txt", sdkType);
private static IEnumerable<string> GetSdkAssemblyVersionDiffExclusionFilters() =>
ParseExclusionsFile("SdkAssemblyVersionDiffExclusions.txt");
private static IEnumerable<string> ParseExclusionsFile(string exclusionsFileName, string? prefix = null)
{
string exclusionsFilePath = Path.Combine(BaselineHelper.GetAssetsDirectory(), exclusionsFileName);
int prefixSkip = prefix?.Length + 1 ?? 0;
return File.ReadAllLines(exclusionsFilePath)
// process only specific sdk exclusions if a prefix is provided
.Where(line => prefix is null || line.StartsWith(prefix + ","))
.Select(line =>
{
// Ignore comments
var index = line.IndexOf('#');
return index >= 0 ? line[prefixSkip..index].TrimEnd() : line[prefixSkip..];
})
.ToList();
}
Utilities.ParseExclusionsFile("SdkAssemblyVersionDiffExclusions.txt");
private static string RemoveDiffMarkers(string source)
{

View file

@ -7,16 +7,14 @@ using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
/// <summary>
/// Shared base class for all smoke tests.
/// Shared base class for all SDK-based smoke tests.
/// </summary>
public abstract class SmokeTests
public abstract class SdkTests : TestBase
{
internal DotNetHelper DotNetHelper { get; }
internal ITestOutputHelper OutputHelper { get; }
protected SmokeTests(ITestOutputHelper outputHelper)
protected SdkTests(ITestOutputHelper outputHelper) : base(outputHelper)
{
DotNetHelper = new DotNetHelper(outputHelper);
OutputHelper = outputHelper;
}
}

View file

@ -13,13 +13,14 @@ using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
public class SourceBuiltArtifactsTests : SmokeTests
public class SourceBuiltArtifactsTests : SdkTests
{
public SourceBuiltArtifactsTests(ITestOutputHelper outputHelper) : base(outputHelper) { }
[Fact]
[SkippableFact(Config.SourceBuiltArtifactsPathEnv, skipOnNullOrWhiteSpaceEnv: true)]
public void VerifyVersionFile()
{
Assert.NotNull(Config.SourceBuiltArtifactsPath);
string outputDir = Path.Combine(Directory.GetCurrentDirectory(), "sourcebuilt-artifacts");
Directory.CreateDirectory(outputDir);
try

View file

@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO;
using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
public abstract class TestBase
{
public static string LogsDirectory { get; } = Path.Combine(Directory.GetCurrentDirectory(), "logs");
public ITestOutputHelper OutputHelper { get; }
public TestBase(ITestOutputHelper outputHelper)
{
OutputHelper = outputHelper;
if (!Directory.Exists(LogsDirectory))
{
Directory.CreateDirectory(LogsDirectory);
}
}
}

View file

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Formats.Tar;
using System.IO;
using System.IO.Compression;
using System.IO.Enumeration;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -18,6 +19,37 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests;
public static class Utilities
{
/// <summary>
/// Returns whether the given file path is excluded by the given exclusions using glob file matching.
/// </summary>
public static bool IsFileExcluded(string filePath, IEnumerable<string> exclusions) =>
GetMatchingFileExclusions(filePath, exclusions, exclusion => exclusion).Any();
public static IEnumerable<T> GetMatchingFileExclusions<T>(string filePath, IEnumerable<T> exclusions, Func<T, string> getExclusionExpression) =>
exclusions.Where(exclusion => FileSystemName.MatchesSimpleExpression(getExclusionExpression(exclusion), filePath));
/// <summary>
/// Parses a common file format in the test suite for listing file exclusions.
/// </summary>
/// <param name="exclusionsFileName">Name of the exclusions file.</param>
/// <param name="prefix">When specified, filters the exclusions to those that begin with the prefix value.</param>
public static IEnumerable<string> ParseExclusionsFile(string exclusionsFileName, string? prefix = null)
{
string exclusionsFilePath = Path.Combine(BaselineHelper.GetAssetsDirectory(), exclusionsFileName);
int prefixSkip = prefix?.Length + 1 ?? 0;
return File.ReadAllLines(exclusionsFilePath)
// process only specific exclusions if a prefix is provided
.Where(line => prefix is null || line.StartsWith(prefix + ","))
.Select(line =>
{
// Ignore comments
var index = line.IndexOf('#');
return index >= 0 ? line[prefixSkip..index].TrimEnd() : line[prefixSkip..];
})
.Where(line => !string.IsNullOrEmpty(line))
.ToList();
}
public static void ExtractTarball(string tarballPath, string outputDir, ITestOutputHelper outputHelper)
{
// TarFile doesn't properly handle hard links (https://github.com/dotnet/runtime/pull/85378#discussion_r1221817490),

View file

@ -16,7 +16,7 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests;
/// <see cref="BaseScenarioTests"/> for related basic scenarios.
/// They are encapsulated in a separate testclass so that they can be run in parallel.
/// </summary>
public class WebScenarioTests : SmokeTests
public class WebScenarioTests : SdkTests
{
public WebScenarioTests(ITestOutputHelper outputHelper) : base(outputHelper) { }

View file

@ -0,0 +1,257 @@
# Contains the list of files to be excluded from license scanning.
#
# This list is processed using FileSystemName.MatchesSimpleExpression
#
# Format:
# Exclude the file entirely from license scanning:
# <vmr-file-path>
# Exclude a specific detected license expression from the scan results for the file:
# <vmr-file-path>|<license-expression>[,<license-expression>...]
#
# arcade
#
# False positive
src/arcade/Documentation/UnifiedBuild/Foundational-Concepts.md
src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/src/BuildFPMToolPreReqs.cs|json
src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/rpm_templates/copyright|cecill-c
src/arcade/src/SignCheck/SignCheck/THIRD-PARTY-NOTICES.TXT
# Doesn't apply to code
src/arcade/src/Microsoft.DotNet.Arcade.Sdk/tools/Licenses/*
# Applies to installer, not source
src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix/eula.rtf
#
# aspnetcore
#
# Line 1 is a generic statement about license applicability that is being detected as "unknown"
src/aspnetcore/src/Components/THIRD-PARTY-NOTICES.txt|unknown
# Windows installer files that have a reference to a URL for license
src/aspnetcore/src/Installers/Windows/**/*.wxl|unknown-license-reference
src/aspnetcore/src/Installers/Windows/**/*.wxs|unknown-license-reference
# License reference used in configuration, but not applying to code
src/aspnetcore/src/Mvc/Settings.StyleCop|unknown-license-reference
src/aspnetcore/src/submodules/MessagePack-CSharp/stylecop.json|unknown
#
# command-line-api
#
# False positive
src/command-line-api/System.CommandLine.sln|json
#
# deployment-tools
#
# False positive
src/deployment-tools/THIRD-PARTY-NOTICES.TXT|unknown-license-reference
#
# diagnostics
#
# False positive
src/diagnostics/THIRD-PARTY-NOTICES.TXT|codesourcery-2004
#
# format
#
# False positive
src/format/THIRD-PARTY-NOTICES.TXT|unknown-license-reference
#
# fsharp
#
# False positive
src/fsharp/tests/EndToEndBuildTests/ProvidedTypes/ProvidedTypes.fs|unknown-license-reference
src/fsharp/tests/service/data/TestTP/ProvidedTypes.fs|unknown-license-reference
src/fsharp/vsintegration/tests/MockTypeProviders/DummyProviderForLanguageServiceTesting/ProvidedTypes.fs|unknown-license-reference
# Applies to installer, not source
src/fsharp/setup/resources/eula/*.rtf
#
# installer
#
# False positive
src/installer/src/core-sdk-tasks/BuildFPMToolPreReqs.cs|json
src/installer/src/redist/targets/packaging/osx/clisdk/resources/en.lproj/welcome.html|cecill-c
src/installer/THIRD-PARTY-NOTICES|proprietary-license
# Configuration, doesn't apply to source directly
src/installer/src/VirtualMonoRepo/THIRD-PARTY-NOTICES.template.txt
src/installer/src/redist/targets/packaging/**/*.json
#
# msbuild
#
# License reference used in build configuration, but not applying to code
src/msbuild/src/Directory.Build.props|ms-net-library-2018-11
# False positive
src/msbuild/src/Build/Instance/ProjectItemInstance.cs|generic-exception
#
# nuget-client
#
# False positive
src/nuget-client/build/NOTICES.txt|other-copyleft
src/nuget-client/README.md|unknown-license-reference
src/nuget-client/src/NuGet.Clients/NuGet.PackageManagement.UI/Resources.Designer.cs|unknown-license-reference
src/nuget-client/src/NuGet.Clients/NuGet.PackageManagement.UI/Actions/UIActionEngine.cs|unknown-license-reference
src/nuget-client/src/NuGet.Clients/NuGet.PackageManagement.VisualStudio/Services/NuGetPackageFileService.cs|proprietary-license
src/nuget-client/src/NuGet.Clients/NuGet.VisualStudio.Internal.Contracts/Formatters/LicenseMetadataFormatter.cs|proprietary-license
src/nuget-client/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/LicenseMetadata.cs|unknown-license-reference
src/nuget-client/src/NuGet.Core/NuGet.Packaging/Rules/DefaultManifestValuesRule.cs|unknown-license-reference
src/nuget-client/test/TestExtensions/GenerateLicenseList/Program.cs|json
# Test data
src/nuget-client/test/**/resources/*.json
src/nuget-client/test/**/resources/*.xml
src/nuget-client/test/NuGet.Clients.Tests/NuGet.PackageManagement.UI.Test/PackageLicenseUtilitiesTests.cs
src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/DefaultManifestValuesRuleTests.cs
src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/LicensesTests/LicenseExpressionTokenizerTests.cs
src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/LicensesTests/NuGetLicenseExpressionParserTests.cs
src/nuget-client/test/NuGet.Core.Tests/NuGet.Packaging.Test/LicensesTests/NuGetLicenseTests.cs
src/nuget-client/test/TestUtilities/Test.Utility/JsonData.cs
#
# roslyn-analyzers
#
# Build asset, not applicable to source
src/roslyn-analyzers/assets/EULA.txt|ms-net-library
#
# roslyn
#
# Test data
src/roslyn/src/Analyzers/VisualBasic/Tests/FileHeaders/FileHeaderTests.vb|unknown-license-reference
src/roslyn/src/EditorFeatures/CSharpTest2/EmbeddedLanguages/RegularExpressions/Regex_RealWorldPatterns.json
# False positive
src/roslyn/src/Compilers/**/Portable/Symbols/NonMissingModuleSymbol.*|proprietary-license
src/roslyn/src/NuGet/ThirdPartyNotices.rtf|json
# Applicable to installer, not source
src/roslyn/src/Setup/Roslyn.ThirdPartyNotices/ThirdPartyNotices.rtf
src/roslyn/src/Setup/Roslyn.VsixLicense/EULA.rtf
#
# runtime
#
# Doc describing licenses, not applicable to source
src/runtime/docs/project/copyright.md
src/runtime/docs/project/glossary.md
# Doc that references a license, not applicable to source
src/runtime/src/coreclr/nativeaot/docs/compiling.md|openssl-ssleay
# Installer asset, not applicable to source
src/runtime/src/installer/pkg/LICENSE-MSFT.TXT
src/runtime/src/installer/pkg/THIRD-PARTY-NOTICES.TXT
# False positive
src/runtime/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs|proprietary-license
src/runtime/src/libraries/System.Configuration.ConfigurationManager/tests/Mono/LongValidatorTest.cs|json
src/runtime/src/libraries/System.Net.Sockets/tests/FunctionalTests/Connect.cs|other-permissive
src/runtime/src/libraries/System.Net.Sockets/tests/FunctionalTests/UdpClientTest.cs|other-permissive
src/runtime/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendReceive/SendReceive.cs|other-permissive
src/runtime/src/libraries/System.Reflection.Metadata/tests/Resources/README.md|unknown-license-reference
src/runtime/src/libraries/System.Runtime/tests/TestModule/README.md|unknown-license-reference
src/runtime/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs|proprietary-license
src/runtime/src/libraries/System.ServiceModel.Syndication/tests/BasicScenarioTests.cs|unknown-license-reference
src/runtime/src/mono/mono/mini/mini-posix.c|unknown-license-reference
src/runtime/src/mono/mono/mini/mini-windows.c|unknown-license-reference
src/runtime/src/native/external/libunwind/doc/libunwind-ia64.*|generic-exception
src/runtime/src/tests/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs|unknown-license-reference
# Test data
src/runtime/src/libraries/System.Private.Xml.Linq/tests/XDocument.Common/InputSpace.cs|other-permissive
src/runtime/src/libraries/System.Private.Xml.Linq/tests/XDocument.Common/THIRD-PARTY-NOTICE|other-permissive
src/runtime/src/libraries/System.ServiceModel.Syndication/tests/TestFeeds/AtomFeeds/*.xml
src/runtime/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/AttRegexTests.cs|other-permissive
# Reference to a license, not applicable to source
src/runtime/src/libraries/System.Text.Json/roadmap/images/core-components.txt|unknown-license-reference
src/runtime/src/libraries/System.Text.Json/roadmap/images/higher-level-components.txt
# Sample data
src/runtime/src/mono/sample/wasm/browser-webpack/package-lock.json
#
# source-build-externals
#
# False positive
src/source-build-externals/src/abstractions-xunit/README.md|free-unknown
src/source-build-externals/src/application-insights/NETCORE/ThirdPartyNotices.txt|unknown
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/benchmark/Microsoft.IdentityModel.Benchmarks/CreateTokenTests.cs|proprietary-license
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/src/Microsoft.IdentityModel.JsonWebTokens/JsonClaimValueTypes.cs|proprietary-license
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/src/Microsoft.IdentityModel.Tokens.Saml/Saml/ClaimProperties.cs|proprietary-license
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/src/Microsoft.IdentityModel.Tokens.Saml/Saml/SamlTokenUtilities.cs|proprietary-license
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/src/Microsoft.IdentityModel.Tokens.Saml/Saml2/ClaimProperties.cs|proprietary-license
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/src/System.IdentityModel.Tokens.Jwt/JsonClaimValueTypes.cs|proprietary-license
src/source-build-externals/src/humanizer/readme.md|free-unknown
src/source-build-externals/src/humanizer/NuSpecs/*.nuspec*
src/source-build-externals/src/xunit/README.md|free-unknown
src/source-build-externals/src/xunit/src/xunit.assert/Asserts/README.md|free-unknown
src/source-build-externals/src/xunit/xunit.sln|json
# A patch which removes the license usage but contains references to the removed license as part of the patch reference lines
src/source-build-externals/patches/application-insights/0002-Remove-WebGrease-from-TPN-2816.patch
#
# source-build-reference-packages
#
# False positive
src/source-build-reference-packages/src/targetPacks/ILsrc/microsoft.netcore.app.ref/3.*/THIRD-PARTY-NOTICES.TXT|codesourcery-2004
src/source-build-reference-packages/src/targetPacks/ILsrc/netstandard.library/1.6.1/ThirdPartyNotices.txt|unknown
src/source-build-reference-packages/src/targetPacks/ILsrc/netstandard.library/2.0.*/THIRD-PARTY-NOTICES.TXT|unknown
src/source-build-reference-packages/src/targetPacks/ILsrc/netstandard.library.ref/2.1.0/THIRD-PARTY-NOTICES.TXT|codesourcery-2004
src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.codeanalysis.collections/4.2.0-1.22102.8/ThirdPartyNotices.rtf|json
src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.netcore.*/1.*/ThirdPartyNotices.txt|unknown
# Contains references to licenses which are not applicable to the source
src/source-build-reference-packages/src/packageSourceGenerator/PackageSourceGeneratorTask/RewriteNuspec.cs|unknown-license-reference,ms-net-library-2018-11
src/source-build-reference-packages/src/textOnlyPackages/src/microsoft.private.intellisense/8.0.0-preview-20230918.1/IntellisenseFiles/windowsdesktop/1033/PresentationCore.xml|proprietary-license
#
# sourcelink
#
# False positive
src/sourcelink/docs/GitSpec/GitSpec.md|unknown-license-reference
#
# test-templates
#
# Not applicable to source
src/test-templates/Templates/**/*.vstemplate
#
# vstest
#
# False positive
src/vstest/src/Microsoft.TestPlatform.Extensions.BlameDataCollector/ProcDumpArgsBuilder.cs|proprietary-license
# Build asset, but not applying to code
src/vstest/src/package/Microsoft.CodeCoverage/ThirdPartyNoticesCodeCoverage.txt
src/vstest/src/package/Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI/License.rtf

View file

@ -0,0 +1,20 @@
{
"files": [
{
"path": "src/tests/GC/Scenarios/GCBench/THIRD-PARTY-NOTICES",
"detected_license_expression": "unknown-license-reference"
},
{
"path": "src/tests/JIT/Performance/CodeQuality/Benchstones/BenchF/LLoops/THIRD-PARTY-NOTICES",
"detected_license_expression": "unknown-license-reference"
},
{
"path": "src/tests/JIT/Performance/CodeQuality/Benchstones/MDBenchF/MDLLoops/THIRD-PARTY-NOTICES",
"detected_license_expression": "unknown-license-reference"
},
{
"path": "src/tests/JIT/Performance/CodeQuality/V8/Richards/THIRD-PARTY-NOTICES",
"detected_license_expression": "unknown-license-reference"
}
]
}

View file

@ -0,0 +1,12 @@
{
"files": [
{
"path": "src/application-insights/LOGGING/ThirdPartyNotices.txt",
"detected_license_expression": "unknown AND apache-2.0 AND mit AND bsd-new"
},
{
"path": "src/application-insights/WEB/ThirdPartyNotices.txt",
"detected_license_expression": "bsd-new AND mit AND ms-pl AND apache-2.0 AND (cc-by-3.0-us AND cc-by-3.0 AND mit) AND ms-net-library AND ms-rl"
}
]
}