From 98f637c53ee5ae05c3335c3213b574e1266c33ab Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 10 Jul 2025 12:39:01 +0000
Subject: [PATCH 1/5] Initial plan
From 8a263f9aecd2615621d9dc307d7599d9323dae16 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 10 Jul 2025 12:47:00 +0000
Subject: [PATCH 2/5] Initial analysis and planning for get rule command
implementation
Co-authored-by: BernieWhite <13513058+BernieWhite@users.noreply.github.com>
---
global.json | 8 ++++----
src/PSRule/Common/Engine.g.cs | 11 +++++++++++
2 files changed, 15 insertions(+), 4 deletions(-)
create mode 100644 src/PSRule/Common/Engine.g.cs
diff --git a/global.json b/global.json
index b3ff631aa4..69f213f419 100644
--- a/global.json
+++ b/global.json
@@ -2,9 +2,9 @@
"msbuild-sdks": {
"Microsoft.Build.NoTargets": "3.7.56"
},
- "sdk": {
- "allowPrerelease": false,
- "version": "8.0.400",
- "rollForward": "latestPatch"
+ "sdk": {
+ "allowPrerelease": false,
+ "version": "8.0.117",
+ "rollForward": "latestPatch"
}
}
diff --git a/src/PSRule/Common/Engine.g.cs b/src/PSRule/Common/Engine.g.cs
new file mode 100644
index 0000000000..36ea42d6f1
--- /dev/null
+++ b/src/PSRule/Common/Engine.g.cs
@@ -0,0 +1,11 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+//
+namespace PSRule
+{
+ public static partial class Engine
+ {
+ private const string _Version = "3.0.0-dev";
+ }
+}
\ No newline at end of file
From ee6b97eb23fb4892a9afe49d1cea1be67f37a8ad Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 10 Jul 2025 12:58:35 +0000
Subject: [PATCH 3/5] Add get rule command structure and options
Co-authored-by: BernieWhite <13513058+BernieWhite@users.noreply.github.com>
---
src/PSRule.CommandLine/Commands/GetCommand.cs | 159 ++++++++++++++++++
.../Models/GetRuleOptions.cs | 45 +++++
src/PSRule.Tool/ClientBuilder.cs | 64 +++++++
src/PSRule.Tool/Resources/CmdStrings.resx | 9 +
4 files changed, 277 insertions(+)
create mode 100644 src/PSRule.CommandLine/Commands/GetCommand.cs
create mode 100644 src/PSRule.CommandLine/Models/GetRuleOptions.cs
diff --git a/src/PSRule.CommandLine/Commands/GetCommand.cs b/src/PSRule.CommandLine/Commands/GetCommand.cs
new file mode 100644
index 0000000000..ac00c54479
--- /dev/null
+++ b/src/PSRule.CommandLine/Commands/GetCommand.cs
@@ -0,0 +1,159 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json;
+using Microsoft.Extensions.Logging;
+using PSRule.CommandLine.Models;
+using PSRule.Configuration;
+using PSRule.Pipeline;
+using PSRule.Pipeline.Dependencies;
+
+namespace PSRule.CommandLine.Commands;
+
+///
+/// Execute features of the get command through the CLI.
+///
+public sealed class GetCommand
+{
+ ///
+ /// A generic error.
+ ///
+ private const int ERROR_GENERIC = 1;
+
+ ///
+ /// Call get rule.
+ ///
+ public static async Task GetRuleAsync(GetRuleOptions operationOptions, ClientContext clientContext, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ var exitCode = 0;
+ var workingPath = operationOptions.WorkspacePath ?? Environment.GetWorkingPath();
+ var file = LockFile.Read(null);
+
+ if (operationOptions.Path != null)
+ {
+ clientContext.Option.Include.Path = operationOptions.Path;
+ }
+
+ if (operationOptions.Name != null && operationOptions.Name.Length > 0)
+ {
+ clientContext.Option.Rule.Include = operationOptions.Name;
+ }
+
+ if (operationOptions.Baseline != null)
+ {
+ clientContext.Option.Baseline.Group = [operationOptions.Baseline];
+ }
+
+ if (operationOptions.Module != null && operationOptions.Module.Length > 0)
+ {
+ clientContext.Option.Requires.Module = operationOptions.Module;
+ }
+
+ if (!operationOptions.NoRestore)
+ {
+ var restoreBuilder = new ModuleRestoreBuilder(workingPath, clientContext.Option);
+ var restoreResult = await restoreBuilder.RestoreAsync(file, restore: true, cancellationToken);
+ }
+
+ var builder = new GetRulePipelineBuilder([workingPath], clientContext);
+ builder.Configure(clientContext.Option);
+
+ if (operationOptions.IncludeDependencies)
+ builder.IncludeDependencies();
+
+ // Use a custom writer to capture the output
+ var capturedObjects = new List