diff --git a/eng/install-scancode.sh b/eng/install-scancode.sh new file mode 100644 index 000000000..9b705f624 --- /dev/null +++ b/eng/install-scancode.sh @@ -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 diff --git a/eng/pipelines/source-build-license-scan.yml b/eng/pipelines/source-build-license-scan.yml new file mode 100644 index 000000000..bcf7e84f1 --- /dev/null +++ b/eng/pipelines/source-build-license-scan.yml @@ -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) diff --git a/src/SourceBuild/content/docs/license-scanning.md b/src/SourceBuild/content/docs/license-scanning.md new file mode 100644 index 000000000..6007776ab --- /dev/null +++ b/src/SourceBuild/content/docs/license-scanning.md @@ -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..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. diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs index f5bf4ebe8..6b7c6f71a 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs @@ -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"); diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BasicScenarioTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BasicScenarioTests.cs index cb008eccc..493898ab8 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BasicScenarioTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BasicScenarioTests.cs @@ -15,7 +15,7 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests; /// for related web scenarios. /// They are encapsulated in a separate testclass so that they can be run in parallel. /// -public class BasicScenarioTests : SmokeTests +public class BasicScenarioTests : SdkTests { public BasicScenarioTests(ITestOutputHelper outputHelper) : base(outputHelper) { } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs index 080e19d67..6bc2393e8 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs @@ -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); } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DebugTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DebugTests.cs index 939339207..c556b0e90 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DebugTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DebugTests.cs @@ -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); diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetFormatTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetFormatTests.cs index b92d0263a..13836de31 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetFormatTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetFormatTests.cs @@ -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"; diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs index 8e8f2521d..9fe99298e 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs @@ -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) diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetWatchTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetWatchTests.cs index 3fbc04899..8594c67d2 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetWatchTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetWatchTests.cs @@ -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) { } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/LicenseScanTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/LicenseScanTests.cs new file mode 100644 index 000000000..6ddf668c5 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/LicenseScanTests.cs @@ -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; + +/// +/// Scans the VMR for licenses and compares them to a baseline. This ensures that only open-source licenses are used for relevant files. +/// +/// +/// 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. +/// +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(); + 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()); + } + } + + private void FilterFiles(ScancodeResults scancodeResults) + { + IEnumerable rawExclusions = Utilities.ParseExclusionsFile("LicenseExclusions.txt"); + IEnumerable 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(); + + // First check whether the file's licenses can all be matched with allowed expressions + IEnumerable 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 matchingExclusions = + Utilities.GetMatchingFileExclusions(file.Path, exclusions, exclusion => exclusion.Path); + + IEnumerable 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 remainingLicenses = disallowedLicenses.Except(excludedLicenses); + + if (!remainingLicenses.Any()) + { + scancodeResults.Files.Remove(file); + } + } + } + } + } + + private record LicenseExclusion(string Repo, string Path, IEnumerable LicenseExpressions); + + private class ScancodeResults + { + [JsonPropertyName("files")] + public List 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; } + } +} diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs index 751b2ebeb..c604ed94a 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs @@ -16,7 +16,7 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests; /// /// OmniSharp tests to ensure it works with a source-built sdk. /// -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"; diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/PoisonTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/PoisonTests.cs index 6eb8203f5..cf2e1182b 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/PoisonTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/PoisonTests.cs @@ -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) { } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs index d3b0c8a26..29bb7dbc5 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs @@ -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 RemoveExclusions(IEnumerable files, IEnumerable exclusions) => - files.Where(item => !IsFileExcluded(item, exclusions)); - - private static bool IsFileExcluded(string filePath, IEnumerable exclusions) => - exclusions.Any(p => FileSystemName.MatchesSimpleExpression(p, filePath)); + files.Where(item => !Utilities.IsFileExcluded(item, exclusions)); private static IEnumerable GetSdkDiffExclusionFilters(string sdkType) => - ParseExclusionsFile("SdkFileDiffExclusions.txt", sdkType); + Utilities.ParseExclusionsFile("SdkFileDiffExclusions.txt", sdkType); private static IEnumerable GetSdkAssemblyVersionDiffExclusionFilters() => - ParseExclusionsFile("SdkAssemblyVersionDiffExclusions.txt"); - - private static IEnumerable 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) { diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SmokeTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkTests.cs similarity index 66% rename from src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SmokeTests.cs rename to src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkTests.cs index 3c197262b..ba3381360 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SmokeTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkTests.cs @@ -7,16 +7,14 @@ using Xunit.Abstractions; namespace Microsoft.DotNet.SourceBuild.SmokeTests; /// -/// Shared base class for all smoke tests. +/// Shared base class for all SDK-based smoke tests. /// -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; } } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SourceBuiltArtifactsTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SourceBuiltArtifactsTests.cs index 9fbbbc781..8ab1a9600 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SourceBuiltArtifactsTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SourceBuiltArtifactsTests.cs @@ -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 diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/TestBase.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/TestBase.cs new file mode 100644 index 000000000..963f07109 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/TestBase.cs @@ -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); + } + } +} diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs index ba5150bf5..8011d6f74 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs @@ -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 { + /// + /// Returns whether the given file path is excluded by the given exclusions using glob file matching. + /// + public static bool IsFileExcluded(string filePath, IEnumerable exclusions) => + GetMatchingFileExclusions(filePath, exclusions, exclusion => exclusion).Any(); + + public static IEnumerable GetMatchingFileExclusions(string filePath, IEnumerable exclusions, Func getExclusionExpression) => + exclusions.Where(exclusion => FileSystemName.MatchesSimpleExpression(getExclusionExpression(exclusion), filePath)); + + /// + /// Parses a common file format in the test suite for listing file exclusions. + /// + /// Name of the exclusions file. + /// When specified, filters the exclusions to those that begin with the prefix value. + public static IEnumerable 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), diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/WebScenarioTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/WebScenarioTests.cs index 248901530..2ee7fa1dd 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/WebScenarioTests.cs +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/WebScenarioTests.cs @@ -16,7 +16,7 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests; /// for related basic scenarios. /// They are encapsulated in a separate testclass so that they can be run in parallel. /// -public class WebScenarioTests : SmokeTests +public class WebScenarioTests : SdkTests { public WebScenarioTests(ITestOutputHelper outputHelper) : base(outputHelper) { } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/LicenseExclusions.txt b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/LicenseExclusions.txt new file mode 100644 index 000000000..e0efc77dd --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/LicenseExclusions.txt @@ -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: +# +# Exclude a specific detected license expression from the scan results for the file: +# |[,...] + +# +# 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 diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.arcade.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.arcade.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.arcade.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.aspnetcore.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.aspnetcore.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.aspnetcore.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.cecil.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.cecil.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.cecil.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.command-line-api.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.command-line-api.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.command-line-api.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.deployment-tools.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.deployment-tools.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.deployment-tools.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.diagnostics.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.diagnostics.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.diagnostics.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.emsdk.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.emsdk.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.emsdk.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.format.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.format.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.format.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.fsharp.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.fsharp.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.fsharp.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.installer.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.installer.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.installer.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.msbuild.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.msbuild.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.msbuild.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.nuget-client.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.nuget-client.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.nuget-client.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.razor.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.razor.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.razor.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.roslyn-analyzers.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.roslyn-analyzers.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.roslyn-analyzers.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.roslyn.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.roslyn.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.roslyn.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.runtime.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.runtime.json new file mode 100644 index 000000000..472899b4c --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.runtime.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.sdk.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.sdk.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.sdk.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.source-build-externals.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.source-build-externals.json new file mode 100644 index 000000000..42c3e6895 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.source-build-externals.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.source-build-reference-packages.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.source-build-reference-packages.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.source-build-reference-packages.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.sourcelink.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.sourcelink.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.sourcelink.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.symreader.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.symreader.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.symreader.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.templating.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.templating.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.templating.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.test-templates.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.test-templates.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.test-templates.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.vstest.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.vstest.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.vstest.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.xdt.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.xdt.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.xdt.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.xliff-tasks.json b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.xliff-tasks.json new file mode 100644 index 000000000..6941fa698 --- /dev/null +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/licenses/Licenses.xliff-tasks.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file