Replace RunTests scripts with .NET app (#20337)

This commit is contained in:
Brennan 2020-04-01 09:01:34 -07:00 committed by GitHub
parent b73e221c64
commit ca5cd91d68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 444 additions and 173 deletions

View File

@ -0,0 +1,2 @@
<Project>
</Project>

View File

@ -0,0 +1,2 @@
<Project>
</Project>

View File

@ -0,0 +1,20 @@
// 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.
namespace RunTests
{
public class ProcessResult
{
public ProcessResult(string standardOutput, string standardError, int exitCode)
{
StandardOutput = standardOutput;
StandardError = standardError;
ExitCode = exitCode;
}
public string StandardOutput { get; }
public string StandardError { get; }
public int ExitCode { get; }
}
}

View File

@ -0,0 +1,158 @@
// 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.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
#nullable enable
namespace RunTests
{
public static class ProcessUtil
{
[DllImport("libc", SetLastError = true, EntryPoint = "kill")]
private static extern int sys_kill(int pid, int sig);
public static async Task<ProcessResult> RunAsync(
string filename,
string arguments,
string? workingDirectory = null,
bool throwOnError = true,
IDictionary<string, string?>? environmentVariables = null,
Action<string>? outputDataReceived = null,
Action<string>? errorDataReceived = null,
Action<int>? onStart = null,
CancellationToken cancellationToken = default)
{
Console.WriteLine($"Running '{filename} {arguments}'");
using var process = new Process()
{
StartInfo =
{
FileName = filename,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
},
EnableRaisingEvents = true
};
if (workingDirectory != null)
{
process.StartInfo.WorkingDirectory = workingDirectory;
}
if (environmentVariables != null)
{
foreach (var kvp in environmentVariables)
{
process.StartInfo.Environment.Add(kvp);
}
}
var outputBuilder = new StringBuilder();
process.OutputDataReceived += (_, e) =>
{
if (e.Data != null)
{
if (outputDataReceived != null)
{
outputDataReceived.Invoke(e.Data);
}
else
{
outputBuilder.AppendLine(e.Data);
}
}
};
var errorBuilder = new StringBuilder();
process.ErrorDataReceived += (_, e) =>
{
if (e.Data != null)
{
if (errorDataReceived != null)
{
errorDataReceived.Invoke(e.Data);
}
else
{
errorBuilder.AppendLine(e.Data);
}
}
};
var processLifetimeTask = new TaskCompletionSource<ProcessResult>();
process.Exited += (_, e) =>
{
Console.WriteLine($"'{process.StartInfo.FileName} {process.StartInfo.Arguments}' completed with exit code '{process.ExitCode}'");
if (throwOnError && process.ExitCode != 0)
{
processLifetimeTask.TrySetException(new InvalidOperationException($"Command {filename} {arguments} returned exit code {process.ExitCode}"));
}
else
{
processLifetimeTask.TrySetResult(new ProcessResult(outputBuilder.ToString(), errorBuilder.ToString(), process.ExitCode));
}
};
process.Start();
onStart?.Invoke(process.Id);
process.BeginOutputReadLine();
process.BeginErrorReadLine();
var cancelledTcs = new TaskCompletionSource<object?>();
await using var _ = cancellationToken.Register(() => cancelledTcs.TrySetResult(null));
var result = await Task.WhenAny(processLifetimeTask.Task, cancelledTcs.Task);
if (result == cancelledTcs.Task)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
sys_kill(process.Id, sig: 2); // SIGINT
var cancel = new CancellationTokenSource();
await Task.WhenAny(processLifetimeTask.Task, Task.Delay(TimeSpan.FromSeconds(5), cancel.Token));
cancel.Cancel();
}
if (!process.HasExited)
{
process.CloseMainWindow();
if (!process.HasExited)
{
process.Kill();
}
}
}
return await processLifetimeTask.Task;
}
public static void KillProcess(int pid)
{
try
{
using var process = Process.GetProcessById(pid);
process?.Kill();
}
catch (ArgumentException) { }
catch (InvalidOperationException) { }
}
}
}

View File

@ -0,0 +1,235 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace RunTests
{
class Program
{
static async Task Main(string[] args)
{
var command = new RootCommand()
{
new Option(
aliases: new string[] { "--target", "-t" },
description: "The test dll to run")
{ Argument = new Argument<string>(), Required = true },
new Option(
aliases: new string[] { "--sdk" },
description: "The version of the sdk being used")
{ Argument = new Argument<string>(), Required = true },
new Option(
aliases: new string[] { "--runtime" },
description: "The version of the runtime being used")
{ Argument = new Argument<string>(), Required = true },
new Option(
aliases: new string[] { "--queue" },
description: "The name of the Helix queue being run on")
{ Argument = new Argument<string>(), Required = true },
new Option(
aliases: new string[] { "--arch" },
description: "The architecture being run on")
{ Argument = new Argument<string>(), Required = true },
new Option(
aliases: new string[] { "--quarantined" },
description: "Whether quarantined tests should run or not")
{ Argument = new Argument<bool>(), Required = true },
new Option(
aliases: new string[] { "--ef" },
description: "The version of the EF tool to use")
{ Argument = new Argument<string>(), Required = true },
};
var parseResult = command.Parse(args);
var target = parseResult.ValueForOption<string>("--target");
var sdkVersion = parseResult.ValueForOption<string>("--sdk");
var runtimeVersion = parseResult.ValueForOption<string>("--runtime");
var helixQueue = parseResult.ValueForOption<string>("--queue");
var architecture = parseResult.ValueForOption<string>("--arch");
var quarantined = parseResult.ValueForOption<bool>("--quarantined");
var efVersion = parseResult.ValueForOption<string>("--ef");
var HELIX_WORKITEM_ROOT = Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT");
var path = Environment.GetEnvironmentVariable("PATH");
var dotnetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT");
// Rename default.NuGet.config to NuGet.config if there is not a custom one from the project
// We use a local NuGet.config file to avoid polluting global machine state and avoid relying on global machine state
if (!File.Exists("NuGet.config"))
{
File.Copy("default.NuGet.config", "NuGet.config");
}
var environmentVariables = new Dictionary<string, string>();
environmentVariables.Add("PATH", path);
environmentVariables.Add("DOTNET_ROOT", dotnetRoot);
environmentVariables.Add("helix", helixQueue);
Console.WriteLine($"Current Directory: {HELIX_WORKITEM_ROOT}");
var helixDir = HELIX_WORKITEM_ROOT;
Console.WriteLine($"Setting HELIX_DIR: {helixDir}");
environmentVariables.Add("HELIX_DIR", helixDir);
environmentVariables.Add("NUGET_FALLBACK_PACKAGES", helixDir);
var nugetRestore = Path.Combine(helixDir, "nugetRestore");
Console.WriteLine($"Creating nuget restore directory: {nugetRestore}");
environmentVariables.Add("NUGET_RESTORE", nugetRestore);
var dotnetEFFullPath = Path.Combine(nugetRestore, $"dotnet-ef/{efVersion}/tools/netcoreapp3.1/any/dotnet-ef.exe");
Console.WriteLine($"Set DotNetEfFullPath: {dotnetEFFullPath}");
environmentVariables.Add("DotNetEfFullPath", dotnetEFFullPath);
Console.WriteLine("Checking for Microsoft.AspNetCore.App/");
if (Directory.Exists("Microsoft.AspNetCore.App"))
{
Console.WriteLine($"Found Microsoft.AspNetCore.App/, copying to {dotnetRoot}/shared/Microsoft.AspNetCore.App/{runtimeVersion}");
foreach (var file in Directory.EnumerateFiles("Microsoft.AspNetCore.App", "*.*", SearchOption.AllDirectories))
{
File.Copy(file, $"{dotnetRoot}/shared/Microsoft.AspNetCore.App/{runtimeVersion}", overwrite: true);
}
Console.WriteLine($"Adding current directory to nuget sources: {HELIX_WORKITEM_ROOT}");
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
$"nuget add source {HELIX_WORKITEM_ROOT} --configfile NuGet.config",
environmentVariables: environmentVariables);
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
"nuget add source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json --configfile NuGet.config",
environmentVariables: environmentVariables);
// Write nuget sources to console, useful for debugging purposes
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
"nuget list source",
environmentVariables: environmentVariables,
outputDataReceived: Console.WriteLine,
errorDataReceived: Console.WriteLine);
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
$"tool install dotnet-ef --global --version {efVersion}",
environmentVariables: environmentVariables);
// ';' is the path separator on Windows, and ':' on Unix
path += RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ";" : ":";
path += $"{Environment.GetEnvironmentVariable("DOTNET_CLI_HOME")}/.dotnet/tools";
environmentVariables["PATH"] = path;
}
Directory.CreateDirectory(nugetRestore);
// Rename default.runner.json to xunit.runner.json if there is not a custom one from the project
if (!File.Exists("xunit.runner.json"))
{
File.Copy("default.runner.json", "xunit.runner.json");
}
Console.WriteLine();
Console.WriteLine("Displaying directory contents:");
foreach (var file in Directory.EnumerateFiles("./"))
{
Console.WriteLine(Path.GetFileName(file));
}
foreach (var file in Directory.EnumerateDirectories("./"))
{
Console.WriteLine(Path.GetFileName(file));
}
Console.WriteLine();
// Run test discovery so we know if there are tests to run
var discoveryResult = await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
$"vstest {target} -lt",
environmentVariables: environmentVariables);
if (discoveryResult.StandardOutput.Contains("Exception thrown"))
{
Console.WriteLine("Exception thrown during test discovery.");
Console.WriteLine(discoveryResult.StandardOutput);
Environment.Exit(1);
return;
}
var exitCode = 0;
var commonTestArgs = $"vstest {target} --logger:xunit --logger:\"console;verbosity=normal\" --blame";
if (quarantined)
{
Console.WriteLine("Running quarantined tests.");
// Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
var result = await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
commonTestArgs + " --TestCaseFilter:\"Quarantined=true\"",
environmentVariables: environmentVariables,
outputDataReceived: Console.WriteLine,
errorDataReceived: Console.WriteLine,
throwOnError: false);
if (result.ExitCode != 0)
{
Console.WriteLine($"Failure in quarantined tests. Exit code: {result.ExitCode}.");
}
}
else
{
Console.WriteLine("Running non-quarantined tests.");
// Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
var result = await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
commonTestArgs + " --TestCaseFilter:\"Quarantined!=true\"",
environmentVariables: environmentVariables,
outputDataReceived: Console.WriteLine,
errorDataReceived: Console.Error.WriteLine,
throwOnError: false);
if (result.ExitCode != 0)
{
Console.WriteLine($"Failure in non-quarantined tests. Exit code: {result.ExitCode}.");
exitCode = result.ExitCode;
}
}
// 'testResults.xml' is the file Helix looks for when processing test results
Console.WriteLine();
if (File.Exists("TestResults/TestResults.xml"))
{
Console.WriteLine("Copying TestResults/TestResults.xml to ./testResults.xml");
File.Copy("TestResults/TestResults.xml", "testResults.xml");
}
else
{
Console.WriteLine("No test results found.");
}
var HELIX_WORKITEM_UPLOAD_ROOT = Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT");
Console.WriteLine($"Copying artifacts/log/ to {HELIX_WORKITEM_UPLOAD_ROOT}/");
if (Directory.Exists("artifacts/log"))
{
foreach (var file in Directory.EnumerateFiles("artifacts/log", "*.log", SearchOption.AllDirectories))
{
// Combine the directory name + log name for the copied log file name to avoid overwriting duplicate test names in different test projects
var logName = $"{Path.GetFileName(Path.GetDirectoryName(file))}_{Path.GetFileName(file)}";
Console.WriteLine($"Copying: {file} to {Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, logName)}");
// Need to copy to HELIX_WORKITEM_UPLOAD_ROOT and HELIX_WORKITEM_UPLOAD_ROOT/../ in order for Azure Devops attachments to link properly and for Helix to store the logs
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, logName));
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, "..", logName));
}
}
else
{
Console.WriteLine("No logs found in artifacts/log");
}
Console.WriteLine("Completed Helix job.");
Environment.Exit(exitCode);
}
}
}

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20158.1" />
</ItemGroup>
</Project>

View File

@ -2,5 +2,6 @@
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View File

@ -3,13 +3,9 @@ REM Need delayed expansion !PATH! so parens in the path don't mess up the parens
setlocal enabledelayedexpansion
REM Use '$' as a variable name prefix to avoid MSBuild variable collisions with these variables
set $target=%1
set $sdkVersion=%2
set $runtimeVersion=%3
set $helixQueue=%4
set $arch=%5
set $quarantined=%6
set $efVersion=%7
set DOTNET_HOME=%HELIX_CORRELATION_PAYLOAD%\sdk
set DOTNET_ROOT=%DOTNET_HOME%\%$arch%
@ -24,89 +20,11 @@ powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePo
echo "Installing Runtime"
powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -useb 'https://dot.net/v1/dotnet-install.ps1'))) -Architecture %$arch% -Runtime dotnet -Version %$runtimeVersion% -InstallDir %DOTNET_ROOT%"
REM "Rename default.NuGet.config to NuGet.config if there is not a custom one from the project"
if not EXIST ".\NuGet.config" (
copy default.NuGet.config NuGet.config
)
echo "Checking for Microsoft.AspNetCore.App"
if EXIST ".\Microsoft.AspNetCore.App" (
echo "Found Microsoft.AspNetCore.App, copying to %DOTNET_ROOT%\shared\Microsoft.AspNetCore.App\%runtimeVersion%"
xcopy /i /y ".\Microsoft.AspNetCore.App" %DOTNET_ROOT%\shared\Microsoft.AspNetCore.App\%runtimeVersion%\
echo "Adding current directory to nuget sources: %HELIX_WORKITEM_ROOT%"
dotnet nuget add source %HELIX_WORKITEM_ROOT% --configfile NuGet.config
dotnet nuget add source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json --configfile NuGet.config
dotnet nuget list source
dotnet tool install dotnet-ef --global --version %$efVersion%
set PATH=!PATH!;%DOTNET_CLI_HOME%\.dotnet\tools
)
echo "Current Directory: %HELIX_WORKITEM_ROOT%"
set HELIX=%$helixQueue%
set HELIX_DIR=%HELIX_WORKITEM_ROOT%
set NUGET_FALLBACK_PACKAGES=%HELIX_DIR%
set NUGET_RESTORE=%HELIX_DIR%\nugetRestore
set DotNetEfFullPath=%HELIX_DIR%\nugetRestore\dotnet-ef\%$efVersion%\tools\netcoreapp3.1\any\dotnet-ef.exe
echo "Set DotNetEfFullPath: %DotNetEfFullPath%"
echo "Setting HELIX_DIR: %HELIX_DIR%"
echo Creating nuget restore directory: %NUGET_RESTORE%
mkdir %NUGET_RESTORE%
mkdir logs
REM "Rename default.runner.json to xunit.runner.json if there is not a custom one from the project"
if not EXIST ".\xunit.runner.json" (
copy default.runner.json xunit.runner.json
)
dir
%DOTNET_ROOT%\dotnet vstest %$target% -lt >discovered.txt
find /c "Exception thrown" discovered.txt
REM "ERRORLEVEL is not %ERRORLEVEL%" https://blogs.msdn.microsoft.com/oldnewthing/20080926-00/?p=20743/
if not errorlevel 1 (
echo Exception thrown during test discovery. 1>&2
type discovered.txt 1>&2
exit /b 1
)
set exit_code=0
if %$quarantined%==True (
set %$quarantined=true
)
REM Disable "!Foo!" expansions because they break the filter syntax
setlocal disabledelayedexpansion
set NONQUARANTINE_FILTER="Quarantined!=true"
set QUARANTINE_FILTER="Quarantined=true"
if %$quarantined%==true (
echo Running quarantined tests.
%DOTNET_ROOT%\dotnet vstest %$target% --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:%QUARANTINE_FILTER%
if errorlevel 1 (
echo Failure in quarantined test 1>&2
REM DO NOT EXIT and DO NOT SET EXIT_CODE to 1
)
) else (
REM Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
echo Running non-quarantined tests.
%DOTNET_ROOT%\dotnet vstest %$target% --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:%NONQUARANTINE_FILTER%
if errorlevel 1 (
echo Failure in non-quarantined test 1>&2
set exit_code=1
REM DO NOT EXIT
)
)
echo "Copying TestResults\TestResults.xml to ."
copy TestResults\TestResults.xml testResults.xml
echo "Copying artifacts/logs to %HELIX_WORKITEM_UPLOAD_ROOT%\..\"
for /R artifacts/log %%f in (*.log) do (
echo "Copying: %%f"
copy "%%f" %HELIX_WORKITEM_UPLOAD_ROOT%\..\
copy "%%f" %HELIX_WORKITEM_UPLOAD_ROOT%\
dotnet restore RunTests\RunTests.csproj --source https://api.nuget.org/v3/index.json --ignore-failed-sources
dotnet run --project RunTests\RunTests.csproj -- --target %1 --sdk %2 --runtime %3 --queue %4 --arch %5 --quarantined %6 --ef %7
if errorlevel 1 (
set exit_code=1
)
exit /b %exit_code%

View File

@ -1,12 +1,7 @@
#!/usr/bin/env bash
test_binary_path="$1"
dotnet_sdk_version="$2"
dotnet_runtime_version="$3"
helix_queue_name="$4"
target_arch="$5"
quarantined="$6"
efVersion="$7"
RESET="\033[0m"
RED="\033[0;31m"
@ -30,19 +25,6 @@ export DOTNET_CLI_HOME="$DIR/.home$RANDOM"
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
# Used by SkipOnHelix attribute
export helix="$helix_queue_name"
export HELIX_DIR="$DIR"
export NUGET_FALLBACK_PACKAGES="$DIR"
export DotNetEfFullPath=$DIR\nugetRestore\dotnet-ef\$efVersion\tools\netcoreapp3.1\any\dotnet-ef.dll
echo "Set DotNetEfFullPath: $DotNetEfFullPath"
export NUGET_RESTORE="$DIR/nugetRestore"
echo "Creating nugetRestore directory: $NUGET_RESTORE"
mkdir $NUGET_RESTORE
mkdir logs
ls -laR
RESET="\033[0m"
RED="\033[0;31m"
YELLOW="\033[0;33m"
@ -93,35 +75,6 @@ if [ $? -ne 0 ]; then
done
fi
# Rename default.NuGet.config to NuGet.config if there is not a custom one from the project
if [ ! -f "NuGet.config" ]
then
cp default.NuGet.config NuGet.config
fi
# Copy over any local shared fx if found
if [ -d "Microsoft.AspNetCore.App" ]
then
echo "Found Microsoft.AspNetCore.App directory, copying to $DOTNET_ROOT/shared/Microsoft.AspNetCore.App/$dotnet_runtime_version."
cp -r Microsoft.AspNetCore.App $DOTNET_ROOT/shared/Microsoft.AspNetCore.App/$dotnet_runtime_version
echo "Adding current directory to nuget sources: $DIR"
dotnet nuget add source $DIR --configfile NuGet.config
dotnet nuget add source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json --configfile NuGet.config
dotnet nuget list source
dotnet tool install dotnet-ef --global --version $efVersion
# Ensure tools are on on PATH
export PATH="$PATH:$DOTNET_CLI_HOME/.dotnet/tools"
fi
# Rename default.runner.json to xunit.runner.json if there is not a custom one from the project
if [ ! -f "xunit.runner.json" ]
then
cp default.runner.json xunit.runner.json
fi
if [ -e /proc/self/coredump_filter ]; then
# Include memory in private and shared file-backed mappings in the dump.
# This ensures that we can see disassembly from our shared libraries when
@ -129,40 +82,11 @@ if [ -e /proc/self/coredump_filter ]; then
echo -n 0x3F > /proc/self/coredump_filter
fi
# dontet-install.sh seems to affect the Linux filesystem and causes test flakiness unless we sync the filesystem before running tests
sync
$DOTNET_ROOT/dotnet vstest $test_binary_path -lt >discovered.txt
if grep -q "Exception thrown" discovered.txt; then
echo -e "${RED}Exception thrown during test discovery${RESET}".
cat discovered.txt
exit 1
fi
exit_code=0
$DOTNET_ROOT/dotnet restore RunTests/RunTests.csproj --source https://api.nuget.org/v3/index.json --ignore-failed-sources
$DOTNET_ROOT/dotnet run --project RunTests/RunTests.csproj -- --target $1 --sdk $2 --runtime $3 --queue $4 --arch $5 --quarantined $6 --ef $7
# Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
NONQUARANTINE_FILTER="Quarantined!=true"
QUARANTINE_FILTER="Quarantined=true"
if [ "$quarantined" == true ]; then
echo "Running all tests including quarantined."
$DOTNET_ROOT/dotnet vstest $test_binary_path --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:"$QUARANTINE_FILTER"
if [ $? != 0 ]; then
echo "Quarantined tests failed!" 1>&2
# DO NOT EXIT
fi
else
echo "Running non-quarantined tests."
$DOTNET_ROOT/dotnet vstest $test_binary_path --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:"$NONQUARANTINE_FILTER"
exit_code=$?
if [ $exit_code != 0 ]; then
echo "Non-quarantined tests failed!" 1>&2
# DO NOT EXIT
fi
fi
echo "Copying TestResults/TestResults to ."
cp TestResults/TestResults.xml testResults.xml
echo "Copying artifacts/logs to $HELIX_WORKITEM_UPLOAD_ROOT/"
cp `find . -name \*.log` $HELIX_WORKITEM_UPLOAD_ROOT/../
cp `find . -name \*.log` $HELIX_WORKITEM_UPLOAD_ROOT/
exit $exit_code
exit $?

View File

@ -27,11 +27,11 @@ namespace Templates.Test.Helpers
public static bool IsCIEnvironment => typeof(Project).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.Any(a => a.Key == "ContinuousIntegrationBuild");
public static string ArtifactsLogDir => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR")))
public static string ArtifactsLogDir => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT")))
? GetAssemblyMetadata("ArtifactsLogDir")
: Path.Combine(Environment.GetEnvironmentVariable("HELIX_DIR"), "logs");
public static string DotNetEfFullPath => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
: Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT");
public static string DotNetEfFullPath => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
? typeof(ProjectFactoryFixture).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.First(attribute => attribute.Key == "DotNetEfFullPath")
.Value
@ -309,7 +309,7 @@ namespace Templates.Test.Helpers
internal async Task<ProcessEx> RunDotNetEfCreateMigrationAsync(string migrationName)
{
var args = $"--verbose --no-build migrations add {migrationName}";
// Only run one instance of 'dotnet new' at once, as a workaround for
// https://github.com/aspnet/templating/issues/63
await DotNetNewLock.WaitAsync();
@ -324,7 +324,7 @@ namespace Templates.Test.Helpers
{
command = "dotnet-ef";
}
var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
await result.Exited;
return result;
@ -353,7 +353,7 @@ namespace Templates.Test.Helpers
{
command = "dotnet-ef";
}
var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
await result.Exited;
return result;