Skip to content

Fix templates sourceName & port of template fixes from main #41536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
May 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b255e51
Fix templates sourceName
DamianEdwards May 5, 2022
ad9943a
Support minimal APIs & program/main together in Web API template
DamianEdwards May 5, 2022
5b4fb44
Clean-up from template fix port
DamianEdwards May 5, 2022
53d6b59
Update for VS compiler changes to nullability & u8 string literals
DamianEdwards May 5, 2022
f507fbe
Template baselines test fix
DamianEdwards May 5, 2022
d934788
Make template baseline test check namespaces match project name
DamianEdwards May 5, 2022
7c6bb28
Comment for clarity
DamianEdwards May 5, 2022
ab6bf0f
Port extra template tests from main
DamianEdwards May 5, 2022
85590ba
Port template test change that fails if warnings present on build or …
DamianEdwards May 6, 2022
a829d58
Use original file name in template baseline test
DamianEdwards May 6, 2022
93cb217
Fix single file exe test
DamianEdwards May 6, 2022
ce8d5bc
Comment out tenmplate baseline test namespace declaration
DamianEdwards May 9, 2022
b30775a
Comment out template warning checks
DamianEdwards May 9, 2022
6f59ea5
Apply test fixes from failures investigation
DamianEdwards May 10, 2022
571f8d7
Set project name
DamianEdwards May 10, 2022
3611bb5
Bump Helix test runner timeout to 60 mins
DamianEdwards May 10, 2022
1fca160
Collect test host dumps on Helix test runner crashes
DamianEdwards May 10, 2022
b2bb477
Print message when test job times out
DamianEdwards May 11, 2022
02eb61a
Make helix runner print timestamps with console logs
DamianEdwards May 11, 2022
e808b74
Ported more test changes from main
DamianEdwards May 12, 2022
465b304
Revert failing project test if new/build/publish emit restore errors …
DamianEdwards May 12, 2022
70f60d0
Fix typos
DamianEdwards May 12, 2022
5e9747a
Port TestRunner.cs changes
DamianEdwards May 13, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions eng/helix/content/RunTests/ProcessUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
Expand Down Expand Up @@ -80,7 +81,7 @@ public static async Task<ProcessResult> RunAsync(
Action<int>? onStart = null,
CancellationToken cancellationToken = default)
{
Console.WriteLine($"Running '{filename} {arguments}'");
PrintMessage($"Running '{filename} {arguments}'");
using var process = new Process()
{
StartInfo =
Expand Down Expand Up @@ -153,7 +154,7 @@ public static async Task<ProcessResult> RunAsync(

process.Exited += (_, e) =>
{
Console.WriteLine($"'{process.StartInfo.FileName} {process.StartInfo.Arguments}' completed with exit code '{process.ExitCode}'");
PrintMessage($"'{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} output: {outputBuilder.ToString()}"));
Expand Down Expand Up @@ -208,5 +209,8 @@ public static async Task<ProcessResult> RunAsync(

return await processLifetimeTask.Task;
}

public static void PrintMessage(string message) => Console.WriteLine($"{DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)} {message}");
public static void PrintErrorMessage(string message) => Console.Error.WriteLine($"{DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)} {message}");
}
}
10 changes: 5 additions & 5 deletions eng/helix/content/RunTests/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static async Task Main(string[] args)
keepGoing = await runner.InstallPlaywrightAsync();
}
#else
Console.WriteLine("Playwright install skipped.");
ProcessUtil.PrintMessage("Playwright install skipped.");
#endif

runner.DisplayContents();
Expand All @@ -34,23 +34,23 @@ static async Task Main(string[] args)
{
if (!await runner.CheckTestDiscoveryAsync())
{
Console.WriteLine("RunTest stopping due to test discovery failure.");
ProcessUtil.PrintMessage("RunTest stopping due to test discovery failure.");
Environment.Exit(1);
return;
}

var exitCode = await runner.RunTestsAsync();
runner.UploadResults();
Console.WriteLine($"Completed Helix job with exit code '{exitCode}'");
ProcessUtil.PrintMessage($"Completed Helix job with exit code '{exitCode}'");
Environment.Exit(exitCode);
}

Console.WriteLine("Tests were not run due to previous failures. Exit code=1");
ProcessUtil.PrintMessage("Tests were not run due to previous failures. Exit code=1");
Environment.Exit(1);
}
catch (Exception e)
{
Console.WriteLine($"RunTests uncaught exception: {e.ToString()}");
ProcessUtil.PrintMessage($"RunTests uncaught exception: {e.ToString()}");
Environment.Exit(1);
}
}
Expand Down
114 changes: 62 additions & 52 deletions eng/helix/content/RunTests/TestRunner.cs

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions eng/targets/Helix.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@

<PropertyGroup>
<CreateHelixPayload>true</CreateHelixPayload>
<HelixTimeout>00:30:00</HelixTimeout>
<HelixTimeout Condition="$(HelixTargetQueue.StartsWith('Windows.10.Amd64'))">00:40:00</HelixTimeout>
<HelixTimeout>00:45:00</HelixTimeout>
<RunQuarantinedTests>false</RunQuarantinedTests>
<HelixTestName>$(MSBuildProjectName)--$(TargetFramework)</HelixTestName>
<LoggingTestingDisableFileLogging Condition="'$(IsHelixJob)' == 'true'">false</LoggingTestingDisableFileLogging>
Expand Down
6 changes: 3 additions & 3 deletions src/Hosting/Hosting/src/Internal/WebHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ public WebHost(
// There's no way to to register multiple service types per definition. See https://github.com/aspnet/DependencyInjection/issues/360
#pragma warning disable CS8634 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.
_applicationServiceCollection.AddSingleton(services
=> services.GetService<ApplicationLifetime>() as IHostApplicationLifetime);
=> services.GetService<ApplicationLifetime>()! as IHostApplicationLifetime);
#pragma warning disable CS0618 // Type or member is obsolete
_applicationServiceCollection.AddSingleton(services
=> services.GetService<ApplicationLifetime>() as AspNetCore.Hosting.IApplicationLifetime);
=> services.GetService<ApplicationLifetime>()! as AspNetCore.Hosting.IApplicationLifetime);
_applicationServiceCollection.AddSingleton(services
=> services.GetService<ApplicationLifetime>() as Extensions.Hosting.IApplicationLifetime);
=> services.GetService<ApplicationLifetime>()! as Extensions.Hosting.IApplicationLifetime);
#pragma warning restore CS0618 // Type or member is obsolete
#pragma warning restore CS8634 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.
_applicationServiceCollection.AddSingleton<HostedServiceExecutor>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected async Task<Project> CreateBuildPublishAsync(string projectName, string
// Additional arguments are needed. See: https://github.com/dotnet/aspnetcore/issues/24278
Environment.SetEnvironmentVariable("EnableDefaultScopedCssItems", "true");

var project = await ProjectFactory.GetOrCreateProject(projectName, Output);
var project = await ProjectFactory.CreateProject(Output);
if (targetFramework != null)
{
project.TargetFramework = targetFramework;
Expand Down
2 changes: 1 addition & 1 deletion src/ProjectTemplates/Shared/ProcessResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public ProcessResult(ProcessEx process)

public string Process { get; }

public int ExitCode { get; }
public int ExitCode { get; set; }

public string Error { get; }

Expand Down
117 changes: 35 additions & 82 deletions src/ProjectTemplates/Shared/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal async Task<ProcessResult> RunDotNetNewAsync(
string language = null,
bool useLocalDB = false,
bool noHttps = false,
bool errorOnRestoreError = true,
string[] args = null,
// Used to set special options in MSBuild
IDictionary<string, string> environmentVariables = null)
Expand Down Expand Up @@ -95,29 +96,15 @@ internal async Task<ProcessResult> RunDotNetNewAsync(

argString += $" -o {TemplateOutputDir}";

// Only run one instance of 'dotnet new' at once, as a workaround for
// https://github.com/aspnet/templating/issues/63

await DotNetNewLock.WaitAsync();
try
{
Output.WriteLine("Acquired DotNetNewLock");

if (Directory.Exists(TemplateOutputDir))
{
Output.WriteLine($"Template directory already exists, deleting contents of {TemplateOutputDir}");
Directory.Delete(TemplateOutputDir, recursive: true);
}

using var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), argString, environmentVariables);
await execution.Exited;
return new ProcessResult(execution);
}
finally
if (Directory.Exists(TemplateOutputDir))
{
DotNetNewLock.Release();
Output.WriteLine("Released DotNetNewLock");
Output.WriteLine($"Template directory already exists, deleting contents of {TemplateOutputDir}");
Directory.Delete(TemplateOutputDir, recursive: true);
}

using var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), argString, environmentVariables);
await execution.Exited;
return new ProcessResult(execution);
}

internal async Task<ProcessResult> RunDotNetPublishAsync(IDictionary<string, string> packageOptions = null, string additionalArgs = null, bool noRestore = true)
Expand Down Expand Up @@ -183,31 +170,19 @@ internal async Task<ProcessResult> RunDotNetEfCreateMigrationAsync(string migrat
{
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();
try
var command = DotNetMuxer.MuxerPathOrDefault();
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
{
Output.WriteLine("Acquired DotNetNewLock");
var command = DotNetMuxer.MuxerPathOrDefault();
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
{
args = $"\"{DotNetEfFullPath}\" " + args;
}
else
{
command = "dotnet-ef";
}

using var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
await result.Exited;
return new ProcessResult(result);
args = $"\"{DotNetEfFullPath}\" " + args;
}
finally
else
{
DotNetNewLock.Release();
Output.WriteLine("Released DotNetNewLock");
command = "dotnet-ef";
}

using var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
await result.Exited;
return new ProcessResult(result);
}

internal async Task<ProcessResult> RunDotNetEfUpdateDatabaseAsync()
Expand All @@ -216,31 +191,19 @@ internal async Task<ProcessResult> RunDotNetEfUpdateDatabaseAsync()

var args = "--verbose --no-build database update";

// Only run one instance of 'dotnet new' at once, as a workaround for
// https://github.com/aspnet/templating/issues/63
await DotNetNewLock.WaitAsync();
try
var command = DotNetMuxer.MuxerPathOrDefault();
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
{
Output.WriteLine("Acquired DotNetNewLock");
var command = DotNetMuxer.MuxerPathOrDefault();
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
{
args = $"\"{DotNetEfFullPath}\" " + args;
}
else
{
command = "dotnet-ef";
}

using var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
await result.Exited;
return new ProcessResult(result);
args = $"\"{DotNetEfFullPath}\" " + args;
}
finally
else
{
DotNetNewLock.Release();
Output.WriteLine("Released DotNetNewLock");
command = "dotnet-ef";
}

using var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
await result.Exited;
return new ProcessResult(result);
}

// If this fails, you should generate new migrations via migrations/updateMigrations.cmd
Expand Down Expand Up @@ -294,25 +257,15 @@ public string ReadFile(string path)

internal async Task<ProcessEx> RunDotNetNewRawAsync(string arguments)
{
await DotNetNewLock.WaitAsync();
try
{
Output.WriteLine("Acquired DotNetNewLock");
var result = ProcessEx.Run(
Output,
AppContext.BaseDirectory,
DotNetMuxer.MuxerPathOrDefault(),
arguments +
$" --debug:disable-sdk-templates --debug:custom-hive \"{TemplatePackageInstaller.CustomHivePath}\"" +
$" -o {TemplateOutputDir}");
await result.Exited;
return result;
}
finally
{
DotNetNewLock.Release();
Output.WriteLine("Released DotNetNewLock");
}
var result = ProcessEx.Run(
Output,
AppContext.BaseDirectory,
DotNetMuxer.MuxerPathOrDefault(),
arguments +
$" --debug:disable-sdk-templates --debug:custom-hive \"{TemplatePackageInstaller.CustomHivePath}\"" +
$" -o {TemplateOutputDir}");
await result.Exited;
return result;
}

public void Dispose()
Expand Down
53 changes: 38 additions & 15 deletions src/ProjectTemplates/Shared/ProjectFactoryFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Templates.Test.Helpers
{
public class ProjectFactoryFixture : IDisposable
{
private const string LetterChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private readonly ConcurrentDictionary<string, Project> _projects = new ConcurrentDictionary<string, Project>();

public IMessageSink DiagnosticsMessageSink { get; }
Expand All @@ -23,6 +24,21 @@ public ProjectFactoryFixture(IMessageSink diagnosticsMessageSink)
DiagnosticsMessageSink = diagnosticsMessageSink;
}

public async Task<Project> CreateProject(ITestOutputHelper output)
{
await TemplatePackageInstaller.EnsureTemplatingEngineInitializedAsync(output);

var project = CreateProjectImpl(output);

var projectKey = Guid.NewGuid().ToString().Substring(0, 10).ToLowerInvariant();
if (!_projects.TryAdd(projectKey, project))
{
throw new InvalidOperationException($"Project key collision in {nameof(ProjectFactoryFixture)}.{nameof(CreateProject)}!");
}

return project;
}

public async Task<Project> GetOrCreateProject(string projectKey, ITestOutputHelper output)
{
await TemplatePackageInstaller.EnsureTemplatingEngineInitializedAsync(output);
Expand All @@ -34,24 +50,31 @@ public async Task<Project> GetOrCreateProject(string projectKey, ITestOutputHelp
}
return _projects.GetOrAdd(
projectKey,
(key, outputHelper) =>
{
var project = new Project
{
Output = outputHelper,
DiagnosticsMessageSink = DiagnosticsMessageSink,
ProjectGuid = Path.GetRandomFileName().Replace(".", string.Empty)
};
project.ProjectName = $"AspNet.{project.ProjectGuid}";

var assemblyPath = GetType().Assembly;
var basePath = GetTemplateFolderBasePath(assemblyPath);
project.TemplateOutputDir = Path.Combine(basePath, project.ProjectName);
return project;
},
(_, outputHelper) => CreateProjectImpl(outputHelper),
output);
}

private Project CreateProjectImpl(ITestOutputHelper output)
{
var project = new Project
{
Output = output,
DiagnosticsMessageSink = DiagnosticsMessageSink,
// Ensure first character is a letter to avoid random insertions of '_' into template namespace
// declarations (i.e. make it more stable for testing)
ProjectGuid = GetRandomLetter() + Path.GetRandomFileName().Replace(".", string.Empty)
};
project.ProjectName = $"AspNetCore.{project.ProjectGuid}";

var assemblyPath = GetType().Assembly;
var basePath = GetTemplateFolderBasePath(assemblyPath);
project.TemplateOutputDir = Path.Combine(basePath, project.ProjectName);

return project;
}

private static char GetRandomLetter() => LetterChars[Random.Shared.Next(LetterChars.Length - 1)];

private static string GetTemplateFolderBasePath(Assembly assembly) =>
(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR")))
? assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#endif
using BlazorServerWeb_CSharp.Data;

namespace Company.WebApplication1;
namespace BlazorServerWeb_CSharp;

public class Program
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
using ComponentsWebAssembly_CSharp;
#endif

namespace Company.WebApplication1;
#if (Hosted)
namespace ComponentsWebAssembly_CSharp.Client;
#else
namespace ComponentsWebAssembly_CSharp;
#endif

public class Program
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
using ComponentsWebAssembly_CSharp.Server.Models;
#endif

namespace Company.WebApplication1;
namespace ComponentsWebAssembly_CSharp;

public class Program
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using GrpcService_CSharp.Services;

namespace Company.WebApplication1;
namespace GrpcService_CSharp;

public class Program
{
Expand Down
Loading