From 6cf009e1feb864b9072fb8b214fbf83d1ed25285 Mon Sep 17 00:00:00 2001 From: Andrei Hava Date: Wed, 11 Mar 2026 18:11:39 +0200 Subject: [PATCH] merge configs --- CHANGELOG.md | 7 +++ Common.Build.Generator/buildConfig.json | 7 --- Common.Build/Config/ProjectConfig.cs | 7 ++- Common.Build/Config/SolutionConfig.cs | 4 +- Common.Build/Core/BuildContext.cs | 14 ++--- Common.Build/Core/PathHandling.cs | 4 +- Common.Build/Tasks/ArchiveTask.cs | 11 +++- Common.Build/Tasks/SubstituteTask.cs | 8 ++- Common.Build/buildConfig.json | 6 -- buildConfig.json | 21 ++++++- schemas/config.schema.json | 79 +++++++++++++++++++++++++ schemas/project.schema.json | 37 ------------ schemas/solution.schema.json | 30 ---------- 13 files changed, 131 insertions(+), 104 deletions(-) delete mode 100644 Common.Build.Generator/buildConfig.json delete mode 100644 Common.Build/buildConfig.json create mode 100644 schemas/config.schema.json delete mode 100644 schemas/project.schema.json delete mode 100644 schemas/solution.schema.json diff --git a/CHANGELOG.md b/CHANGELOG.md index cbb4e28..59c4f1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.7.0 +**Features** +- Added the configuration file name as an argument +- Merged the project and solution configuration files +- Separated archive naming from project names +- Added ability to add arbitrary substitutions + ## 0.6.0 **Other** - Upgraded to .NET 10 diff --git a/Common.Build.Generator/buildConfig.json b/Common.Build.Generator/buildConfig.json deleted file mode 100644 index e49377b..0000000 --- a/Common.Build.Generator/buildConfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "../schemas/project.schema.json", - "name": "Generator", - "substitute": [ - "Common.Build.Generator.csproj" - ] -} diff --git a/Common.Build/Config/ProjectConfig.cs b/Common.Build/Config/ProjectConfig.cs index d127492..90262b3 100644 --- a/Common.Build/Config/ProjectConfig.cs +++ b/Common.Build/Config/ProjectConfig.cs @@ -5,7 +5,8 @@ namespace Common.Build.Config; [UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.Members)] public class ProjectConfig { - public required string? Name { get; init; } - public required string? OutputSubdir { get; init; } - public required List Substitute { get; init; } + public required string Name { get; init; } + public required string? ArchiveSuffix { get; init; } + public required string? OutputSubdirectory { get; init; } + public required List SubstitutionTargets { get; init; } } diff --git a/Common.Build/Config/SolutionConfig.cs b/Common.Build/Config/SolutionConfig.cs index 16911f0..436d88d 100644 --- a/Common.Build/Config/SolutionConfig.cs +++ b/Common.Build/Config/SolutionConfig.cs @@ -5,6 +5,8 @@ namespace Common.Build.Config; [UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.Members)] public class SolutionConfig { - public required string Name { get; init; } + public required string? ArchiveName { get; init; } public required string? DefaultProject { get; init; } + public required List Projects { get; init; } + public required Dictionary? Substitutions { get; init; } } diff --git a/Common.Build/Core/BuildContext.cs b/Common.Build/Core/BuildContext.cs index d02a6d5..495a374 100644 --- a/Common.Build/Core/BuildContext.cs +++ b/Common.Build/Core/BuildContext.cs @@ -17,12 +17,11 @@ public class BuildContext : FrostingContext public BuildContext(ICakeContext context) : base(context) { // General + var configFile = context.Argument("general-config", "buildConfig.json"); var project = context.Argument("general-project", null); var profile = context.Argument("general-profile", "Release"); var version = context.Argument("general-version", "12.34.56"); var skipSubstitution = context.Argument("general-skipSubstitution", false); - var solutionConfigFile = context.Argument("config-solution", "buildConfig.json"); - var projectConfigFile = context.Argument("config-project", "buildConfig.json"); // Internal config { @@ -38,7 +37,7 @@ public BuildContext(ICakeContext context) : base(context) // Solution config { - SolutionConfig = LoadConfig(context, Path.Combine("..", solutionConfigFile)); + SolutionConfig = LoadConfig(context, Path.Combine("..", configFile)); } // Project picking @@ -47,7 +46,7 @@ public BuildContext(ICakeContext context) : base(context) { if (SolutionConfig.DefaultProject is null) { - throw new InvalidOperationException("No project specified as an argument and no default project specified in the solution config"); + throw new InvalidOperationException("No project specified as an argument and no default project specified in the build config"); } InternalConfig.Project = SolutionConfig.DefaultProject; @@ -57,12 +56,7 @@ public BuildContext(ICakeContext context) : base(context) InternalConfig.Project = project; } - InternalConfig.ProjectFilePath = Path.Combine("..", InternalConfig.Project, $"{InternalConfig.Project}.csproj"); - } - - // Project config - { - ProjectConfig = LoadConfig(context, Path.Combine("..", InternalConfig.Project, projectConfigFile)); + ProjectConfig = SolutionConfig.Projects.First(projectConfig => projectConfig.Name == InternalConfig.Project); } } diff --git a/Common.Build/Core/PathHandling.cs b/Common.Build/Core/PathHandling.cs index 0ea1a54..612cf71 100644 --- a/Common.Build/Core/PathHandling.cs +++ b/Common.Build/Core/PathHandling.cs @@ -8,9 +8,9 @@ public static string InputPath(BuildContext context, string? path = null) { var inputPath = Path.Combine("..", context.InternalConfig.Project, "bin", context.InternalConfig.Profile); - if (!string.IsNullOrWhiteSpace(context.ProjectConfig.OutputSubdir)) + if (!string.IsNullOrWhiteSpace(context.ProjectConfig.OutputSubdirectory)) { - inputPath = Path.Combine(inputPath, context.ProjectConfig.OutputSubdir); + inputPath = Path.Combine(inputPath, context.ProjectConfig.OutputSubdirectory); } inputPath = Path.Combine(inputPath, "publish"); diff --git a/Common.Build/Tasks/ArchiveTask.cs b/Common.Build/Tasks/ArchiveTask.cs index 8379e58..96237b3 100644 --- a/Common.Build/Tasks/ArchiveTask.cs +++ b/Common.Build/Tasks/ArchiveTask.cs @@ -11,11 +11,16 @@ public class ArchiveTask : FrostingTask { public override void Run(BuildContext context) { - var archiveName = new StringBuilder(context.SolutionConfig.Name.ToLowerInvariant()); - if (!string.IsNullOrWhiteSpace(context.ProjectConfig.Name)) + if (string.IsNullOrWhiteSpace(context.SolutionConfig.ArchiveName)) + { + throw new InvalidOperationException("Archival task invoked without specifying an archive name in the build config"); + } + + var archiveName = new StringBuilder(context.SolutionConfig.ArchiveName); + if (!string.IsNullOrWhiteSpace(context.ProjectConfig.ArchiveSuffix)) { archiveName.Append('_'); - archiveName.Append(context.ProjectConfig.Name.ToLowerInvariant()); + archiveName.Append(context.ProjectConfig.ArchiveSuffix); } archiveName.Append('_'); diff --git a/Common.Build/Tasks/SubstituteTask.cs b/Common.Build/Tasks/SubstituteTask.cs index 005b63b..7f70475 100644 --- a/Common.Build/Tasks/SubstituteTask.cs +++ b/Common.Build/Tasks/SubstituteTask.cs @@ -13,9 +13,9 @@ public class SubstituteTask : FrostingTask public override void Run(BuildContext context) { - foreach (var substitute in context.ProjectConfig.Substitute) + foreach (var substitutionTarget in context.ProjectConfig.SubstitutionTargets) { - var path = Path.Combine("..", context.InternalConfig.Project, substitute); + var path = Path.Combine("..", context.InternalConfig.Project, substitutionTarget); if (!File.Exists(path)) { throw new ApplicationException($"File for substitution \"{path}\" does not exist"); @@ -24,6 +24,10 @@ public override void Run(BuildContext context) var contents = File.ReadAllText(path); contents = contents.Replace(VersionPlaceholder, context.InternalConfig.Version); + foreach (var substitution in context.SolutionConfig.Substitutions ?? []) + { + contents = contents.Replace(substitution.Key, substitution.Value); + } File.WriteAllText(path, contents); } diff --git a/Common.Build/buildConfig.json b/Common.Build/buildConfig.json deleted file mode 100644 index 5632803..0000000 --- a/Common.Build/buildConfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "../schemas/project.schema.json", - "substitute": [ - "Common.Build.csproj" - ] -} diff --git a/buildConfig.json b/buildConfig.json index 451d73a..2b05eec 100644 --- a/buildConfig.json +++ b/buildConfig.json @@ -1,5 +1,20 @@ { - "$schema": "schemas/solution.schema.json", - "name": "CommonBuild", - "defaultProject": "Common.Build" + "$schema": "schemas/config.schema.json", + "archiveName": "commonbuild", + "defaultProject": "Common.Build", + "projects": [ + { + "name": "Common.Build", + "substitutionTargets": [ + "Common.Build.csproj" + ] + }, + { + "name": "Common.Build.Generator", + "archiveSuffix": "generator", + "substitutionTargets": [ + "Common.Build.Generator.csproj" + ] + } + ] } diff --git a/schemas/config.schema.json b/schemas/config.schema.json new file mode 100644 index 0000000..bcab839 --- /dev/null +++ b/schemas/config.schema.json @@ -0,0 +1,79 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "$id": "https://raw.githubusercontent.com/devpikachu/Common.Build/refs/heads/main/schemas/config.schema.json", + "title": "Configuration", + "description": "Build configuration", + "type": "object", + "required": [ + "projects" + ], + "properties": { + "$schema": { + "type": "string" + }, + "archiveName": { + "type": "string", + "description": "The name of the archive emitted by the archival task.", + "minLength": 1, + "pattern": "^[a-zA-Z0-9]+$" + }, + "defaultProject": { + "type": [ + "string", + "null" + ], + "description": "The default project to use when none is specified.", + "minLength": 1, + "pattern": "^[a-zA-Z0-9\\.]+$" + }, + "projects": { + "type": "array", + "description": "The list of projects that can be built.", + "items": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "The project name. Must match the subdirectory and csproj file name exactly.", + "minLength": 1, + "pattern": "^[a-zA-Z0-9\\.]+$" + }, + "archiveSuffix": { + "type": "string", + "description": "The suffix to append to the archive name emitted by the archival task.", + "minLength": 1, + "pattern": "^[a-zA-Z0-9]+$" + }, + "outputSubdirectory": { + "type": [ + "string", + "null" + ], + "description": "Used by path handling, primarily by the archival task. Specify if the files to be archived are in a subdirectory of the output.", + "minLength": 1 + }, + "substitutionTargets": { + "type": "array", + "description": "A list of relative file paths to perform substitution on.", + "items": { + "type": "string", + "minLength": 1 + } + } + }, + "additionalProperties": false + } + }, + "substitutions": { + "type": "object", + "description": "Key-value pairs of substitution to be performed, in addition to the built-in ones.", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false +} diff --git a/schemas/project.schema.json b/schemas/project.schema.json deleted file mode 100644 index a72bf74..0000000 --- a/schemas/project.schema.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft-07/schema", - "$id": "https://git.omni.ms/vintage-story-mods/common-build/raw/branch/main/schemas/project.schema.json", - "title": "Project Configuration", - "description": "Project-level build configuration", - "type": "object", - "required": [ - "substitute" - ], - "properties": { - "name": { - "type": [ - "string", - "null" - ], - "description": "The name of the project", - "minLength": 1, - "pattern": "^[a-zA-Z0-9]+$" - }, - "outputSubdir": { - "type": [ - "string", - "null" - ], - "description": "The subdirectory the project is built into, used to flatten archives", - "minLength": 1 - }, - "substitute": { - "type": "array", - "description": "The list of relative paths pointing to files to perform variable substitutions in", - "items": { - "type": "string", - "minLength": 1 - } - } - } -} diff --git a/schemas/solution.schema.json b/schemas/solution.schema.json deleted file mode 100644 index 68d8b94..0000000 --- a/schemas/solution.schema.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft-07/schema", - "$id": "https://git.omni.ms/vintage-story-mods/common-build/raw/branch/main/schema/solution.schema.json", - "title": "Solution Configuration", - "description": "Solution-level build configuration", - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": [ - "string", - "null" - ], - "description": "The name of the overall project", - "minLength": 1, - "pattern": "^[a-zA-Z0-9]+$" - }, - "defaultProject": { - "type": [ - "string", - "null" - ], - "description": "The default project to use when none is specified", - "minLength": 1, - "pattern": "^[a-zA-Z0-9\\.]+$" - } - } -}