зеркало из https://github.com/dotnet/tye.git
Use out-of-proc MSBuild evaluation (#674)
* Use out-of-proc MSBuild evaluation This allows for support for new SDKs/TFMs without needing tye to target those TFMs * Combine restore and metadata evaluation * Batch process projects
This commit is contained in:
Родитель
f0c4f2f54d
Коммит
bbef222754
|
@ -0,0 +1,3 @@
|
|||
@ECHO OFF
|
||||
SETLOCAL
|
||||
PowerShell -NoProfile -NoLogo -ExecutionPolicy ByPass -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = ''; try { & '%~dp0clean.ps1' %*; exit $LASTEXITCODE } catch { write-host $_; exit 1 }"
|
|
@ -0,0 +1,42 @@
|
|||
#requires -version 5
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Clean this repository.
|
||||
|
||||
.DESCRIPTION
|
||||
This script cleans this repository interactively, leaving downloaded infrastructure untouched.
|
||||
Clean operation is interactive to avoid losing new but unstaged files. Press 'c' then [Enter]
|
||||
to perform the proposed deletions.
|
||||
|
||||
.EXAMPLE
|
||||
Perform default clean operation.
|
||||
|
||||
clean.ps1
|
||||
|
||||
.EXAMPLE
|
||||
Clean everything but downloaded infrastructure and VS / VS Code folders.
|
||||
|
||||
clean.ps1 -e .vs/ -e .vscode/
|
||||
#>
|
||||
|
||||
[CmdletBinding(PositionalBinding = $false)]
|
||||
param(
|
||||
# Other lifecycle targets
|
||||
[switch]$Help, # Show help
|
||||
|
||||
# Capture the rest
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
[string[]]$GitArguments
|
||||
)
|
||||
|
||||
Set-StrictMode -Version 2
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if ($Help) {
|
||||
Get-Help $PSCommandPath
|
||||
exit 0
|
||||
}
|
||||
|
||||
git clean -dix -e .dotnet/ -e .tools/ @GitArguments
|
||||
git checkout -- $(git ls-files -d)
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
#
|
||||
# Functions
|
||||
#
|
||||
__usage() {
|
||||
echo "Usage: $(basename "${BASH_SOURCE[0]}") <Arguments>
|
||||
|
||||
Arguments:
|
||||
<Arguments>... Arguments passed to the 'git' command. Any number of arguments allowed.
|
||||
|
||||
Description:
|
||||
This script cleans the repository interactively, leaving downloaded infrastructure untouched.
|
||||
Clean operation is interactive to avoid losing new but unstaged files. Press 'c' then [Enter]
|
||||
to perform the proposed deletions.
|
||||
"
|
||||
}
|
||||
|
||||
git_args=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-\?|-h|--help)
|
||||
__usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
git_args[${#git_args[*]}]="$1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# This incantation avoids unbound variable issues if git_args is empty
|
||||
# https://stackoverflow.com/questions/7577052/bash-empty-array-expansion-with-set-u
|
||||
git clean -dix -e .dotnet/ -e .tools/ ${git_args[@]+"${git_args[@]}"}
|
|
@ -4,9 +4,12 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Tye.ConfigModel;
|
||||
|
||||
|
@ -74,6 +77,88 @@ namespace Microsoft.Tye
|
|||
config.Services.Where(filter.ServicesFilter).ToList() :
|
||||
config.Services;
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
// Project services will be restored and evaluated before resolving all other services.
|
||||
// This batching will mitigate the performance cost of running MSBuild out of process.
|
||||
var projectServices = services.Where(s => !string.IsNullOrEmpty(s.Project));
|
||||
var projectMetadata = new Dictionary<string, string>();
|
||||
|
||||
using (var directory = TempDirectory.Create())
|
||||
{
|
||||
var projectPath = Path.Combine(directory.DirectoryPath, Path.GetRandomFileName() + ".proj");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("<Project>");
|
||||
sb.AppendLine(" <ItemGroup>");
|
||||
|
||||
foreach (var project in projectServices)
|
||||
{
|
||||
var expandedProject = Environment.ExpandEnvironmentVariables(project.Project!);
|
||||
project.ProjectFullPath = Path.Combine(config.Source.DirectoryName!, expandedProject);
|
||||
|
||||
if (!File.Exists(project.ProjectFullPath))
|
||||
{
|
||||
throw new CommandException($"Failed to locate project: '{project.ProjectFullPath}'.");
|
||||
}
|
||||
|
||||
sb.AppendLine($" <MicrosoftTye_ProjectServices " +
|
||||
$"Include=\"{project.ProjectFullPath}\" " +
|
||||
$"Name=\"{project.Name}\" " +
|
||||
$"BuildProperties=\"{(project.BuildProperties.Any() ? project.BuildProperties.Select(kvp => $"{kvp.Name}={kvp.Value}").Aggregate((a, b) => a + ";" + b) : string.Empty)}\" />");
|
||||
}
|
||||
sb.AppendLine(@" </ItemGroup>");
|
||||
|
||||
sb.AppendLine($@" <Target Name=""MicrosoftTye_EvaluateProjects"">");
|
||||
sb.AppendLine($@" <MsBuild Projects=""@(MicrosoftTye_ProjectServices)"" "
|
||||
+ $@"Properties=""%(BuildProperties);"
|
||||
+ $@"MicrosoftTye_ProjectName=%(Name)"" "
|
||||
+ $@"Targets=""MicrosoftTye_GetProjectMetadata"" BuildInParallel=""true"" />");
|
||||
|
||||
sb.AppendLine(" </Target>");
|
||||
sb.AppendLine("</Project>");
|
||||
File.WriteAllText(projectPath, sb.ToString());
|
||||
|
||||
output.WriteDebugLine("Restoring and evaluating projects");
|
||||
|
||||
var msbuildEvaluationResult = await ProcessUtil.RunAsync(
|
||||
"dotnet",
|
||||
$"build " +
|
||||
$"\"{projectPath}\" " +
|
||||
$"/p:CustomAfterMicrosoftCommonTargets={Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "ProjectEvaluation.targets")} " +
|
||||
$"/nologo",
|
||||
throwOnError: false,
|
||||
workingDirectory: directory.DirectoryPath);
|
||||
|
||||
// If the build fails, we're not really blocked from doing our work.
|
||||
// For now we just log the output to debug. There are errors that occur during
|
||||
// running these targets we don't really care as long as we get the data.
|
||||
if (msbuildEvaluationResult.ExitCode != 0)
|
||||
{
|
||||
output.WriteDebugLine($"Evaluating project failed with exit code {msbuildEvaluationResult.ExitCode}:" +
|
||||
$"{Environment.NewLine}Ouptut: {msbuildEvaluationResult.StandardOutput}" +
|
||||
$"{Environment.NewLine}Error: {msbuildEvaluationResult.StandardError}");
|
||||
}
|
||||
|
||||
var msbuildEvaluationOutput = msbuildEvaluationResult
|
||||
.StandardOutput
|
||||
.Split(Environment.NewLine);
|
||||
|
||||
foreach (var line in msbuildEvaluationOutput)
|
||||
{
|
||||
if (line.Trim().StartsWith("Microsoft.Tye metadata: "))
|
||||
{
|
||||
var values = line.Split(':', 3);
|
||||
var projectName = values[1].Trim();
|
||||
var metadataPath = values[2].Trim();
|
||||
projectMetadata.Add(projectName, metadataPath);
|
||||
|
||||
output.WriteDebugLine($"Resolved metadata for service {projectName} at {metadataPath}");
|
||||
}
|
||||
}
|
||||
|
||||
output.WriteDebugLine($"Restore and project evaluation took: {sw.Elapsed.TotalMilliseconds}ms");
|
||||
}
|
||||
|
||||
foreach (var configService in services)
|
||||
{
|
||||
ServiceBuilder service;
|
||||
|
@ -87,9 +172,7 @@ namespace Microsoft.Tye
|
|||
|
||||
if (!string.IsNullOrEmpty(configService.Project))
|
||||
{
|
||||
var expandedProject = Environment.ExpandEnvironmentVariables(configService.Project);
|
||||
var projectFile = new FileInfo(Path.Combine(config.Source.DirectoryName!, expandedProject));
|
||||
var project = new DotnetProjectServiceBuilder(configService.Name!, projectFile);
|
||||
var project = new DotnetProjectServiceBuilder(configService.Name!, new FileInfo(configService.ProjectFullPath));
|
||||
service = project;
|
||||
|
||||
project.Build = configService.Build ?? true;
|
||||
|
@ -107,7 +190,13 @@ namespace Microsoft.Tye
|
|||
// to prompt for the registry name.
|
||||
project.ContainerInfo = new ContainerInfo() { UseMultiphaseDockerfile = false, };
|
||||
|
||||
await ProjectReader.ReadProjectDetailsAsync(output, project);
|
||||
// If project evaluation is successful this should not happen, therefore an exception will be thrown.
|
||||
if (!projectMetadata.ContainsKey(configService.Name))
|
||||
{
|
||||
throw new CommandException($"Evaluated project metadata file could not be found for service {configService.Name}");
|
||||
}
|
||||
|
||||
ProjectReader.ReadProjectDetails(output, project, projectMetadata[configService.Name]);
|
||||
|
||||
// Do k8s by default.
|
||||
project.ManifestInfo = new KubernetesManifestInfo();
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace Microsoft.Tye.ConfigModel
|
|||
public Dictionary<string, string> DockerFileArgs { get; set; } = new Dictionary<string, string>();
|
||||
public string? DockerFileContext { get; set; }
|
||||
public string? Project { get; set; }
|
||||
public string? ProjectFullPath { get; set; }
|
||||
public string? Include { get; set; }
|
||||
public string? Repository { get; set; }
|
||||
public bool? Build { get; set; }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Tye</RootNamespace>
|
||||
<AssemblyName>Microsoft.Tye.Core</AssemblyName>
|
||||
<PackageId>Microsoft.Tye.Core</PackageId>
|
||||
|
|
|
@ -10,15 +10,9 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Loader;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Build.Construction;
|
||||
using Microsoft.Build.Definition;
|
||||
using Microsoft.Build.Evaluation;
|
||||
using Microsoft.Build.Execution;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Locator;
|
||||
using Microsoft.Build.Logging;
|
||||
using Semver;
|
||||
|
||||
namespace Microsoft.Tye
|
||||
|
@ -61,7 +55,7 @@ namespace Microsoft.Tye
|
|||
}
|
||||
}
|
||||
|
||||
public static Task ReadProjectDetailsAsync(OutputContext output, DotnetProjectServiceBuilder project)
|
||||
public static void ReadProjectDetails(OutputContext output, DotnetProjectServiceBuilder project, string metadataFile)
|
||||
{
|
||||
if (output is null)
|
||||
{
|
||||
|
@ -73,14 +67,12 @@ namespace Microsoft.Tye
|
|||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
if (!Directory.Exists(project.ProjectFile.DirectoryName))
|
||||
if (project is null)
|
||||
{
|
||||
throw new CommandException($"Failed to locate directory: '{project.ProjectFile.DirectoryName}'.");
|
||||
throw new ArgumentNullException(nameof(metadataFile));
|
||||
}
|
||||
|
||||
EnsureMSBuildRegistered(output, project.ProjectFile);
|
||||
|
||||
EvaluateProject(output, project);
|
||||
EvaluateProject(output, project, metadataFile);
|
||||
|
||||
if (!SemVersion.TryParse(project.Version, out var version))
|
||||
{
|
||||
|
@ -88,8 +80,6 @@ namespace Microsoft.Tye
|
|||
version = new SemVersion(0, 1, 0);
|
||||
project.Version = version.ToString();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static void EnsureMSBuildRegistered(OutputContext? output, FileInfo projectFile)
|
||||
|
@ -138,118 +128,40 @@ namespace Microsoft.Tye
|
|||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void LogIt(OutputContext output)
|
||||
{
|
||||
output.WriteDebugLine("Loaded: " + typeof(ProjectInstance).Assembly.FullName);
|
||||
output.WriteDebugLine("Loaded From: " + typeof(ProjectInstance).Assembly.Location);
|
||||
}
|
||||
|
||||
// Do not load MSBuild types before using EnsureMSBuildRegistered.
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void EvaluateProject(OutputContext output, DotnetProjectServiceBuilder project)
|
||||
private static void EvaluateProject(OutputContext output, DotnetProjectServiceBuilder project, string metadataFile)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
// Currently we only log at debug level.
|
||||
var logger = new ConsoleLogger(
|
||||
verbosity: LoggerVerbosity.Normal,
|
||||
write: message => output.WriteDebug(message),
|
||||
colorSet: null,
|
||||
colorReset: null);
|
||||
var metadata = new Dictionary<string, string>();
|
||||
var metadataKVPs = File.ReadLines(metadataFile).Select(l => l.Split(new[] { ':' }, 2));
|
||||
|
||||
// We need to isolate projects from each other for testing. MSBuild does not support
|
||||
// loading the same project twice in the same collection.
|
||||
var projectCollection = new ProjectCollection();
|
||||
|
||||
ProjectInstance projectInstance;
|
||||
Microsoft.Build.Evaluation.Project msbuildProject;
|
||||
|
||||
try
|
||||
foreach (var metadataKVP in metadataKVPs)
|
||||
{
|
||||
output.WriteDebugLine($"Loading project '{project.ProjectFile.FullName}'.");
|
||||
msbuildProject = Microsoft.Build.Evaluation.Project.FromFile(project.ProjectFile.FullName, new ProjectOptions()
|
||||
if (!string.IsNullOrEmpty(metadataKVP[1]))
|
||||
{
|
||||
ProjectCollection = projectCollection,
|
||||
GlobalProperties = project.BuildProperties
|
||||
});
|
||||
projectInstance = msbuildProject.CreateProjectInstance();
|
||||
output.WriteDebugLine($"Loaded project '{project.ProjectFile.FullName}'.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new CommandException($"Failed to load project: '{project.ProjectFile.FullName}'.", ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AssemblyLoadContext.Default.Resolving += ResolveAssembly;
|
||||
|
||||
output.WriteDebugLine($"Restoring project '{project.ProjectFile.FullName}'.");
|
||||
|
||||
// Similar to what MSBuild does for restore:
|
||||
// https://github.com/microsoft/msbuild/blob/3453beee039fb6f5ccc54ac783ebeced31fec472/src/MSBuild/XMake.cs#L1417
|
||||
//
|
||||
// We need to do restore as a separate operation
|
||||
var restoreRequest = new BuildRequestData(
|
||||
projectInstance,
|
||||
targetsToBuild: new[] { "Restore" },
|
||||
hostServices: null,
|
||||
flags: BuildRequestDataFlags.ClearCachesAfterBuild | BuildRequestDataFlags.SkipNonexistentTargets | BuildRequestDataFlags.IgnoreMissingEmptyAndInvalidImports);
|
||||
|
||||
var parameters = new BuildParameters(projectCollection)
|
||||
{
|
||||
Loggers = new[] { logger, },
|
||||
};
|
||||
|
||||
// We don't really look at the result, because it's not clear we should halt totally
|
||||
// if restore fails.
|
||||
var restoreResult = BuildManager.DefaultBuildManager.Build(parameters, restoreRequest);
|
||||
output.WriteDebugLine($"Restored project '{project.ProjectFile.FullName}'.");
|
||||
|
||||
msbuildProject.MarkDirty();
|
||||
projectInstance = msbuildProject.CreateProjectInstance();
|
||||
|
||||
var targets = new List<string>()
|
||||
{
|
||||
"ResolveReferences",
|
||||
"ResolvePackageDependenciesDesignTime",
|
||||
"PrepareResources",
|
||||
"GetAssemblyAttributes",
|
||||
};
|
||||
|
||||
var result = projectInstance.Build(
|
||||
targets: targets.ToArray(),
|
||||
loggers: new[] { logger, });
|
||||
|
||||
// If the build fails, we're not really blocked from doing our work.
|
||||
// For now we just log the output to debug. There are errors that occur during
|
||||
// running these targets we don't really care as long as we get the data.
|
||||
}
|
||||
finally
|
||||
{
|
||||
AssemblyLoadContext.Default.Resolving -= ResolveAssembly;
|
||||
metadata.Add(metadataKVP[0], metadataKVP[1].Trim());
|
||||
}
|
||||
}
|
||||
|
||||
// Reading a few different version properties to be more resilient.
|
||||
var version =
|
||||
projectInstance.GetProperty("AssemblyInformationalVersion")?.EvaluatedValue ??
|
||||
projectInstance.GetProperty("InformationalVersion")?.EvaluatedValue ??
|
||||
projectInstance.GetProperty("Version").EvaluatedValue;
|
||||
var version = GetMetadataValueOrNull("AssemblyInformationalVersion") ??
|
||||
GetMetadataValueOrNull("InformationalVersion") ??
|
||||
GetMetadataValueOrEmpty("Version");
|
||||
project.Version = version;
|
||||
output.WriteDebugLine($"Found application version: {version}");
|
||||
|
||||
var targetFrameworks = projectInstance.GetPropertyValue("TargetFrameworks");
|
||||
project.TargetFrameworks = targetFrameworks.Split(';', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();
|
||||
project.TargetFrameworks = GetMetadataValueOrNull("TargetFrameworks")?.Split(';', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();
|
||||
|
||||
// Figure out if functions app.
|
||||
// If so, run app with function host.
|
||||
project.RunCommand = projectInstance.GetPropertyValue("RunCommand");
|
||||
project.RunArguments = projectInstance.GetPropertyValue("RunArguments");
|
||||
project.TargetPath = projectInstance.GetPropertyValue("TargetPath");
|
||||
project.PublishDir = projectInstance.GetPropertyValue("PublishDir");
|
||||
project.AssemblyName = projectInstance.GetPropertyValue("AssemblyName");
|
||||
project.IntermediateOutputPath = projectInstance.GetPropertyValue("IntermediateOutputPath");
|
||||
project.RunCommand = GetMetadataValueOrEmpty("RunCommand");
|
||||
project.RunArguments = GetMetadataValueOrEmpty("RunArguments");
|
||||
project.TargetPath = GetMetadataValueOrEmpty("TargetPath");
|
||||
project.PublishDir = GetMetadataValueOrEmpty("PublishDir");
|
||||
project.AssemblyName = GetMetadataValueOrEmpty("AssemblyName");
|
||||
project.IntermediateOutputPath = GetMetadataValueOrEmpty("IntermediateOutputPath");
|
||||
|
||||
output.WriteDebugLine($"RunCommand={project.RunCommand}");
|
||||
output.WriteDebugLine($"RunArguments={project.RunArguments}");
|
||||
|
@ -263,63 +175,37 @@ namespace Microsoft.Tye
|
|||
project.TargetPath = Path.Combine(project.ProjectFile.DirectoryName!, NormalizePath(project.TargetPath));
|
||||
project.PublishDir = Path.Combine(project.ProjectFile.DirectoryName!, NormalizePath(project.PublishDir));
|
||||
|
||||
var targetFramework = projectInstance.GetPropertyValue("TargetFramework");
|
||||
var targetFramework = GetMetadataValueOrEmpty("TargetFramework");
|
||||
project.TargetFramework = targetFramework;
|
||||
output.WriteDebugLine($"Found target framework: {targetFramework}");
|
||||
|
||||
// TODO: Parse the name and version manually out of the TargetFramework field if it's non-null
|
||||
project.TargetFrameworkName = projectInstance.GetPropertyValue("_ShortFrameworkIdentifier");
|
||||
project.TargetFrameworkVersion = projectInstance.GetPropertyValue("_ShortFrameworkVersion") ?? projectInstance.GetPropertyValue("_TargetFrameworkVersionWithoutV");
|
||||
project.TargetFrameworkName = GetMetadataValueOrEmpty("_ShortFrameworkIdentifier");
|
||||
project.TargetFrameworkVersion = GetMetadataValueOrNull("_ShortFrameworkVersion") ?? GetMetadataValueOrEmpty("_TargetFrameworkVersionWithoutV");
|
||||
|
||||
var sharedFrameworks = projectInstance.GetItems("FrameworkReference").Select(i => i.EvaluatedInclude).ToList();
|
||||
var sharedFrameworks = GetMetadataValueOrNull("FrameworkReference")?.Split(';') ?? Enumerable.Empty<string>();
|
||||
project.Frameworks.AddRange(sharedFrameworks.Select(s => new Framework(s)));
|
||||
output.WriteDebugLine($"Found shared frameworks: {string.Join(", ", sharedFrameworks)}");
|
||||
|
||||
// determine container base image
|
||||
if (project.ContainerInfo != null)
|
||||
{
|
||||
project.ContainerInfo.BaseImageName = projectInstance.GetPropertyValue("ContainerBaseImage");
|
||||
project.ContainerInfo.BaseImageTag = projectInstance.GetPropertyValue("ContainerBaseTag");
|
||||
}
|
||||
|
||||
bool PropertyIsTrue(string property)
|
||||
{
|
||||
return projectInstance.GetPropertyValue(property) is string s && !string.IsNullOrEmpty(s) && bool.Parse(s);
|
||||
project.ContainerInfo.BaseImageName = GetMetadataValueOrEmpty("ContainerBaseImage");
|
||||
project.ContainerInfo.BaseImageTag = GetMetadataValueOrEmpty("ContainerBaseTag");
|
||||
}
|
||||
|
||||
project.IsAspNet = project.Frameworks.Any(f => f.Name == "Microsoft.AspNetCore.App") ||
|
||||
projectInstance.GetPropertyValue("MicrosoftNETPlatformLibrary") == "Microsoft.AspNetCore.App" ||
|
||||
PropertyIsTrue("_AspNetCoreAppSharedFxIsEnabled") ||
|
||||
PropertyIsTrue("UsingMicrosoftNETSdkWeb");
|
||||
GetMetadataValueOrEmpty("MicrosoftNETPlatformLibrary") == "Microsoft.AspNetCore.App" ||
|
||||
MetadataIsTrue("_AspNetCoreAppSharedFxIsEnabled") ||
|
||||
MetadataIsTrue("UsingMicrosoftNETSdkWeb");
|
||||
|
||||
output.WriteDebugLine($"IsAspNet={project.IsAspNet}");
|
||||
|
||||
output.WriteDebugLine($"Evaluation Took: {sw.Elapsed.TotalMilliseconds}ms");
|
||||
|
||||
// The Microsoft.Build.Locator doesn't handle the loading of other assemblies
|
||||
// that are shipped with MSBuild (ex NuGet).
|
||||
//
|
||||
// This means that the set of assemblies that need special handling depends on the targets
|
||||
// that we run :(
|
||||
//
|
||||
// This is workaround for this limitation based on the targets we need to run
|
||||
// to resolve references and versions.
|
||||
//
|
||||
// See: https://github.com/microsoft/MSBuildLocator/issues/86
|
||||
Assembly? ResolveAssembly(AssemblyLoadContext context, AssemblyName assemblyName)
|
||||
{
|
||||
if (assemblyName.Name is object)
|
||||
{
|
||||
var msbuildDirectory = Environment.GetEnvironmentVariable("MSBuildExtensionsPath")!;
|
||||
var assemblyFilePath = Path.Combine(msbuildDirectory, assemblyName.Name + ".dll");
|
||||
if (File.Exists(assemblyFilePath))
|
||||
{
|
||||
return context.LoadFromAssemblyPath(assemblyFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
string? GetMetadataValueOrNull(string key) => metadata!.TryGetValue(key, out var value) ? value : null;
|
||||
string GetMetadataValueOrEmpty(string key) => metadata!.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
bool MetadataIsTrue(string key) => metadata!.TryGetValue(key, out var value) && bool.Parse(value);
|
||||
}
|
||||
|
||||
private static string NormalizePath(string path)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Description>Diagnostics collector and exporter for .NET Core applications.</Description>
|
||||
<AssemblyName>Microsoft.Tye.Hosting.Diagnostics</AssemblyName>
|
||||
<PackageId>Microsoft.Tye.Hosting.Diagnostics</PackageId>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Description>Orchestration host APIs.</Description>
|
||||
<AssemblyName>Microsoft.Tye.Hosting</AssemblyName>
|
||||
<PackageId>Microsoft.Tye.Hosting</PackageId>
|
||||
|
@ -17,7 +17,7 @@
|
|||
<ItemGroup>
|
||||
<None Include="Watch\assets\**\*" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bedrock.Framework" Version="0.1.38-alpha.gd25d5b37ad" />
|
||||
<PackageReference Include="FeatherHttp" Version="0.1.42-alpha.gf06a8747e7" />
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Microsoft.Tye</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<Project>
|
||||
<Target Name="MicrosoftTye_GetProjectMetadata" DependsOnTargets="Restore;ResolveReferences;ResolvePackageDependenciesDesignTime;PrepareResources;GetAssemblyAttributes" >
|
||||
<PropertyGroup>
|
||||
<_MicrosoftTye_MetadataFile>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)MicrosoftTye.ProjectMetadata.txt'))</_MicrosoftTye_MetadataFile>
|
||||
<_MicrosoftTye_ProjectFrameworkReference>@(FrameworkReference, '%3B')</_MicrosoftTye_ProjectFrameworkReference>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_MicrosoftTye_ProjectMetadata Include="AssemblyInformationalVersion: $(AssemblyInformationalVersion)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="InformationalVersion: $(InformationalVersion)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="Version: $(Version)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="TargetFrameworks: $(TargetFrameworks)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="RunCommand: $(RunCommand)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="RunArguments: $(RunArguments)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="TargetPath: $(TargetPath)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="PublishDir: $(PublishDir)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="AssemblyName: $(AssemblyName)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="IntermediateOutputPath: $(IntermediateOutputPath)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="TargetFramework: $(TargetFramework)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="_ShortFrameworkIdentifier: $(_ShortFrameworkIdentifier)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="_ShortFrameworkVersion: $(_ShortFrameworkVersion)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="_TargetFrameworkVersionWithoutV: $(_TargetFrameworkVersionWithoutV)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="FrameworkReference: $(_MicrosoftTye_ProjectFrameworkReference)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="ContainerBaseImage: $(ContainerBaseImage)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="ContainerBaseTag: $(ContainerBaseTag)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="MicrosoftNETPlatformLibrary: $(MicrosoftNETPlatformLibrary)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="_AspNetCoreAppSharedFxIsEnabled: $(_AspNetCoreAppSharedFxIsEnabled)" />
|
||||
<_MicrosoftTye_ProjectMetadata Include="UsingMicrosoftNETSdkWeb: $(UsingMicrosoftNETSdkWeb)" />
|
||||
</ItemGroup>
|
||||
|
||||
<WriteLinesToFile
|
||||
File="$(_MicrosoftTye_MetadataFile)"
|
||||
Lines="@(_MicrosoftTye_ProjectMetadata)"
|
||||
Overwrite="true"
|
||||
WriteOnlyWhenDifferent="true"/>
|
||||
|
||||
<Message Text="Microsoft.Tye metadata: $(MicrosoftTye_ProjectName): $(_MicrosoftTye_MetadataFile)" Importance="High"/>
|
||||
|
||||
</Target>
|
||||
</Project>
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Microsoft.Tye</RootNamespace>
|
||||
<AssemblyName>tye</AssemblyName>
|
||||
<PackageId>Microsoft.Tye</PackageId>
|
||||
|
@ -10,6 +10,10 @@
|
|||
<PackAsTool>true</PackAsTool>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="ProjectEvaluation.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\shared\KubectlDetector.cs" Link="KubectlDetector.cs" />
|
||||
<Compile Include="..\shared\TempFile.cs" Link="TempFile.cs" />
|
||||
|
|
|
@ -118,8 +118,8 @@ services:
|
|||
var exception = await Assert.ThrowsAsync<CommandException>(async () =>
|
||||
await ApplicationFactory.CreateAsync(outputContext, projectFile));
|
||||
|
||||
var wrongProjectPath = Path.Combine(projectDirectory.DirectoryPath, "backend1");
|
||||
Assert.Equal($"Failed to locate directory: '{wrongProjectPath}'.", exception.Message);
|
||||
var wrongProjectPath = Path.Combine(projectDirectory.DirectoryPath, "backend1/backend.csproj");
|
||||
Assert.Equal($"Failed to locate project: '{wrongProjectPath}'.", exception.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Microsoft.Tye.E2ETest</AssemblyName>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<IsUnitTestProject>true</IsUnitTestProject>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TestRunnerName>XUnit</TestRunnerName>
|
||||
<Nullable>disable</Nullable>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Microsoft.Tye.UnitTests</AssemblyName>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<IsUnitTestProject>true</IsUnitTestProject>
|
||||
|
|
Загрузка…
Ссылка в новой задаче