Skip to content

Commit

Permalink
Merge pull request #206 from NoxOrg/feature/new-demo-template
Browse files Browse the repository at this point in the history
- Improve console prompt default handling
  • Loading branch information
jan-schutte authored Mar 22, 2024
2 parents 3a1c920 + a2ee77a commit d535b38
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 94 deletions.
16 changes: 8 additions & 8 deletions src/Nox.Cli.Abstractions/Helpers/YamlHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Nox.Cli.Abstractions.Helpers;

public static class YamlHelper
{
private static readonly Regex _referenceRegex = new(@"\$ref\S*:\s*(?<variable>[\w:\.\/\\]+\b[\w\-\.\/]+)\s*", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(5));
private static readonly Regex _referenceRegex = new(@"(?<!\x22)(\$ref\S*:\s*(?<variable>[\w:\.\/\\]+\b[\w\-\.\/]+)\s*)", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(5));

/// <summary>
/// Resolve $ref &lt;path&gt; tags in a yaml source yaml file. <br/>
Expand All @@ -22,7 +22,7 @@ public static string ResolveYamlReferences(string path)
var sourcePath = Path.GetDirectoryName(sourceFullPath);

var sourceLines = File.ReadAllLines(path);
var outputLines = ResolveYamlReferences(sourceLines.ToList(), sourcePath!).Result;
var outputLines = ResolveYamlReferences(sourceLines.ToList(), sourcePath!, Path.GetFileName(path)).Result;

return string.Join('\n', outputLines.ToArray());
}
Expand All @@ -42,12 +42,12 @@ public static async Task<string> ResolveYamlReferencesAsync(string path)
var sourcePath = Path.GetDirectoryName(sourceFullPath);

var sourceLines = await File.ReadAllLinesAsync(path);
var outputLines = await ResolveYamlReferences(sourceLines.ToList(), sourcePath!);
var outputLines = await ResolveYamlReferences(sourceLines.ToList(), sourcePath!, Path.GetFileName(path));

return string.Join('\n', outputLines.ToArray());
}

private static async Task<List<string>> ResolveYamlReferences(List<string> sourceLines, string path)
private static async Task<List<string>> ResolveYamlReferences(List<string> sourceLines, string path, string parentFile)
{
var outputLines = new List<string>();
foreach (var sourceLine in sourceLines)
Expand All @@ -58,9 +58,9 @@ private static async Task<List<string>> ResolveYamlReferences(List<string> sourc
if (match.Success)
{
var padding = new string(' ', match.Index);
var childPath = match.Groups[1].Value;
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}");
if (!File.Exists(childPath)) throw new NoxCliException($"Referenced yaml file does not exist for reference: {match.Groups[1].Value} in file: {parentFile}");
var childLines = await File.ReadAllLinesAsync(childPath);
foreach (var childLine in childLines)
{
Expand All @@ -78,9 +78,9 @@ private static async Task<List<string>> ResolveYamlReferences(List<string> sourc
}
}

if (outputLines.Any(ol => ol.Contains("$ref:") && !ol.TrimStart().StartsWith('#')))
if (outputLines.Any(ol => ol.Contains("$ref:") && !ol.Contains("\"$ref:") && !ol.TrimStart().StartsWith('#')))
{
outputLines = await ResolveYamlReferences(outputLines, path);
outputLines = await ResolveYamlReferences(outputLines, path, parentFile);
}

return outputLines;
Expand Down
4 changes: 2 additions & 2 deletions src/Nox.Cli.Caching/NoxCliCacheBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ public class NoxCliCacheBuilder
{
private readonly NoxCliCacheManager _manager;

public NoxCliCacheBuilder(string remoteUrl, IPersistedTokenCache? tokenCache = null)
public NoxCliCacheBuilder(string remoteUrl, bool forceOffline, IPersistedTokenCache? tokenCache = null)
{
_manager = new NoxCliCacheManager(remoteUrl, tokenCache);
_manager = new NoxCliCacheManager(remoteUrl, forceOffline, tokenCache);
}

public NoxCliCacheBuilder ForServer()
Expand Down
58 changes: 30 additions & 28 deletions src/Nox.Cli.Caching/NoxCliCacheManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class NoxCliCacheManager: INoxCliCacheManager
private string _workflowCachePath;
private string _templateCachePath;
private string _localWorkflowPath;
private bool _forceOffline;
private bool _isServer;
private readonly Uri _remoteUri;
private Uri? _workflowUri;
Expand All @@ -37,6 +38,29 @@ public class NoxCliCacheManager: INoxCliCacheManager
private IDeserializer _deserializer;
private string? _tenantId;

public NoxCliCacheManager(string? remoteUrl, bool forceOffline, IPersistedTokenCache? tokenCache = null)
{
_buildLog = new List<string>();
if (string.IsNullOrEmpty(remoteUrl))
{
_remoteUri = new Uri("https://noxorg.dev");
}
else
{
_remoteUri = new Uri(remoteUrl);
}

_forceOffline = forceOffline;
_cachePath = WellKnownPaths.CachePath;
_workflowCachePath = WellKnownPaths.WorkflowsCachePath;
_templateCachePath = WellKnownPaths.TemplatesCachePath;
Directory.CreateDirectory(_cachePath);
_cacheFile = WellKnownPaths.CacheFile;
_localWorkflowPath = ".";
_tokenCache = tokenCache;
_deserializer = BuildDeserializer();
}

internal void ForServer()
{
_isServer = true;
Expand Down Expand Up @@ -73,6 +97,7 @@ internal void AddBuildEventHandler(EventHandler<ICacheManagerBuildEventArgs> han
public bool IsOnline {
get
{
if (_forceOffline) return false;
if (_remoteUri.Host == "localhost") return true;
return PingHelper.ServicePing(_remoteUri.Host);
}
Expand Down Expand Up @@ -138,32 +163,6 @@ public void RefreshTemplate(string name)
}
}
}
else
{
throw new NoxCliException($"Unable to communicate with the online cache.");
}
}

public NoxCliCacheManager(string? remoteUrl, IPersistedTokenCache? tokenCache = null)
{
_buildLog = new List<string>();
if (string.IsNullOrEmpty(remoteUrl))
{
_remoteUri = new Uri("https://noxorg.dev");
}
else
{
_remoteUri = new Uri(remoteUrl);
}

_cachePath = WellKnownPaths.CachePath;
_workflowCachePath = WellKnownPaths.WorkflowsCachePath;
_templateCachePath = WellKnownPaths.TemplatesCachePath;
Directory.CreateDirectory(_cachePath);
_cacheFile = WellKnownPaths.CacheFile;
_localWorkflowPath = ".";
_tokenCache = tokenCache;
_deserializer = BuildDeserializer();
}

internal INoxCliCacheManager Build()
Expand Down Expand Up @@ -494,9 +493,12 @@ private string[] FindWorkflowsAndManifest(string searchPath = "")
private FileInfo[] GetFilesWithSearchPatterns(DirectoryInfo path, string[] searchPatterns, SearchOption searchOption)
{
var files = new List<FileInfo>();
foreach (var pattern in searchPatterns)
if (path.Exists)
{
files.AddRange( path.GetFiles(pattern, searchOption) );
foreach (var pattern in searchPatterns)
{
files.AddRange( path.GetFiles(pattern, searchOption) );
}
}
return files.ToArray();
}
Expand Down
6 changes: 3 additions & 3 deletions src/Nox.Cli.Helpers/YamlCleaner.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.CodeDom.Compiler;
using System.Text;
using YamlDotNet.Core;
using YamlDotNet.RepresentationModel;
Expand All @@ -13,11 +14,10 @@ public static StringBuilder RemoveEmptyNodes(StringBuilder sourceYaml)
yaml.Load(input);
var root = (YamlMappingNode)yaml.Documents[0].RootNode;
RemoveEmptyChildren(root);
var yamlDoc = new YamlDocument(root);
var yamlStream = new YamlStream(yamlDoc);
var sb = new StringBuilder();
var writer = new StringWriter(sb);
yamlStream.Save(writer, false);
var textWriter = new IndentedTextWriter(writer, " ");
yaml.Save(textWriter, false);
writer.Flush();
writer.Close();
return sb;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ public NoxActionMetaData Discover()
private readonly RestClient _client = new();

private readonly Regex _resolveRefs = new("\"\\$ref\\\"\\s*:\\s*\\\"(?<url>[\\w:/\\.]+)\\\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);

private readonly Regex _yamlVariableRegex = new(@"\$\{\{\s*(yaml)\.(?<variable>\b[\w\-_:]+)\s*\}\}", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1));

private readonly Dictionary<string, object> _responses = new();

Expand Down Expand Up @@ -199,7 +201,7 @@ public async Task<IDictionary<string, object>> ProcessAsync(INoxWorkflowContext

if (_fileOptions != null && _fileOptions.ContainsKey("filename"))
{
_yaml = YamlCleaner.RemoveEmptyNodes(_yaml);
//_yaml = YamlCleaner.RemoveEmptyNodes(_yaml);

_yaml.Insert(0, Environment.NewLine);

Expand Down Expand Up @@ -297,6 +299,7 @@ private async Task ProcessSchema(JsonSchema.JsonSchema schema, string rootKey =
{
var newKey = $"{rootKey}.{key}".TrimStart('.');


var prefix = $"[grey]{newKey.PadRight(40, '.').EscapeMarkup()}[/] ";
var yamlSpacing = new string(' ', newKey.Count(d => d == '.') * 2);

Expand Down Expand Up @@ -547,42 +550,80 @@ private void AppendKey(string yamlSpacing, string key)
{
if (_defaults?.ContainsKey(key) ?? false)
{
return (T)Convert.ChangeType(_defaults[key], typeof(T));
var defaultValue = _defaults[key];
var match = _yamlVariableRegex.Match(defaultValue.ToString()!);
if (match.Success)
{
var variableValue = _responses[match.Groups["variable"].ToString()].ToString();
return (T)Convert.ChangeType(defaultValue.ToString()!.Replace(match.Groups[0].ToString(), variableValue), typeof(T));
}
else
{
return (T)Convert.ChangeType(defaultValue, typeof(T));
}
}

return default;
}

private void ProcessDefaults(string key, string yamlSpacing, string yamlSpacingPostfix)
{
Regex defaultArrayRegex = new(@"\[(.*?)\]\.(.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1));
var processor = new DefaultsProcessor();
foreach (var defaultEntry in _defaults!.Where(d => d.Key.StartsWith(key, StringComparison.CurrentCultureIgnoreCase)))
{
processor.Process(defaultEntry);
}

_yaml.AppendLine($"{yamlSpacing}{key}:");
var arrayIndex = -1;
foreach (var defaultItem in _defaults!.Where(d => d.Key.StartsWith(key, StringComparison.CurrentCultureIgnoreCase)))
AppendYaml(processor.Result!, yamlSpacing);
}

private void AppendYaml(DefaultNode node, string yamlSpacing, string spacingPostFix = "")
{
var value = "";
if (!string.IsNullOrWhiteSpace(node.Value)) value = node.Value;
var key = node.Key;
if (key.StartsWith('['))
{
//check if this item is an array
var itemKey = defaultItem.Key;
var defaultSpacing = new string(' ', itemKey.Count(d => d == '.') * 2);
var match = defaultArrayRegex.Match(itemKey);
if (match.Success) //array
if (node.Children is { Count: > 0 } || node.Value!.StartsWith("$ref"))
{
if (int.TryParse(match.Groups[1].ToString(), out var itemIndex))
{
var defaultPrefix = " ";
if (itemIndex != arrayIndex)
{
defaultPrefix = "- ";
arrayIndex = itemIndex;
}
_yaml.AppendLine($"{defaultSpacing}{defaultPrefix}{match.Groups[2]}: {defaultItem.Value}");
}
spacingPostFix = "- ";
}
else
{
_yaml.AppendLine($"{yamlSpacing}{yamlSpacingPostfix}{key}: {_defaults![key]}");
_yaml.AppendLine($"{yamlSpacing}{value}");
}
}
else
{
key += ": ";
yamlSpacing = AddPostFix(yamlSpacing, spacingPostFix);
_yaml.AppendLine($"{yamlSpacing}{key}{value}");
}

if (node.Children.Count != 0)
{
yamlSpacing += " ";
foreach (var childNode in node.Children)
{
AppendYaml(childNode, yamlSpacing, spacingPostFix);
spacingPostFix = "";
}
}
else if (node.Value!.StartsWith("$ref"))
{
yamlSpacing += " ";
yamlSpacing = AddPostFix(yamlSpacing, spacingPostFix);
_yaml.AppendLine($"{yamlSpacing}{value}");
}

}

private string AddPostFix(string source, string postFix)
{
if (string.IsNullOrEmpty(postFix)) return source;
var result = source.Substring(0, source.Length - postFix.Length);
result += postFix;
return result;
}
}

8 changes: 8 additions & 0 deletions src/Nox.Cli.Plugins/Nox.Cli.Plugin.Console/DefaultNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Nox.Cli.Plugin.Console;

public class DefaultNode
{
public string Key { get; set; } = string.Empty;
public string? Value { get; set; }
public List<DefaultNode> Children { get; set; } = new();
}
Loading

0 comments on commit d535b38

Please sign in to comment.