diff --git a/.gitignore b/.gitignore index f0ad3214bc..f78ee9c2e4 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,6 @@ project.lock.json *.ipch *.vs/ .testPublish/ -.build/ \ No newline at end of file +.build/ +*.nuget.props +*.nuget.targets \ No newline at end of file diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index d836176437..54c59783b5 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -5,7 +5,9 @@ ], "packages": { "Microsoft.AspNetCore.Server.IISIntegration": { }, - "Microsoft.AspNetCore.Server.IISIntegration.Tools": { } + "Microsoft.AspNetCore.Server.IISIntegration.Tools": { + "packageTypes": ["DotnetCliTool"] + } } }, "Default": { // Rules to run for packages not listed in any other set. diff --git a/makefile.shade b/makefile.shade index 562494d144..f6c45643b4 100644 --- a/makefile.shade +++ b/makefile.shade @@ -1,3 +1,7 @@ +use namespace="System.IO" + +default BASE_DIR_LOCAL='${Directory.GetCurrentDirectory()}' +default BUILD_DIR_LOCAL='${Path.Combine(BASE_DIR_LOCAL, "artifacts", "build")}' var VERSION='0.1' var FULL_VERSION='0.1' @@ -5,3 +9,21 @@ var AUTHORS='Microsoft Open Technologies, Inc.' use-standard-lifecycle k-standard-goals + +#build-pack .build-compile target='compile' + @{ + if (Directory.Exists("src") && !IsLinux) + { + Directory.CreateDirectory(BUILD_DIR_LOCAL); + Dotnet("run -p tools/NuGetPackager -- -c " + E("Configuration") + + " -o artifacts/build/ "+ + "-n src/Microsoft.AspNetCore.Server.IISIntegration.Tools/Microsoft.AspNetCore.Server.IISIntegration.Tools.nuspec"); + + DotnetPack("src/Microsoft.AspNetCore.Server.IISIntegration/project.json", BUILD_DIR_LOCAL, E("Configuration"), E("KOREBUILD_DOTNET_PACK_OPTIONS") + " --no-build"); + + foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR_LOCAL, "*/" + E("Configuration") + "/*.nupkg"))) + { + File.Copy(nupkg, Path.Combine(BUILD_DIR_LOCAL, Path.GetFileName(nupkg)), true); + } + } + } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration.Tools/Microsoft.AspNetCore.Server.IISIntegration.Tools.nuspec b/src/Microsoft.AspNetCore.Server.IISIntegration.Tools/Microsoft.AspNetCore.Server.IISIntegration.Tools.nuspec new file mode 100644 index 0000000000..50f59676c0 --- /dev/null +++ b/src/Microsoft.AspNetCore.Server.IISIntegration.Tools/Microsoft.AspNetCore.Server.IISIntegration.Tools.nuspec @@ -0,0 +1,29 @@ + + + + Microsoft.AspNetCore.Server.IISIntegration.Tools + $version$ + Microsoft + Microsoft + false + IIS Integration publish tool for .NET Core CLI. Contains the dotnet-publish-iis command for publishing web applications to be hosted using IIS. + aspnetcore,iis + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration.Tools/project.json b/src/Microsoft.AspNetCore.Server.IISIntegration.Tools/project.json index 79f5b7fea0..fb53ad9dd3 100644 --- a/src/Microsoft.AspNetCore.Server.IISIntegration.Tools/project.json +++ b/src/Microsoft.AspNetCore.Server.IISIntegration.Tools/project.json @@ -24,14 +24,14 @@ "dependencies": { "Microsoft.Extensions.CommandLineUtils": "1.1.0-*", "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "System.Diagnostics.Process": "4.1.0-*" + "System.Diagnostics.Process": "4.3.0-*" }, "frameworks": { "netcoreapp1.0": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0-*" + "version": "1.1.0-*" } } } diff --git a/test/Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests/project.json b/test/Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests/project.json index 6d41a17208..171808128a 100644 --- a/test/Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests/project.json +++ b/test/Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests/project.json @@ -5,11 +5,11 @@ "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-*" }, "frameworks": { - "netcoreapp1.0": { + "netcoreapp1.1": { "dependencies": { "Microsoft.NETCore.App": { "type": "platform", - "version": "1.0.0-*" + "version": "1.1.0-*" } } } diff --git a/tools/NuGetPackager/PackCommand.cs b/tools/NuGetPackager/PackCommand.cs new file mode 100644 index 0000000000..687d0e0d64 --- /dev/null +++ b/tools/NuGetPackager/PackCommand.cs @@ -0,0 +1,150 @@ +// 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.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.ProjectModel.Utilities; +using NuGet.Frameworks; +using NuGet.Versioning; + +namespace NuGetPackager +{ + internal class PackCommand + { + private readonly string _baseDir; + + public PackCommand(string baseDir) + { + _baseDir = baseDir; + } + + public async Task PackAsync(string nuspec, string config, string outputDir) + { + var project = ProjectContext.Create(Path.GetDirectoryName(nuspec), FrameworkConstants.CommonFrameworks.NetCoreApp10); + var props = "configuration=" + config; + var idx = 0; + foreach (var depVersion in GetDependencies(project).OrderBy(p => p.Item1).Select(p => p.Item2)) + { + props += $";dep_{++idx}={depVersion}"; + } + + var buildCommand = Command.CreateDotNet("build", + new[] { project.ProjectFile.ProjectFilePath, "--configuration", config }, + configuration: config); + + if (buildCommand.Execute().ExitCode != 0) + { + throw new GracefulException("Build failed"); + } + + Directory.CreateDirectory(outputDir); + + var version = project.ProjectFile.Version.ToNormalizedString(); + await Nuget("pack", + nuspec, + "-Verbosity", "detailed", + "-OutputDirectory", outputDir, + "-Version", version, + "-Properties", props); + } + + private IEnumerable> GetDependencies(ProjectContext context) + { + // copied from https://github.com/dotnet/cli/blob/da0e365264e0ab555cdde978bdfd2e504bada49a/src/dotnet/commands/dotnet-pack/PackageGenerator.cs + var project = context.RootProject; + + foreach (var dependency in project.Dependencies) + { + if (dependency.Type.Equals(LibraryDependencyType.Build)) + { + continue; + } + + // TODO: Efficiency + var dependencyDescription = context.LibraryManager.GetLibraries().First(l => l.RequestedRanges.Contains(dependency)); + + // REVIEW: Can we get this far with unresolved dependencies + if (!dependencyDescription.Resolved) + { + continue; + } + + if (dependencyDescription.Identity.Type == LibraryType.Project && + ((ProjectDescription)dependencyDescription).Project.EmbedInteropTypes) + { + continue; + } + + VersionRange dependencyVersion = null; + + if (dependency.VersionRange == null || + dependency.VersionRange.IsFloating) + { + dependencyVersion = new VersionRange(dependencyDescription.Identity.Version); + } + else + { + dependencyVersion = dependency.VersionRange; + } + + Reporter.Verbose.WriteLine($"Adding dependency {dependency.Name.Yellow()} {VersionUtility.RenderVersion(dependencyVersion).Yellow()}"); + + yield return new Tuple(dependency.Name, dependencyVersion.MinVersion.ToString()); + } + } + + private static string GetLockFileVersion(ProjectContext project, string name) => + project + .LockFile + .PackageLibraries + .First(l => l.Name.Equals(name)) + .Version + .ToNormalizedString(); + + private async Task Nuget(params string[] args) + { + var pInfo = new ProcessStartInfo + { + Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args), + FileName = await GetNugetExePath() + }; + Console.WriteLine("command: ".Bold().Blue() + pInfo.FileName); + Console.WriteLine("arguments: ".Bold().Blue() + pInfo.Arguments); + + Process.Start(pInfo).WaitForExit(); + } + + private async Task GetNugetExePath() + { + if (Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE") != null) + { + return Environment.GetEnvironmentVariable("KOREBUILD_NUGET_EXE"); + } + + var nugetPath = Path.Combine(_baseDir, ".build", "nuget.3.5.0-rc1.exe"); + if (File.Exists(nugetPath)) + { + return nugetPath; + } + + Console.WriteLine("log : Downloading nuget.exe 3.5.0-rc1".Bold().Black()); + + var response = await new HttpClient().GetAsync("https://dist.nuget.org/win-x86-commandline/v3.5.0-rc1/NuGet.exe"); + using (var file = new FileStream(nugetPath, FileMode.CreateNew)) + { + response.EnsureSuccessStatusCode(); + await response.Content.LoadIntoBufferAsync(); + await response.Content.CopyToAsync(file); + } + return nugetPath; + } + } +} \ No newline at end of file diff --git a/tools/NuGetPackager/Program.cs b/tools/NuGetPackager/Program.cs new file mode 100644 index 0000000000..d73a31a39d --- /dev/null +++ b/tools/NuGetPackager/Program.cs @@ -0,0 +1,55 @@ +// 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.IO; +using System.Linq; +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.DotNet.Cli.Utils; + +namespace NuGetPackager +{ + /// + /// This replaces the "dotnet-pack" command, which doesn't not yet support "package types" + /// and probably won't in time for the next release. + /// TODO remove this once CLI supports package type + /// + public class Program + { + public static int Main(string[] args) + { + var app = new CommandLineApplication(); + var optOutput = app.Option("-o|--output-dir ", "Output dir", CommandOptionType.SingleValue); + var optConfig = app.Option("-c|--configuration ", "Config", CommandOptionType.SingleValue); + var optsNuspec = app.Option("-n|--nuspec ", "nuspec", CommandOptionType.MultipleValue); + + app.OnExecute(async () => + { + if (!optsNuspec.Values.Any()) + { + Reporter.Error.WriteLine("Missing values for --nuspec"); + return 1; + } + + var config = optConfig.HasValue() + ? optConfig.Value() + : "Debug"; + var output = optOutput.Value() ?? Directory.GetCurrentDirectory(); + + if (!Path.IsPathRooted(output)) + { + output = Path.Combine(Directory.GetCurrentDirectory(), output); + } + + var packer = new PackCommand(Directory.GetCurrentDirectory()); + foreach (var nuspec in optsNuspec.Values) + { + await packer.PackAsync(nuspec, config, output); + } + + return 0; + }); + + return app.Execute(args); + } + } +} \ No newline at end of file diff --git a/tools/NuGetPackager/project.json b/tools/NuGetPackager/project.json new file mode 100644 index 0000000000..f42b3d92d0 --- /dev/null +++ b/tools/NuGetPackager/project.json @@ -0,0 +1,19 @@ +{ + "buildOptions": { + "emitEntryPoint": true + }, + + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.1.0-*" + }, + "Microsoft.DotNet.ProjectModel": "1.0.0-*", + "Microsoft.DotNet.Cli.Utils": "1.0.0-*", + "Microsoft.Extensions.CommandLineUtils": "1.1.0-*" + }, + + "frameworks": { + "netcoreapp1.1": { } + } +} \ No newline at end of file