diff --git a/.gitignore b/.gitignore index 03b6e2d..1ecb8e3 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ Robust.Cdn/content.db* Robust.Cdn/manifest.db* *.user testData/ +/.vs/** diff --git a/Robust.Cdn/Controllers/ForkPublishController.Multi.cs b/Robust.Cdn/Controllers/ForkPublishController.Multi.cs index 935a9dc..dd49360 100644 --- a/Robust.Cdn/Controllers/ForkPublishController.Multi.cs +++ b/Robust.Cdn/Controllers/ForkPublishController.Multi.cs @@ -45,16 +45,45 @@ public async Task MultiPublishStart( publishManager.AbortMultiPublish(fork, request.Version, tx, commit: false); } - await dbCon.ExecuteAsync(""" - INSERT INTO PublishInProgress (Version, ForkId, StartTime, EngineVersion) - VALUES (@Version, @ForkId, @StartTime, @EngineVersion) + await dbCon.ExecuteAsync( + """ + INSERT INTO PublishInProgress ( + Version, + ForkId, + StartTime, + EngineVersion, + SourceUrl, + SourceCommitId, + SourceBranchName, + EngineSourceUrl, + EngineSourceCommitId, + EngineSourceBranchName + ) + VALUES ( + @Version, + @ForkId, + @StartTime, + @EngineVersion, + @SourceUrl, + @SourceCommitId, + @SourceBranchName, + @EngineSourceUrl, + @EngineSourceCommitId, + @EngineSourceBranchName + ) """, new { request.Version, request.EngineVersion, ForkId = forkId, - StartTime = DateTime.UtcNow + StartTime = DateTime.UtcNow, + request.SourceUrl, + request.SourceCommitId, + request.SourceBranchName, + request.EngineSourceUrl, + request.EngineSourceCommitId, + request.EngineSourceBranchName, }); var versionDir = buildDirectoryManager.GetBuildVersionPath(fork, request.Version); @@ -127,8 +156,9 @@ public async Task MultiPublishFinish( await using var tx = await dbCon.BeginTransactionAsync(cancel); var forkId = dbCon.QuerySingle("SELECT Id FROM Fork WHERE Name = @Name", new { Name = fork }); - var versionMetadata = dbCon.QuerySingleOrDefault(""" - SELECT Version, EngineVersion + var versionMetadata = dbCon.QuerySingleOrDefault( + """ + SELECT Version, EngineVersion, SourceUrl, SourceCommitId, SourceBranchName, EngineSourceUrl, EngineSourceCommitId, EngineSourceBranchName FROM PublishInProgress WHERE Version = @Name AND ForkId = @Fork """, @@ -175,11 +205,10 @@ FROM PublishInProgress return NoContent(); } - public sealed class PublishMultiRequest - { - public required string Version { get; set; } - public required string EngineVersion { get; set; } - } + /// + /// Request for start of multi-step publishing process of a new version. + /// + public sealed class PublishMultiRequest : PublishStartRequestBase; public sealed class PublishFinishRequest { diff --git a/Robust.Cdn/Controllers/ForkPublishController.OneShot.cs b/Robust.Cdn/Controllers/ForkPublishController.OneShot.cs index 75bcf74..dcf61cc 100644 --- a/Robust.Cdn/Controllers/ForkPublishController.OneShot.cs +++ b/Robust.Cdn/Controllers/ForkPublishController.OneShot.cs @@ -1,4 +1,4 @@ -using System.IO.Compression; +using System.IO.Compression; using Microsoft.AspNetCore.Mvc; using Robust.Cdn.Helpers; @@ -51,7 +51,12 @@ public async Task PostPublish( var versionDir = buildDirectoryManager.GetBuildVersionPath(fork, request.Version); - var metadata = new VersionMetadata { Version = request.Version, EngineVersion = request.EngineVersion }; + var metadata = new VersionMetadata( + request.Version, + request.EngineVersion, + new(request.SourceUrl, request.SourceCommitId, request.SourceBranchName), + new(request.EngineSourceUrl, request.EngineSourceCommitId, request.EngineSourceBranchName) + ); try { diff --git a/Robust.Cdn/Controllers/ForkPublishController.cs b/Robust.Cdn/Controllers/ForkPublishController.cs index 17bd747..8ec5ce9 100644 --- a/Robust.Cdn/Controllers/ForkPublishController.cs +++ b/Robust.Cdn/Controllers/ForkPublishController.cs @@ -1,4 +1,4 @@ -using System.IO.Compression; +using System.IO.Compression; using System.Security.Cryptography; using System.Text; using System.Text.Json; @@ -132,7 +132,7 @@ private MemoryStream GenerateBuildJson( logger.LogDebug("Client zip hash is {ZipHash}, manifest hash is {ManifestHash}", hash, manifestHash); - var data = new Dictionary + var data = new Dictionary { { "download", baseUrlManager.MakeBuildInfoUrl($"fork/{{FORK_ID}}/version/{{FORK_VERSION}}/file/{diskFileName}") }, { "version", metadata.Version }, @@ -141,7 +141,13 @@ private MemoryStream GenerateBuildJson( { "engine_version", metadata.EngineVersion }, { "manifest_url", baseUrlManager.MakeBuildInfoUrl("fork/{FORK_ID}/version/{FORK_VERSION}/manifest") }, { "manifest_download_url", baseUrlManager.MakeBuildInfoUrl("fork/{FORK_ID}/version/{FORK_VERSION}/download") }, - { "manifest_hash", manifestHash } + { "manifest_hash", manifestHash }, + { "built_on_source_url", metadata.BuildVersionInfo.SourceUrl }, + { "built_on_commit_id", metadata.BuildVersionInfo.CommitId }, + { "built_on_branch_name", metadata.BuildVersionInfo.BranchName}, + { "built_on_engine_url", metadata.EngineSourceVersionInfo.SourceUrl }, + { "built_on_engine_commit_id", metadata.EngineSourceVersionInfo.CommitId }, + { "built_on_engine_branch_name", metadata.EngineSourceVersionInfo.BranchName }, }; var stream = new MemoryStream(); @@ -290,19 +296,123 @@ private static FileStream CreateTempFile() FileOptions.DeleteOnClose); } - public sealed class PublishRequest + /// + /// Base type with publish start info. + /// + public abstract class PublishStartRequestBase { + /// + /// Human-readable version of the build. This is used to identify the build in the CDN and in the game client. + /// public required string Version { get; set; } + + /// + /// Human-readable version of the engine used to build this version. + /// public required string EngineVersion { get; set; } + + /// + /// URL of the fork repository. Optional, but useful for debugging. + /// + public string? SourceUrl { get; set; } + + /// + /// Commit ID on which version was built. Optional, but useful for debugging. + /// + public string? SourceCommitId { get; set; } + + /// + /// Branch on which version was built. Optional, but useful for debugging. + /// + public string? SourceBranchName { get; set; } + + /// + /// Url for RobustToolbox repository (or its fork), used for this version. Optional, but useful for debugging. + /// + public string? EngineSourceUrl { get; set; } + + /// + /// Branch on which RobustToolbox for this version was built. Optional, but useful for debugging. + /// + public string? EngineSourceBranchName { get; set; } + + /// + /// Commit ID of RobustToolbox, used for this version. Optional, but useful for debugging. + /// + public string? EngineSourceCommitId { get; set; } + } + + /// + /// Request for one-shot publishing of a new version. + /// + /// + public sealed class PublishRequest : PublishStartRequestBase + { + /// + /// Uri for new build artifact. + /// public required string Archive { get; set; } } + /// + /// Build version metadata. + /// private sealed class VersionMetadata { - public required string Version { get; init; } - public required string EngineVersion { get; set; } + public VersionMetadata(string version, string engineVersion, SourceVersionInfo buildVersionInfo, SourceVersionInfo engineSourceVersionInfo) + { + Version = version; + EngineVersion = engineVersion; + BuildVersionInfo = buildVersionInfo; + EngineSourceVersionInfo = engineSourceVersionInfo; + } + + public VersionMetadata( + string version, + string engineVersion, + string? sourceUrl, + string? sourceCommitId, + string? sourceBranchName, + string? engineSourceUrl, + string? engineSourceCommitId, + string? engineSourceBranchName + ) + { + Version = version; + EngineVersion = engineVersion; + BuildVersionInfo = new SourceVersionInfo(sourceUrl, sourceCommitId, sourceBranchName); + EngineSourceVersionInfo = new SourceVersionInfo(engineSourceUrl, engineSourceCommitId, engineSourceBranchName); + } + + /// + /// Human-readable version of the build. This is used to identify the build in the CDN and in the game client. + /// + public string Version { get; } + + /// + /// Human-readable version of the engine used to build this version. + /// + public string EngineVersion { get; } + + /// + /// Version info for sources, used for build. + /// + public SourceVersionInfo BuildVersionInfo { get; } + + /// + /// Version info for sources of engine, used for build. + /// + public SourceVersionInfo EngineSourceVersionInfo { get; } } + /// + /// Detailed info on sources used for building version. + /// + /// URL for repository that holds sources. + /// Commit ID used for building sources. + /// Branch name or tag, used for building sources. + public record SourceVersionInfo(string? SourceUrl, string? CommitId, string? BranchName); + // File cannot start with a dot but otherwise most shit is fair game. [GeneratedRegex(@"[a-zA-Z0-9\-_][a-zA-Z0-9\-_.]*")] private static partial Regex ValidVersionRegexBuilder(); diff --git a/Robust.Cdn/ManifestMigrations/Script0004_AlterPublishInProgress_AddCommitColumns.sql b/Robust.Cdn/ManifestMigrations/Script0004_AlterPublishInProgress_AddCommitColumns.sql new file mode 100644 index 0000000..e5a573c --- /dev/null +++ b/Robust.Cdn/ManifestMigrations/Script0004_AlterPublishInProgress_AddCommitColumns.sql @@ -0,0 +1,7 @@ +-- Add columns that can represent sources used to build version that should be published +ALTER TABLE PublishInProgress ADD COLUMN SourceUrl TEXT NULL; +ALTER TABLE PublishInProgress ADD COLUMN SourceCommitId TEXT NULL; +ALTER TABLE PublishInProgress ADD COLUMN SourceBranchName TEXT NULL; +ALTER TABLE PublishInProgress ADD COLUMN EngineSourceUrl TEXT NULL; +ALTER TABLE PublishInProgress ADD COLUMN EngineSourceCommitId TEXT NULL; +ALTER TABLE PublishInProgress ADD COLUMN EngineSourceBranchName TEXT NULL;