diff --git a/.nox/design/SampleCurrency.solution.nox.yaml b/.nox/design/SampleCurrency.solution.nox.yaml
new file mode 100755
index 00000000..7d4249db
--- /dev/null
+++ b/.nox/design/SampleCurrency.solution.nox.yaml
@@ -0,0 +1,58 @@
+#
+# Cli Sample Solution definition
+#
+# yaml-language-server: $schema=https://raw.githubusercontent.com/NoxOrg/Nox/main/src/Nox.Core/Schemas/NoxConfiguration.json
+#
+
+#
+
+name: CliDemo
+
+description: A Cli Demo Nox Configuration
+environments:
+
+ - name: dev
+ description: Used for development and testing
+
+ - name: test
+ description: Test environment
+
+ - name: uat
+ description: For them end users to check it works
+
+ - name: prod
+ description: Production environment used for, well - the real thing!
+ isProduction: true
+
+versionControl:
+ provider: azureDevops
+ host: https://dev.azure.com/iwgplc
+ folders:
+ sourceCode: /src
+ containers: /docker
+
+team:
+
+ - name: Andre Sharpe
+ userName: andre.sharpe@iwgplc.com
+ roles: [architect, owner, administrator, developer, manager]
+
+ - name: Jan Schutte
+ userName: jan.schutte@iwgplc.com
+ roles: [architect, administrator, developer, devOpsEngineer]
+
+ - name: Anton Du Plessis
+ userName: anton.duplessis@iwgplc.com
+ roles: [projectManager]
+
+ - name: Morne Van Zyl
+ userName: morne.vanzyl@iwgplc.com
+ roles: [technicalWriter]
+
+ - name: Dmytro Dorodnykh
+ userName: dmytro.dorodnykh@iwgplc.com
+ roles: [developer]
+
+ - name: Oleksandr Vlasenko
+ userName: oleksandr.vlasenko@regus.com
+ roles: [architect, developer]
\ No newline at end of file
diff --git a/samples/Design/SampleCurrency.service.nox.yaml b/samples/Design/SampleCurrency.service.nox.yaml
deleted file mode 100755
index 8707500d..00000000
--- a/samples/Design/SampleCurrency.service.nox.yaml
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-# Service definition
-#
-# yaml-language-server: $schema=https://raw.githubusercontent.com/NoxOrg/Nox/main/src/Nox.Core/Schemas/NoxConfiguration.json
-#
-
-#
-
-name: CliDemo
-
-description: A Cli Demo Nox Configuration
-
-autoMigrations: false
-
-secrets:
- validFor:
- hours: 12
- providers:
- - provider: azure-keyvault
- url: https://svc-6A9B1182FC66686F.vault.azure.net/
-
-database:
- name: SampleCurrencyDb
- server: localhost
- provider: postgres
- options: Trusted_Connection=no;connection timeout=120;
- user: sa
- password: Developer*123
-
-messagingProviders:
-
- - name: AppServiceBus
- provider: rabbitMQ
- connectionString: rabbitmq://guest:guest@localhost/
-
-dataSources:
- - name: JsonSeedData
- provider: json
- options: Source=File;Path=../../docs/sample-data/;
-
-versionControl:
- provider: azureDevOps
- server: https://dev.azure.com/iwgplc
- project: Nox.CliDemo
- repository: CliDemo.Project.V1
-
-team:
- developers:
- - name: Dionisis Stoubos
- userName: dionisis.stoubos@iwgplc.com
- isAdmin: true
- email: dionisis.stoubos@iwgplc.com
- - name: Andre Sharpe
- userName: andre.sharpe@iwgplc.com
- mobilePhoneNumber: +41789461056
- isAdmin: true
- - name: Jan Schutte
- userName: jan.schutte@iwgplc.com
- isAdmin: true
- email: jan.schutte@iwgplc.com
- - name: Anton Du Plessis
- userName: anton.duplessis@iwgplc.com
- isAdmin: false
- email: anton.duplessis@iwgplc.com
- - name: Morne Van Zyl
- userName: morne.vanzyl@iwgplc.com
- isAdmin: false
- email: morne.vanzyl@iwgplc.com
- - name: Dmytro Dorodnykh
- userName: dmytro.dorodnykh@iwgplc.com
- isAdmin: false
- email: dmytro.dorodnykh@iwgplc.com
- - name: Oleksandr Vlasenko
- userName: oleksandr.vlasenko@regus.com
- isAdmin: false
- email: oleksandr.vlasenko@regus.com
diff --git a/src/CoreTests/CoreTests.csproj b/src/CoreTests/CoreTests.csproj
index 9de48379..543b7824 100755
--- a/src/CoreTests/CoreTests.csproj
+++ b/src/CoreTests/CoreTests.csproj
@@ -10,9 +10,9 @@
-
+
-
+
all
diff --git a/src/Nox.Cli.Abstractions/Constants/FileExtension.cs b/src/Nox.Cli.Abstractions/Constants/FileExtension.cs
new file mode 100644
index 00000000..f5ab3392
--- /dev/null
+++ b/src/Nox.Cli.Abstractions/Constants/FileExtension.cs
@@ -0,0 +1,6 @@
+namespace Nox.Cli.Abstractions.Constants;
+
+public static class FileExtension
+{
+ public const string WorkflowDefinition = @"*.workflow.nox.yaml";
+}
\ No newline at end of file
diff --git a/src/Nox.Cli.Abstractions/Helpers/YamlHelper.cs b/src/Nox.Cli.Abstractions/Helpers/YamlHelper.cs
new file mode 100644
index 00000000..a9fb1ce2
--- /dev/null
+++ b/src/Nox.Cli.Abstractions/Helpers/YamlHelper.cs
@@ -0,0 +1,89 @@
+using System.Text.RegularExpressions;
+using Nox.Cli.Abstractions.Exceptions;
+
+namespace Nox.Cli.Abstractions.Helpers;
+
+public static class YamlHelper
+{
+ private static readonly Regex _referenceRegex = new(@"\$ref\S*:\s*(?[\w:\.\/\\]+\b[\w\-\.\/]+)\s*", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(5));
+
+ ///
+ /// Resolve $ref <path> tags in a yaml source yaml file.
+ /// Loads the source yaml file, resolves the $ref's and replaces them with the yaml from the files specified in <path>
+ /// Note: This call is recursive, all $refs in the yaml hierarchy will be resolved.
+ /// Note: child nodes are added at the same indentation as the $ref tag.
+ ///
+ /// Full or relative path to the source yaml file.
+ ///
+ public static string ResolveYamlReferences(string path)
+ {
+ var sourceFullPath = Path.GetFullPath(path);
+ if (!File.Exists(sourceFullPath)) throw new NoxCliException($"Yaml file {path} does not exist!");
+ var sourcePath = Path.GetDirectoryName(sourceFullPath);
+
+ var sourceLines = File.ReadAllLines(path);
+ var outputLines = ResolveYamlReferences(sourceLines.ToList(), sourcePath!).Result;
+
+ return string.Join('\n', outputLines.ToArray());
+ }
+
+ ///
+ /// Resolve $ref <path> tags in a yaml source yaml file.
+ /// Loads the source yaml file, resolves the $ref's and replaces them with the yaml from the files specified in <path>
+ /// Note: This call is recursive, all $refs in the yaml hierarchy will be resolved.
+ /// Note: child nodes are added at the same indentation as the $ref tag.
+ ///
+ /// Full or relative path to the source yaml file.
+ ///
+ public static async Task ResolveYamlReferencesAsync(string path)
+ {
+ var sourceFullPath = Path.GetFullPath(path);
+ if (!File.Exists(sourceFullPath)) throw new NoxCliException($"Yaml file {path} does not exist!");
+ var sourcePath = Path.GetDirectoryName(sourceFullPath);
+
+ var sourceLines = await File.ReadAllLinesAsync(path);
+ var outputLines = await ResolveYamlReferences(sourceLines.ToList(), sourcePath!);
+
+ return string.Join('\n', outputLines.ToArray());
+ }
+
+ private static async Task> ResolveYamlReferences(List sourceLines, string path)
+ {
+ var outputLines = new List();
+ foreach (var sourceLine in sourceLines)
+ {
+ if (!sourceLine.TrimStart().StartsWith('#'))
+ {
+ var match = _referenceRegex.Match(sourceLine);
+ if (match.Success)
+ {
+ var padding = new string(' ', match.Index);
+ var childPath = match.Groups[1].Value;
+ if (!Path.IsPathRooted(childPath)) childPath = Path.Combine(path!, childPath);
+ if (!File.Exists(childPath)) throw new NoxCliException($"Referenced yaml file does not exist for reference: {match.Groups[1].Value}");
+ var childLines = await File.ReadAllLinesAsync(childPath);
+ foreach (var childLine in childLines)
+ {
+ outputLines.Add(padding + childLine);
+ }
+ }
+ else
+ {
+ outputLines.Add(sourceLine);
+ }
+ }
+ else
+ {
+ outputLines.Add(sourceLine);
+ }
+ }
+
+ if (outputLines.Any(ol => ol.Contains("$ref:") && !ol.TrimStart().StartsWith('#')))
+ {
+ outputLines = await ResolveYamlReferences(outputLines, path);
+ }
+
+ return outputLines;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Nox.Cli.Abstractions/INoxWorkflowContext.cs b/src/Nox.Cli.Abstractions/INoxWorkflowContext.cs
index 4167b84b..c48ee071 100755
--- a/src/Nox.Cli.Abstractions/INoxWorkflowContext.cs
+++ b/src/Nox.Cli.Abstractions/INoxWorkflowContext.cs
@@ -1,5 +1,6 @@
using Nox.Cli.Abstractions.Caching;
-using Nox.Core.Interfaces;
+using Nox.Secrets.Abstractions;
+using Nox.Solution;
namespace Nox.Cli.Abstractions
{
@@ -15,6 +16,7 @@ public interface INoxWorkflowContext
void SetState(ActionState state);
INoxCliCacheManager? CacheManager { get; }
- void SetProjectConfiguration(IProjectConfiguration projectConfiguration);
+ INoxSecretsResolver? NoxSecretsResolver { get; }
+ void SetProjectConfiguration(NoxSolution projectConfiguration);
}
}
\ No newline at end of file
diff --git a/src/Nox.Cli.Abstractions/Nox.Cli.Abstractions.csproj b/src/Nox.Cli.Abstractions/Nox.Cli.Abstractions.csproj
index 21b9aa02..75209238 100755
--- a/src/Nox.Cli.Abstractions/Nox.Cli.Abstractions.csproj
+++ b/src/Nox.Cli.Abstractions/Nox.Cli.Abstractions.csproj
@@ -8,6 +8,7 @@
-
+
+
diff --git a/src/Nox.Cli.Authentication.Azure/Nox.Cli.Authentication.Azure.csproj b/src/Nox.Cli.Authentication.Azure/Nox.Cli.Authentication.Azure.csproj
index 2f9a6b29..acc0e39a 100755
--- a/src/Nox.Cli.Authentication.Azure/Nox.Cli.Authentication.Azure.csproj
+++ b/src/Nox.Cli.Authentication.Azure/Nox.Cli.Authentication.Azure.csproj
@@ -12,6 +12,6 @@
-
+
diff --git a/src/Nox.Cli.Authentication.Tests/Nox.Cli.Authentication.Tests.csproj b/src/Nox.Cli.Authentication.Tests/Nox.Cli.Authentication.Tests.csproj
index b23472dc..2f68d317 100755
--- a/src/Nox.Cli.Authentication.Tests/Nox.Cli.Authentication.Tests.csproj
+++ b/src/Nox.Cli.Authentication.Tests/Nox.Cli.Authentication.Tests.csproj
@@ -10,9 +10,9 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Nox.Cli.Authentication/Nox.Cli.Authentication.csproj b/src/Nox.Cli.Authentication/Nox.Cli.Authentication.csproj
index 3813de4b..128c4417 100755
--- a/src/Nox.Cli.Authentication/Nox.Cli.Authentication.csproj
+++ b/src/Nox.Cli.Authentication/Nox.Cli.Authentication.csproj
@@ -9,10 +9,10 @@
-
+
-
-
+
+
diff --git a/src/Nox.Cli.Caching/Nox.Cli.Caching.csproj b/src/Nox.Cli.Caching/Nox.Cli.Caching.csproj
index 0353f585..9a00cca4 100755
--- a/src/Nox.Cli.Caching/Nox.Cli.Caching.csproj
+++ b/src/Nox.Cli.Caching/Nox.Cli.Caching.csproj
@@ -12,10 +12,11 @@
-
-
+
+
+
diff --git a/src/Nox.Cli.Caching/NoxCliCacheManager.cs b/src/Nox.Cli.Caching/NoxCliCacheManager.cs
index e8ec1424..fd004ef4 100755
--- a/src/Nox.Cli.Caching/NoxCliCacheManager.cs
+++ b/src/Nox.Cli.Caching/NoxCliCacheManager.cs
@@ -1,20 +1,21 @@
+using System.Net;
using System.Net.NetworkInformation;
using System.Text.Json;
using Newtonsoft.Json;
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Caching;
using Nox.Cli.Abstractions.Configuration;
+using Nox.Cli.Abstractions.Constants;
using Nox.Cli.Abstractions.Exceptions;
+using Nox.Cli.Abstractions.Helpers;
using Nox.Cli.Configuration;
-using Nox.Core.Constants;
-using Nox.Core.Exceptions;
-using Nox.Core.Helpers;
using Nox.Utilities.Configuration;
using Nox.Utilities.Credentials;
using RestSharp;
using Spectre.Console;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
+using IDeserializer = YamlDotNet.Serialization.IDeserializer;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace Nox.Cli.Caching;
@@ -77,6 +78,7 @@ public bool IsOnline {
try
{
var uri = new Uri(_remoteUrl);
+ if (uri.Host == "localhost") return true;
var reply = ping.Send(uri.Host, 3000);
if (reply.Status == IPStatus.Success)
{
@@ -279,7 +281,7 @@ private void GetOnlineWorkflowsAndManifest(IDictionary yamlFiles
Directory.CreateDirectory(_workflowCachePath);
var existingCacheList = Directory
- .GetFiles(_workflowCachePath, FileExtension.WorflowDefinition)
+ .GetFiles(_workflowCachePath, FileExtension.WorkflowDefinition)
.Select(f => (new FileInfo(f)).Name).ToHashSet();
foreach (var file in onlineFiles!)
@@ -394,7 +396,7 @@ private void ResolveManifest(IDeserializer deserializer, Dictionary yamlFiles)
{
_workflows = new List();
- foreach (var yaml in yamlFiles.Where(kv => kv.Key.EndsWith(FileExtension.WorflowDefinition.TrimStart('*'))))
+ foreach (var yaml in yamlFiles.Where(kv => kv.Key.EndsWith(FileExtension.WorkflowDefinition.TrimStart('*'))))
{
try
{
@@ -402,14 +404,14 @@ private void ResolveWorkflows(IDeserializer deserializer, Dictionary {onlineFilesJson.ErrorException?.Message}");
}
+ if (onlineFilesJson.StatusCode != HttpStatusCode.OK) return;
+
var onlineFiles = JsonSerializer.Deserialize>(onlineFilesJson.Content, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
diff --git a/src/Nox.Cli.Configuration/Nox.Cli.Configuration.csproj b/src/Nox.Cli.Configuration/Nox.Cli.Configuration.csproj
index 305d1d58..78238c47 100755
--- a/src/Nox.Cli.Configuration/Nox.Cli.Configuration.csproj
+++ b/src/Nox.Cli.Configuration/Nox.Cli.Configuration.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Nox.Cli.PersonalAccessToken/Nox.Cli.PersonalAccessToken.csproj b/src/Nox.Cli.PersonalAccessToken/Nox.Cli.PersonalAccessToken.csproj
index 77f31165..37c1b919 100755
--- a/src/Nox.Cli.PersonalAccessToken/Nox.Cli.PersonalAccessToken.csproj
+++ b/src/Nox.Cli.PersonalAccessToken/Nox.Cli.PersonalAccessToken.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/ArmConnect_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/ArmConnect_v1.cs
index 7d5d8973..36cc1bad 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/ArmConnect_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/ArmConnect_v1.cs
@@ -1,8 +1,8 @@
using Azure.Identity;
using Azure.ResourceManager;
using Nox.Cli.Abstractions;
+using Nox.Cli.Abstractions.Exceptions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Exceptions;
namespace Nox.Cli.Plugin.Arm;
@@ -64,7 +64,7 @@ public async Task> ProcessAsync(INoxWorkflowContext
var subs = client.GetSubscriptions();
var subResponse = await subs.GetAsync(_subscriptionId);
var sub = subResponse.Value;
- outputs["subscription"] = sub ?? throw new NoxException($"Unable to connect to subscription {_subscriptionId}");
+ outputs["subscription"] = sub ?? throw new NoxCliException($"Unable to connect to subscription {_subscriptionId}");
ctx.SetState(ActionState.Success);
}
catch (Exception ex)
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/Nox.Cli.Plugin.Arm.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/Nox.Cli.Plugin.Arm.csproj
index 543d3af6..169f8487 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/Nox.Cli.Plugin.Arm.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Arm/Nox.Cli.Plugin.Arm.csproj
@@ -7,11 +7,11 @@
-
+
+
-
+
-
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevOpsMergeFolder_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevOpsMergeFolder_v1.cs
index 005d8787..a130cd4c 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevOpsMergeFolder_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevOpsMergeFolder_v1.cs
@@ -1,9 +1,9 @@
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.WebApi;
using Nox.Cli.Abstractions;
+using Nox.Cli.Abstractions.Exceptions;
using Nox.Cli.Abstractions.Extensions;
using Nox.Cli.Plugin.AzDevOps.Helpers;
-using Nox.Core.Exceptions;
namespace Nox.Cli.Plugin.AzDevOps;
@@ -148,7 +148,7 @@ private GitCommitRef CreateCommit()
private async Task CreatePush(string branchName, GitCommitRef commit)
{
var serverBranches = await _gitClient!.GetRefsAsync(_repoId!.Value.ToString(), filter: $"heads/{branchName}");
- if (serverBranches.Count != 1) throw new NoxException($"Unable to locate branch {branchName}");
+ if (serverBranches.Count != 1) throw new NoxCliException($"Unable to locate branch {branchName}");
var branch = new GitRefUpdate
{
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevopsCreateBuildDefinition_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevopsCreateBuildDefinition_v1.cs
index e0979779..49978310 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevopsCreateBuildDefinition_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/AzDevopsCreateBuildDefinition_v1.cs
@@ -2,8 +2,8 @@
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.WebApi;
using Nox.Cli.Abstractions;
+using Nox.Cli.Abstractions.Exceptions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Exceptions;
namespace Nox.Cli.Plugin.AzDevOps;
@@ -121,7 +121,7 @@ public async Task> ProcessAsync(INoxWorkflowContext
try
{
var repo = await _repoClient.GetRepositoryAsync(_repoId!.Value.ToString());
- if (repo == null) throw new NoxException("Unable to locate the source repository!");
+ if (repo == null) throw new NoxCliException("Unable to locate the source repository!");
var ymlProcess = new YamlProcess
{
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/Nox.Cli.Plugin.AzDevOps.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/Nox.Cli.Plugin.AzDevOps.csproj
index bca357d1..e228d2bb 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/Nox.Cli.Plugin.AzDevOps.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzDevOps/Nox.Cli.Plugin.AzDevOps.csproj
@@ -11,7 +11,6 @@
-
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzureAd/Nox.Cli.Plugin.AzureAd.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzureAd/Nox.Cli.Plugin.AzureAd.csproj
index 9763be3a..e59a635d 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzureAd/Nox.Cli.Plugin.AzureAd.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.AzureAd/Nox.Cli.Plugin.AzureAd.csproj
@@ -8,8 +8,7 @@
-
-
+
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/ConsolePromptSchema_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/ConsolePromptSchema_v1.cs
index 6600f5d7..cf78b660 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/ConsolePromptSchema_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/ConsolePromptSchema_v1.cs
@@ -4,6 +4,7 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Exceptions;
using Nox.Cli.Abstractions.Extensions;
+using Nox.Cli.Plugin.Console.JsonSchema;
using RestSharp;
using Spectre.Console;
@@ -79,6 +80,8 @@ public NoxActionMetaData Discover()
private string? _schema = null!;
+ private IDictionary? _schemaCache;
+
private string[]? _includedPrompts;
private string[]? _excludedPrompts;
@@ -91,10 +94,11 @@ public NoxActionMetaData Discover()
private readonly RestClient _client = new();
- private readonly Regex resolveRefs = new("\"\\$ref\\\"\\s*:\\s*\\\"(?[\\w:/\\.]+)\\\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ private readonly Regex _resolveRefs = new("\"\\$ref\\\"\\s*:\\s*\\\"(?[\\w:/\\.]+)\\\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private readonly Dictionary _responses = new();
+ private bool _isArrayStart = false;
public Task BeginAsync(IDictionary inputs)
{
@@ -104,7 +108,7 @@ public Task BeginAsync(IDictionary inputs)
if (Uri.IsWellFormedUriString(schemaUrl, UriKind.Absolute))
{
_schemaUrl = (new Uri(schemaUrl)).AbsoluteUri;
- };
+ }
_schema = inputs.Value("schema");
@@ -137,18 +141,35 @@ public async Task> ProcessAsync(INoxWorkflowContext
{
try
{
+ var json = _schema;
- var json = _schema ?? await AnsiConsole.Status()
- .Spinner(Spinner.Known.Clock)
- .StartAsync("Reading schemas...", ctx =>
- ReadSchemaFromUrl(_schemaUrl!, ctx)
- );
-
+ if (string.IsNullOrWhiteSpace(json))
+ {
+ var baseUrl = "";
+ var schemaName = "";
+ var lastIndex = _schemaUrl!.LastIndexOf('/');
+ if (lastIndex != -1)
+ {
+ baseUrl = _schemaUrl![..lastIndex];
+ schemaName = _schemaUrl!.Substring(lastIndex + 1);
+ }
+ json = await AnsiConsole.Status()
+ .Spinner(Spinner.Known.Clock)
+ .StartAsync("Reading schemas...", fn =>
+ ReadSchemaFromUrl(baseUrl, schemaName, fn)
+ );
+ }
+
if (json != null)
{
- var jsonSchema = JsonSerializer.Deserialize(json, new JsonSerializerOptions {
+ var serializeOptions = new JsonSerializerOptions
+ {
+ WriteIndented = false,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
- });
+ };
+ serializeOptions.Converters.Add(new JsonSchemaTypeConverter());
+
+ var jsonSchema = JsonSerializer.Deserialize(json, serializeOptions);
if (jsonSchema != null)
{
@@ -160,13 +181,14 @@ public async Task> ProcessAsync(INoxWorkflowContext
_sbYaml.AppendLine($"#");
_sbYaml.AppendLine($"");
- await AskForProperties(jsonSchema);
+ await ProcessSchema(jsonSchema);
foreach(var (key,value) in _responses)
{
outputs[key] = value;
}
+
if (_fileOptions != null && _fileOptions.ContainsKey("filename"))
{
_sbYaml.Insert(0,$"# {Path.GetFileName(_fileOptions["filename"])}{Environment.NewLine}");
@@ -174,6 +196,8 @@ public async Task> ProcessAsync(INoxWorkflowContext
var contents = _sbYaml.ToString();
+ //await File.WriteAllTextAsync("/home/jan/Downloads/solution.yaml", contents);
+
var outputFilePath = _fileOptions["filename"];
if (_fileOptions.TryGetValue("folder", out var folder))
{
@@ -205,243 +229,299 @@ public Task EndAsync()
return Task.CompletedTask;
}
- private async Task ReadSchemaFromUrl(string url, StatusContext ctx)
+ private async Task ReadSchemaFromUrl(string baseUrl, string schemaName, StatusContext ctx, bool isRecursiveCall = false)
{
- ctx.Status = $"Reading schema {url}...";
+ ctx.Status = $"Reading schema {schemaName}...";
- var request = new RestRequest(url) { Method = Method.Get };
+ if (!isRecursiveCall) _schemaCache = new Dictionary();
- request.AddHeader("Accept", "application/json");
+ var json = "";
- var onlineFilesJson = await _client.ExecuteAsync(request);
+ if (!_schemaCache!.ContainsKey(schemaName))
+ {
- var json = onlineFilesJson.Content;
+ var request = new RestRequest($"{baseUrl}/{schemaName}") { Method = Method.Get };
- if (json == null)
- {
- return null;
- }
+ request.AddHeader("Accept", "application/json");
- var matches = resolveRefs.Matches(json);
+ var onlineFilesJson = await _client.ExecuteAsync(request);
- foreach(Match match in matches)
- {
- var subRef = await ReadSchemaFromUrl(match.Groups["url"].Value, ctx);
- if (subRef != null)
+ json = onlineFilesJson.Content;
+
+ _schemaCache![schemaName] = json;
+
+ if (json == null)
+ {
+ return null;
+ }
+
+ var matches = _resolveRefs.Matches(json);
+
+ foreach (Match match in matches)
{
- subRef = subRef.Trim();
- subRef = subRef.Substring(1, subRef.Length - 2);
- json = json.Replace(match.Value, subRef);
+ var subRef = await ReadSchemaFromUrl(baseUrl, match.Groups["url"].Value, ctx, true);
+ if (!string.IsNullOrWhiteSpace(subRef))
+ {
+ subRef = subRef.Trim();
+ subRef = subRef.Substring(1, subRef.Length - 2);
+ json = json.Replace(match.Value, subRef);
+ }
}
}
return json;
}
- private async Task AskForProperties(JsonSchema.JsonSchema jsonSchema, string indent = "", string fullKey = "")
+ ///
+ /// This method is recursive through the schema, it is quite complicated, proceed with caution.
+ ///
+ /// The input schema
+ /// the root path of the current key
+ /// The current key to process
+ private async Task ProcessSchema(JsonSchema.JsonSchema schema, string rootKey = "", string key = "")
{
- if (!string.IsNullOrWhiteSpace(jsonSchema.Description))
- {
- AnsiConsole.WriteLine();
- AnsiConsole.MarkupLine($"[yellow]{jsonSchema.Description.EscapeMarkup()}[/]");
- }
-
- var yamlSpacing = indent.Replace('.', ' ');
+ var newKey = $"{rootKey}.{key}".TrimStart('.');
+ var prefix = $"[grey]{newKey.PadRight(40, '.').EscapeMarkup()}[/] ";
+ var yamlSpacing = new string(' ', newKey.Count(d => d == '.') * 2);
+
var yamlSpacingPostfix = "";
- if (fullKey.EndsWith(']'))
+ if (_isArrayStart)
{
yamlSpacingPostfix = "- ";
}
-
- indent += "..";
-
- foreach (var (key,prop) in jsonSchema.Properties)
+ else
{
- var newFullKey = $"{fullKey}.{key}".TrimStart('.');
+ if (rootKey.EndsWith(']')) yamlSpacing += " ";
+ }
- if (_includedPrompts != null && !_includedPrompts.Any(f => newFullKey.StartsWith(f,StringComparison.OrdinalIgnoreCase)))
+ if (!string.IsNullOrWhiteSpace(key) && _includedPrompts != null && !_includedPrompts.Any(f => newKey.StartsWith(f, StringComparison.OrdinalIgnoreCase)))
+ {
+ if (_defaults != null && _defaults.Any(d => key.Equals(d.Key, StringComparison.OrdinalIgnoreCase)))
{
- if (_defaults != null && _defaults.Any(d => newFullKey.Equals(d.Key, StringComparison.OrdinalIgnoreCase)))
- {
- _sbYaml.AppendLine($"{yamlSpacing}{yamlSpacingPostfix}{key}: {_defaults[newFullKey]}");
- _responses[newFullKey] = _defaults[newFullKey];
- }
- continue;
+ _sbYaml.AppendLine($"{key}: {_defaults[key]}");
+ _responses[newKey] = _defaults[newKey];
}
- if (_excludedPrompts != null && _excludedPrompts.Any(f => newFullKey.StartsWith(f, StringComparison.OrdinalIgnoreCase)))
+ return;
+ }
+
+ if (!string.IsNullOrWhiteSpace(key) && _excludedPrompts != null && _excludedPrompts.Any(f => newKey.StartsWith(f, StringComparison.OrdinalIgnoreCase)))
+ {
+ if (_defaults != null && _defaults.Any(d => newKey.Equals(d.Key, StringComparison.OrdinalIgnoreCase)))
{
- if (_defaults != null && _defaults.Any(d => newFullKey.Equals(d.Key, StringComparison.OrdinalIgnoreCase)))
- {
- _sbYaml.AppendLine($"{yamlSpacing}{yamlSpacingPostfix}{key}: {_defaults[newFullKey]}");
- _responses[newFullKey] = _defaults[newFullKey];
- }
- continue;
+ _sbYaml.AppendLine($"{key}: {_defaults[newKey]}");
+ _responses[prefix] = _defaults[newKey];
}
- if (prop.Type.Equals("object", StringComparison.OrdinalIgnoreCase))
+ return;
+ }
+
+ if (!string.IsNullOrWhiteSpace(schema.Description))
+ {
+ AnsiConsole.WriteLine();
+ AnsiConsole.MarkupLine($"[yellow]{schema.Description.EscapeMarkup()}[/]");
+ }
+
+ var message = (schema.Description ?? newKey).EscapeMarkup();
+ var prompt = $"{prefix}[bold]{message}[/]:";
+ var isRequired = schema.Required != null && schema.Required.Contains(newKey);
+
+ if (schema.JsonSchemaType == null)
+ {
+ if (schema.AnyOf != null)
{
- _sbYaml.AppendLine($"{yamlSpacing}{key}:");
- await AskForProperties(prop, indent, newFullKey);
+ await ProcessSchema(schema.AnyOf[0], rootKey, key);
}
-
- else if (prop.Type.Equals("array", StringComparison.OrdinalIgnoreCase))
+ }
+ else
+ {
+ switch (schema.JsonSchemaType.Type)
{
- var index = 0;
- if (prop.Items != null)
- {
- _sbYaml.AppendLine($"{yamlSpacing}{key}:");
-
- do
+ case SchemaType.Boolean:
+ _isArrayStart = false;
+ PromptBoolean(prompt, rootKey, key, yamlSpacing + yamlSpacingPostfix);
+ break;
+ case SchemaType.Integer:
+ _isArrayStart = false;
+ PromptInteger(prompt, rootKey, key, yamlSpacing + yamlSpacingPostfix, isRequired);
+ break;
+ case SchemaType.String:
+ _isArrayStart = false;
+ if (schema.Enum != null)
{
- await AskForProperties(prop.Items, indent, $"{newFullKey}[{index}]");
- AnsiConsole.WriteLine();
- index++;
+ PromptEnum(prompt, rootKey, key, yamlSpacing + yamlSpacingPostfix, schema.Enum);
}
- while (
- AnsiConsole.Prompt(
- new TextPrompt($"[grey]{new string('.',30)}[/] [bold]Add another[/]?")
- .DefaultValueStyle(Style.Parse("mediumpurple3_1"))
- .ChoicesStyle(Style.Parse("mediumpurple3_1"))
- .PromptStyle(Style.Parse("seagreen1"))
- .DefaultValue('n')
- .AddChoice('y')
- .AddChoice('n')
- ) == 'y');
- }
- }
- else
- {
- var prefix = $"[grey]{newFullKey.PadRight(30, '.').EscapeMarkup()}[/] ";
- var message = (prop.Description ?? newFullKey).EscapeMarkup();
- var prompt = $"{prefix}[bold]{message}[/]:";
-
- AnsiConsole.WriteLine();
-
- switch (prop.Type.ToLower())
- {
- case "boolean":
- var responseBool = AnsiConsole.Prompt(
- new TextPrompt(prompt)
- .DefaultValueStyle(Style.Parse("mediumpurple3_1"))
- .ChoicesStyle(Style.Parse("mediumpurple3_1"))
- .PromptStyle(Style.Parse("seagreen1"))
- .DefaultValue('y')
- .AddChoice('y')
- .AddChoice('n')
- ) == 'y';
-
- _sbYaml.AppendLine($"{yamlSpacing}{yamlSpacingPostfix}{key}: {responseBool.ToString().ToLower()}");
- _responses[newFullKey] = responseBool;
-
- break;
-
- case "integer":
- var promptObjInt = new TextPrompt(prompt)
- .PromptStyle(Style.Parse("seagreen1"))
- .DefaultValueStyle(Style.Parse("mediumpurple3_1"));
-
- var defaultValueInt = GetDefaultInt(prop, newFullKey);
-
- if (defaultValueInt != 0)
- {
- promptObjInt.DefaultValue(defaultValueInt);
- }
- var responseInt = AnsiConsole.Prompt(promptObjInt);
-
- _sbYaml.AppendLine($"{yamlSpacing}{yamlSpacingPostfix}{key}: {responseInt}");
- _responses[newFullKey] = responseInt;
-
- break;
-
- default:
- if (prop.OneOf == null)
+ else
+ {
+ PromptString(prompt, rootKey, key, yamlSpacing + yamlSpacingPostfix, isRequired);
+ }
+ break;
+ case SchemaType.Object:
+ if (!key.EndsWith(']'))
+ {
+ _sbYaml.AppendLine();
+ AppendKey(yamlSpacing, key);
+ }
+ foreach (var prop in schema.Properties!)
+ {
+ await ProcessSchema(prop.Value, newKey, prop.Key);
+ }
+ break;
+ case SchemaType.Array:
+ _isArrayStart = false;
+ if (schema.Items != null)
+ {
+ if (schema.Items.AnyOf != null)
{
- var promptObjString = new TextPrompt(prompt)
- .PromptStyle(Style.Parse("seagreen1"))
- .DefaultValueStyle(Style.Parse("mediumpurple3_1"));
-
-
- promptObjString.AllowEmpty = !jsonSchema.Required.Contains(key);
-
- var defaultValueString = GetDefaultString(prop, newFullKey);
-
- if (!string.IsNullOrWhiteSpace(defaultValueString))
- {
- promptObjString.DefaultValue(defaultValueString);
- }
+ _sbYaml.AppendLine();
+ AppendKey(yamlSpacing, key);
- var responseString = AnsiConsole.Prompt(promptObjString);
- if (!string.IsNullOrEmpty(responseString))
+ var index = 0;
+ do
{
- _sbYaml.AppendLine($"{yamlSpacing}{yamlSpacingPostfix}{key}: {responseString}");
- _responses[newFullKey] = responseString;
- }
- }
- else
+ _isArrayStart = true;
+ await ProcessSchema(schema.Items.AnyOf[0], rootKey, $"{key}[{index}]");
+ _sbYaml.AppendLine();
+ AnsiConsole.WriteLine();
+ index++;
+ } while (
+ AnsiConsole.Prompt(
+ new TextPrompt($"[grey]{yamlSpacing}[/] [bold]Add another[/]?")
+ .DefaultValueStyle(Style.Parse("mediumpurple3_1"))
+ .ChoicesStyle(Style.Parse("mediumpurple3_1"))
+ .PromptStyle(Style.Parse("seagreen1"))
+ .DefaultValue('n')
+ .AddChoice('y')
+ .AddChoice('n')
+ ) == 'y');
+ } else if (schema.Items.Enum != null)
{
- var responseChoice = AnsiConsole.Prompt(
- new SelectionPrompt()
- .Title(prompt)
- .HighlightStyle(Style.Parse("mediumpurple3_1"))
- .AddChoices(prop.OneOf.Select(c => c.Const).ToArray())
- );
-
- _responses[newFullKey] = responseChoice;
- _sbYaml.AppendLine($"{yamlSpacing}{yamlSpacingPostfix}{key}: {responseChoice}");
- AnsiConsole.MarkupLine($"{prompt} [seagreen1]{_responses[newFullKey]}[/]");
-
+ schema.Items.JsonSchemaType!.Type = SchemaType.EnumList;
+ await ProcessSchema(schema.Items, rootKey, key);
}
- break;
- }
+ }
+ break;
+ case SchemaType.EnumList:
+ _isArrayStart = false;
+ PromptMultipleEnum(prompt, rootKey, key, yamlSpacing + yamlSpacingPostfix, schema.Enum!);
+ break;
}
+ }
+ }
+
+ private void PromptBoolean(string prompt, string rootKey, string key, string yamlPrefix)
+ {
+ var newKey = $"{rootKey}.{key}".TrimStart('.');
+ var response = AnsiConsole.Prompt(
+ new TextPrompt(prompt)
+ .DefaultValueStyle(Style.Parse("mediumpurple3_1"))
+ .ChoicesStyle(Style.Parse("mediumpurple3_1"))
+ .PromptStyle(Style.Parse("seagreen1"))
+ .DefaultValue('y')
+ .AddChoice('y')
+ .AddChoice('n')
+ ) == 'y';
+
+ _sbYaml.AppendLine($"{yamlPrefix}{key}: {response.ToString().ToLower()}");
+ _responses[newKey] = response;
+ }
+
+ private void PromptInteger(string prompt, string rootKey, string key, string yamlPrefix, bool isRequired)
+ {
+ var newKey = $"{rootKey}.{key}".TrimStart('.');
+ var spectrePrompt = new TextPrompt(prompt)
+ .PromptStyle(Style.Parse("seagreen1"))
+ .DefaultValueStyle(Style.Parse("mediumpurple3_1"));
- if (fullKey.EndsWith(']'))
- {
- yamlSpacingPostfix = " ";
- }
+ spectrePrompt.AllowEmpty = !isRequired;
+
+ var defaultValue = GetDefault(newKey);
+ if (defaultValue != 0)
+ {
+ spectrePrompt.DefaultValue(defaultValue);
}
+
+ var response = AnsiConsole.Prompt(spectrePrompt);
+
+ _sbYaml.AppendLine($"{yamlPrefix}{key}: {response}");
+ _responses[newKey] = response;
}
- private string GetDefaultString(JsonSchema.JsonSchema prop, string key)
+ private void PromptString(string prompt, string rootKey, string key, string yamlPrefix, bool isRequired)
{
- string? defaultValue = null;
-
- if (_defaults?.ContainsKey(key) ?? false)
+ var newKey = $"{rootKey}.{key}".TrimStart('.');
+ var spectrePrompt = new TextPrompt(prompt)
+ .PromptStyle(Style.Parse("seagreen1"))
+ .DefaultValueStyle(Style.Parse("mediumpurple3_1"));
+
+ spectrePrompt.AllowEmpty = !isRequired;
+
+ var defaultValue = GetDefault(newKey);
+
+ if (!string.IsNullOrWhiteSpace(defaultValue))
{
- defaultValue = (string)_defaults[key];
+ spectrePrompt.DefaultValue(defaultValue);
}
- if (string.IsNullOrWhiteSpace(defaultValue))
+ var response = AnsiConsole.Prompt(spectrePrompt);
+ if (!string.IsNullOrEmpty(response))
{
- if (!string.IsNullOrWhiteSpace(prop.Default?.ToString()))
- {
- defaultValue = prop.Default.ToString();
- }
+ _sbYaml.AppendLine($"{yamlPrefix}{key}: {response}");
+ _responses[newKey] = response;
}
- return defaultValue ?? string.Empty;
}
- private int GetDefaultInt(JsonSchema.JsonSchema prop, string key)
+ private void PromptEnum(string prompt, string rootKey, string key, string yamlPrefix, List enumList)
+ {
+ var newKey = $"{rootKey}.{key}".TrimStart('.');
+ var response = AnsiConsole.Prompt(
+ new SelectionPrompt()
+ .Title(prompt)
+ .HighlightStyle(Style.Parse("mediumpurple3_1"))
+ .AddChoices(enumList.ToArray())
+ );
+
+ _responses[newKey] = response;
+ _sbYaml.AppendLine($"{yamlPrefix}{key}: {response}");
+ AnsiConsole.MarkupLine($"{prompt} [seagreen1]{_responses[newKey]}[/]");
+ }
+
+ private void PromptMultipleEnum(string prompt, string rootKey, string key, string yamlPrefix, List enumList)
{
- int? defaultValue = null;
+ var newKey = $"{rootKey}.{key}".TrimStart('.');
+ var response = AnsiConsole.Prompt(
+ new MultiSelectionPrompt()
+ .Title(prompt)
+ .HighlightStyle(Style.Parse("mediumpurple3_1"))
+ .AddChoices(enumList.ToArray())
+ );
+
+ var responseValue = String.Join(',', response);
+ _responses[newKey] = responseValue;
+ _sbYaml.AppendLine($"{yamlPrefix}{key}: [{responseValue}]");
+ AnsiConsole.MarkupLine($"{prompt} [seagreen1]{_responses[newKey]}[/]");
+ }
- if (_defaults?.ContainsKey(key) ?? false)
+ private void AppendKey(string yamlSpacing, string key)
+ {
+ if (!string.IsNullOrWhiteSpace(key))
{
- defaultValue = int.Parse(_defaults[key]?.ToString() ?? "0");
+ _sbYaml.AppendLine($"{yamlSpacing}{key}:");
}
-
- if (defaultValue == 0)
+ }
+
+
+ private T? GetDefault(string key)
+ {
+ if (_defaults?.ContainsKey(key) ?? false)
{
- if (!string.IsNullOrWhiteSpace(prop.Default?.ToString()))
- {
- defaultValue = int.Parse(prop.Default.ToString() ?? "0");
- }
+ return (T)_defaults[key];
}
- return defaultValue ?? 0;
- }
+ return default;
+ }
+
}
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchema.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchema.cs
index 91b2cf0b..fd292171 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchema.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchema.cs
@@ -1,21 +1,28 @@
-namespace Nox.Cli.Plugin.Console.JsonSchema;
+using System.Text.Json.Serialization;
+
+namespace Nox.Cli.Plugin.Console.JsonSchema;
+
internal class JsonSchema
{
- public string Title { get; set; } = string.Empty;
- public string Description { get; set; } = string.Empty;
- public string Type { get; set; } = "object";
+ public string? Title { get; set; } = string.Empty;
+ public string? Description { get; set; } = string.Empty;
+
+ [JsonConverter(typeof(JsonSchemaTypeConverter))]
+ [JsonPropertyName("type")]
+ public JsonSchemaType? JsonSchemaType { get; set; }
+
public object? Default { get; set; } = null;
- public string[] Required { get; set; } = new string[0];
- public Dictionary Properties { get; set; } = null!;
+ public List? Required { get; set; } = new();
+
+ public Dictionary? Properties { get; set; } = null!;
+
public JsonSchema? Items { get; set; } = null!;
- public OneOfEntry[]? OneOf { get; set; } = null!;
+
+ public JsonSchema[]? AnyOf { get; set; }
+
+ public List? Enum { get; set; }
}
-internal class OneOfEntry
-{
- public string Const { get; set; } = string.Empty;
- public string Description { get; set; } = string.Empty;
-}
\ No newline at end of file
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchemaType.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchemaType.cs
new file mode 100644
index 00000000..1f75ff29
--- /dev/null
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchemaType.cs
@@ -0,0 +1,7 @@
+namespace Nox.Cli.Plugin.Console.JsonSchema;
+
+internal class JsonSchemaType
+{
+ public SchemaType? Type { get; set; }
+ public object? Default { get; set; }
+}
\ No newline at end of file
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchemaTypeConverter.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchemaTypeConverter.cs
new file mode 100644
index 00000000..c848eb0d
--- /dev/null
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/JsonSchemaTypeConverter.cs
@@ -0,0 +1,45 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Nox.Cli.Plugin.Console.JsonSchema;
+
+internal class JsonSchemaTypeConverter : JsonConverter
+{
+ public override JsonSchemaType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ var result = new JsonSchemaType();
+
+ switch (reader.TokenType)
+ {
+ case JsonTokenType.String:
+ result.Type = GetSchemaTypeFromString(reader.GetString());
+ break;
+ case JsonTokenType.StartArray:
+ reader.Read();
+ result.Type = GetSchemaTypeFromString(reader.GetString());
+ reader.Read();
+ result.Default = reader.GetString()!;
+ reader.Read();
+ break;
+ }
+
+ return result;
+ }
+
+ public override void Write(Utf8JsonWriter writer, JsonSchemaType? value, JsonSerializerOptions options)
+ {
+ throw new NotImplementedException();
+ }
+
+ private SchemaType GetSchemaTypeFromString(string? source)
+ {
+ return source?.ToLower() switch
+ {
+ "object" => SchemaType.Object,
+ "array" => SchemaType.Array,
+ "boolean" => SchemaType.Boolean,
+ "integer" => SchemaType.Integer,
+ _ => SchemaType.String
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/SchemaType.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/SchemaType.cs
new file mode 100644
index 00000000..685a8ec4
--- /dev/null
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/JsonSchema/SchemaType.cs
@@ -0,0 +1,11 @@
+namespace Nox.Cli.Plugin.Console.JsonSchema;
+
+public enum SchemaType
+{
+ String,
+ Boolean,
+ Integer,
+ Array,
+ Object,
+ EnumList
+}
\ No newline at end of file
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/CoreLoadNoxConfiguration_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/CoreLoadNoxConfiguration_v1.cs
index c75d4ac4..7490ae51 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/CoreLoadNoxConfiguration_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/CoreLoadNoxConfiguration_v1.cs
@@ -1,6 +1,8 @@
+using System.Reflection;
using Nox.Cli.Abstractions;
+using Nox.Cli.Abstractions.Exceptions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Builders;
+using Nox.Solution;
namespace Nox.Cli.Plugin.Core;
@@ -36,6 +38,7 @@ public Task BeginAsync(IDictionary inputs)
public Task> ProcessAsync(INoxWorkflowContext ctx)
{
+ if (ctx.IsServer) throw new NoxCliException("This action cannot be executed on a server. remove the run-at-server attribute for this step in your Nox workflow.");
var outputs = new Dictionary();
ctx.SetState(ActionState.Error);
@@ -49,18 +52,20 @@ public Task> ProcessAsync(INoxWorkflowContext ctx)
try
{
var fullPath = Path.GetFullPath(_path);
- var projectConfig = new ProjectConfigurationBuilder(fullPath)
+ var solution = new NoxSolutionBuilder()
+ .OnResolveSecrets((_, args) =>
+ {
+ var secretsConfig = args.SecretsConfig;
+ var secretKeys = args.Variables;
+ var resolver = ctx.NoxSecretsResolver;
+ if (resolver == null) throw new NoxCliException("Cannot load Nox solution definition, Secrets resolved has not been initialized.");
+ resolver.Configure(secretsConfig!, Assembly.GetEntryAssembly());
+ args.Secrets = resolver.Resolve(secretKeys!);
+ })
.Build();
- if (projectConfig == null)
- {
- ctx.SetErrorMessage($"Unable to load Nox project configuration from {fullPath}");
- }
- else
- {
- ctx.SetProjectConfiguration(projectConfig);
+ ctx.SetProjectConfiguration(solution);
- ctx.SetState(ActionState.Success);
- }
+ ctx.SetState(ActionState.Success);
}
catch (Exception ex)
{
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/Nox.Cli.Plugin.Core.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/Nox.Cli.Plugin.Core.csproj
index bf385e6a..4a020c5f 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/Nox.Cli.Plugin.Core.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Core/Nox.Cli.Plugin.Core.csproj
@@ -11,8 +11,7 @@
-
-
+
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValue_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValue_v1.cs
index cb52f2bd..359b0fce 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValue_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValue_v1.cs
@@ -1,6 +1,5 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Exceptions;
using Octopus.CoreParsers.Hcl;
using Sprache;
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValues_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValues_v1.cs
index 72bd3bdd..f6ed0184 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValues_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclAddValues_v1.cs
@@ -1,6 +1,5 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Exceptions;
using Octopus.CoreParsers.Hcl;
using Sprache;
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclHelpers.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclHelpers.cs
index b76c77c9..71d8ef56 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclHelpers.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/HclHelpers.cs
@@ -1,5 +1,4 @@
using Nox.Cli.Abstractions.Exceptions;
-using Nox.Core.Exceptions;
using Octopus.CoreParsers.Hcl;
namespace Nox.Cli.Plugin.Hcl;
@@ -9,7 +8,7 @@ public static class HclHelpers
public static bool ValueExists(HclElement template, string valuePath)
{
var pathValues = valuePath.Split('/');
- if (pathValues.Length == 0) throw new NoxException("Node path is invalid!");
+ if (pathValues.Length == 0) throw new NoxCliException("Node path is invalid!");
var foundNode = template.Child;
if (foundNode == null) throw new NoxCliException("HCL template contains no children.");
for (var i = 0; i < pathValues.Length; i++)
@@ -52,7 +51,7 @@ public static void AddValue(HclElement template, string path, string value)
}
catch (Exception ex)
{
- throw new NoxException(ex.Message);
+ throw new NoxCliException(ex.Message);
}
}
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/Nox.Cli.Plugin.Hcl.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/Nox.Cli.Plugin.Hcl.csproj
index 7c98a64b..542d8200 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/Nox.Cli.Plugin.Hcl.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Hcl/Nox.Cli.Plugin.Hcl.csproj
@@ -12,7 +12,6 @@
-
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Powershell/Nox.Cli.Plugin.Powershell.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Powershell/Nox.Cli.Plugin.Powershell.csproj
index 403cd1cd..33832cd1 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Powershell/Nox.Cli.Plugin.Powershell.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Powershell/Nox.Cli.Plugin.Powershell.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/Nox.Cli.Plugin.Project.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/Nox.Cli.Plugin.Project.csproj
index b0001435..df74af94 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/Nox.Cli.Plugin.Project.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/Nox.Cli.Plugin.Project.csproj
@@ -5,10 +5,6 @@
enable
enable
-
-
-
-
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminEmails_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminEmails_v1.cs
old mode 100755
new mode 100644
index f50c8947..3bbff105
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminEmails_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminEmails_v1.cs
@@ -1,7 +1,6 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Configuration;
-using Nox.Core.Models;
+using Nox.Solution;
namespace Nox.Cli.Plugin.Project;
@@ -72,15 +71,18 @@ public Task> ProcessAsync(INoxWorkflowContext ctx)
var result = "";
foreach (var item in _members)
{
- if (!string.IsNullOrEmpty(item.Email) && item.IsAdmin)
+ if (!string.IsNullOrEmpty(item.UserName) && item.Roles != null && item.Roles.Contains(TeamRole.Administrator))
{
- if (string.IsNullOrEmpty(result))
+ if (item.UserName.Contains("@"))
{
- result = item.Email;
- }
- else
- {
- result += _delimiter + item.Email;
+ if (string.IsNullOrEmpty(result))
+ {
+ result = item.UserName;
+ }
+ else
+ {
+ result += _delimiter + item.UserName;
+ }
}
}
}
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminUserNames_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminUserNames_v1.cs
index ce040afb..9aa4e08f 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminUserNames_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetAdminUserNames_v1.cs
@@ -1,7 +1,6 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Configuration;
-using Nox.Core.Models;
+using Nox.Solution;
namespace Nox.Cli.Plugin.Project;
@@ -72,7 +71,7 @@ public Task> ProcessAsync(INoxWorkflowContext ctx)
var result = "";
foreach (var item in _members)
{
- if (!string.IsNullOrEmpty(item.UserName) && item.IsAdmin)
+ if (!string.IsNullOrEmpty(item.UserName) && item.Roles != null && item.Roles.Contains(TeamRole.Administrator))
{
if (string.IsNullOrEmpty(result))
{
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetOwnerEmails_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetOwnerEmails_v1.cs
index b5cb77e6..b29aeb0c 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetOwnerEmails_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetOwnerEmails_v1.cs
@@ -1,7 +1,6 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Configuration;
-using Nox.Core.Models;
+using Nox.Solution;
namespace Nox.Cli.Plugin.Project;
@@ -72,15 +71,18 @@ public Task> ProcessAsync(INoxWorkflowContext ctx)
var result = "";
foreach (var item in _members)
{
- if (!string.IsNullOrEmpty(item.Email) && item.IsProductOwner)
+ if (!string.IsNullOrEmpty(item.UserName) && item.Roles != null && item.Roles.Contains(TeamRole.Owner))
{
- if (string.IsNullOrEmpty(result))
+ if (item.UserName.Contains('@'))
{
- result = item.Email;
- }
- else
- {
- result += _delimiter + item.Email;
+ if (string.IsNullOrEmpty(result))
+ {
+ result = item.UserName;
+ }
+ else
+ {
+ result += _delimiter + item.UserName;
+ }
}
}
}
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamEmails_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamEmails_v1.cs
index a741c56b..917abb0f 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamEmails_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamEmails_v1.cs
@@ -1,7 +1,6 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Configuration;
-using Nox.Core.Models;
+using Nox.Solution;
namespace Nox.Cli.Plugin.Project;
@@ -81,16 +80,19 @@ public Task> ProcessAsync(INoxWorkflowContext ctx)
var result = "";
foreach (var item in _members)
{
- if (item.IsAdmin && !_includeAdmin == true) continue;
- if (!string.IsNullOrEmpty(item.Email))
+ if (item.Roles != null && item.Roles.Contains(TeamRole.Administrator) && !_includeAdmin == true) continue;
+ if (!string.IsNullOrEmpty(item.UserName))
{
- if (string.IsNullOrEmpty(result))
+ if (item.UserName.Contains('@'))
{
- result = item.Email;
- }
- else
- {
- result += _delimiter + item.Email;
+ if (string.IsNullOrEmpty(result))
+ {
+ result = item.UserName;
+ }
+ else
+ {
+ result += _delimiter + item.UserName;
+ }
}
}
}
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamUserNames_v1.cs b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamUserNames_v1.cs
index 059490cc..a29f53dc 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamUserNames_v1.cs
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Project/ProjectGetTeamUserNames_v1.cs
@@ -1,7 +1,6 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;
-using Nox.Core.Configuration;
-using Nox.Core.Models;
+using Nox.Solution;
namespace Nox.Cli.Plugin.Project;
@@ -81,7 +80,7 @@ public Task> ProcessAsync(INoxWorkflowContext ctx)
var result = "";
foreach (var item in _members)
{
- if (item.IsAdmin && !_includeAdmin == true) continue;
+ if (item.Roles != null && item.Roles.Contains(TeamRole.Administrator) && !_includeAdmin == true) continue;
if (!string.IsNullOrEmpty(item.UserName))
{
if (string.IsNullOrEmpty(result))
diff --git a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Teams/Nox.Cli.Plugin.Teams.csproj b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Teams/Nox.Cli.Plugin.Teams.csproj
index dea05dc7..1da09389 100755
--- a/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Teams/Nox.Cli.Plugin.Teams.csproj
+++ b/src/Nox.Cli.Plugins/Nox.Cli.Plugin.Teams/Nox.Cli.Plugin.Teams.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/src/Nox.Cli.Secrets/IProjectSecretResolver.cs b/src/Nox.Cli.Secrets/IProjectSecretResolver.cs
deleted file mode 100755
index 632f41a0..00000000
--- a/src/Nox.Cli.Secrets/IProjectSecretResolver.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Nox.Core.Interfaces;
-using Nox.Core.Interfaces.Configuration;
-
-namespace Nox.Cli.Secrets;
-
-public interface IProjectSecretResolver
-{
- Task Resolve(IDictionary variables, IProjectConfiguration config);
-}
\ No newline at end of file
diff --git a/src/Nox.Cli.Secrets/Nox.Cli.Secrets.csproj b/src/Nox.Cli.Secrets/Nox.Cli.Secrets.csproj
index 042a474c..192b75d7 100755
--- a/src/Nox.Cli.Secrets/Nox.Cli.Secrets.csproj
+++ b/src/Nox.Cli.Secrets/Nox.Cli.Secrets.csproj
@@ -9,10 +9,9 @@
-
-
+
-
+
diff --git a/src/Nox.Cli.Secrets/ProjectSecretResolver.cs b/src/Nox.Cli.Secrets/ProjectSecretResolver.cs
deleted file mode 100755
index 31175909..00000000
--- a/src/Nox.Cli.Secrets/ProjectSecretResolver.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using Nox.Core.Interfaces;
-using Nox.Core.Interfaces.Configuration;
-using Nox.Utilities.Secrets;
-
-namespace Nox.Cli.Secrets;
-
-public class ProjectSecretResolver: IProjectSecretResolver
-{
- private readonly IPersistedSecretStore _store;
-
- public ProjectSecretResolver(IPersistedSecretStore store)
- {
- _store = store;
- }
-
- public async Task Resolve(IDictionary variables, IProjectConfiguration projectConfig)
- {
- var secretKeys = variables
- .Where(kv => kv.Value == null)
- .Select(kv => kv.Key)
- .Where(e => e.StartsWith("project.secrets.", StringComparison.OrdinalIgnoreCase))
- .Select(e => e[16..])
- .ToList();
-
- if (projectConfig.Secrets == null) return;
-
- //Default secret ttl to 30 minutes if not set
- var validFor = projectConfig.Secrets.ValidFor;
- TimeSpan ttl = TimeSpan.Zero;
- if (validFor != null)
- {
- ttl = new TimeSpan(validFor.Days ?? 0, validFor.Hours ?? 0, validFor.Minutes ?? 0, validFor.Seconds ?? 0);
- }
- if (ttl == TimeSpan.Zero)
- {
- ttl = new TimeSpan(0, 30, 0);
- }
-
- var resolvedSecrets = new List>();
- foreach (var key in secretKeys)
- {
- var cachedSecret = await _store.LoadAsync($"{projectConfig.Name}.{key}", ttl);
- resolvedSecrets.Add(new KeyValuePair(key, cachedSecret ?? ""));
- }
-
- //Resolve any remaining secrets from the vaults
- var unresolvedSecrets = resolvedSecrets.Where(s => s.Value == "").ToList();
- if (unresolvedSecrets.Any() && projectConfig.Secrets.Providers != null)
- {
- foreach (var vault in projectConfig.Secrets.Providers)
- {
- if (!unresolvedSecrets.Any()) break;
- switch (vault.Provider.ToLower())
- {
- case "azure-keyvault":
- var azureVault = new AzureSecretProvider(vault.Url);
- var azureSecrets = azureVault.GetSecretsAsync(unresolvedSecrets.Select(k => k.Key).ToArray()).Result;
- if (azureSecrets != null)
- {
- if (azureSecrets.Any())
- {
- resolvedSecrets.AddRange(azureSecrets);
- }
- foreach (var azureSecret in azureSecrets)
- {
- await _store.SaveAsync($"{projectConfig.Name}.{azureSecret.Key}", azureSecret.Value);
- }
- }
- break;
- }
- unresolvedSecrets = resolvedSecrets.Where(s => s.Value == "").ToList();
- }
- }
-
- if (!resolvedSecrets.Any()) return;
-
- foreach (var kv in resolvedSecrets)
- {
- variables[$"project.secrets.{kv.Key}"] = kv.Value;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nox.Cli.Secrets/ServiceExtensions.cs b/src/Nox.Cli.Secrets/ServiceExtensions.cs
index 7378e1d0..35eba071 100755
--- a/src/Nox.Cli.Secrets/ServiceExtensions.cs
+++ b/src/Nox.Cli.Secrets/ServiceExtensions.cs
@@ -5,12 +5,6 @@ namespace Nox.Cli.Secrets;
public static class ServiceExtensions
{
- public static IServiceCollection AddProjectSecretResolver(this IServiceCollection services)
- {
- services.AddSingleton();
- return services;
- }
-
public static IServiceCollection AddOrgSecretResolver(this IServiceCollection services)
{
services.AddSingleton();
diff --git a/src/Nox.Cli.Server/Nox.Cli.Server.csproj b/src/Nox.Cli.Server/Nox.Cli.Server.csproj
index 235bbec0..ddb1901e 100755
--- a/src/Nox.Cli.Server/Nox.Cli.Server.csproj
+++ b/src/Nox.Cli.Server/Nox.Cli.Server.csproj
@@ -9,14 +9,14 @@
-
-
-
-
+
+
+
+
-
-
+
+
diff --git a/src/Nox.Cli.Server/Services/WorkflowContext.cs b/src/Nox.Cli.Server/Services/WorkflowContext.cs
index 9bde6f83..a2e5180c 100755
--- a/src/Nox.Cli.Server/Services/WorkflowContext.cs
+++ b/src/Nox.Cli.Server/Services/WorkflowContext.cs
@@ -1,11 +1,11 @@
using System.Text.RegularExpressions;
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Caching;
-using Nox.Cli.Abstractions.Configuration;
using Nox.Cli.Abstractions.Helpers;
using Nox.Cli.Secrets;
using Nox.Cli.Variables;
-using Nox.Core.Interfaces;
+using Nox.Secrets.Abstractions;
+using Nox.Solution;
namespace Nox.Cli.Server.Services;
@@ -107,8 +107,11 @@ public void SetState(ActionState state)
}
public INoxCliCacheManager? CacheManager { get => _cachManager; }
- public void SetProjectConfiguration(IProjectConfiguration projectConfiguration)
+
+ public INoxSecretsResolver? NoxSecretsResolver => throw new NotImplementedException();
+
+ public void SetProjectConfiguration(NoxSolution projectConfiguration)
{
- throw new NotImplementedException();
+
}
}
\ No newline at end of file
diff --git a/src/Nox.Cli.Server/appsettings.Production.json b/src/Nox.Cli.Server/appsettings.Production.json
index 62603d88..864d1e30 100755
--- a/src/Nox.Cli.Server/appsettings.Production.json
+++ b/src/Nox.Cli.Server/appsettings.Production.json
@@ -7,7 +7,7 @@
"Microsoft.AspNetCore": "Debug"
}
},
- "NoxScriptsUrl": "https://nox-cli-scripts-test.ingena-int.work",
+ "NoxScriptsUrl": "https://noxorg.dev",
"ElasticApm": {
"ServerUrl": "http://localhost:8200",
"SecretToken": "",
diff --git a/src/Nox.Cli.Variables/ClientVariableProvider.cs b/src/Nox.Cli.Variables/ClientVariableProvider.cs
index b7941e49..35357a41 100755
--- a/src/Nox.Cli.Variables/ClientVariableProvider.cs
+++ b/src/Nox.Cli.Variables/ClientVariableProvider.cs
@@ -4,8 +4,6 @@
using Nox.Cli.Abstractions.Caching;
using Nox.Cli.Abstractions.Configuration;
using Nox.Cli.Secrets;
-using Nox.Core.Interfaces;
-using Nox.Core.Interfaces.Configuration;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
@@ -16,23 +14,20 @@ public class ClientVariableProvider: IClientVariableProvider
private readonly Regex _variableRegex = new(@"\$\{\{\s*(?[\w\.\-_:]+)\s*\}\}", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1));
private readonly Dictionary _variables;
- private readonly IProjectSecretResolver _projectSecretResolver;
private readonly IOrgSecretResolver _orgSecretResolver;
- private IProjectConfiguration? _projectConfig;
+ private Solution.Solution? _projectConfig;
private readonly INoxCliCache? _cache;
private readonly ILocalTaskExecutorConfiguration? _lteConfig;
public ClientVariableProvider(
IWorkflowConfiguration workflow,
- IProjectSecretResolver projectSecretResolver,
IOrgSecretResolver orgSecretResolver,
- IProjectConfiguration? projectConfig = null,
+ Solution.Solution? projectConfig = null,
ILocalTaskExecutorConfiguration? lteConfig = null,
INoxCliCache? cache = null)
{
_variables = new Dictionary(StringComparer.OrdinalIgnoreCase);
- _projectSecretResolver = projectSecretResolver;
_orgSecretResolver = orgSecretResolver;
_projectConfig = projectConfig;
_lteConfig = lteConfig;
@@ -97,7 +92,7 @@ public void StoreOutputVariables(INoxAction action, IDictionary
ResolveAllVariables(action);
}
- public void SetProjectConfiguration(IProjectConfiguration projectConfig)
+ public void SetProjectConfiguration(Solution.Solution projectConfig)
{
_projectConfig = projectConfig;
}
@@ -115,11 +110,6 @@ public async Task ResolveForServer()
await _orgSecretResolver.Resolve(_variables, _lteConfig);
}
- if (_projectConfig != null)
- {
- await _projectSecretResolver.Resolve(_variables, _projectConfig);
- }
-
await ResolveProjectVariables();
await _variables.ResolveEnvironmentVariables();
diff --git a/src/Nox.Cli.Variables/IClientVariableProvider.cs b/src/Nox.Cli.Variables/IClientVariableProvider.cs
index 73386f1c..a6303747 100755
--- a/src/Nox.Cli.Variables/IClientVariableProvider.cs
+++ b/src/Nox.Cli.Variables/IClientVariableProvider.cs
@@ -1,5 +1,4 @@
using Nox.Cli.Abstractions;
-using Nox.Core.Interfaces;
namespace Nox.Cli.Variables;
@@ -10,7 +9,7 @@ public interface IClientVariableProvider
IDictionary GetInputVariables(INoxAction action);
IDictionary GetUnresolvedInputVariables(INoxAction action);
void StoreOutputVariables(INoxAction action, IDictionary outputs);
- void SetProjectConfiguration(IProjectConfiguration projectConfig);
+ void SetProjectConfiguration(Solution.Solution projectConfig);
Task ResolveAll();
Task ResolveForServer();
diff --git a/src/Nox.Cli.Variables/Nox.Cli.Variables.csproj b/src/Nox.Cli.Variables/Nox.Cli.Variables.csproj
index 2718cdd0..ef7af58e 100755
--- a/src/Nox.Cli.Variables/Nox.Cli.Variables.csproj
+++ b/src/Nox.Cli.Variables/Nox.Cli.Variables.csproj
@@ -14,9 +14,10 @@
-
+
+
-
+
diff --git a/src/Nox.Cli.Variables/ObjectExtensions.cs b/src/Nox.Cli.Variables/ObjectExtensions.cs
index cc443c46..1bb650c0 100755
--- a/src/Nox.Cli.Variables/ObjectExtensions.cs
+++ b/src/Nox.Cli.Variables/ObjectExtensions.cs
@@ -10,7 +10,7 @@ public static class ObjectExtensions
/// The object to walk the properties of.
/// The action to perform on each property. The action will be passed the full path of the property and its value as arguments.
/// The current path of the object being walked. This parameter is for internal use and should not be specified when calling the method.
- public static void WalkProperties(this object obj, Action propertyAction, string path = "")
+ public static void WalkProperties(this object? obj, Action propertyAction, string path = "")
{
if (obj == null)
{
diff --git a/src/Nox.Cli.Variables/ProjectVariableResolver.cs b/src/Nox.Cli.Variables/ProjectVariableResolver.cs
index b00eab6d..d4ddf93b 100755
--- a/src/Nox.Cli.Variables/ProjectVariableResolver.cs
+++ b/src/Nox.Cli.Variables/ProjectVariableResolver.cs
@@ -1,20 +1,17 @@
-using Nox.Core.Interfaces;
-using Nox.Core.Interfaces.Configuration;
-
namespace Nox.Cli.Variables;
public static class ProjectVariableResolver
{
- public static Task ResolveProjectVariables(this IDictionary variables, IProjectConfiguration config)
+ public static Task ResolveProjectVariables(this IDictionary variables, Solution.Solution config)
{
- var projectKeys = variables
+ var solutionKeys = variables
//.Where(pk => pk.Value == null)
.Select(pk => pk.Key)
- .Where(pk => pk.StartsWith("project.", StringComparison.OrdinalIgnoreCase))
- .Select(pk => pk[8..])
+ .Where(pk => pk.StartsWith("solution.", StringComparison.OrdinalIgnoreCase))
+ .Select(pk => pk[9..])
.ToArray();
- config.WalkProperties( (name, value) => { if (projectKeys.Contains(name, StringComparer.OrdinalIgnoreCase)) { variables[$"project.{name}"] = value; } });
+ config.WalkProperties( (name, value) => { if (solutionKeys.Contains(name, StringComparer.OrdinalIgnoreCase)) { variables[$"solution.{name}"] = value; } });
return Task.CompletedTask;
}
diff --git a/src/Nox.Cli.Variables/TypeExtensions.cs b/src/Nox.Cli.Variables/TypeExtensions.cs
index 043f1063..d32f70a8 100755
--- a/src/Nox.Cli.Variables/TypeExtensions.cs
+++ b/src/Nox.Cli.Variables/TypeExtensions.cs
@@ -9,13 +9,15 @@ public static bool IsSimpleType(
{
return
type.IsPrimitive ||
+ type.IsEnum ||
new Type[] {
typeof(String),
typeof(Decimal),
typeof(DateTime),
typeof(DateTimeOffset),
typeof(TimeSpan),
- typeof(Guid)
+ typeof(Guid),
+ typeof(Uri)
}.Contains(type) ||
Convert.GetTypeCode(type) != TypeCode.Object;
}
diff --git a/src/Nox.Cli/Actions/NoxWorkflowContext.cs b/src/Nox.Cli/Actions/NoxWorkflowContext.cs
index 2d64cc7e..573fbb11 100755
--- a/src/Nox.Cli/Actions/NoxWorkflowContext.cs
+++ b/src/Nox.Cli/Actions/NoxWorkflowContext.cs
@@ -6,8 +6,9 @@
using Nox.Cli.Variables;
using System.Diagnostics;
using Nox.Cli.Abstractions.Caching;
-using Nox.Core.Exceptions;
-using Nox.Core.Interfaces;
+using Nox.Cli.Abstractions.Exceptions;
+using Nox.Secrets.Abstractions;
+using Nox.Solution;
namespace Nox.Cli.Actions;
@@ -17,6 +18,7 @@ public class NoxWorkflowContext : INoxWorkflowContext
private readonly IDictionary _steps;
private readonly IClientVariableProvider _varProvider;
private readonly INoxCliCacheManager _cacheManager;
+ private readonly INoxSecretsResolver? _secretsResolver;
private int _currentActionSequence = 0;
@@ -30,16 +32,17 @@ public class NoxWorkflowContext : INoxWorkflowContext
public NoxWorkflowContext(
IWorkflowConfiguration workflow,
- IProjectConfiguration projectConfig,
- IProjectSecretResolver projectSecretResolver,
+ NoxSolution projectConfig,
IOrgSecretResolver orgSecretResolver,
INoxCliCacheManager cacheManager,
- ILocalTaskExecutorConfiguration? lteConfig)
+ ILocalTaskExecutorConfiguration? lteConfig,
+ INoxSecretsResolver? secretsResolver)
{
WorkflowId = Guid.NewGuid();
_workflow = workflow;
- _varProvider = new ClientVariableProvider(workflow, projectSecretResolver, orgSecretResolver, projectConfig, lteConfig, cacheManager.Cache);
+ _varProvider = new ClientVariableProvider(workflow, orgSecretResolver, projectConfig, lteConfig, cacheManager.Cache);
_cacheManager = cacheManager;
+ _secretsResolver = secretsResolver;
_steps = ParseSteps();
_currentActionSequence = 0;
NextStep();
@@ -66,12 +69,11 @@ public void SetState(ActionState state)
}
}
- public INoxCliCacheManager? CacheManager
- {
- get => _cacheManager;
- }
+ public INoxCliCacheManager? CacheManager => _cacheManager;
+
+ public INoxSecretsResolver? NoxSecretsResolver => _secretsResolver;
- public void SetProjectConfiguration(IProjectConfiguration projectConfiguration)
+ public void SetProjectConfiguration(NoxSolution projectConfiguration)
{
_varProvider.SetProjectConfiguration(projectConfiguration);
_varProvider.ResolveProjectVariables();
@@ -134,7 +136,7 @@ private Dictionary ParseSteps()
{
if (steps.ContainsKey(step.Id))
{
- throw new NoxException($"Step Id {step.Id} exists more than once in your workflow configuration. Step Ids must be unique in a workflow configuration");
+ throw new NoxCliException($"Step Id {step.Id} exists more than once in your workflow configuration. Step Ids must be unique in a workflow configuration");
}
sequence++;
diff --git a/src/Nox.Cli/Actions/NoxWorkflowExecutor.cs b/src/Nox.Cli/Actions/NoxWorkflowExecutor.cs
index 9fd2a888..6a3abb95 100755
--- a/src/Nox.Cli/Actions/NoxWorkflowExecutor.cs
+++ b/src/Nox.Cli/Actions/NoxWorkflowExecutor.cs
@@ -4,7 +4,8 @@
using Nox.Cli.Abstractions.Configuration;
using Nox.Cli.Secrets;
using Nox.Cli.Server.Integration;
-using Nox.Core.Interfaces;
+using Nox.Secrets.Abstractions;
+using Nox.Solution;
using Spectre.Console;
namespace Nox.Cli.Actions;
@@ -14,31 +15,28 @@ public class NoxWorkflowExecutor: INoxWorkflowExecutor
private readonly INoxCliServerIntegration? _serverIntegration;
private readonly List _processedActions = new();
private readonly IAnsiConsole _console;
- private readonly IProjectConfiguration _noxConfig;
- private readonly IConfiguration _appConfig;
- private readonly IProjectSecretResolver _projectSecretResolver;
+ private readonly NoxSolution _noxConfig;
private readonly IOrgSecretResolver _orgSecretResolver;
private readonly ILocalTaskExecutorConfiguration? _lteConfig;
private readonly INoxCliCacheManager _cacheManager;
+ private readonly INoxSecretsResolver? _noxSecretsResolver;
public NoxWorkflowExecutor(
IAnsiConsole console,
- IProjectConfiguration noxConfig,
- IConfiguration appConfig,
- IProjectSecretResolver projectSecretResolver,
+ NoxSolution noxConfig,
IOrgSecretResolver orgSecretResolver,
INoxCliCacheManager cacheManager,
ILocalTaskExecutorConfiguration? lteConfig = null,
- INoxCliServerIntegration? serverIntegration = null)
+ INoxCliServerIntegration? serverIntegration = null,
+ INoxSecretsResolver? noxSecretsResolver = null)
{
_serverIntegration = serverIntegration;
_console = console;
_noxConfig = noxConfig;
- _appConfig = appConfig;
_lteConfig = lteConfig;
- _projectSecretResolver = projectSecretResolver;
_orgSecretResolver = orgSecretResolver;
_cacheManager = cacheManager;
+ _noxSecretsResolver = noxSecretsResolver;
}
public async Task Execute(IWorkflowConfiguration workflow)
@@ -51,7 +49,7 @@ public async Task Execute(IWorkflowConfiguration workflow)
var ctx = _console.Status()
.Spinner(Spinner.Known.Clock)
- .Start("Verifying the workflow script...", _ => new NoxWorkflowContext(workflow, _noxConfig, _projectSecretResolver, _orgSecretResolver, _cacheManager, _lteConfig));
+ .Start("Verifying the workflow script...", _ => new NoxWorkflowContext(workflow, _noxConfig, _orgSecretResolver, _cacheManager, _lteConfig, _noxSecretsResolver));
bool success = true;
diff --git a/src/Nox.Cli/Commands/Base/NoxCliCommand.cs b/src/Nox.Cli/Commands/Base/NoxCliCommand.cs
index 026804be..08a6274a 100755
--- a/src/Nox.Cli/Commands/Base/NoxCliCommand.cs
+++ b/src/Nox.Cli/Commands/Base/NoxCliCommand.cs
@@ -1,5 +1,5 @@
using Nox.Cli.Helpers;
-using Nox.Core.Interfaces;
+using Nox.Solution;
namespace Nox.Cli.Commands;
@@ -11,34 +11,30 @@ public abstract class NoxCliCommand : AsyncCommand where T
{
protected readonly IAnsiConsole _console;
protected readonly IConsoleWriter _consoleWriter;
- protected readonly IProjectConfiguration _noxConfiguration;
- protected readonly IConfiguration _configuration;
+ protected readonly NoxSolution _solution;
public NoxCliCommand(IAnsiConsole console, IConsoleWriter consoleWriter,
- IProjectConfiguration noxConfiguration, IConfiguration configuration)
+ NoxSolution solution)
{
_console = console;
_consoleWriter = consoleWriter;
- _noxConfiguration = noxConfiguration;
- _configuration = configuration;
+ _solution = solution;
}
public override Task ExecuteAsync(CommandContext context, TSettings settings)
{
_console.WriteLine();
_consoleWriter.WriteInfo($"Design folder:");
- _console.WriteLine(_configuration["NoxCli:DesignFolder"]!);
- if (string.IsNullOrEmpty(_noxConfiguration.Name))
+ if (string.IsNullOrEmpty(_solution.Name))
{
return Task.FromResult(0);
}
- if (_noxConfiguration.Team is null
- || _noxConfiguration.Team.Developers is null
- || _noxConfiguration.Team.Developers.Count == 0)
+ if (_solution.Team is null
+ || _solution.Team.Count == 0)
{
- throw new Exception($"The nox definition contains no 'Developers' in the 'Team' section. This section is required.");
+ throw new Exception($"The nox definition contains no members in the 'Team' section. This section is required.");
}
_console.WriteLine();
@@ -46,7 +42,7 @@ public override Task ExecuteAsync(CommandContext context, TSettings setting
_console.WriteLine();
_consoleWriter.WriteInfo($"Project:");
- _console.WriteLine(_noxConfiguration.Name);
+ _console.WriteLine(_solution.Name);
return Task.FromResult(0);
}
diff --git a/src/Nox.Cli/Commands/DynamicCommand.cs b/src/Nox.Cli/Commands/DynamicCommand.cs
index 4be2e4ae..094cc8b9 100755
--- a/src/Nox.Cli/Commands/DynamicCommand.cs
+++ b/src/Nox.Cli/Commands/DynamicCommand.cs
@@ -1,5 +1,5 @@
using Nox.Cli.Abstractions;
-using Nox.Core.Interfaces;
+using Nox.Solution;
namespace Nox.Cli.Commands;
@@ -17,9 +17,8 @@ public DynamicCommand(
INoxWorkflowExecutor executor,
IAnsiConsole console,
IConsoleWriter consoleWriter,
- IProjectConfiguration noxConfiguration,
- IConfiguration configuration)
- : base(console, consoleWriter, noxConfiguration, configuration)
+ NoxSolution solution)
+ : base(console, consoleWriter, solution)
{
_executor = executor;
}
diff --git a/src/Nox.Cli/Extensions/ConfiguratorExtensions.cs b/src/Nox.Cli/Extensions/ConfiguratorExtensions.cs
index dd90fde7..d4d15848 100755
--- a/src/Nox.Cli/Extensions/ConfiguratorExtensions.cs
+++ b/src/Nox.Cli/Extensions/ConfiguratorExtensions.cs
@@ -15,8 +15,10 @@ namespace Nox.Cli;
internal static class ConfiguratorExtensions
{
- public static IConfigurator AddNoxCommands(this IConfigurator cliConfig, IServiceCollection services, bool isOnline, string onlineCacheUrl = "")
+ public static IConfigurator AddNoxCommands(this IConfigurator cliConfig, IServiceCollection services, bool isOnline, string? remoteUrl = null)
{
+ var onlineCacheUrl = "https://noxorg.dev";
+ if (!string.IsNullOrWhiteSpace(remoteUrl)) onlineCacheUrl = remoteUrl;
var persistedTokenCache = services.BuildServiceProvider().GetRequiredService();
var cacheBuilder = new NoxCliCacheBuilder(onlineCacheUrl, persistedTokenCache)
.WithBuildEventHandler((sender, args) =>
diff --git a/src/Nox.Cli/Extensions/ServiceCollectionExtensions.cs b/src/Nox.Cli/Extensions/ServiceCollectionExtensions.cs
index db77aa4a..ede053ec 100755
--- a/src/Nox.Cli/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Nox.Cli/Extensions/ServiceCollectionExtensions.cs
@@ -1,65 +1,33 @@
-using Nox.Core.Extensions;
-using Nox.Core.Helpers;
-using Nox.Core.Interfaces;
-using Nox.Core.Models;
-using Spectre.Console;
+using System.Reflection;
+using Nox.Secrets;
+using Nox.Secrets.Abstractions;
+using Nox.Solution;
namespace Nox.Cli;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
-using Nox.Core.Constants;
-using Nox.Core.Exceptions;
-using System.IO;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddNoxCliServices(this IServiceCollection services, string[] args)
{
- var configuration = ConfigurationHelper.GetNoxAppSettings();
-
- if (configuration == null)
- {
- throw new ConfigurationException("Could not load Nox configuration.");
- }
-
- var designPath = ResolveDesignPath(args, configuration);
-
- configuration["NoxCli:DesignFolder"] = designPath;
-
- services.AddSingleton(configuration);
-
- if (Directory.GetFiles(designPath, FileExtension.ServiceDefinition, SearchOption.AllDirectories).Length > 0)
- {
- services.AddNoxConfiguration(designPath);
- AnsiConsole.MarkupLine($"Found solution configuration in {Path.GetFullPath(designPath)}");
- }
- else
- {
- services.AddSingleton(new ProjectConfiguration());
- }
- return services;
+ return services
+ .AddSingleton(typeof(NoxSolution), CreateSolution)
+ .AddSecretsResolver();
}
-
- private static string ResolveDesignPath(string[] args, IConfiguration configuration)
+
+ private static NoxSolution CreateSolution(IServiceProvider serviceProvider)
{
- string? path = null;
-
- for (var i = args.Length-1; i >= 0; i--)
- {
- if (args[i].Equals("--path", StringComparison.OrdinalIgnoreCase))
+ return new NoxSolutionBuilder()
+ .AllowMissingSolutionYaml()
+ .OnResolveSecrets((_, args) =>
{
- if (i + 1 < args.Length)
- {
- path = args[i + 1];
- }
- }
- }
-
- path ??= configuration["Nox:DefinitionRootPath"];
-
- path ??= Directory.GetCurrentDirectory();
-
- return path;
+ var secretsConfig = args.SecretsConfig;
+ var secretKeys = args.Variables;
+ var resolver = serviceProvider.GetRequiredService();
+ resolver.Configure(secretsConfig!, Assembly.GetEntryAssembly());
+ args.Secrets = resolver.Resolve(secretKeys!);
+ })
+ .Build();
}
}
\ No newline at end of file
diff --git a/src/Nox.Cli/Nox.Cli.csproj b/src/Nox.Cli/Nox.Cli.csproj
index d5f9821a..ddaa7244 100755
--- a/src/Nox.Cli/Nox.Cli.csproj
+++ b/src/Nox.Cli/Nox.Cli.csproj
@@ -18,9 +18,9 @@
false
Copyright (c) Andre Sharpe 2022
true
- 1.0.18.0
- 1.0.18.0
- 1.0.18
+ 1.0.19.0
+ 1.0.19.0
+ 1.0.19
MIT
https://github.com/NoxOrg/Nox.Cli
https://github.com/NoxOrg/Nox.Cli.git
@@ -29,28 +29,26 @@
-
- Always
-
-
-
+
+
-
+
-
+
+
+
-
-
+
@@ -75,4 +73,9 @@
+
+
+ design\SampleCurrency.solution.nox.yaml
+
+
\ No newline at end of file
diff --git a/src/Nox.Cli/Program.cs b/src/Nox.Cli/Program.cs
index 452378e5..d98fac1a 100755
--- a/src/Nox.Cli/Program.cs
+++ b/src/Nox.Cli/Program.cs
@@ -2,14 +2,11 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console;
using Spectre.Console.Cli;
-
using Nox.Cli;
using Nox.Cli.Abstractions;
-using Nox.Cli.Abstractions.Caching;
using Nox.Cli.Abstractions.Exceptions;
using Nox.Cli.Actions;
using Nox.Cli.Caching;
@@ -20,14 +17,18 @@
using Nox.Cli.Secrets;
using Nox.Utilities.Secrets;
-var appConfig = new ConfigurationBuilder()
- .AddJsonFile("appsettings.json")
- .Build();
-
var isLoggingOut = (args.Length > 0 && args[0].ToLower().Equals("logout"));
var isGettingVersion = (args.Length > 0 && args[0].ToLower().Equals("version"));
+var remoteUrl = string.Empty;
+
+var remoteUrlArg = args.FirstOrDefault(arg => arg.StartsWith("--remoteUrl="));
+if (remoteUrlArg != null)
+{
+ remoteUrl = remoteUrlArg.Replace("--remoteUrl=", "");
+}
+
if (!isGettingVersion || args.Length == 0)
{
var installedVersion = VersionChecker.GetInstalledNoxCliVersion();
@@ -39,17 +40,15 @@
}
var isOnline = InternetChecker.CheckForInternet();
-
var services = new ServiceCollection();
services.AddSingleton();
services.AddSingleton();
-services.AddTransient();
services.AddNoxTokenCache();
services.AddNoxCliServices(args);
services.AddPersistedSecretStore();
-services.AddProjectSecretResolver();
services.AddOrgSecretResolver();
+services.AddTransient();
services.AddAutoMapper(Assembly.GetExecutingAssembly());
var registrar = new TypeRegistrar(services);
@@ -68,7 +67,7 @@
if(!isGettingVersion && !isLoggingOut)
{
- config.AddNoxCommands(services, isOnline, appConfig["OnlineScriptsUrl"]!);
+ config.AddNoxCommands(services, isOnline, remoteUrl);
}
config.AddCommand("logout")
diff --git a/src/Nox.Cli/Properties/launchSettings.json b/src/Nox.Cli/Properties/launchSettings.json
index b861262e..da3c438d 100755
--- a/src/Nox.Cli/Properties/launchSettings.json
+++ b/src/Nox.Cli/Properties/launchSettings.json
@@ -3,7 +3,7 @@
"Nox.Cli": {
"commandName": "Project",
"commandLineArgs": "init solution",
- "workingDirectory": "$(ProjectDir)",
+ "workingDirectory": "/home/jan/demo/CliDemo",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/src/Nox.Cli/Properties/launchSettings.json.default b/src/Nox.Cli/Properties/launchSettings.json.default
deleted file mode 100755
index b861262e..00000000
--- a/src/Nox.Cli/Properties/launchSettings.json.default
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "profiles": {
- "Nox.Cli": {
- "commandName": "Project",
- "commandLineArgs": "init solution",
- "workingDirectory": "$(ProjectDir)",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nox.Cli/Properties/launchSettings.json.init-solution b/src/Nox.Cli/Properties/launchSettings.json.init-solution
deleted file mode 100755
index 0660aab5..00000000
--- a/src/Nox.Cli/Properties/launchSettings.json.init-solution
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "profiles": {
- "Nox.Cli": {
- "commandName": "Project",
- "commandLineArgs": "init solution",
- "workingDirectory": "/home/jan/demo/Nox.WeatherTwo",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nox.Cli/Properties/launchSettings.json.test-cname b/src/Nox.Cli/Properties/launchSettings.json.test-cname
deleted file mode 100755
index 0ef7b534..00000000
--- a/src/Nox.Cli/Properties/launchSettings.json.test-cname
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "profiles": {
- "Nox.Cli": {
- "commandName": "Project",
- "commandLineArgs": "test find-cname-record --path /home/jan/Projects/IWG/Nox.WeatherOne/.nox/design",
- "workingDirectory": "$(ProjectDir)",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nox.Cli/Services/VersionChecker.cs b/src/Nox.Cli/Services/VersionChecker.cs
index 10200401..e56c5f95 100755
--- a/src/Nox.Cli/Services/VersionChecker.cs
+++ b/src/Nox.Cli/Services/VersionChecker.cs
@@ -26,7 +26,10 @@ public static void CheckForLatestVersion()
if (latestVersion.FirstOrDefault() == 'v')
latestVersion = latestVersion[1..]; // remove the 'v' prefix. equivalent to `latest.Substring(1, latest.Length - 1)`
- if (installedVersion != latestVersion)
+ var installedVersionNo = Convert.ToInt32(installedVersion.Replace(".", ""));
+ var latestVersionNo = Convert.ToInt32(latestVersion.Replace(".", ""));
+
+ if (installedVersionNo < latestVersionNo)
AnsiConsole.MarkupLine(@$"{Environment.NewLine}[bold underline seagreen1]This version of NOX.Cli ({installedVersion}) is older than that of the latest version ({latestVersion}) Update the tools for the latest features and bug fixes (`dotnet tool update -g Nox.Cli`).[/]{Environment.NewLine}");
}
catch (Exception)
diff --git a/src/Nox.Cli/appsettings.Development.json b/src/Nox.Cli/appsettings.Development.json
deleted file mode 100755
index e56cb33d..00000000
--- a/src/Nox.Cli/appsettings.Development.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "Nox": {
- "DefinitionRootPath": "./",
- "KeyVaultUri": "https://we-key-Nox-02.vault.azure.net/"
- },
- "OnlineScriptsUrl": "http://localhost:9000"
-}
\ No newline at end of file
diff --git a/src/Nox.Cli/appsettings.Production.json b/src/Nox.Cli/appsettings.Production.json
deleted file mode 100755
index 287263a1..00000000
--- a/src/Nox.Cli/appsettings.Production.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "Nox": {
- "DefinitionRootPath": "./",
- "KeyVaultUri": "https://we-key-Nox-02.vault.azure.net/"
- },
- "OnlineScriptsUrl": "https://nox-cli-scripts-test.ingena.work/"
-}
\ No newline at end of file
diff --git a/src/Nox.Cli/appsettings.json b/src/Nox.Cli/appsettings.json
deleted file mode 100755
index b1f1384e..00000000
--- a/src/Nox.Cli/appsettings.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "Nox": {
- "DefinitionRootPath": "./",
- "KeyVaultUri": "https://we-key-Nox-02.vault.azure.net/"
- },
- "OnlineScriptsUrl": "http://localhost:9000"
-}
\ No newline at end of file
diff --git a/src/Nox.Cli/appsettings.nox-cli-scripts.json b/src/Nox.Cli/appsettings.nox-cli-scripts.json
deleted file mode 100755
index a42fc427..00000000
--- a/src/Nox.Cli/appsettings.nox-cli-scripts.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "Nox": {
- "DefinitionRootPath": "../../samples/Nox.Cli.Scripts",
- "KeyVaultUri": "https://we-key-Nox-02.vault.azure.net/"
- },
- "OnlineWorkflowUrl": "http://localhost:9000/workflows"
-}
\ No newline at end of file
diff --git a/src/Nox.Cli/appsettings.nox-demo.json b/src/Nox.Cli/appsettings.nox-demo.json
deleted file mode 100755
index d517b60d..00000000
--- a/src/Nox.Cli/appsettings.nox-demo.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "Nox": {
- "DefinitionRootPath": "/home/jan/NoxDemo/Design",
- "KeyVaultUri": "https://we-key-Nox-02.vault.azure.net/"
- },
- "OnlineWorkflowUrl": "http://localhost:9000/workflows"
-}
\ No newline at end of file
diff --git a/tests/Nox.Cli.Server.Tests/Nox.Cli.Server.Tests.csproj b/tests/Nox.Cli.Server.Tests/Nox.Cli.Server.Tests.csproj
index d004176a..cced5a6e 100755
--- a/tests/Nox.Cli.Server.Tests/Nox.Cli.Server.Tests.csproj
+++ b/tests/Nox.Cli.Server.Tests/Nox.Cli.Server.Tests.csproj
@@ -10,9 +10,9 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive