diff --git a/CSharpInteractive.Tests/README_TEMPLATE.md b/CSharpInteractive.Tests/README_TEMPLATE.md index 9c516dd..4b8b56c 100644 --- a/CSharpInteractive.Tests/README_TEMPLATE.md +++ b/CSharpInteractive.Tests/README_TEMPLATE.md @@ -1,13 +1,7 @@  -## Usage Scenarios +## API -- Global state - - [Using Args](#using-args) - - [Using Props](#using-props) - - [Using the Host property](#using-the-host-property) - - [Get services](#get-services) - - [Service collection](#service-collection) -- Logging +- Output, logging and tracing - [Write a line to a build log](#write-a-line-to-a-build-log) - [Write a line highlighted with "Header" color to a build log](#write-a-line-highlighted-with-"header"-color-to-a-build-log) - [Write an empty line to a build log](#write-an-empty-line-to-a-build-log) @@ -15,7 +9,17 @@ - [Log a warning to a build log](#log-a-warning-to-a-build-log) - [Log information to a build log](#log-information-to-a-build-log) - [Log trace information to a build log](#log-trace-information-to-a-build-log) -- Command Line API +- Arguments and parameters + - [Using Args](#using-args) + - [Using Props](#using-props) +- Microsoft DI + - [Using the Host property](#using-the-host-property) + - [Get services](#get-services) + - [Service collection](#service-collection) +- NuGet + - [Restore NuGet a package of newest version](#restore-nuget-a-package-of-newest-version) + - [Restore a NuGet package by a version range for the specified .NET and path](#restore-a-nuget-package-by-a-version-range-for-the-specified-.net-and-path) +- Command Line - [Build command lines](#build-command-lines) - [Run a command line](#run-a-command-line) - [Run a command line asynchronously](#run-a-command-line-asynchronously) @@ -23,10 +27,10 @@ - [Run asynchronously in parallel](#run-asynchronously-in-parallel) - [Cancellation of asynchronous run](#cancellation-of-asynchronous-run) - [Run timeout](#run-timeout) -- Docker API +- Docker CLI - [Build a project in a docker container](#build-a-project-in-a-docker-container) - [Running in docker](#running-in-docker) -- .NET build API +- .NET CLI - [Build a project](#build-a-project) - [Build a project using MSBuild](#build-a-project-using-msbuild) - [Clean a project](#clean-a-project) @@ -41,12 +45,79 @@ - [Test a project using the MSBuild VSTest target](#test-a-project-using-the-msbuild-vstest-target) - [Test an assembly](#test-an-assembly) - [Shuts down build servers](#shuts-down-build-servers) -- NuGet API - - [Restore NuGet a package of newest version](#restore-nuget-a-package-of-newest-version) - - [Restore a NuGet package by a version range for the specified .NET and path](#restore-a-nuget-package-by-a-version-range-for-the-specified-.net-and-path) -- TeamCity Service Messages API +- TeamCity API - [TeamCity integration via service messages](#teamcity-integration-via-service-messages) +### Write a line to a build log + + + +``` CSharp +WriteLine("Hello"); +``` + + + +### Write an empty line to a build log + + + +``` CSharp +WriteLine(); +``` + + + +### Write a line highlighted with "Header" color to a build log + + + +``` CSharp +WriteLine("Hello", Header); +``` + + + +### Log an error to a build log + + + +``` CSharp +Error("Error info", "Error identifier"); +``` + + + +### Log a warning to a build log + + + +``` CSharp +Warning("Warning info"); +``` + + + +### Log information to a build log + + + +``` CSharp +Info("Some info"); +``` + + + +### Log trace information to a build log + + + +``` CSharp +Trace("Some trace info"); +``` + + + ### Using Args _Args_ have got from the script arguments. @@ -133,72 +204,38 @@ private class MyTask(ICommandLineRunner runner) -### Write a line to a build log - - - -``` CSharp -WriteLine("Hello"); -``` - - - -### Write an empty line to a build log - - - -``` CSharp -WriteLine(); -``` - - - -### Write a line highlighted with "Header" color to a build log - - - -``` CSharp -WriteLine("Hello", Header); -``` - - - -### Log an error to a build log +### Restore NuGet a package of newest version ``` CSharp -Error("Error info", "Error identifier"); -``` - - - -### Log a warning to a build log - - +// Adds the namespace "HostApi" to use INuGet +using HostApi; -``` CSharp -Warning("Warning info"); +IEnumerable packages = GetService() + .Restore(new NuGetRestoreSettings("IoC.Container").WithVersionRange(VersionRange.All)); ``` -### Log information to a build log +### Restore a NuGet package by a version range for the specified .NET and path ``` CSharp -Info("Some info"); -``` - - - -### Log trace information to a build log +// Adds the namespace "HostApi" to use INuGet +using HostApi; +var packagesPath = Path.Combine( + Path.GetTempPath(), + Guid.NewGuid().ToString()[..4]); +var settings = new NuGetRestoreSettings("IoC.Container") + .WithVersionRange(VersionRange.Parse("[1.3, 1.3.8)")) + .WithTargetFrameworkMoniker("net5.0") + .WithPackagesPath(packagesPath); -``` CSharp -Trace("Some trace info"); +IEnumerable packages = GetService().Restore(settings); ``` @@ -380,6 +417,66 @@ exitCode.HasValue.ShouldBeFalse(); +### Build a project in a docker container + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API and Docker API +using HostApi; + +// Creates a base docker command line +var dockerRun = new DockerRun() + .WithAutoRemove(true) + .WithInteractive(true) + .WithImage("mcr.microsoft.com/dotnet/sdk") + .WithPlatform("linux") + .WithContainerWorkingDirectory("/MyProjects") + .AddVolumes((ToAbsoluteLinuxPath(Environment.CurrentDirectory), "/MyProjects")); + + +// Creates a new library project in a docker container +dockerRun + .WithCommandLine(new DotNetCustom("new", "classlib", "-n", "MyLib", "--force")) + .Run() + .EnsureSuccess(); + +// Builds the library project in a docker container +var result = dockerRun + .WithCommandLine(new DotNetBuild().WithProject("MyLib/MyLib.csproj")) + .Build() + .EnsureSuccess(); + +// The "result" variable provides details about a build +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); +result.ExitCode.ShouldBe(0); + +string ToAbsoluteLinuxPath(string path) => + "/" + path.Replace(":", "").Replace('\\', '/'); +``` + + + +### Running in docker + + + +``` CSharp +// Adds the namespace "HostApi" to use Command Line API and Docker API +using HostApi; + +// Creates some command line to run in a docker container +var cmd = new CommandLine("whoami"); + +// Runs the command line in a docker container +var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") + .WithAutoRemove(true) + .Run() + .EnsureSuccess(); +``` + + + ### Build a project @@ -812,102 +909,6 @@ new DotNetBuildServerShutdown() -### Restore NuGet a package of newest version - - - -``` CSharp -// Adds the namespace "HostApi" to use INuGet -using HostApi; - -IEnumerable packages = GetService() - .Restore(new NuGetRestoreSettings("IoC.Container").WithVersionRange(VersionRange.All)); -``` - - - -### Restore a NuGet package by a version range for the specified .NET and path - - - -``` CSharp -// Adds the namespace "HostApi" to use INuGet -using HostApi; - -var packagesPath = Path.Combine( - Path.GetTempPath(), - Guid.NewGuid().ToString()[..4]); - -var settings = new NuGetRestoreSettings("IoC.Container") - .WithVersionRange(VersionRange.Parse("[1.3, 1.3.8)")) - .WithTargetFrameworkMoniker("net5.0") - .WithPackagesPath(packagesPath); - -IEnumerable packages = GetService().Restore(settings); -``` - - - -### Build a project in a docker container - - - -``` CSharp -// Adds the namespace "HostApi" to use .NET build API and Docker API -using HostApi; - -// Creates a base docker command line -var dockerRun = new DockerRun() - .WithAutoRemove(true) - .WithInteractive(true) - .WithImage("mcr.microsoft.com/dotnet/sdk") - .WithPlatform("linux") - .WithContainerWorkingDirectory("/MyProjects") - .AddVolumes((ToAbsoluteLinuxPath(Environment.CurrentDirectory), "/MyProjects")); - - -// Creates a new library project in a docker container -dockerRun - .WithCommandLine(new DotNetCustom("new", "classlib", "-n", "MyLib", "--force")) - .Run() - .EnsureSuccess(); - -// Builds the library project in a docker container -var result = dockerRun - .WithCommandLine(new DotNetBuild().WithProject("MyLib/MyLib.csproj")) - .Build() - .EnsureSuccess(); - -// The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); - -string ToAbsoluteLinuxPath(string path) => - "/" + path.Replace(":", "").Replace('\\', '/'); -``` - - - -### Running in docker - - - -``` CSharp -// Adds the namespace "HostApi" to use Command Line API and Docker API -using HostApi; - -// Creates some command line to run in a docker container -var cmd = new CommandLine("whoami"); - -// Runs the command line in a docker container -var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") - .WithAutoRemove(true) - .Run() - .EnsureSuccess(); -``` - - - ### TeamCity integration via service messages For more details how to use TeamCity service message API please see [this](https://github.com/JetBrains/TeamCity.ServiceMessages) page. Instead of creating a root message writer like in the following example: diff --git a/CSharpInteractive.Tests/README_TEMPLATE.tt b/CSharpInteractive.Tests/README_TEMPLATE.tt index 6c5e903..119cfac 100644 --- a/CSharpInteractive.Tests/README_TEMPLATE.tt +++ b/CSharpInteractive.Tests/README_TEMPLATE.tt @@ -100,10 +100,10 @@ vars["body"] = string.Join(Environment.NewLine, content) + Environment.NewLine; } #> -## Usage Scenarios +## API <# - foreach (var group in infos.Where(info => info["visible"] == "true").GroupBy(i => i["tag"]).OrderBy(i => i.Key[0])) + foreach (var group in infos.Where(info => info["visible"] == "true").GroupBy(i => i["tag"]).OrderBy(i => i.Key)) { var groupNameIndex = group.Key.IndexOf(' '); var groupName = group.Key.Substring(groupNameIndex + 1, group.Key.Length - groupNameIndex - 1); diff --git a/CSharpInteractive.Tests/UsageScenarios/ArgsScenario.cs b/CSharpInteractive.Tests/UsageScenarios/ArgsScenario.cs index 37731f2..2c348aa 100644 --- a/CSharpInteractive.Tests/UsageScenarios/ArgsScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/ArgsScenario.cs @@ -6,7 +6,7 @@ public class ArgsScenario : BaseScenario public void Run() { // $visible=true - // $tag=08 Global state + // $tag=02 Arguments and parameters // $priority=00 // $description=Using Args // $header=_Args_ have got from the script arguments. diff --git a/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncCancellation.cs b/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncCancellation.cs index b831f94..397feb1 100644 --- a/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncCancellation.cs +++ b/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncCancellation.cs @@ -16,7 +16,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=10 Command Line API + // $tag=05 Command Line // $priority=06 // $description=Cancellation of asynchronous run // $header=Cancellation will destroy the process and its child processes. diff --git a/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncScenario.cs b/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncScenario.cs index 254b9a4..3faee58 100644 --- a/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/CommandLineAsyncScenario.cs @@ -17,7 +17,7 @@ public async Task Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=10 Command Line API + // $tag=05 Command Line // $priority=02 // $description=Run a command line asynchronously // { diff --git a/CSharpInteractive.Tests/UsageScenarios/CommandLineInParallelScenario.cs b/CSharpInteractive.Tests/UsageScenarios/CommandLineInParallelScenario.cs index 15f77f9..409d2da 100644 --- a/CSharpInteractive.Tests/UsageScenarios/CommandLineInParallelScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/CommandLineInParallelScenario.cs @@ -17,7 +17,7 @@ public async Task Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=10 Command Line API + // $tag=05 Command Line // $priority=05 // $description=Run asynchronously in parallel // { diff --git a/CSharpInteractive.Tests/UsageScenarios/CommandLineOutputScenario.cs b/CSharpInteractive.Tests/UsageScenarios/CommandLineOutputScenario.cs index 97e67ba..5a861d1 100644 --- a/CSharpInteractive.Tests/UsageScenarios/CommandLineOutputScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/CommandLineOutputScenario.cs @@ -16,7 +16,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=10 Command Line API + // $tag=05 Command Line // $priority=04 // $description=Run and process output // { diff --git a/CSharpInteractive.Tests/UsageScenarios/CommandLineScenario.cs b/CSharpInteractive.Tests/UsageScenarios/CommandLineScenario.cs index e2ffd7f..61ee921 100644 --- a/CSharpInteractive.Tests/UsageScenarios/CommandLineScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/CommandLineScenario.cs @@ -16,7 +16,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=10 Command Line API + // $tag=05 Command Line // $priority=01 // $description=Run a command line // { diff --git a/CSharpInteractive.Tests/UsageScenarios/CommandLineWithTimeoutScenario.cs b/CSharpInteractive.Tests/UsageScenarios/CommandLineWithTimeoutScenario.cs index 5c22890..c179e7e 100644 --- a/CSharpInteractive.Tests/UsageScenarios/CommandLineWithTimeoutScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/CommandLineWithTimeoutScenario.cs @@ -17,7 +17,7 @@ public void Run() ExpectedExitCode = 1; // $visible=true - // $tag=10 Command Line API + // $tag=05 Command Line // $priority=06 // $description=Run timeout // $header=If timeout expired a process will be killed. diff --git a/CSharpInteractive.Tests/UsageScenarios/CommandLinesScenario.cs b/CSharpInteractive.Tests/UsageScenarios/CommandLinesScenario.cs index 234e8e6..e39981f 100644 --- a/CSharpInteractive.Tests/UsageScenarios/CommandLinesScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/CommandLinesScenario.cs @@ -18,7 +18,7 @@ public void Run() Skip.IfNot(Environment.OSVersion.Platform == PlatformID.Win32NT); // $visible=true - // $tag=10 Command Line API + // $tag=05 Command Line // $priority=00 // $description=Build command lines // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DockerDotNetBuildScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DockerDotNetBuildScenario.cs index 1f5836f..0820416 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DockerDotNetBuildScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DockerDotNetBuildScenario.cs @@ -19,7 +19,7 @@ public class DockerDotNetBuildScenario : BaseScenario public void Run() { // $visible=true - // $tag=12 Docker API + // $tag=06 Docker CLI // $priority=01 // $description=Build a project in a docker container // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DockerRunScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DockerRunScenario.cs index d5a59b0..da1a214 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DockerRunScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DockerRunScenario.cs @@ -14,7 +14,7 @@ public class DockerRunScenario : BaseScenario public void Run() { // $visible=true - // $tag=12 Docker API + // $tag=06 Docker CLI // $priority=01 // $description=Running in docker // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs index 7626865..779df78 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs @@ -14,7 +14,7 @@ public class DotNetBuildScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Build a project // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetBuildServerShutdownScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetBuildServerShutdownScenario.cs index 3dd2a5c..c5e11a9 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetBuildServerShutdownScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetBuildServerShutdownScenario.cs @@ -13,7 +13,7 @@ public class DotNetBuildServerShutdownScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=02 // $description=Shuts down build servers // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetCleanScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetCleanScenario.cs index 152d08a..f2c47e0 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetCleanScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetCleanScenario.cs @@ -14,7 +14,7 @@ public class DotNetCleanScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Clean a project // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetCustomScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetCustomScenario.cs index 1d4873a..e772d14 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetCustomScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetCustomScenario.cs @@ -16,7 +16,7 @@ public class DotNetCustomScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Run a custom .NET command // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetMSBuildVSTestScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetMSBuildVSTestScenario.cs index 992a9e7..f259be7 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetMSBuildVSTestScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetMSBuildVSTestScenario.cs @@ -14,7 +14,7 @@ public class DotNetMSBuildVSTestScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Test a project using the MSBuild VSTest target // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetPackScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetPackScenario.cs index a37e7c5..03bd1d0 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetPackScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetPackScenario.cs @@ -14,7 +14,7 @@ public class DotNetPackScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Pack a project // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetPublishScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetPublishScenario.cs index 6f196fd..c83cbd6 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetPublishScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetPublishScenario.cs @@ -14,7 +14,7 @@ public class DotNetPublishScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Publish a project // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetRestoreScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetRestoreScenario.cs index 008d524..5fe7b2e 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetRestoreScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetRestoreScenario.cs @@ -14,7 +14,7 @@ public class DotNetRestoreScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Restore a project // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetRunScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetRunScenario.cs index 639937b..0067138 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetRunScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetRunScenario.cs @@ -15,7 +15,7 @@ public class DotNetRunScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Run a project // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetTestScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetTestScenario.cs index baf93b1..98980c2 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetTestScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetTestScenario.cs @@ -13,7 +13,7 @@ public class DotNetTestScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Test a project // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetTestWithDotCoverScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetTestWithDotCoverScenario.cs index 304b095..9438014 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetTestWithDotCoverScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetTestWithDotCoverScenario.cs @@ -13,7 +13,7 @@ public class DotNetTestWithDotCoverScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Run tests under dotCover // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetToolRestoreScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetToolRestoreScenario.cs index 1eb2aa5..dfe52f1 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetToolRestoreScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetToolRestoreScenario.cs @@ -14,7 +14,7 @@ public class DotNetToolRestoreScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Restore local tools // { diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetVSTestScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetVSTestScenario.cs index ecd086d..c26dd63 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetVSTestScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetVSTestScenario.cs @@ -14,7 +14,7 @@ public class DotNetVSTestScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Test an assembly // { diff --git a/CSharpInteractive.Tests/UsageScenarios/GetServiceScenario.cs b/CSharpInteractive.Tests/UsageScenarios/GetServiceScenario.cs index 9867b06..23f5e7c 100644 --- a/CSharpInteractive.Tests/UsageScenarios/GetServiceScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/GetServiceScenario.cs @@ -11,7 +11,7 @@ public class GetServiceScenario : BaseScenario public void Run() { // $visible=true - // $tag=08 Global state + // $tag=03 Microsoft DI // $priority=03 // $description=Get services // $header=This method might be used to get access to different APIs like [INuGet](TeamCity.CSharpInteractive.HostApi/INuGet.cs) or [ICommandLine](TeamCity.CSharpInteractive.HostApi/ICommandLine.cs). diff --git a/CSharpInteractive.Tests/UsageScenarios/HostScenario.cs b/CSharpInteractive.Tests/UsageScenarios/HostScenario.cs index f30808a..edd51a9 100644 --- a/CSharpInteractive.Tests/UsageScenarios/HostScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/HostScenario.cs @@ -11,7 +11,7 @@ public class HostScenario : BaseScenario public void Run() { // $visible=true - // $tag=08 Global state + // $tag=03 Microsoft DI // $priority=02 // $description=Using the Host property // $header=[_Host_](TeamCity.CSharpInteractive.HostApi/IHost.cs) is actually the provider of all global properties and methods. diff --git a/CSharpInteractive.Tests/UsageScenarios/LogErrorScenario.cs b/CSharpInteractive.Tests/UsageScenarios/LogErrorScenario.cs index 0c44b1a..6d13e80 100644 --- a/CSharpInteractive.Tests/UsageScenarios/LogErrorScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/LogErrorScenario.cs @@ -12,7 +12,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=09 Logging + // $tag=01 Output, logging and tracing // $priority=02 // $description=Log an error to a build log // { diff --git a/CSharpInteractive.Tests/UsageScenarios/LogInfoScenario.cs b/CSharpInteractive.Tests/UsageScenarios/LogInfoScenario.cs index 5a044e9..3591de0 100644 --- a/CSharpInteractive.Tests/UsageScenarios/LogInfoScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/LogInfoScenario.cs @@ -12,7 +12,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=09 Logging + // $tag=01 Output, logging and tracing // $priority=04 // $description=Log information to a build log // { diff --git a/CSharpInteractive.Tests/UsageScenarios/LogTraceScenario.cs b/CSharpInteractive.Tests/UsageScenarios/LogTraceScenario.cs index 47c8807..f906f8f 100644 --- a/CSharpInteractive.Tests/UsageScenarios/LogTraceScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/LogTraceScenario.cs @@ -12,7 +12,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=09 Logging + // $tag=01 Output, logging and tracing // $priority=05 // $description=Log trace information to a build log // { diff --git a/CSharpInteractive.Tests/UsageScenarios/LogWarningScenario.cs b/CSharpInteractive.Tests/UsageScenarios/LogWarningScenario.cs index 26bac07..ec2ee7c 100644 --- a/CSharpInteractive.Tests/UsageScenarios/LogWarningScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/LogWarningScenario.cs @@ -12,7 +12,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=09 Logging + // $tag=01 Output, logging and tracing // $priority=03 // $description=Log a warning to a build log // { diff --git a/CSharpInteractive.Tests/UsageScenarios/MSBuildScenario.cs b/CSharpInteractive.Tests/UsageScenarios/MSBuildScenario.cs index 5e27145..dcf5981 100644 --- a/CSharpInteractive.Tests/UsageScenarios/MSBuildScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/MSBuildScenario.cs @@ -15,7 +15,7 @@ public class MSBuildScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 .NET build API + // $tag=07 .NET CLI // $priority=01 // $description=Build a project using MSBuild // { diff --git a/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreAdvanced.cs b/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreAdvanced.cs index 53f4781..8176dd4 100644 --- a/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreAdvanced.cs +++ b/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreAdvanced.cs @@ -13,7 +13,7 @@ public class NuGetRestoreAdvanced : BaseScenario public void Run() { // $visible=true - // $tag=11 NuGet API + // $tag=04 NuGet // $priority=01 // $description=Restore a NuGet package by a version range for the specified .NET and path // { diff --git a/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreScenario.cs b/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreScenario.cs index 0b78864..2bc087d 100644 --- a/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/NuGetRestoreScenario.cs @@ -13,7 +13,7 @@ public class NuGetRestoreScenario : BaseScenario public void Run() { // $visible=true - // $tag=11 NuGet API + // $tag=04 NuGet // $priority=00 // $description=Restore NuGet a package of newest version // { diff --git a/CSharpInteractive.Tests/UsageScenarios/PropsScenario.cs b/CSharpInteractive.Tests/UsageScenarios/PropsScenario.cs index 6361737..57f9438 100644 --- a/CSharpInteractive.Tests/UsageScenarios/PropsScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/PropsScenario.cs @@ -8,7 +8,7 @@ public class PropsScenario : BaseScenario public void Run() { // $visible=true - // $tag=08 Global state + // $tag=02 Arguments and parameters // $priority=01 // $description=Using Props // { diff --git a/CSharpInteractive.Tests/UsageScenarios/ServiceCollectionScenario.cs b/CSharpInteractive.Tests/UsageScenarios/ServiceCollectionScenario.cs index 6a75fa7..a943a84 100644 --- a/CSharpInteractive.Tests/UsageScenarios/ServiceCollectionScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/ServiceCollectionScenario.cs @@ -9,7 +9,7 @@ public class ServiceCollectionScenario : BaseScenario { [Fact] // $visible=true - // $tag=08 Global state + // $tag=03 Microsoft DI // $priority=03 // $description=Service collection // { diff --git a/CSharpInteractive.Tests/UsageScenarios/TeamCityServiceMessagesScenario.cs b/CSharpInteractive.Tests/UsageScenarios/TeamCityServiceMessagesScenario.cs index ab32826..bc6c956 100644 --- a/CSharpInteractive.Tests/UsageScenarios/TeamCityServiceMessagesScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/TeamCityServiceMessagesScenario.cs @@ -13,7 +13,7 @@ public void Run() Skip.IfNot(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"))); // $visible=true - // $tag=3 TeamCity Service Messages API + // $tag=3 TeamCity API // $priority=00 // $description=TeamCity integration via service messages // $header=For more details how to use TeamCity service message API please see [this](https://github.com/JetBrains/TeamCity.ServiceMessages) page. Instead of creating a root message writer like in the following example: diff --git a/CSharpInteractive.Tests/UsageScenarios/WriteEmptyLineScenario.cs b/CSharpInteractive.Tests/UsageScenarios/WriteEmptyLineScenario.cs index 4acbfdc..dadc221 100644 --- a/CSharpInteractive.Tests/UsageScenarios/WriteEmptyLineScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/WriteEmptyLineScenario.cs @@ -8,7 +8,7 @@ public class WriteEmptyLineScenario : BaseScenario public void Run() { // $visible=true - // $tag=09 Logging + // $tag=01 Output, logging and tracing // $priority=01 // $description=Write an empty line to a build log // { diff --git a/CSharpInteractive.Tests/UsageScenarios/WriteLineScenario.cs b/CSharpInteractive.Tests/UsageScenarios/WriteLineScenario.cs index 8556095..bf1ba73 100644 --- a/CSharpInteractive.Tests/UsageScenarios/WriteLineScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/WriteLineScenario.cs @@ -8,7 +8,7 @@ public class WriteLineScenario : BaseScenario public void Run() { // $visible=true - // $tag=09 Logging + // $tag=01 Output, logging and tracing // $priority=00 // $description=Write a line to a build log // { diff --git a/CSharpInteractive.Tests/UsageScenarios/WriteLineWithColourScenario.cs b/CSharpInteractive.Tests/UsageScenarios/WriteLineWithColourScenario.cs index 145bfda..bf13006 100644 --- a/CSharpInteractive.Tests/UsageScenarios/WriteLineWithColourScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/WriteLineWithColourScenario.cs @@ -10,7 +10,7 @@ public class WriteLineWithColourScenario : BaseScenario public void Run() { // $visible=true - // $tag=09 Logging + // $tag=01 Output, logging and tracing // $priority=01 // $description=Write a line highlighted with "Header" color to a build log // { diff --git a/CSharpInteractive.sln b/CSharpInteractive.sln index e1d8b6b..fe16dd5 100644 --- a/CSharpInteractive.sln +++ b/CSharpInteractive.sln @@ -15,6 +15,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution", "Solution", "{12 Directory.Build.props = Directory.Build.props LICENSE = LICENSE README_BODY.md = README_BODY.md + README.md = README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{CE315710-ACE8-4CAC-B030-4778257652DB}" diff --git a/CSharpInteractive.sln.DotSettings b/CSharpInteractive.sln.DotSettings index 6f07ccc..67afbc9 100644 --- a/CSharpInteractive.sln.DotSettings +++ b/CSharpInteractive.sln.DotSettings @@ -231,6 +231,7 @@ True True True + True True True True diff --git a/README.md b/README.md index 0c34b8d..8cebc26 100644 --- a/README.md +++ b/README.md @@ -12,173 +12,23 @@ C# interactive build automation system makes it easy to build .NET projects. It ## Advantages - [X] 3 compatible [operating modes](#operating-modes) -- [X] .NET console application [project](#net-build-project) -- [X] Part of .NET solution -- [X] C# - [X] Cross-platform - [X] Debugging capability -- [X] No model binding (Task, Target, DependsOn, etc.) - - no restrictions - - no learning curve - - can use common .NET development practices -- [X] Simple and powerful API for building .NET projects -- [X] Passing named parameters as in MSBuild -- [X] Summarised statistics as in MSBuild - - Child processes - - Warnings and errors - - Tests - - Execution time -- [X] CI/CD integration - - GitLab/GitHub Actions/JetBrains Space etc. - - TeamCity - - [Special runner](https://jetbrains.com/help/teamcity/c-script.html#C%23+Script+Settings) - - Report on warnings and errors - - Test statistics - - Execution progress - - Real-time integration - - Parameters passing between build configuration steps +- [X] No model limitations (Task, Target, DependsOn, etc.) + - Regular .NET code + - Best programming practices +- [X] Powerful API for building .NET projects +- [X] Summarised statistics ## Operating modes -- [REPL](#script-runner-and-repl-tool) -- [C# scripts running](#script-runner-and-repl-tool) -- [.NET build project](#net-build-project) +- [Interactive](#interactive-repl) +- [Running C# script](#running-c-script) +- [Regular .NET build project](#net-build-project) These modes are practically compatible, i.e., for example, a script can be run as a .NET project, and vice versa, with minimal or no changes. -## API -- Output, logging and tracing -- Arguments and parameters -- Command line -- Docker -- Microsoft DI API to resolve dependencies -- NuGet -- .NET CLI - -```c# -// This directive in a script allows you to use host API types -// without specifying the fully qualified namespace of these types -using HostApi; - -// Output, logging and tracing API -WriteLine("Hello"); -WriteLine("Hello !!!", Color.Highlighted); -Error("Error details", "ErrorId"); -Warning("Warning"); -Info("Some info"); -Trace("Trace message"); - -// API for arguments and parameters -Info("First argument: " + (Args.Count > 0 ? Args[0] : "empty")); -Info("Version: " + Props.Get("version", "1.0.0")); -Props["version"] = "1.0.1"; - -var configuration = Props.Get("configuration", "Release"); -Info($"Configuration: {configuration}"); - -// Command line API -var cmd = new CommandLine("whoami"); - -cmd.Run().EnsureSuccess(); - -// Asynchronous way -await cmd.RunAsync().EnsureSuccess(); - -// API for Docker CLI -await new DockerRun("ubuntu") - .WithCommandLine(cmd) - .WithPull(DockerPullType.Always) - .WithAutoRemove(true) - .RunAsync() - .EnsureSuccess(); - -// Microsoft DI API to resolve dependencies -var nuget = GetService(); - -// Creating a custom service provider -var serviceCollection = GetService(); -serviceCollection.AddSingleton(); - -var myServiceProvider = serviceCollection.BuildServiceProvider(); -var tool = myServiceProvider.GetRequiredService(); - -// API for NuGet -var settings = new NuGetRestoreSettings("MySampleLib") - .WithVersionRange(VersionRange.Parse("[1.0.14, 1.1)")) - .WithTargetFrameworkMoniker("net6.0") - .WithPackagesPath(".packages"); - -var packages = nuget.Restore(settings); -foreach (var package in packages) -{ - Info(package.Path); -} - -// API for .NET CLI -var buildResult = new DotNetBuild().WithConfiguration(configuration).WithNoLogo(true) - .Build().EnsureSuccess(); - -var warnings = buildResult.Warnings - .Where(warn => Path.GetFileName(warn.File) == "Calculator.cs") - .Select(warn => $"{warn.Code}({warn.LineNumber}:{warn.ColumnNumber})") - .Distinct(); - -foreach (var warning in warnings) -{ - await new HttpClient().GetAsync( - "https://api.telegram.org/bot7102686717:AAEHw7HZinme_5kfIRV7TwXK4Xql9WPPpM3/" + - "sendMessage?chat_id=878745093&text=" - + HttpUtility.UrlEncode(warning)); -} - -// Asynchronous way -var cts = new CancellationTokenSource(); -await new DotNetTest() - .WithConfiguration(configuration) - .WithNoLogo(true) - .WithNoBuild(true) - .BuildAsync(CancellationOnFirstFailedTest, cts.Token) - .EnsureSuccess(); - -void CancellationOnFirstFailedTest(BuildMessage message) -{ - if (message.TestResult is { State: TestState.Failed }) cts.Cancel(); -} - -// Parallel tests -var tempDir = Directory.CreateTempSubdirectory(); -try -{ - new DotNetPublish() - .WithConfiguration(configuration) - .WithNoLogo(true) - .WithNoBuild(true) - .WithFramework("net8.0") - .AddProps(("PublishDir", tempDir.FullName)) - .Build().EnsureSuccess(); - - var test = new VSTest().WithTestFileNames("*.Tests.dll"); - - var tasks = from tagSuffix in new[] {"bookworm-slim", "alpine", "noble"} - let image = $"mcr.microsoft.com/dotnet/sdk:8.0-{tagSuffix}" - let dockerRun = new DockerRun(image) - .WithCommandLine(test) - .WithAutoRemove(true) - .WithVolumes((tempDir.FullName, "/app")) - .WithContainerWorkingDirectory("/app") - select dockerRun.BuildAsync(CancellationOnFirstFailedTest, cts.Token); - - await Task.WhenAll(tasks).EnsureSuccess(); -} -finally { tempDir.Delete(); } - -class MyTool(INuGet nuGet); -``` - -> [!IMPORTANT] -> `using HostApi;` directive in a script allows you to use host API types without specifying the fully qualified namespace of these types. - -## Script runner and REPL tool +## Interactive (REPL) Please see [this page](https://github.com/DevTeam/csharp-interactive/wiki/Install-the-C%23-script-template) for installation details. @@ -187,17 +37,24 @@ Launch the tool in the interactive mode: ```Shell dotnet csi ``` +Simply enter C# commands sequentially one line after another and get the result in console output. + +## Running C# script + Run a specified script with a given argument: ```Shell -dotnet csi Samples/Scripts/hello.csx World +dotnet csi ./MyDirectory/hello.csx World ``` + Run a single script located in the _MyDirectory_ directory: ```Shell -dotnet csi Samples/Build +dotnet csi ./MyDirectory World ``` -Usage: + +
+Usage details ```Shell dotnet csi [options] [--] [script] [script arguments] @@ -223,6 +80,8 @@ Supported options: | --property | Define a key-value pair(s) for the script properties called _Props_, which is accessible in scripts. | `-p`, `/property`, `/p` | | --property: | Define a key-value pair(s) in MSBuild style for the script properties called _Props_, which is accessible in scripts. | `-p:`, `/property:`, `/p:`, `--property:key1=val1;key2=val2` | +
+ ## .NET build project Please see [this page](https://github.com/DevTeam/csharp-interactive/wiki/Install-the-C%23-script-template) for details on how to install the [project template](https://www.nuget.org/packages/CSharpInteractive.Templates). @@ -235,28 +94,17 @@ dotnet new build -o ./Build The created project contains 2 entry points: - _Program.csx_ to run as a script + ```shell + dotnet csi ./Build + ``` - _Program.cs_ to run as .NET application + ```shell + dotnet run --project ./Build + ``` -To run the script from the command line from the directory *__Build__*: - -```shell -dotnet csi Build -``` - -To run as a .NET console application: - -```shell -dotnet run --project Build -``` -## Usage Scenarios +## API -- Global state - - [Using Args](#using-args) - - [Using Props](#using-props) - - [Using the Host property](#using-the-host-property) - - [Get services](#get-services) - - [Service collection](#service-collection) -- Logging +- Output, logging and tracing - [Write a line to a build log](#write-a-line-to-a-build-log) - [Write a line highlighted with "Header" color to a build log](#write-a-line-highlighted-with-"header"-color-to-a-build-log) - [Write an empty line to a build log](#write-an-empty-line-to-a-build-log) @@ -264,7 +112,17 @@ dotnet run --project Build - [Log a warning to a build log](#log-a-warning-to-a-build-log) - [Log information to a build log](#log-information-to-a-build-log) - [Log trace information to a build log](#log-trace-information-to-a-build-log) -- Command Line API +- Arguments and parameters + - [Using Args](#using-args) + - [Using Props](#using-props) +- Microsoft DI + - [Using the Host property](#using-the-host-property) + - [Get services](#get-services) + - [Service collection](#service-collection) +- NuGet + - [Restore NuGet a package of newest version](#restore-nuget-a-package-of-newest-version) + - [Restore a NuGet package by a version range for the specified .NET and path](#restore-a-nuget-package-by-a-version-range-for-the-specified-.net-and-path) +- Command Line - [Build command lines](#build-command-lines) - [Run a command line](#run-a-command-line) - [Run a command line asynchronously](#run-a-command-line-asynchronously) @@ -272,10 +130,10 @@ dotnet run --project Build - [Run asynchronously in parallel](#run-asynchronously-in-parallel) - [Cancellation of asynchronous run](#cancellation-of-asynchronous-run) - [Run timeout](#run-timeout) -- Docker API +- Docker CLI - [Build a project in a docker container](#build-a-project-in-a-docker-container) - [Running in docker](#running-in-docker) -- .NET build API +- .NET CLI - [Build a project](#build-a-project) - [Build a project using MSBuild](#build-a-project-using-msbuild) - [Clean a project](#clean-a-project) @@ -290,12 +148,79 @@ dotnet run --project Build - [Test a project using the MSBuild VSTest target](#test-a-project-using-the-msbuild-vstest-target) - [Test an assembly](#test-an-assembly) - [Shuts down build servers](#shuts-down-build-servers) -- NuGet API - - [Restore NuGet a package of newest version](#restore-nuget-a-package-of-newest-version) - - [Restore a NuGet package by a version range for the specified .NET and path](#restore-a-nuget-package-by-a-version-range-for-the-specified-.net-and-path) -- TeamCity Service Messages API +- TeamCity API - [TeamCity integration via service messages](#teamcity-integration-via-service-messages) +### Write a line to a build log + + + +``` CSharp +WriteLine("Hello"); +``` + + + +### Write an empty line to a build log + + + +``` CSharp +WriteLine(); +``` + + + +### Write a line highlighted with "Header" color to a build log + + + +``` CSharp +WriteLine("Hello", Header); +``` + + + +### Log an error to a build log + + + +``` CSharp +Error("Error info", "Error identifier"); +``` + + + +### Log a warning to a build log + + + +``` CSharp +Warning("Warning info"); +``` + + + +### Log information to a build log + + + +``` CSharp +Info("Some info"); +``` + + + +### Log trace information to a build log + + + +``` CSharp +Trace("Some trace info"); +``` + + + ### Using Args _Args_ have got from the script arguments. @@ -382,72 +307,38 @@ private class MyTask(ICommandLineRunner runner) -### Write a line to a build log - - - -``` CSharp -WriteLine("Hello"); -``` - - - -### Write an empty line to a build log - - - -``` CSharp -WriteLine(); -``` - - - -### Write a line highlighted with "Header" color to a build log - - - -``` CSharp -WriteLine("Hello", Header); -``` - - - -### Log an error to a build log +### Restore NuGet a package of newest version ``` CSharp -Error("Error info", "Error identifier"); -``` - - - -### Log a warning to a build log - - +// Adds the namespace "HostApi" to use INuGet +using HostApi; -``` CSharp -Warning("Warning info"); +IEnumerable packages = GetService() + .Restore(new NuGetRestoreSettings("IoC.Container").WithVersionRange(VersionRange.All)); ``` -### Log information to a build log +### Restore a NuGet package by a version range for the specified .NET and path ``` CSharp -Info("Some info"); -``` - - - -### Log trace information to a build log +// Adds the namespace "HostApi" to use INuGet +using HostApi; +var packagesPath = Path.Combine( + Path.GetTempPath(), + Guid.NewGuid().ToString()[..4]); +var settings = new NuGetRestoreSettings("IoC.Container") + .WithVersionRange(VersionRange.Parse("[1.3, 1.3.8)")) + .WithTargetFrameworkMoniker("net5.0") + .WithPackagesPath(packagesPath); -``` CSharp -Trace("Some trace info"); +IEnumerable packages = GetService().Restore(settings); ``` @@ -629,6 +520,66 @@ exitCode.HasValue.ShouldBeFalse(); +### Build a project in a docker container + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API and Docker API +using HostApi; + +// Creates a base docker command line +var dockerRun = new DockerRun() + .WithAutoRemove(true) + .WithInteractive(true) + .WithImage("mcr.microsoft.com/dotnet/sdk") + .WithPlatform("linux") + .WithContainerWorkingDirectory("/MyProjects") + .AddVolumes((ToAbsoluteLinuxPath(Environment.CurrentDirectory), "/MyProjects")); + + +// Creates a new library project in a docker container +dockerRun + .WithCommandLine(new DotNetCustom("new", "classlib", "-n", "MyLib", "--force")) + .Run() + .EnsureSuccess(); + +// Builds the library project in a docker container +var result = dockerRun + .WithCommandLine(new DotNetBuild().WithProject("MyLib/MyLib.csproj")) + .Build() + .EnsureSuccess(); + +// The "result" variable provides details about a build +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); +result.ExitCode.ShouldBe(0); + +string ToAbsoluteLinuxPath(string path) => + "/" + path.Replace(":", "").Replace('\\', '/'); +``` + + + +### Running in docker + + + +``` CSharp +// Adds the namespace "HostApi" to use Command Line API and Docker API +using HostApi; + +// Creates some command line to run in a docker container +var cmd = new CommandLine("whoami"); + +// Runs the command line in a docker container +var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") + .WithAutoRemove(true) + .Run() + .EnsureSuccess(); +``` + + + ### Build a project @@ -1061,102 +1012,6 @@ new DotNetBuildServerShutdown() -### Restore NuGet a package of newest version - - - -``` CSharp -// Adds the namespace "HostApi" to use INuGet -using HostApi; - -IEnumerable packages = GetService() - .Restore(new NuGetRestoreSettings("IoC.Container").WithVersionRange(VersionRange.All)); -``` - - - -### Restore a NuGet package by a version range for the specified .NET and path - - - -``` CSharp -// Adds the namespace "HostApi" to use INuGet -using HostApi; - -var packagesPath = Path.Combine( - Path.GetTempPath(), - Guid.NewGuid().ToString()[..4]); - -var settings = new NuGetRestoreSettings("IoC.Container") - .WithVersionRange(VersionRange.Parse("[1.3, 1.3.8)")) - .WithTargetFrameworkMoniker("net5.0") - .WithPackagesPath(packagesPath); - -IEnumerable packages = GetService().Restore(settings); -``` - - - -### Build a project in a docker container - - - -``` CSharp -// Adds the namespace "HostApi" to use .NET build API and Docker API -using HostApi; - -// Creates a base docker command line -var dockerRun = new DockerRun() - .WithAutoRemove(true) - .WithInteractive(true) - .WithImage("mcr.microsoft.com/dotnet/sdk") - .WithPlatform("linux") - .WithContainerWorkingDirectory("/MyProjects") - .AddVolumes((ToAbsoluteLinuxPath(Environment.CurrentDirectory), "/MyProjects")); - - -// Creates a new library project in a docker container -dockerRun - .WithCommandLine(new DotNetCustom("new", "classlib", "-n", "MyLib", "--force")) - .Run() - .EnsureSuccess(); - -// Builds the library project in a docker container -var result = dockerRun - .WithCommandLine(new DotNetBuild().WithProject("MyLib/MyLib.csproj")) - .Build() - .EnsureSuccess(); - -// The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); - -string ToAbsoluteLinuxPath(string path) => - "/" + path.Replace(":", "").Replace('\\', '/'); -``` - - - -### Running in docker - - - -``` CSharp -// Adds the namespace "HostApi" to use Command Line API and Docker API -using HostApi; - -// Creates some command line to run in a docker container -var cmd = new CommandLine("whoami"); - -// Runs the command line in a docker container -var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") - .WithAutoRemove(true) - .Run() - .EnsureSuccess(); -``` - - - ### TeamCity integration via service messages For more details how to use TeamCity service message API please see [this](https://github.com/JetBrains/TeamCity.ServiceMessages) page. Instead of creating a root message writer like in the following example: diff --git a/README_BODY.md b/README_BODY.md index 4d2368a..5238f36 100644 --- a/README_BODY.md +++ b/README_BODY.md @@ -12,173 +12,23 @@ C# interactive build automation system makes it easy to build .NET projects. It ## Advantages - [X] 3 compatible [operating modes](#operating-modes) -- [X] .NET console application [project](#net-build-project) -- [X] Part of .NET solution -- [X] C# - [X] Cross-platform - [X] Debugging capability -- [X] No model binding (Task, Target, DependsOn, etc.) - - no restrictions - - no learning curve - - can use common .NET development practices -- [X] Simple and powerful API for building .NET projects -- [X] Passing named parameters as in MSBuild -- [X] Summarised statistics as in MSBuild - - Child processes - - Warnings and errors - - Tests - - Execution time -- [X] CI/CD integration - - GitLab/GitHub Actions/JetBrains Space etc. - - TeamCity - - [Special runner](https://jetbrains.com/help/teamcity/c-script.html#C%23+Script+Settings) - - Report on warnings and errors - - Test statistics - - Execution progress - - Real-time integration - - Parameters passing between build configuration steps +- [X] No model limitations (Task, Target, DependsOn, etc.) + - Regular .NET code + - Best programming practices +- [X] Powerful API for building .NET projects +- [X] Summarised statistics ## Operating modes -- [REPL](#script-runner-and-repl-tool) -- [C# scripts running](#script-runner-and-repl-tool) -- [.NET build project](#net-build-project) +- [Interactive](#interactive-repl) +- [Running C# script](#running-c-script) +- [Regular .NET build project](#net-build-project) These modes are practically compatible, i.e., for example, a script can be run as a .NET project, and vice versa, with minimal or no changes. -## API -- Output, logging and tracing -- Arguments and parameters -- Command line -- Docker -- Microsoft DI API to resolve dependencies -- NuGet -- .NET CLI - -```c# -// This directive in a script allows you to use host API types -// without specifying the fully qualified namespace of these types -using HostApi; - -// Output, logging and tracing API -WriteLine("Hello"); -WriteLine("Hello !!!", Color.Highlighted); -Error("Error details", "ErrorId"); -Warning("Warning"); -Info("Some info"); -Trace("Trace message"); - -// API for arguments and parameters -Info("First argument: " + (Args.Count > 0 ? Args[0] : "empty")); -Info("Version: " + Props.Get("version", "1.0.0")); -Props["version"] = "1.0.1"; - -var configuration = Props.Get("configuration", "Release"); -Info($"Configuration: {configuration}"); - -// Command line API -var cmd = new CommandLine("whoami"); - -cmd.Run().EnsureSuccess(); - -// Asynchronous way -await cmd.RunAsync().EnsureSuccess(); - -// API for Docker CLI -await new DockerRun("ubuntu") - .WithCommandLine(cmd) - .WithPull(DockerPullType.Always) - .WithAutoRemove(true) - .RunAsync() - .EnsureSuccess(); - -// Microsoft DI API to resolve dependencies -var nuget = GetService(); - -// Creating a custom service provider -var serviceCollection = GetService(); -serviceCollection.AddSingleton(); - -var myServiceProvider = serviceCollection.BuildServiceProvider(); -var tool = myServiceProvider.GetRequiredService(); - -// API for NuGet -var settings = new NuGetRestoreSettings("MySampleLib") - .WithVersionRange(VersionRange.Parse("[1.0.14, 1.1)")) - .WithTargetFrameworkMoniker("net6.0") - .WithPackagesPath(".packages"); - -var packages = nuget.Restore(settings); -foreach (var package in packages) -{ - Info(package.Path); -} - -// API for .NET CLI -var buildResult = new DotNetBuild().WithConfiguration(configuration).WithNoLogo(true) - .Build().EnsureSuccess(); - -var warnings = buildResult.Warnings - .Where(warn => Path.GetFileName(warn.File) == "Calculator.cs") - .Select(warn => $"{warn.Code}({warn.LineNumber}:{warn.ColumnNumber})") - .Distinct(); - -foreach (var warning in warnings) -{ - await new HttpClient().GetAsync( - "https://api.telegram.org/bot7102686717:AAEHw7HZinme_5kfIRV7TwXK4Xql9WPPpM3/" + - "sendMessage?chat_id=878745093&text=" - + HttpUtility.UrlEncode(warning)); -} - -// Asynchronous way -var cts = new CancellationTokenSource(); -await new DotNetTest() - .WithConfiguration(configuration) - .WithNoLogo(true) - .WithNoBuild(true) - .BuildAsync(CancellationOnFirstFailedTest, cts.Token) - .EnsureSuccess(); - -void CancellationOnFirstFailedTest(BuildMessage message) -{ - if (message.TestResult is { State: TestState.Failed }) cts.Cancel(); -} - -// Parallel tests -var tempDir = Directory.CreateTempSubdirectory(); -try -{ - new DotNetPublish() - .WithConfiguration(configuration) - .WithNoLogo(true) - .WithNoBuild(true) - .WithFramework("net8.0") - .AddProps(("PublishDir", tempDir.FullName)) - .Build().EnsureSuccess(); - - var test = new VSTest().WithTestFileNames("*.Tests.dll"); - - var tasks = from tagSuffix in new[] {"bookworm-slim", "alpine", "noble"} - let image = $"mcr.microsoft.com/dotnet/sdk:8.0-{tagSuffix}" - let dockerRun = new DockerRun(image) - .WithCommandLine(test) - .WithAutoRemove(true) - .WithVolumes((tempDir.FullName, "/app")) - .WithContainerWorkingDirectory("/app") - select dockerRun.BuildAsync(CancellationOnFirstFailedTest, cts.Token); - - await Task.WhenAll(tasks).EnsureSuccess(); -} -finally { tempDir.Delete(); } - -class MyTool(INuGet nuGet); -``` - -> [!IMPORTANT] -> `using HostApi;` directive in a script allows you to use host API types without specifying the fully qualified namespace of these types. - -## Script runner and REPL tool +## Interactive (REPL) Please see [this page](https://github.com/DevTeam/csharp-interactive/wiki/Install-the-C%23-script-template) for installation details. @@ -187,17 +37,24 @@ Launch the tool in the interactive mode: ```Shell dotnet csi ``` +Simply enter C# commands sequentially one line after another and get the result in console output. + +## Running C# script + Run a specified script with a given argument: ```Shell -dotnet csi Samples/Scripts/hello.csx World +dotnet csi ./MyDirectory/hello.csx World ``` + Run a single script located in the _MyDirectory_ directory: ```Shell -dotnet csi Samples/Build +dotnet csi ./MyDirectory World ``` -Usage: + +
+Usage details ```Shell dotnet csi [options] [--] [script] [script arguments] @@ -223,6 +80,8 @@ Supported options: | --property | Define a key-value pair(s) for the script properties called _Props_, which is accessible in scripts. | `-p`, `/property`, `/p` | | --property: | Define a key-value pair(s) in MSBuild style for the script properties called _Props_, which is accessible in scripts. | `-p:`, `/property:`, `/p:`, `--property:key1=val1;key2=val2` | +
+ ## .NET build project Please see [this page](https://github.com/DevTeam/csharp-interactive/wiki/Install-the-C%23-script-template) for details on how to install the [project template](https://www.nuget.org/packages/CSharpInteractive.Templates). @@ -235,16 +94,10 @@ dotnet new build -o ./Build The created project contains 2 entry points: - _Program.csx_ to run as a script + ```shell + dotnet csi ./Build + ``` - _Program.cs_ to run as .NET application - -To run the script from the command line from the directory *__Build__*: - -```shell -dotnet csi Build -``` - -To run as a .NET console application: - -```shell -dotnet run --project Build -``` \ No newline at end of file + ```shell + dotnet run --project ./Build + ```