I'm developing a .net tool for building our projects. I'm using System.CommandLine package for collect command line argument without sweat. My build command looks like this:
[Command(Description = "Runs build process")]
public class Build
{
public int Execute(
[Option] string targetDirectory,
[Option(Aliases = new[] {"-c"})] string configuration = "Release")
{
return new CakeHost()
.UseContext<BuildContext>()
.Run(Enumerable.Empty<string>());
}
}
Note that there are attributes not available in the Microsoft's library. It's my addition. Type is converted into Command
on the fly.
The important thing is that Cake
takes arguments only as string collection. So the only way I can see here, is to convert arguments into strings and parse it again inside a task. I will not able to sleep for a month if I do that.
The solution I would expect here is to create and pass an instance of BuildContext
type (it inherits from FrostingContext
). I could simply have properties corresponding to app arguments.
Any ideas how to workaround it? Or maybe there is a feature I don't know?
CodePudding user response:
To achieve this you could use dependency injection to inject your custom arguments into your own build context as a singleton.
This could look something like
[Command(Description = "Runs build process")]
public class Build
{
public int Execute(
[Option] string targetDirectory,
[Option(Aliases = new[] {"-c"})] string configuration = "Release")
=> new CakeHost()
.ConfigureServices(services => services.AddSingleton(new BuildParameters(targetDirectory, configuration)))
.UseContext<BuildContext>()
.Run(Array.Empty<string>());
}
In this case, BuildParameters
is defined like this
public class BuildParameters
{
public DirectoryPath TargetDirectory { get; }
public string Configuration { get; }
public BuildParameters(string targetDirectory, string configuration)
{
Configuration = configuration;
TargetDirectory = DirectoryPath.FromString(targetDirectory);
}
}
A minimal FrostingContext utilizing this
public class BuildContext : FrostingContext
{
public BuildParameters BuildParameters { get; }
public BuildContext(ICakeContext context, BuildParameters buildParameters)
: base(context)
{
BuildParameters = buildParameters;
}
}
And then in all your Frosting tasks, you'll have a BuildParameters
property you can access like this.
[TaskName("Hello")]
public sealed class HelloTask : FrostingTask<BuildContext>
{
public override void Run(BuildContext context)
{
context.Log.Information("Configuration {0}", context.BuildParameters.Configuration);
}
}
CodePudding user response:
I feel you have two ways to go about this:
If you want to use Cake Frosting, which is meant to parse command line arguments, you'd have to pass all the arguments you are given, something like
new CakeHost()
.UseContext<BuildContext>()
.Run(new[]
{
$"--configuration={configuration}"
});
(Alternatively, you could check if System.CommandLine
contains a feature to access the arguments "raw" as they were given.)
Or, if you want to do all the parsing and setup in "your" app, you should have a look at Cake.Bridge which allows for using Cake-features fully programmatically. (IMHO this is the longer/harder path)