Sitecore CLI: Extend the Command Line Interface with NuGet
Sitecore Command Line Interface (CLI) allows console communication with a Sitecore instance. Sitecore CLI allows adding commands by writing custom plugins. Sitecore provides some plugins like Publishing and Serialization.
The purpose of this blog is to create a simple Sitecore CLI plugin which will print any message which you pass as parameter or print a default message.
Sitecore CLI Document
Prerequisites
Code Repository
Usages
dotnet sitecore plugin [subcommand] [options]
Below are some subcommands:
Create a custom CLI plugin command
- Create a blank new Solution “CustomCLI” in Visual Studio, then add a class library with .Net core 3.1 with the name “CLI.DevEX.Extensibility.Custom”.
- PackageSources node contains all package sources. Plugin sources need to be specified in Nuget.Config, Local package source will take the package from “Build/nugets” folder which we have generated in the previous step. This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> <add key="Sitecore" value="https://sitecore.myget.org/F/sc-packages/api/v3/index.json" /> <add key="Local" value="_Build\nugets"></add> </packageSources> <packageRestore> <add key="enabled" value="True" /> <add key="automatic" value="True" /> </packageRestore> <activePackageSource> <add key="All" value="(Aggregate source)" /> </activePackageSource> </configuration> - Add NuGet references to Sitecore.Devex.Client.Cli.Extensibility and Spectre.Console in the class library.
- Create a class named RegisterExtension and inherit it from ISitecoreCliExtension class. AddCommands method allows the plugin to add a command to the RootCommand of the System.CommandLine processor. AddConfiguration method will allow the plug-in to add configuration to a config builder. AddServices method will allow the plug-in to service to the IOC container.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Sitecore.Devex.Client.Cli.Extensibility; using Sitecore.Devex.Client.Cli.Extensibility.Subcommands; using CLI.DevEX.Extensibility.Custom.Commands; using System; using System.Collections.Generic; namespace CLI.DevEX.Extensibility.Custom { public class RegisterExtension : ISitecoreCliExtension { public IEnumerable<ISubcommand> AddCommands(IServiceProvider container) { if (container == null) { throw new ArgumentNullException(nameof(container)); } CustomCommand customCommand = new CustomCommand("Custom", "This is a custom command"); PrintCommand printCommand = container.GetRequiredService<PrintCommand>(); customCommand.AddCommand(printCommand); return new ISubcommand[] { customCommand }; } public void AddConfiguration(IConfigurationBuilder configBuilder) { } public void AddServices(IServiceCollection serviceCollection) { serviceCollection.AddSingleton<CustomCommand>().AddSingleton<PrintCommand>(); } } } - Create a subfolder named Commands and add a class CustomCommand inside the Commands folder which will inherit Command and ISubcommand class.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
using Sitecore.Devex.Client.Cli.Extensibility.Subcommands; using System.CommandLine; namespace CLI.DevEX.Extensibility.Custom.Commands { public class CustomCommand: Command, ISubcommand { public CustomCommand(string name, string description = null) : base(name, description) { } } } - Now create a class named PrintCommand inside the Commands folder. SubcommandBase class will handle exceptions for Sitecore CLI subcommands.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
using Sitecore.Devex.Client.Cli.Extensibility.Subcommands; using CLI.DevEX.Extensibility.Custom.Tasks; using System; using System.Threading.Tasks; namespace CLI.DevEX.Extensibility.Custom.Commands { public class PrintCommand : SubcommandBase<PrintTask, PrintTaskOptions> { public PrintCommand(IServiceProvider container) : base("Print", "Print test message", container) { AddOption(PrintArgOptions.Message); } protected override async Task<int> Handle(PrintTask task, PrintTaskOptions args) { args.Validate(); await task.Execute(args).ConfigureAwait(false); return 0; } } } - Add a class named PrintArgOptions inside the Tasks folder.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
using System.CommandLine; namespace CLI.DevEX.Extensibility.Custom.Tasks { public class PrintArgOptions { public static readonly Option Message = new Option(new[] { "--message", "-m" }, "Name to be displayed. Default: Swati Gupta") { Argument = new Argument<string>(() => "Swati Gupta") }; } } - Add a new subfolder named Tasks and create a class PrintTask inside this folder.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
using Spectre.Console; using System.Threading.Tasks; namespace CLI.DevEX.Extensibility.Custom.Tasks { public class PrintTask { public async Task Execute(PrintTaskOptions options) { await PrintMessage(options); } private async Task PrintMessage(PrintTaskOptions options) { AnsiConsole.Write(new FigletText(options.Message).LeftAligned().Color(Color.Red)); } } } - Create PrintTaskOptions which inherit TaskOptionsBase. This class will validate the utility of the task option class.This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
using Sitecore.DevEx.Client.Tasks; namespace CLI.DevEX.Extensibility.Custom.Tasks { public class PrintTaskOptions : TaskOptionsBase { public string Message { get; set; } public override void Validate() { Require(nameof(Message)); } } } - Open CLI.DevEX.Extensibility.Custom.csproj file and update the below settings:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<TargetFramework>netcoreapp3.1</TargetFramework> | |
<PackageVersion>1.0.0</PackageVersion> | |
<PackageOutputPath>..\..\_Build\nugets</PackageOutputPath> | |
<OutputPath>.\bin\</OutputPath> | |
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> | |
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> | |
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> | |
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);CustomBuildOutputTarget</TargetsForTfmSpecificContentInPackage> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Sitecore.Devex.Client.Cli.Extensibility" Version="4.1.1" /> | |
<PackageReference Include="Spectre.Console" Version="0.43.0" /> | |
</ItemGroup> | |
<Target Name="CustomBuildOutputTarget"> | |
<ItemGroup> | |
<TfmSpecificPackageFile Include="$(OutputPath)CLI.DevEX.Extensibility.Custom.dll" PackagePath="plugin" /> | |
<TfmSpecificPackageFile Include="$(OutputPath)Spectre.Console.dll" PackagePath="plugin" /> | |
</ItemGroup> | |
</Target> | |
</Project> |
PackageOutputPath
Determines the output path in which the packed package will be dropped. Default is $(OutputPath). To make Sitecore CLI able to find our Nuget without publishing it to the public feed we instead use a local Nuget folder. “$(SolutionDir)_Build/nugets”. In the csproj file we can set the ‘PackageOutputPath’ property to output our package to this folder.
CopyLocalLockFileAssemblies
The CopyLocalLockFileAssemblies property is useful for plugin projects that have dependencies on other libraries. If you set this property to true, any NuGet package dependencies are copied to the output directory. That means you can use the output of dotnet build to run your plugin on any machine.
AppendTargetFrameworkToOutputPath
Setting AppendTargetFrameworkToOutputPath to false prevents the target framework moniker from being appended to the output path.
PackageReference
Package references, using the PackageReference node, manage NuGet dependencies directly within project files.
TargetsForTfmSpecificContentInPackage
TargetsForTfmSpecificContentInPackage write a custom target. PackagePath where the file should be output in the package.
Plugin assembly needs to be placed inside a plugin folder so that’s why PackagePath is mentioned as a plugin.
How to Run Custom CLI Plugin
- Open terminal, Run as Administrator.
- Run the below command to restore:
- dotnet tool restore
- Run below command to add your custom plugin:
- Run “dotnet sitecore -h” command to check available commands:
- To check the custom command run “dotnet sitecore Custom -h”.
- Now finally when you will run “dotnet sitecore Custom Print” command, it will print the default name.
- You can pass some message like this “dotnet sitecore Custom print -m Sitecore”.
Note: Extensions/customizations to the CLI and Sitecore Management Services module are unsupported by Sitecore.
Comments