aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-09-06 20:50:06 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-09-06 20:50:06 -0400
commit7f1482c5d77b1b5f7e369ade925d2351d7623fa1 (patch)
treec99a0c8a0137e940492892977ef1e4f6f42b6d52 /src
parent79d824cfb0e0cc9ff4fab0e0c546a83c0edaae1c (diff)
cleanup and add fluent-ftp as an publishing location
Diffstat (limited to 'src')
-rw-r--r--src/BuildFailedException.cs16
-rw-r--r--src/BuildPipeline.cs3
-rw-r--r--src/BuildStepFailedException.cs20
-rw-r--r--src/Commands/BaseCommand.cs14
-rw-r--r--src/Commands/PublishCommand.cs97
-rw-r--r--src/Constants/Utils.cs7
-rw-r--r--src/Extensions/BuildExtensions.cs2
-rw-r--r--src/Extensions/ProjectExtensions.cs16
-rw-r--r--src/MinioUploadManager.cs60
-rw-r--r--src/Model/IUploadManager.cs6
-rw-r--r--src/Publishing/BuildPublisher.cs (renamed from src/BuildPublisher.cs)26
-rw-r--r--src/Publishing/FtpUploadManager.cs98
-rw-r--r--src/Publishing/GpgSigner.cs (renamed from src/GpgSigner.cs)8
-rw-r--r--src/Publishing/MinioUploadManager.cs43
-rw-r--r--src/Publishing/SleetFeedManager.cs (renamed from src/SleetFeedManager.cs)7
-rw-r--r--src/TaskFile.cs18
-rw-r--r--src/vnbuild.csproj11
17 files changed, 313 insertions, 139 deletions
diff --git a/src/BuildFailedException.cs b/src/BuildFailedException.cs
new file mode 100644
index 0000000..7f8f695
--- /dev/null
+++ b/src/BuildFailedException.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace VNLib.Tools.Build.Executor
+{
+ internal class BuildFailedException : Exception
+ {
+ public BuildFailedException()
+ { }
+
+ public BuildFailedException(string? message) : base(message)
+ { }
+
+ public BuildFailedException(string? message, Exception? innerException) : base(message, innerException)
+ { }
+ }
+} \ No newline at end of file
diff --git a/src/BuildPipeline.cs b/src/BuildPipeline.cs
index 2435566..70f6fd8 100644
--- a/src/BuildPipeline.cs
+++ b/src/BuildPipeline.cs
@@ -11,9 +11,10 @@ using VNLib.Tools.Build.Executor.Model;
using VNLib.Tools.Build.Executor.Modules;
using VNLib.Tools.Build.Executor.Extensions;
using VNLib.Tools.Build.Executor.Constants;
+using VNLib.Tools.Build.Executor.Publishing;
namespace VNLib.Tools.Build.Executor
-{
+{
public sealed class BuildPipeline(Logger Log) : IDisposable
{
diff --git a/src/BuildStepFailedException.cs b/src/BuildStepFailedException.cs
index 0b78bf3..3ba5633 100644
--- a/src/BuildStepFailedException.cs
+++ b/src/BuildStepFailedException.cs
@@ -2,7 +2,7 @@
namespace VNLib.Tools.Build.Executor
{
- sealed class BuildStepFailedException : Exception
+ internal sealed class BuildStepFailedException : BuildFailedException
{
public string? ArtifactName { get; set; }
@@ -13,17 +13,17 @@ namespace VNLib.Tools.Build.Executor
{ }
- public BuildStepFailedException(string? message, Exception? innerException) : base(message, innerException)
+ public BuildStepFailedException(string? message, Exception? innerException)
+ : base(message, innerException)
{ }
- public BuildStepFailedException(string? message, Exception? innerException, string name) : base(message, innerException)
- {
- ArtifactName = name;
- }
+ public BuildStepFailedException(string? message, Exception? innerException, string name)
+ : base(message, innerException)
+ => ArtifactName = name;
- public BuildStepFailedException(string message, string artifactName):base(message)
- {
- this.ArtifactName = artifactName;
- }
+ public BuildStepFailedException(string message, string artifactName) : base(message)
+ => ArtifactName = artifactName;
+
+ public override string Message => $"in: {ArtifactName} msg -> {base.Message}";
}
} \ No newline at end of file
diff --git a/src/Commands/BaseCommand.cs b/src/Commands/BaseCommand.cs
index 6362c22..25dcb0a 100644
--- a/src/Commands/BaseCommand.cs
+++ b/src/Commands/BaseCommand.cs
@@ -21,7 +21,7 @@ namespace VNLib.Tools.Build.Executor.Commands
[CommandOption("force", 'f', Description = "Forces the operation even if steps are required")]
public bool Force { get; set; }
- [CommandOption("modules", 'm', Description = "Only use the specified modules, comma separated list")]
+ [CommandOption("include", 'i', Description = "Only use the specified modules, comma separated list")]
public string? Modules { get; set; }
[CommandOption("exclude", 'x', Description = "Ignores the specified modules, comma separated list")]
@@ -79,11 +79,17 @@ namespace VNLib.Tools.Build.Executor.Commands
}
catch (OperationCanceledException)
{
- console.WithForegroundColor(ConsoleColor.Red, static o => o.Output.WriteLine("Operation cancelled"));
+ console.WithForegroundColor(
+ ConsoleColor.Red,
+ static o => o.Error.WriteLine("Operation cancelled")
+ );
}
- catch(BuildStepFailedException be)
+ catch(BuildFailedException be)
{
- console.WithForegroundColor(ConsoleColor.Red, o => o.Output.WriteLine("FATAL: Build step failed on module {0}, msg -> {1}", be.ArtifactName, be.Message));
+ console.WithForegroundColor(
+ ConsoleColor.Red,
+ o => o.Error.WriteLine("FATAL: Build step failed {0}", be.Message)
+ );
}
}
diff --git a/src/Commands/PublishCommand.cs b/src/Commands/PublishCommand.cs
index 4179f86..33a7329 100644
--- a/src/Commands/PublishCommand.cs
+++ b/src/Commands/PublishCommand.cs
@@ -2,20 +2,25 @@
using System;
using System.Linq;
using System.Threading.Tasks;
+using System.Collections.Generic;
using Typin.Console;
using Typin.Attributes;
using VNLib.Tools.Build.Executor.Model;
using VNLib.Tools.Build.Executor.Constants;
+using VNLib.Tools.Build.Executor.Publishing;
namespace VNLib.Tools.Build.Executor.Commands
{
[Command("publish", Description = "Runs publishig build steps on a completed build")]
public sealed class PublishCommand(BuildPipeline pipeline, ConfigManager bm) : BaseCommand(pipeline, bm)
{
- [CommandOption("upload-path", 'p', Description = "The path to upload the build artifacts")]
- public string? UploadPath { get; set; }
+ [CommandOption("minio", Description = "The path to upload the build artifacts")]
+ public string? MinioPath { get; set; }
+
+ [CommandOption("ftp", Description = "The FTP server address to upload the build artifacts. Enables FTP mode over s3")]
+ public string? FtpServerAddress { get; set; }
[CommandOption("sign", 's', Description = "Enables gpg signing of build artifacts")]
public bool Sign { get; set; } = false;
@@ -35,46 +40,102 @@ namespace VNLib.Tools.Build.Executor.Commands
public override async ValueTask ExecStepsAsync(IConsole console)
{
//Specify custom output dir
- (base.Config.Index as Dirs)!.OutputDir = BuildDirs.GetOrCreateDir(Constants.Config.OUTPUT_DIR, CustomOutDir);
+ (Config.Index as Dirs)!.OutputDir = BuildDirs.GetOrCreateDir(Constants.Config.OUTPUT_DIR, CustomOutDir);
- IUploadManager? uploads = MinioUploadManager.Create(UploadPath);
+ IUploadManager uploads = GetUploadManager(console);
IFeedManager? feed = Feeds.FirstOrDefault();
//Optional gpg signer for signing published artifacts
BuildPublisher pub = new(Config, new GpgSigner(Sign, GpgKey));
- console.WithForegroundColor(ConsoleColor.DarkGreen, static o => o.Output.WriteLine("Publishing modules"));
+ console.WithForegroundColor(
+ ConsoleColor.DarkGreen,
+ static o => o.Output.WriteLine("Publishing modules")
+ );
//Run publish steps
- await pipeline.OnPublishingAsync().ConfigureAwait(false);
+ await pipeline.OnPublishingAsync()
+ .ConfigureAwait(false);
- console.WithForegroundColor(ConsoleColor.DarkGreen, static o => o.Output.WriteLine("Preparing module output for upload"));
+ console.WithForegroundColor(
+ ConsoleColor.DarkGreen,
+ static o => o.Output.WriteLine("Preparing module output for upload")
+ );
//Prepare the output
- await pipeline.PrepareOutputAsync(pub).ConfigureAwait(false);
-
- if(uploads is null)
- {
- console.WithForegroundColor(ConsoleColor.DarkYellow, static o => o.Output.WriteLine("No upload path specified. Skipping upload"));
- console.WithForegroundColor(ConsoleColor.Green, static o => o.Output.WriteLine("Upload build complete"));
- return;
- }
+ await pipeline.PrepareOutputAsync(pub)
+ .ConfigureAwait(false);
//Run upload
- await pipeline.ManualUpload(pub, uploads).ConfigureAwait(false);
+ await pipeline.ManualUpload(pub, uploads)
+ .ConfigureAwait(false);
//Publish feeds
if (feed is not null)
{
- console.WithForegroundColor(ConsoleColor.DarkGreen, static o => o.Output.WriteLine("Uploading feeds..."));
+ console.WithForegroundColor(
+ ConsoleColor.DarkGreen,
+ static o => o.Output.WriteLine("Uploading feeds...")
+ );
//Exec feed upload
await uploads.UploadDirectoryAsync(feed.FeedOutputDir);
}
- console.WithForegroundColor(ConsoleColor.Green, static o => o.Output.WriteLine("Upload build complete"));
+ console.WithForegroundColor(
+ ConsoleColor.Green,
+ static o => o.Output.WriteLine("Upload build complete")
+ );
}
public override IFeedManager[] Feeds => SleetPath is null ? [] : [SleetFeedManager.GetSleetFeed(SleetPath)];
+
+ private MultiUploadManager GetUploadManager(IConsole console)
+ {
+ try
+ {
+ IUploadManager[] uploadMan = [];
+
+ if (!string.IsNullOrWhiteSpace(MinioPath))
+ {
+ console.Output.WriteLine("Creating Minio publisher");
+
+ uploadMan = [MinioUploadManager.Create(MinioPath), ..uploadMan];
+ }
+
+ if (!string.IsNullOrWhiteSpace(FtpServerAddress))
+ {
+ console.Output.WriteLine("Using FTP publisher");
+
+ uploadMan = [FtpUploadManager.Create(FtpServerAddress), .. uploadMan];
+ }
+
+ if(uploadMan.Length == 0)
+ {
+ console.WithForegroundColor(
+ ConsoleColor.DarkYellow,
+ static o => o.Output.WriteLine("No upload manager specified, output will be skipped")
+ );
+ }
+
+ return new MultiUploadManager(uploadMan);
+ }
+ catch(UriFormatException urie)
+ {
+ throw new BuildFailedException("Invalid server address", urie);
+ }
+ }
+
+ private sealed class MultiUploadManager(params IUploadManager[] managers) : IUploadManager
+ {
+ private readonly IUploadManager[] _managers = managers;
+
+ public async Task UploadDirectoryAsync(string path)
+ {
+ IEnumerable<Task> tasks = _managers.Select(m => m.UploadDirectoryAsync(path));
+
+ await Task.WhenAll(tasks);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/Constants/Utils.cs b/src/Constants/Utils.cs
index 6047c35..80e8ceb 100644
--- a/src/Constants/Utils.cs
+++ b/src/Constants/Utils.cs
@@ -20,7 +20,12 @@ namespace VNLib.Tools.Build.Executor.Constants
/// <param name="process">The name of the process to run</param>
/// <param name="args">CLI arguments to pass to the process</param>
/// <returns>The process exit code</returns>
- public static async Task<int> RunProcessAsync(string process, string? workingDir, string[] args, IReadOnlyDictionary<string, string>? env = null)
+ public static async Task<int> RunProcessAsync(
+ string process,
+ string? workingDir,
+ string[] args,
+ IReadOnlyDictionary<string, string>? env = null
+ )
{
//Init new console cancellation token
using ConsoleCancelToken ctToken = new();
diff --git a/src/Extensions/BuildExtensions.cs b/src/Extensions/BuildExtensions.cs
index 24af05e..a7e5931 100644
--- a/src/Extensions/BuildExtensions.cs
+++ b/src/Extensions/BuildExtensions.cs
@@ -103,7 +103,7 @@ namespace VNLib.Tools.Build.Executor.Extensions
SemVersion baseVersion;
//Get latest version tag from git
- Tag? vTag = mod.Repository.Tags.OrderByDescending(p => SemVersion.Parse(p.FriendlyName, style)).FirstOrDefault();
+ Tag? vTag = mod.Repository.Tags.OrderByDescending(p => SemVersion.Parse(p.FriendlyName, style), SemVersion.SortOrderComparer).FirstOrDefault();
//Find the number of commits since the last tag
if (vTag != null)
diff --git a/src/Extensions/ProjectExtensions.cs b/src/Extensions/ProjectExtensions.cs
index a24e6c5..9bb55c1 100644
--- a/src/Extensions/ProjectExtensions.cs
+++ b/src/Extensions/ProjectExtensions.cs
@@ -61,12 +61,14 @@ namespace VNLib.Tools.Build.Executor.Extensions
//realtive file path
outDir = Path.Combine(project.WorkingDir.FullName, outDir);
- return new DirectoryInfo(outDir).EnumerateFiles(config.OutputFileType, SearchOption.TopDirectoryOnly);
- }
- else
- {
- return project.WorkingDir.EnumerateFiles(config.OutputFileType, SearchOption.AllDirectories);
+ if (Directory.Exists(outDir))
+ {
+ return new DirectoryInfo(outDir)
+ .EnumerateFiles(config.OutputFileType, SearchOption.TopDirectoryOnly);
+ }
}
+
+ return project.WorkingDir.EnumerateFiles(config.OutputFileType, SearchOption.AllDirectories);
}
/// <summary>
@@ -122,7 +124,9 @@ namespace VNLib.Tools.Build.Executor.Extensions
public static string GetSafeProjectName(this IProject project)
{
- return project.ProjectName.Replace('/', '-').Replace('\\','-');
+ return project.ProjectName
+ .Replace('/', '-')
+ .Replace('\\','-');
}
}
} \ No newline at end of file
diff --git a/src/MinioUploadManager.cs b/src/MinioUploadManager.cs
deleted file mode 100644
index 8337438..0000000
--- a/src/MinioUploadManager.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Threading.Tasks;
-
-using VNLib.Tools.Build.Executor.Model;
-
-using static VNLib.Tools.Build.Executor.Constants.Utils;
-
-namespace VNLib.Tools.Build.Executor
-{
- internal class MinioUploadManager : IUploadManager
- {
- private readonly string _minioPath;
-
- private MinioUploadManager(string minioPath)
- {
- _minioPath = minioPath;
- }
-
- public Task CleanAllAsync(string path)
- {
- throw new System.NotImplementedException();
- }
-
- public Task DeleteFileAsync(string filePath)
- {
- throw new System.NotImplementedException();
- }
-
- public async Task UploadDirectoryAsync(string path)
- {
- //Recursivley copy all files in the working directory
- string[] args =
- {
- "cp",
- "--recursive",
- ".",
- _minioPath
- };
-
- //Set working dir to the supplied dir path, and run the command
- int result = await RunProcessAsync("mc", path, args);
-
- if(result != 0)
- {
- throw new BuildStepFailedException($"Failed to upload directory {path} with status code {result:x}");
- }
- }
-
- public Task UploadFileAsync(string filePath)
- {
- throw new System.NotImplementedException();
- }
-
- [return:NotNullIfNotNull(nameof(uploadPath))]
- public static IUploadManager? Create(string? uploadPath)
- {
- return string.IsNullOrWhiteSpace(uploadPath) ? null : new MinioUploadManager(uploadPath);
- }
- }
-} \ No newline at end of file
diff --git a/src/Model/IUploadManager.cs b/src/Model/IUploadManager.cs
index 01d7081..a132af7 100644
--- a/src/Model/IUploadManager.cs
+++ b/src/Model/IUploadManager.cs
@@ -4,12 +4,6 @@ namespace VNLib.Tools.Build.Executor.Model
{
public interface IUploadManager
{
- Task CleanAllAsync(string path);
-
- Task DeleteFileAsync(string filePath);
-
Task UploadDirectoryAsync(string path);
-
- Task UploadFileAsync(string filePath);
}
} \ No newline at end of file
diff --git a/src/BuildPublisher.cs b/src/Publishing/BuildPublisher.cs
index a2dc2bf..67807d5 100644
--- a/src/BuildPublisher.cs
+++ b/src/Publishing/BuildPublisher.cs
@@ -16,7 +16,7 @@ using VNLib.Tools.Build.Executor.Extensions;
using VNLib.Tools.Build.Executor.Projects;
using static VNLib.Tools.Build.Executor.Constants.Config;
-namespace VNLib.Tools.Build.Executor
+namespace VNLib.Tools.Build.Executor.Publishing
{
public sealed class BuildPublisher(BuildConfig config, GpgSigner signer)
@@ -159,9 +159,9 @@ namespace VNLib.Tools.Build.Executor
//Build project array
writer.WriteStartArray("versions");
-
+
//Write all git hashes from head back to the first commit
- foreach(Commit commit in mod.Repository.Commits)
+ foreach (Commit commit in mod.Repository.Commits)
{
writer.WriteStringValue(commit.Sha);
}
@@ -172,7 +172,7 @@ namespace VNLib.Tools.Build.Executor
writer.WriteStartArray("releases");
//Write all git tags
- foreach(Tag tag in mod.Repository.Tags.OrderByDescending(static p => p.FriendlyName))
+ foreach (Tag tag in mod.Repository.Tags.OrderByDescending(static p => p.FriendlyName))
{
writer.WriteStartObject();
@@ -230,7 +230,10 @@ namespace VNLib.Tools.Build.Executor
await mod.FileManager.WriteFileAsync(ModuleFileType.GitHistory, ms.ToArray());
- await mod.FileManager.WriteFileAsync(ModuleFileType.LatestHash, Encoding.UTF8.GetBytes(mod.Repository.Head.Tip.Sha));
+ await mod.FileManager.WriteFileAsync(
+ ModuleFileType.LatestHash,
+ Encoding.UTF8.GetBytes(mod.Repository.Head.Tip.Sha)
+ );
}
/*
@@ -263,9 +266,9 @@ namespace VNLib.Tools.Build.Executor
);
//Sign synchronously
- foreach(FileInfo artifact in artifacts)
+ foreach (FileInfo artifact in artifacts)
{
- await signer.SignFileAsync(artifact);
+ await signer.SignFileAsync(artifact);
}
}
}
@@ -297,7 +300,7 @@ namespace VNLib.Tools.Build.Executor
//Write tag history for current repo
writer.WriteStartArray("tags");
-
+
foreach (Tag tag in repo.Tags)
{
//clamp message length and ellipsis if too long
@@ -312,7 +315,7 @@ namespace VNLib.Tools.Build.Executor
writer.WriteString("sha", tag.Target.Sha);
writer.WriteString("message", message);
writer.WriteString("author", tag.Annotation?.Tagger.Name);
- writer.WriteString("date", (tag.Annotation?.Tagger.When ?? default));
+ writer.WriteString("date", tag.Annotation?.Tagger.When ?? default);
writer.WriteEndObject();
}
@@ -387,7 +390,8 @@ namespace VNLib.Tools.Build.Executor
private IEnumerable<FileInfo> GetProjOutputFiles(IModuleFileManager man, IProject project)
{
- return man.GetArtifactOutputDir(project).EnumerateFiles("*.*", SearchOption.TopDirectoryOnly)
+ return man.GetArtifactOutputDir(project)
+ .EnumerateFiles("*.*", SearchOption.TopDirectoryOnly)
.Where(p => p.Extension != $".{config.HashFuncName}");
}
@@ -403,7 +407,7 @@ namespace VNLib.Tools.Build.Executor
string? archiveFile = Directory.EnumerateFiles(mod.Repository.Info.WorkingDirectory, config.SourceArchiveName, SearchOption.TopDirectoryOnly).FirstOrDefault();
//If archive is null ignore and continue
- if(string.IsNullOrWhiteSpace(archiveFile))
+ if (string.IsNullOrWhiteSpace(archiveFile))
{
Log.Information("No archive file found for module {mod}", mod.ModuleName);
return null;
diff --git a/src/Publishing/FtpUploadManager.cs b/src/Publishing/FtpUploadManager.cs
new file mode 100644
index 0000000..a955bb8
--- /dev/null
+++ b/src/Publishing/FtpUploadManager.cs
@@ -0,0 +1,98 @@
+using System;
+using System.IO;
+
+using FluentFTP;
+
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+using VNLib.Tools.Build.Executor.Model;
+using VNLib.Tools.Build.Executor.Constants;
+
+namespace VNLib.Tools.Build.Executor.Publishing
+{
+ internal sealed class FtpUploadManager(AsyncFtpClient client, string remotePath) : IUploadManager
+ {
+ public async Task UploadDirectoryAsync(string path)
+ {
+ path = Directory.GetParent(path)!.FullName;
+
+ await client.AutoConnect();
+
+ var res = await client.UploadDirectory(
+ localFolder: path,
+ remoteFolder: remotePath,
+ FtpFolderSyncMode.Update,
+ FtpRemoteExists.Overwrite,
+ FtpVerify.Throw | FtpVerify.Retry
+ );
+
+ foreach(FtpResult fileResult in res)
+ {
+ switch (fileResult.ToStatus())
+ {
+ case FtpStatus.Success:
+ Config.Log.Information(
+ "Uploaded {size} bytes, {0} -> {1}",
+ fileResult.Size,
+ fileResult.LocalPath,
+ fileResult.RemotePath
+ );
+ break;
+
+ case FtpStatus.Skipped:
+ Config.Log.Information("Skipped {0} -> {1}", fileResult.LocalPath, fileResult.RemotePath);
+ break;
+
+ case FtpStatus.Failed:
+ Config.Log.Warning(
+ "Failed to upload {0}, reason: {exp}",
+ fileResult.LocalPath,
+ fileResult.Exception?.Message
+ );
+ break;
+ }
+ }
+ }
+
+ [return: NotNullIfNotNull(nameof(serverAddress))]
+ public static IUploadManager? Create(string? serverAddress)
+ {
+ if(string.IsNullOrWhiteSpace(serverAddress))
+ {
+ return null;
+ }
+
+ //Convert to uri, this may throw but this is currently the best way to validate the address
+ Uri serverUri = new(serverAddress);
+
+ //Initlaize the client
+ AsyncFtpClient client = new()
+ {
+ Host = serverUri.Host,
+ Port = serverUri.Port,
+
+
+ Config = new()
+ {
+ LogToConsole = Config.Log.IsEnabled(Serilog.Events.LogEventLevel.Verbose),
+
+ //Disable senstive logging in case running in automated CI pipelines where logs may be published
+ LogUserName = false,
+ LogPassword = false,
+ //EncryptionMode = FtpEncryptionMode.Auto,
+ RetryAttempts = 3,
+ },
+
+ Credentials = new()
+ {
+ //Pull credentials from the environment instead of command line
+ UserName = Environment.GetEnvironmentVariable("FTP_USERNAME"),
+ Password = Environment.GetEnvironmentVariable("FTP_PASSWORD")
+ },
+ };
+
+ return new FtpUploadManager(client, serverUri.LocalPath);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/GpgSigner.cs b/src/Publishing/GpgSigner.cs
index 76943f9..3ed216a 100644
--- a/src/GpgSigner.cs
+++ b/src/Publishing/GpgSigner.cs
@@ -5,7 +5,7 @@ using System.Collections.Generic;
using VNLib.Tools.Build.Executor.Constants;
-namespace VNLib.Tools.Build.Executor
+namespace VNLib.Tools.Build.Executor.Publishing
{
public sealed class GpgSigner(bool enabled, string? defaultKey)
{
@@ -18,7 +18,9 @@ namespace VNLib.Tools.Build.Executor
return;
}
- List<string> args = [ "--detach-sign" ];
+ List<string> args = [
+ "--detach-sign"
+ ];
if (!string.IsNullOrWhiteSpace(defaultKey))
{
@@ -45,7 +47,7 @@ namespace VNLib.Tools.Build.Executor
case 0:
break;
default:
- throw new Exception($"Failed to sign file {file.FullName}");
+ throw new BuildFailedException($"Failed to sign file {file.FullName}");
}
}
}
diff --git a/src/Publishing/MinioUploadManager.cs b/src/Publishing/MinioUploadManager.cs
new file mode 100644
index 0000000..502392f
--- /dev/null
+++ b/src/Publishing/MinioUploadManager.cs
@@ -0,0 +1,43 @@
+using System.Threading.Tasks;
+using System.Diagnostics.CodeAnalysis;
+
+using VNLib.Tools.Build.Executor.Model;
+
+using static VNLib.Tools.Build.Executor.Constants.Utils;
+
+namespace VNLib.Tools.Build.Executor.Publishing
+{
+
+ internal sealed class MinioUploadManager : IUploadManager
+ {
+ private readonly string _minioPath;
+
+ private MinioUploadManager(string minioPath) => _minioPath = minioPath;
+
+ public async Task UploadDirectoryAsync(string path)
+ {
+ //Recursivley copy all files in the working directory
+ string[] args =
+ {
+ "cp",
+ "--recursive",
+ ".",
+ _minioPath
+ };
+
+ //Set working dir to the supplied dir path, and run the command
+ int result = await RunProcessAsync("mc", path, args);
+
+ if (result != 0)
+ {
+ throw new BuildFailedException($"Failed to upload directory {path} with status code {result:x}");
+ }
+ }
+
+ [return: NotNullIfNotNull(nameof(uploadPath))]
+ public static IUploadManager? Create(string? uploadPath)
+ {
+ return string.IsNullOrWhiteSpace(uploadPath) ? null : new MinioUploadManager(uploadPath);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/SleetFeedManager.cs b/src/Publishing/SleetFeedManager.cs
index bc77ff1..997dcf2 100644
--- a/src/SleetFeedManager.cs
+++ b/src/Publishing/SleetFeedManager.cs
@@ -2,10 +2,9 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text.Json;
-
using VNLib.Tools.Build.Executor.Model;
-namespace VNLib.Tools.Build.Executor
+namespace VNLib.Tools.Build.Executor.Publishing
{
internal sealed class SleetFeedManager : IFeedManager
{
@@ -35,10 +34,10 @@ namespace VNLib.Tools.Build.Executor
/// <returns>The feed manager if found, null otherwise</returns>
/// <exception cref="FileNotFoundException"></exception>
/// <exception cref="ArgumentException"></exception>
- [return:NotNullIfNotNull(nameof(feedPath))]
+ [return: NotNullIfNotNull(nameof(feedPath))]
public static IFeedManager? GetSleetFeed(string? feedPath)
{
- if(string.IsNullOrWhiteSpace(feedPath))
+ if (string.IsNullOrWhiteSpace(feedPath))
{
return null;
}
diff --git a/src/TaskFile.cs b/src/TaskFile.cs
index 6eef779..e8fa26e 100644
--- a/src/TaskFile.cs
+++ b/src/TaskFile.cs
@@ -56,7 +56,7 @@ namespace VNLib.Tools.Build.Executor
args.Add(GetCommand(command));
//Exec task in the module dir
- int result = await RunProcessAsync(taskFilePath, scope.WorkingDir.FullName, args.ToArray(), vars);
+ int result = await RunProcessAsync(taskFilePath, scope.WorkingDir.FullName, [.. args], vars);
if(throwIfFailed)
{
@@ -68,14 +68,14 @@ namespace VNLib.Tools.Build.Executor
{
return cmd switch
{
- TaskfileComamnd.Clean => "clean",
- TaskfileComamnd.Build => "build",
- TaskfileComamnd.Upload => "upload",
- TaskfileComamnd.Update => "update",
- TaskfileComamnd.PostbuildSuccess => "postbuild_success",
- TaskfileComamnd.PostbuildFailure => "postbuild_failed",
- TaskfileComamnd.Publish => "publish",
- TaskfileComamnd.Test => "test",
+ TaskfileComamnd.Clean => "clean",
+ TaskfileComamnd.Build => "build",
+ TaskfileComamnd.Upload => "upload",
+ TaskfileComamnd.Update => "update",
+ TaskfileComamnd.PostbuildSuccess => "postbuild_success",
+ TaskfileComamnd.PostbuildFailure => "postbuild_failed",
+ TaskfileComamnd.Publish => "publish",
+ TaskfileComamnd.Test => "test",
_ => throw new NotImplementedException()
};
}
diff --git a/src/vnbuild.csproj b/src/vnbuild.csproj
index b3e32df..b506f59 100644
--- a/src/vnbuild.csproj
+++ b/src/vnbuild.csproj
@@ -33,13 +33,14 @@
</ItemGroup>
<ItemGroup>
+ <PackageReference Include="FluentFTP" Version="51.0.0" />
<PackageReference Include="Typin" Version="3.1.0" />
<PackageReference Include="LibGit2Sharp" Version="0.30.0" />
- <PackageReference Include="Microsoft.Build" Version="17.10.0-preview-24081-01" />
- <PackageReference Include="Semver" Version="3.0.0-beta.1" />
- <PackageReference Include="Serilog" Version="4.0.0-dev-02166" />
- <PackageReference Include="Serilog.Sinks.Console" Version="5.1.0-dev-00943" />
- <PackageReference Include="Serilog.Sinks.File" Version="5.0.1-dev-00972" />
+ <PackageReference Include="Microsoft.Build" Version="17.11.4" />
+ <PackageReference Include="Semver" Version="2.3.0" />
+ <PackageReference Include="Serilog" Version="4.0.1" />
+ <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
+ <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
</ItemGroup>
</Project>