Skip to content

Commit

Permalink
Merge pull request #35 from travisnielsen/feature/buildscriptupdate
Browse files Browse the repository at this point in the history
Upgrade codebase to .NET6 and re-factor dependencies (1 of 3)
  • Loading branch information
Potherca authored Aug 2, 2022
2 parents 31b82b5 + a1949e5 commit e38467c
Show file tree
Hide file tree
Showing 19 changed files with 1,223 additions and 570 deletions.
437 changes: 434 additions & 3 deletions .gitignore

Large diffs are not rendered by default.

26 changes: 17 additions & 9 deletions scripts/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@
"version": "0.2.0",
"configurations": [
{
"name": ".NET Script Debug",
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"program": "dotnet",
"args": [
"exec",
"${env:USERPROFILE}/.dotnet/tools/.store/dotnet-script/0.53.0/dotnet-script/0.53.0/tools/netcoreapp3.1/any/dotnet-script.dll",
"${file}"
],
"cwd": "${workspaceRoot}",
"stopAtEntry": true
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net6.0/GeneratePuml.dll",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
42 changes: 42 additions & 0 deletions scripts/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/GeneratePuml.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/GeneratePuml.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/GeneratePuml.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}
241 changes: 241 additions & 0 deletions scripts/GeneratePlantuml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using System.Drawing;
using System.Text;
using System.Diagnostics;

public class GeneratePlantuml : IHostedService
{
readonly ILogger logger;
readonly IHostApplicationLifetime lifetime;
readonly string sourceFolder;
readonly string originalSourceFolder;
readonly string manualSourceFolder;
readonly string targetFolder;
readonly int targetImageHeight = 70;
readonly Color azureColor;
readonly string plantUmlPath;
IImageManager svgManager;

public GeneratePlantuml(ILogger<GeneratePlantuml> logprovider, IConfiguration config, IImageManager exporter, IHostApplicationLifetime appLifetime)
{
logger = logprovider;
lifetime = appLifetime;
sourceFolder = config.GetSection("sourceFolderPath").Value;
originalSourceFolder = Path.Combine(sourceFolder, "official");
manualSourceFolder = Path.Combine(sourceFolder, "manual");
targetFolder = config.GetSection("targetFolderPath").Value;
azureColor = System.Drawing.ColorTranslator.FromHtml(config.GetSection("monochromeColorHex").Value);
plantUmlPath = config.GetSection("plantUmlPath").Value;
svgManager = exporter;
}

public Task StartAsync(CancellationToken cancellationToken)
{
logger.LogInformation("GeneratePlantUml is starting.");
_ = ProcessFiles();
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
logger.LogInformation("GeneratePlantUml is stopping.");
lifetime.StopApplication();
return Task.CompletedTask;
}

private async Task ProcessFiles()
{
var lookupTable = Config.ReadConfig("Config.yaml");

// Cleanup
if (Directory.Exists(targetFolder))
{
Directory.Delete(targetFolder, true);
}
Directory.CreateDirectory(targetFolder);

File.Copy(Path.Combine(sourceFolder, "AzureRaw.puml"), Path.Combine(targetFolder, "AzureRaw.puml"));
File.Copy(Path.Combine(sourceFolder, "AzureCommon.puml"), Path.Combine(targetFolder, "AzureCommon.puml"));
File.Copy(Path.Combine(sourceFolder, "AzureC4Integration.puml"), Path.Combine(targetFolder, "AzureC4Integration.puml"));
File.Copy(Path.Combine(sourceFolder, "AzureSimplified.puml"), Path.Combine(targetFolder, "AzureSimplified.puml"));

foreach (var service in lookupTable)
{
await ProcessService(service);
}

foreach (var category in lookupTable.Select(_ => _.Category).Distinct())
{
var categoryDirectoryPath = Path.Combine(targetFolder, category!);
var catAllFilePath = Path.Combine(categoryDirectoryPath, "all.puml");
CombineMultipleFilesIntoSingleFile(categoryDirectoryPath, "*.puml", catAllFilePath);
}

await VSCodeSnippets.GenerateSnippets(targetFolder);
await MarkdownTable.GenerateTable(targetFolder);
await this.StopAsync(new System.Threading.CancellationToken());
}

async Task ProcessService(ConfigLookupEntry service)
{
logger.LogInformation($"Processing {service.ServiceSource}");

// NOTE: All icons as colored as supplied
var monochromExists = false;
var coloredExists = false;
var coloredSourceFilePath = GetSourceFilePath(service.ServiceSource!, true);
coloredExists = !string.IsNullOrEmpty(coloredSourceFilePath);

if (!coloredExists && !monochromExists)
{
logger.LogWarning($"Error: Missing {service.ServiceSource} color or mono");
return;
}

var categoryDirectoryPath = Path.Combine(targetFolder, service.Category!);
Directory.CreateDirectory(categoryDirectoryPath);

try
{
if (coloredExists)
{

await svgManager.ResizeAndCopy(coloredSourceFilePath, Path.Combine(categoryDirectoryPath, service.ServiceTarget + ".svg"), targetImageHeight);
await svgManager.ExportToPng(Path.Combine(categoryDirectoryPath, service.ServiceTarget + ".svg"), Path.Combine(categoryDirectoryPath, service.ServiceTarget + ".png"), targetImageHeight);
}
else
{
logger.LogWarning($"Missing SVG file for: {service.ServiceSource}. Please add the file or remove the entry from Config.yaml ");
}

var monochromSvgFilePath = Path.Combine(categoryDirectoryPath, service.ServiceTarget + "(m).svg");

// This should never be called if we assume only colored SVGs are provided on input.
if (monochromExists)
{
await svgManager.ResizeAndCopy(Path.Combine(categoryDirectoryPath, service.ServiceTarget + ".svg"), monochromSvgFilePath, targetImageHeight);
}
else
{
await svgManager.ResizeAndCopy(Path.Combine(categoryDirectoryPath, service.ServiceTarget + ".svg"), monochromSvgFilePath, targetImageHeight);
await svgManager.ExportToMonochrome(monochromSvgFilePath, monochromSvgFilePath, azureColor);
}

var monochromPngFilePath = Path.Combine(categoryDirectoryPath, service.ServiceTarget + "(m).png");
// First generation with background needed for PUML sprite generation
await svgManager.ExportToPng(monochromSvgFilePath, monochromPngFilePath, targetImageHeight, omitBackground: false);
ConvertToPuml(monochromPngFilePath, service.ServiceTarget + ".puml");

// Second generation without background needed other usages
await svgManager.ExportToPng(monochromSvgFilePath, monochromPngFilePath, targetImageHeight, omitBackground: true);
}
catch (Exception ex)
{
logger.LogError(ex.Message);
return;
}

}

void CombineMultipleFilesIntoSingleFile(string inputDirectoryPath, string inputFileNamePattern, string outputFilePath)
{
string[] inputFilePaths = Directory.GetFiles(inputDirectoryPath, inputFileNamePattern, SearchOption.AllDirectories);
using (var outputStream = File.Create(outputFilePath))
{
foreach (var inputFilePath in inputFilePaths)
{
using (var inputStream = File.OpenRead(inputFilePath))
{
inputStream.CopyTo(outputStream);
byte[] newline = Encoding.ASCII.GetBytes(Environment.NewLine);
outputStream.Write(newline, 0, newline.Length);
}
}
}
}

string GetSourceFilePath(string sourceFileName, bool color = true)
{
var patterns = new List<string> {
"*-icon-service-{0}.svg",
"{0}_COLOR.svg",
"{0}.svg"
};

foreach (var p in patterns)
{
var x = string.Format(p, sourceFileName);
if (x.Contains("-") || x.Contains(" "))
{
// Original files have hyphen not space so assume that based on pattern
x = x.Replace(" ", "-");
}
var files = Directory.GetFiles(originalSourceFolder, x, new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = true });

if (files.Length == 0)
{
files = Directory.GetFiles(manualSourceFolder, x, new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = true });
}

if (files.Length >= 1)
{
if (files.Length > 1)
{
var matches = String.Join(",", files);
logger.LogWarning($"Warning: File found in multiple locations {sourceFileName}: {matches}");
}
return files[0];
}
}

return string.Empty; // no result
}

string ConvertToPuml(string pngPath, string pumlFileName)
{
var format = "16z";
var entityName = Path.GetFileNameWithoutExtension(pumlFileName);
var pumlPath = Path.Combine(Directory.GetParent(pngPath)!.FullName, pumlFileName);
var processInfo = new ProcessStartInfo();

if (OperatingSystem.IsMacOS())
{
processInfo.FileName = "/bin/zsh";
// processInfo.FileName = "java";
string commandArgs = $"-c \"java -Djava.awt.headless=true -jar {plantUmlPath} -encodesprite {format} '{pngPath}'\"";
processInfo.Arguments = commandArgs;
// processInfo.Arguments = $"-Djava.awt.headless=true -jar {plantUmlPath} -encodesprite {format} {pngPath}";
}
if (OperatingSystem.IsWindows())
{
processInfo.FileName = "java";
processInfo.Arguments = $"-jar {plantUmlPath} -encodesprite {format} \"{pngPath}\"";
}
if (OperatingSystem.IsLinux())
{
processInfo.FileName = "java";
processInfo.Arguments = $"-jar {plantUmlPath} -encodesprite {format} {pngPath}";
}

processInfo.RedirectStandardOutput = true;
processInfo.UseShellExecute = false;
processInfo.CreateNoWindow = true;

var pumlContent = new StringBuilder();
using (var process = Process.Start(processInfo))
{
process!.WaitForExit();
pumlContent.Append(process.StandardOutput.ReadToEnd());
}

pumlContent.AppendLine($"AzureEntityColoring({entityName})");
pumlContent.AppendLine($"!define {entityName}(e_alias, e_label, e_techn) AzureEntity(e_alias, e_label, e_techn, AZURE_SYMBOL_COLOR, {entityName}, {entityName})");
pumlContent.AppendLine($"!define {entityName}(e_alias, e_label, e_techn, e_descr) AzureEntity(e_alias, e_label, e_techn, e_descr, AZURE_SYMBOL_COLOR, {entityName}, {entityName})");

File.WriteAllText(pumlPath, pumlContent.ToString());
return pumlPath;
}

}
21 changes: 21 additions & 0 deletions scripts/GeneratePuml.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
<PackageReference Include="YamlDotNet" Version="11.2.1" />
<PackageReference Include="Microsoft.Playwright" Version="1.21.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

</Project>
17 changes: 17 additions & 0 deletions scripts/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
public static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<GeneratePlantuml>();
services.AddSingleton<IImageManager, SvgManager>();
})
.Build()
.RunAsync();
}
}
Loading

0 comments on commit e38467c

Please sign in to comment.