using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using ln.application; using ln.build.pipeline; using ln.build.semver; using ln.build.support.dotnet; using ln.logging; using ln.type; namespace ln.build.commands { public static class DotNetCommand { public static void Prepare(Stage stage,params string[] arguments) { if (Directory.Exists(".build")) Directory.Delete(".build", true); List projectFiles = new List(); List slnFiles = new List(); foreach (string argument in arguments) { foreach (string filename in PathHelper.ResolvePattern(argument, stage.CommandEnvironment.WorkingDirectory)) { stage.CommandEnvironment.Logger.Log(LogLevel.INFO, "dotnet prepare: found {0}", filename); if (filename.EndsWith(".csproj",StringComparison.InvariantCultureIgnoreCase)) projectFiles.Add(filename); else slnFiles.Add(filename); } } // ToDo: Parse .sln files for referenced projects foreach (string projectFileName in projectFiles) { stage.PipeLine.CommandEnvironment.Extend("DOTNET_PROJECTS", projectFileName); CSProjHelper csp = new CSProjHelper(projectFileName); string projectName = csp.GetName(); SemVersion projectVersion= csp.GetVersion(); string ot = csp.GetOutputType(); stage.CommandEnvironment.Logger.Log(LogLevel.INFO, "dotnet prepare: project {0} version={1} type={2}", projectName, projectVersion, ot); } } public static void Build(Stage stage,params string[] arguments) { foreach (string projectFileName in stage.CommandEnvironment.Get("DOTNET_PROJECTS","").Split(':')) { new CommandRunner("dotnet","build", projectFileName, new CommandRunner.Option("-c", stage.CommandEnvironment.Get("DOTNET_CONFIGURATION"))) .Run(stage.CommandEnvironment); } } public static void Pack(Stage stage,params string[] arguments) { foreach (string projectFileName in stage.CommandEnvironment.Get("DOTNET_PROJECTS","").Split(':')) { CSProjHelper csProject = new CSProjHelper(projectFileName); if (!csProject.GetOutputType().Equals("Library")) { stage.CommandEnvironment.Logger.Log(LogLevel.WARNING, "dotnet pack: not packing {0} [{1}]",projectFileName, csProject.GetOutputType()); continue; } stage.CommandEnvironment.Logger.Log(LogLevel.WARNING, "dotnet pack: packing now {0} [{1}]",projectFileName, csProject.GetOutputType()); new CommandRunner("dotnet","pack", projectFileName) .AddArgument(new CommandRunner.Option("-c", stage.CommandEnvironment.Get("DOTNET_CONFIGURATION"))) .AddArguments("-o", ".build/") .Run(stage.CommandEnvironment); string artefact = String.Format(".build/{0}.{1}.nupkg",csProject.GetName(), csProject.GetVersion()); if (!File.Exists(artefact)) throw new FileNotFoundException(artefact); stage.PipeLine.CommandEnvironment.Extend("DOTNET_ARTEFACTS", artefact); } } public static void Publish(Stage stage,params string[] arguments) { List projectFileNames = new List(); List artefacts = new List(); if (arguments.Length == 0) projectFileNames.AddRange(stage.CommandEnvironment.Get("DOTNET_PROJECTS","").Split(':')); else projectFileNames.AddRange(arguments); foreach (string projectFileName in projectFileNames) { CSProjHelper csProject = new CSProjHelper(projectFileName); if (!csProject.GetOutputType().Equals("Exe")) { stage.CommandEnvironment.Logger.Log(LogLevel.WARNING, "dotnet publish: not publishing {0} [{1}]",projectFileName, csProject.GetOutputType()); continue; } stage.CommandEnvironment.Logger.Log(LogLevel.WARNING, "dotnet publish: publishing now {0} [{1}]",projectFileName, csProject.GetOutputType()); CommandRunner cr = new CommandRunner("dotnet","publish", projectFileName) .AddArgument(new CommandRunner.Option("-c", stage.CommandEnvironment.Get("DOTNET_CONFIGURATION"))) .AddArguments("-p:PublishTrimmed=true","-p:PublishSingleFile=true","-p:PublishReadyToRun=false"); CommandRunner.Option outputOption = new CommandRunner.Option("-o", ".build/"); cr.AddArgument(outputOption); string[] rids = stage.CommandEnvironment.Get("DOTNET_RIDS","").Split(':'); stage.CommandEnvironment.Logger.Log(LogLevel.INFO,"dotnet publish: using rids: {0}", string.Join(' ', rids)); if (rids.Length == 0) { cr.Run(stage.CommandEnvironment); } else { CommandRunner.Option ridOption = new CommandRunner.Option("-r", ""); cr.AddArgument(ridOption); cr.AddArgument("--self-contained"); foreach (string rid in rids) { ridOption.SetValue(rid); outputOption.SetValue(String.Format(".build/{0}/", rid)); cr.Run(stage.CommandEnvironment); string artefact = Directory.GetFiles(String.Format(".build/{0}/", rid)).Where((fn)=>!fn.EndsWith(".pdb")).FirstOrDefault(); if (artefact != null) { string ext = Path.GetExtension(artefact); if (!ext.Equals(".exe")) ext = ""; string finalName = string.Format(".build/{0}-{1}{2}",csProject.GetName(), rid, ext); File.Move(artefact, finalName); artefacts.Add(finalName); stage.PipeLine.CommandEnvironment.Extend("DOTNET_ARTEFACTS", finalName); Directory.Delete(String.Format(".build/{0}/", rid), true); } } } } stage.CommandEnvironment.Logger.Log(LogLevel.INFO,"dotnet publish: created the following artefacts: {0}", string.Join(' ', artefacts)); } public static void Test(Stage stage,params string[] arguments) { foreach (string projectFileName in stage.CommandEnvironment.Get("DOTNET_PROJECTS","").Split(':')) { new CommandRunner("dotnet","test", projectFileName, new CommandRunner.Option("-c", stage.CommandEnvironment.Get("DOTNET_CONFIGURATION"))) .Run(stage.CommandEnvironment); } } public static void Push(Stage stage,params string[] arguments) { if (stage.CommandEnvironment.SecretStorage == null) { stage.CommandEnvironment.Logger.Log(LogLevel.WARNING,"dotnet push: no SecretStorage available, push operations are going to fail without authorization!"); } else { stage.CommandEnvironment.Logger.Log(LogLevel.INFO,"dotnet push: using secrets from {0}", stage.CommandEnvironment.SecretStorage.FileName); } string[] nupkgList = stage.CommandEnvironment.Get("DOTNET_ARTEFACTS","").Split(':').Where((fn)=>fn.EndsWith(".nupkg")).ToArray(); string[] binaryList = stage.CommandEnvironment.Get("DOTNET_ARTEFACTS","").Split(':').Where((fn)=>!fn.EndsWith(".nupkg")).ToArray(); if (nupkgList.Length > 0) { string nugetSource = stage.CommandEnvironment.Get("NUGET_SOURCE"); string nugetApiKey = null; if (!(stage.CommandEnvironment.SecretStorage?.TryGetSecret(nugetSource, out nugetApiKey) ?? false)) { URI uriNuget = new URI(nugetSource); stage.CommandEnvironment.SecretStorage?.TryGetSecret(new URI(uriNuget.Scheme, uriNuget.Authority, "").ToString(), out nugetApiKey); } CommandRunner cr = new CommandRunner("dotnet", "nuget", "push"); CommandRunner.Argument argNupkg = new CommandRunner.Argument(""); cr.AddArgument(argNupkg); CommandRunner.Option optSource = new CommandRunner.Option("-s",nugetSource); cr.AddArgument(optSource); CommandRunner.Option optApiKey = new CommandRunner.Option("-k", nugetApiKey); cr.AddArgument(optApiKey); foreach (string nupkg in nupkgList) { argNupkg.SetValue(nupkg); cr.Run(stage.CommandEnvironment); } } } } }