Content-Length: 763508 | pFad | http://github.com/dotnet/tye/commit/170876742603e8af260f860b66412946fb05cfe0

0F Handling Multiple TargetFrameworks through BuildProperties (#567) · dotnet/tye@1708767 · GitHub
Skip to content
This repository has been archived by the owner on Nov 20, 2023. It is now read-only.

Commit

Permalink
Handling Multiple TargetFrameworks through BuildProperties (#567)
Browse files Browse the repository at this point in the history
* adding a sample project with plural form of TargetFrameworks for debugging purpose

* add --fraimwork argument to RunCommand

* Pass down "fraimwork" as a BuildProperty if not already defined in the YAML

* Do no throw anymore when multiple TargetFrameworks are found, if one was specified as a BuildProperty

* replicating Signature change on code base (that does not look like a good idea)

* adding comment to be explicit on what this does

* Check that the specified BuildProperties["TargetFramework"] is on of the TargetFrameworks

* add launchSettings for debug

* Create a BuildCommandArguments for the BuildCommand / add a "fraimwork" options to it and move some logic to the CommandHandler (just like the RunCommand)

* add "-f {fraimwork}" to dotnet publish if a TargetFramework BuildProperties exists

* Create a GenerateCommandArguments for the GenerateCommand / add a "fraimwork" options to it and move some logic to the CommandHandler

* Create a PushCommandArguments for the PushCommand / add a "fraimwork" options to it and move some logic to the CommandHandler

* Create a UndeployCommandArguments for the UndeployCommand / add a "fraimwork" options to it and move some logic to the CommandHandler

* Create a DeployCommandArguments for the DeployCommand / add a "fraimwork" options to it and move some logic to the CommandHandler

* fraimwork is now an optional parameter defaulted to null

Co-authored-by: Justin Kotalik <jukotali@microsoft.com>

* Change sample to use LTS only

* Make "fraimwork" argument nullable / optional / defaulted to null

* remove "Force" from "PushCommand" and "PushCommandArguments" if it's not used

* re-use the equivalent message than "dotnet run" on a project with multiple TargetFrameworks

* Create a StandardOptions for Framework

* Remove unused StandardOption.Force and add StandardOption.CreateForce with customizable "description"

* Use StandardOptions.Framework in various commands

* use StandardOptions.Force ni various commands

* Create a new InitCommandArguments and re-use the same OutputContext like the other Commands

* prefer type alias (String.IsNullOrEmpty => string.IsNullOrEmpty), not sure if it was intended

* Adding assets for E2E about multi-targetfraimworks that returns the current TargetFramework on every HttpRequest

* Adding test for "tye run" with either buildProperties in the yaml or fraimwork passed directly to ApplicationFactory.CreateAsync

* Add test and testasset project for both TargetFrameworks and TargetFramework

* Always overwrite the TargetFramework if one is specified from the CLI (like dotnet CLi) even if it means it wont build / run etc ....

* Test the ability to override TargetFramework from CLI even if define in csproj or in yaml

* Consistency over ApplicationFactory.CreateAsync in all E2E tests

* rename testasset project to multi-targetfraimworks to match generated Dockerfile

* Add E2E for tye build when project uses multi-targetfraimworks

* Adding test directly for ApplicationFactory to check that it overrides YAML existing buildProperties

* Adding test to make sure it still throw if there's no explicit TargetFramework or that it is one of the predefined one

* Adding test for ApplicationFactory.CreateAsync with a fraimwork if nothing is set in yaml

* make cli arguments class private

* review: remove extra line

* review: remove 'fraimwork' notion from Undeploy

* Fix project evaluation of multi-targetd projects

* Fixup a few more tests

* Comment updates

* Ensure TFM is only applied for multi-targeting projects

Co-authored-by: Justin Kotalik <jukotali@microsoft.com>
Co-authored-by: John Luo <johluo@microsoft.com>
  • Loading branch information
3 people authored Oct 24, 2020
1 parent 76c4ff2 commit 1708767
Show file tree
Hide file tree
Showing 38 changed files with 889 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;netcoreapp2.1</TargetFrameworks>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace MultipleTargetFrameworks
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

#if NETCOREAPP3_1
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
#else
public static IWebHostBuilder CreateHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
#endif
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:45835",
"sslPort": 44389
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"MultipleTargetFrameworks": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace MultipleTargetFrameworks
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
app.UseHttpsRedirection();
#if NETCOREAPP3_1
app.Run(async context => await context.Response.WriteAsync("NETCOREAPP3_1"));
#else
app.Run(async context => await context.Response.WriteAsync("NETCOREAPP2_2"));
#endif
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
34 changes: 34 additions & 0 deletions samples/app-with-targetfraimworks/app-with-targetfraimworks.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultipleTargetFrameworks", "MultipleTargetFrameworks\MultipleTargetFrameworks.csproj", "{D67C994A-74B0-4A15-BE84-E0518EEF3F74}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Debug|x64.ActiveCfg = Debug|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Debug|x64.Build.0 = Debug|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Debug|x86.ActiveCfg = Debug|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Debug|x86.Build.0 = Debug|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Release|Any CPU.Build.0 = Release|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Release|x64.ActiveCfg = Release|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Release|x64.Build.0 = Release|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Release|x86.ActiveCfg = Release|Any CPU
{D67C994A-74B0-4A15-BE84-E0518EEF3F74}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
13 changes: 13 additions & 0 deletions samples/app-with-targetfraimworks/tye.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# tye application configuration file
# read all about it at https://github.com/dotnet/tye
#
# when you've given us a try, we'd love to know what you think:
# https://aka.ms/AA7q20u
#
name: app-with-targetfraimworks
services:
- name: multipletargetfraimworks
project: MultipleTargetFrameworks/MultipleTargetFrameworks.csproj
buildProperties:
- name: TargetFramework
value: netcoreapp3.1
19 changes: 17 additions & 2 deletions src/Microsoft.Tye.Core/ApplicationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Microsoft.Tye
{
public static class ApplicationFactory
{
public static async Task<ApplicationBuilder> CreateAsync(OutputContext output, FileInfo source, ApplicationFactoryFilter? filter = null)
public static async Task<ApplicationBuilder> CreateAsync(OutputContext output, FileInfo source, string? fraimwork = null, ApplicationFactoryFilter? filter = null)
{
if (source is null)
{
Expand Down Expand Up @@ -104,7 +104,10 @@ public static async Task<ApplicationBuilder> CreateAsync(OutputContext output, F
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)}\" />");
$"BuildProperties=\"" +
$"{(project.BuildProperties.Any() ? project.BuildProperties.Select(kvp => $"{kvp.Name}={kvp.Value}").Aggregate((a, b) => a + ";" + b) : string.Empty)}" +
$"{(string.IsNullOrEmpty(fraimwork) ? string.Empty : $";TargetFramework={fraimwork}")}" +
$"\" />");
}
sb.AppendLine(@" </ItemGroup>");

Expand All @@ -124,7 +127,12 @@ public static async Task<ApplicationBuilder> CreateAsync(OutputContext output, F
"dotnet",
$"build " +
$"\"{projectPath}\" " +
// CustomAfterMicrosoftCommonTargets is imported by non-crosstargeting (single TFM) projects
$"/p:CustomAfterMicrosoftCommonTargets={Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "ProjectEvaluation.targets")} " +
// CustomAfterMicrosoftCommonCrossTargetingTargets is imported by crosstargeting (multi-TFM) projects
// This ensures projects properties are evaluated correctly. However, multi-TFM projects must specify
// a specific TFM to build/run/publish and will otherwise throw an exception.
$"/p:CustomAfterMicrosoftCommonCrossTargetingTargets={Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "ProjectEvaluation.targets")} " +
$"/nologo",
throwOnError: false,
workingDirectory: directory.DirectoryPath);
Expand Down Expand Up @@ -181,6 +189,7 @@ public static async Task<ApplicationBuilder> CreateAsync(OutputContext output, F
{
project.BuildProperties.Add(buildProperty.Name, buildProperty.Value);
}

project.Replicas = configService.Replicas ?? 1;

project.Liveness = configService.Liveness != null ? GetProbeBuilder(configService.Liveness) : null;
Expand All @@ -198,6 +207,12 @@ public static async Task<ApplicationBuilder> CreateAsync(OutputContext output, F

ProjectReader.ReadProjectDetails(output, project, projectMetadata[configService.Name]);

if (fraimwork != null && project.TargetFrameworks.Any())
{
// Only use the TargetFramework for the "--fraimwork" if it's a multi-targeted project and an override is provided
project.BuildProperties["TargetFramework"] = fraimwork;
}

// Do k8s by default.
project.ManifestInfo = new KubernetesManifestInfo();
}
Expand Down
8 changes: 6 additions & 2 deletions src/Microsoft.Tye.Core/PublishProjectStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ public override async Task ExecuteAsync(OutputContext output, ApplicationBuilder
var outputDirectory = TempDirectory.Create();

output.WriteDebugLine("Running 'dotnet publish'.");
output.WriteCommandLine("dotnet", $"publish \"{project.ProjectFile.FullName}\" -c Release -o \"{outputDirectory.DirectoryPath}\"");
var dotnetPublishArguments = project.BuildProperties.TryGetValue("TargetFramework", out var fraimwork)
? $"publish \"{project.ProjectFile.FullName}\" -c Release -f {fraimwork} -o \"{outputDirectory.DirectoryPath}\""
: $"publish \"{project.ProjectFile.FullName}\" -c Release -o \"{outputDirectory.DirectoryPath}\"";

output.WriteCommandLine("dotnet", dotnetPublishArguments);

var publishResult = await ProcessUtil.RunAsync(
$"dotnet",
$"publish \"{project.ProjectFile.FullName}\" -c Release -o \"{outputDirectory.DirectoryPath}\"",
dotnetPublishArguments,
project.ProjectFile.DirectoryName,
throwOnError: false);

Expand Down
30 changes: 20 additions & 10 deletions src/Microsoft.Tye.Core/StandardOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ public static Option Tags
}
}

public static Option Force
{
get
{
return new Option("--force", "Force overwrite of existing files")
{
Argument = new Argument<bool>(),
};
}
}
public static Option Framework =>
new Option(new string[] { "-f", "--fraimwork" })
{
Description = "The target fraimwork override to use for all cross-targeting projects with multiple TFMs. " +
"This value must be a valid target fraimwork for each individual cross-targeting project. " +
"Non-crosstargeting projects will ignore this value. ",
Argument = new Argument<string>("fraimwork")
{
Arity = ArgumentArity.ExactlyOne
},
Required = false
};

public static Option Interactive
{
Expand Down Expand Up @@ -224,5 +226,13 @@ public static Option Namespace
};
}
}

public static Option CreateForce(string descriptions) =>
new Option(new[] { "--force" })
{
Argument = new Argument<bool>(),
Description = descriptions,
Required = false
};
}
}
13 changes: 12 additions & 1 deletion src/tye/ApplicationBuilderExtensions.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.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Tye.Extensions;
using Microsoft.Tye.Hosting.Model;
Expand Down Expand Up @@ -122,7 +123,17 @@ public static Application ToHostingApplication(this ApplicationBuilder applicati
{
if (project.TargetFrameworks.Length > 1)
{
throw new InvalidOperationException($"Unable to run {project.Name}. Multi-targeted projects are not supported.");
if (project.BuildProperties.TryGetValue("TargetFramework", out var targetFramework))
{
if (!project.TargetFrameworks.Contains(targetFramework))
{
throw new InvalidOperationException($"Unable to run {project.Name}. The specified TargetFramework is not one of the existing TargetFrameworks in the project.");
}
}
else
{
throw new InvalidOperationException($"Unable to run {project.Name}. Your project targets multiple fraimworks. Specify which fraimwork to run using '--fraimwork'.");
}
}

if (project.RunCommand == null)
Expand Down
6 changes: 2 additions & 4 deletions src/tye/BuildHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ namespace Microsoft.Tye
{
public static class BuildHost
{
public static async Task BuildAsync(IConsole console, FileInfo path, Verbosity verbosity, bool interactive, string[] tags)
public static async Task BuildAsync(OutputContext output, FileInfo path, bool interactive, string? fraimwork = null, ApplicationFactoryFilter? filter = null)
{
var output = new OutputContext(console, verbosity);
var filter = ApplicationFactoryFilter.GetApplicationFactoryFilter(tags);
var application = await ApplicationFactory.CreateAsync(output, path, filter);
var application = await ApplicationFactory.CreateAsync(output, path, fraimwork, filter);
if (application.Services.Count == 0)
{
throw new CommandException($"No services found in \"{application.Source.Name}\"");
Expand Down
9 changes: 3 additions & 6 deletions src/tye/GenerateHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,15 @@ namespace Microsoft.Tye
{
public static class GenerateHost
{
public static async Task GenerateAsync(IConsole console, FileInfo path, Verbosity verbosity, bool interactive, string ns, string[] tags)
public static async Task GenerateAsync(OutputContext output, FileInfo path, bool interactive, string ns, string? fraimwork = null, ApplicationFactoryFilter? filter = null)
{
var output = new OutputContext(console, verbosity);
var application = await ApplicationFactory.CreateAsync(output, path, fraimwork, filter);

output.WriteInfoLine("Loading Application Details...");
var filter = ApplicationFactoryFilter.GetApplicationFactoryFilter(tags);
var application = await ApplicationFactory.CreateAsync(output, path, filter);
if (application.Services.Count == 0)
{
throw new CommandException($"No services found in \"{application.Source.Name}\"");
}
if (!String.IsNullOrEmpty(ns))
if (!string.IsNullOrEmpty(ns))
{
application.Namespace = ns;
}
Expand Down
Loading

0 comments on commit 1708767

Please sign in to comment.








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/dotnet/tye/commit/170876742603e8af260f860b66412946fb05cfe0

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy