{"id":15430914,"url":"https://github.com/richardsondev/aggregateconfigbuildtask","last_synced_at":"2025-04-09T17:42:34.576Z","repository":{"id":256128732,"uuid":"854362274","full_name":"richardsondev/AggregateConfigBuildTask","owner":"richardsondev","description":"A cross-platform MSBuild task that aggregates and transforms configuration files into more consumable formats.","archived":false,"fork":false,"pushed_at":"2025-04-01T17:06:04.000Z","size":797,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T12:38:25.983Z","etag":null,"topics":["configuration-as-code","msbuild","msbuild-task","msbuild-tasks"],"latest_commit_sha":null,"homepage":"https://docs.richardson.dev/AggregateConfigBuildTask/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/richardsondev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-09T03:08:49.000Z","updated_at":"2025-04-01T17:06:01.000Z","dependencies_parsed_at":"2024-10-20T19:23:40.946Z","dependency_job_id":null,"html_url":"https://github.com/richardsondev/AggregateConfigBuildTask","commit_stats":{"total_commits":27,"total_committers":1,"mean_commits":27.0,"dds":0.0,"last_synced_commit":"7f5a98d4c5b219f5c66a87fb8b9f0d268a104ff1"},"previous_names":["richardsondev/aggregateconfigbuildtask"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardsondev%2FAggregateConfigBuildTask","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardsondev%2FAggregateConfigBuildTask/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardsondev%2FAggregateConfigBuildTask/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardsondev%2FAggregateConfigBuildTask/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/richardsondev","download_url":"https://codeload.github.com/richardsondev/AggregateConfigBuildTask/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248079618,"owners_count":21044350,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration-as-code","msbuild","msbuild-task","msbuild-tasks"],"created_at":"2024-10-01T18:19:32.660Z","updated_at":"2025-04-09T17:42:34.537Z","avatar_url":"https://github.com/richardsondev.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# Aggregate Config Build Task\r\n\r\n[![NuGet Version](https://img.shields.io/nuget/v/AggregateConfigBuildTask)](https://www.nuget.org/packages/AggregateConfigBuildTask) [![GitHub Build Status](https://img.shields.io/github/actions/workflow/status/richardsondev/AggregateConfigBuildTask/build.yml?branch=main\r\n)](https://github.com/richardsondev/AggregateConfigBuildTask/actions/workflows/build.yml?query=branch%3Amain)\r\n\r\n**AggregateConfigBuildTask** is a cross-platform MSBuild task that aggregates and transforms configuration files into more consumable formats like JSON, Azure ARM template parameters, YAML during the build process.\r\n\r\n## Features\r\n\r\n- Merge multiple configuration files into a single output format (JSON, Azure ARM parameters, or YAML).\r\n- Support for injecting custom metadata (e.g., `ResourceGroup`, `Environment`) into the output.\r\n- Optionally include the source file name in each configuration entry.\r\n- Embed output files as resources in the assembly for easy inclusion in your project.\r\n\r\n## Links\r\n\r\n* Documentation: https://docs.richardson.dev/AggregateConfigBuildTask\r\n* NuGet.org: https://www.nuget.org/packages/AggregateConfigBuildTask\r\n* GitHub: https://github.com/richardsondev/AggregateConfigBuildTask\r\n\r\n## Installation\r\n\r\nTo install the `AggregateConfigBuildTask` NuGet package, run the following command:\r\n\r\n```bash\r\ndotnet add package AggregateConfigBuildTask\r\n```\r\n\r\nAlternatively, add the following line to your `.csproj` file:\r\n\r\n```xml\r\n\u003cPackageReference Include=\"AggregateConfigBuildTask\" Version=\"{latest}\" /\u003e\r\n```\r\n\r\n`{latest}` can be found [here](https://www.nuget.org/packages/AggregateConfigBuildTask#versions-body-tab).\r\n\r\n## Parameters\r\n\r\n| Parameter | Description | Supported Values | Default |\r\n|----------|----------|----------|----------|\r\n| **OutputFile**\u003cbr\u003e*(Required)* | The file path to write output to. Should include the extension. | | |\r\n| **OutputType**\u003cbr\u003e*(Required)* | Specifies the format of the output file. | `Json`, `Arm`, `Yaml` | |\r\n| **InputDirectory**\u003cbr\u003e*(Required)* | The directory containing the files that need to be aggregated. | | |\r\n| **InputType** | Specifies the format of the input files. Refer to the [File Types](#file-types) table below for the corresponding file extensions that will be searched for. | `Json`, `Arm`, `Yaml` | `Yaml` |\r\n| **AddSourceProperty** | Adds a `source` property to each object in the output, specifying the filename from which the object originated. | `true`, `false` | `false` |\r\n| **AdditionalProperties** | A set of custom top-level properties to include in the final output. Use `ItemGroup` syntax to define key-value pairs. See [below](#additional-properties) for usage details. | | |\r\n| **IsQuietMode** | When true, only warning and error logs are generated by the task, suppressing standard informational output. | `true`, `false` | `false` |\r\n\r\n### File Types\r\n\r\nThe `InputDirectory` will be scanned for files based on the specified `InputType`. The following table lists the file extensions that will be considered for each `InputType`:\r\n\r\n| **InputType** | **Extensions Scanned** |\r\n|---------------|------------------------|\r\n| `Json`        | `.json`                |\r\n| `Arm`         | `.json`                |\r\n| `Yaml`        | `.yml`, `.yaml`        |\r\n\r\n## Usage\r\n\r\n### Basic Example\r\n\r\nIn your `.csproj` file, use the task to aggregate YAML files and output them in a specific format. Here’s an example of aggregating YAML files and generating JSON output:\r\n\r\n```xml\r\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\r\n\r\n  \u003cTarget Name=\"AggregateConfigs\" BeforeTargets=\"PrepareForBuild\"\u003e\r\n    \u003cAggregateConfig \r\n      InputDirectory=\"Configs\"\r\n      OutputFile=\"$(MSBuildProjectDirectory)\\out\\output.json\"\r\n      AddSourceProperty=\"true\"\r\n      InputType=\"Yaml\"\r\n      OutputType=\"Json\" /\u003e\r\n  \u003c/Target\u003e\r\n\r\n\u003c/Project\u003e\r\n```\r\n\r\nIn this example:\r\n- The `Configs` directory contains the YAML files to be aggregated.\r\n- The output will be generated as `out/output.json`.\r\n- The `AddSourceProperty` flag adds the source file name to each configuration entry.\r\n\r\n### ARM Template Parameters Output Example\r\n\r\nYou can also generate Azure ARM template parameters. Here's how to modify the configuration to output in the ARM parameter format:\r\n\r\n```xml\r\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\r\n\r\n  \u003cTarget Name=\"AggregateConfigsForARM\" BeforeTargets=\"PrepareForBuild\"\u003e\r\n    \u003cAggregateConfig \r\n      InputDirectory=\"Configs\"\r\n      OutputFile=\"$(MSBuildProjectDirectory)\\out\\output.parameters.json\"\r\n      OutputType=\"Arm\" /\u003e\r\n  \u003c/Target\u003e\r\n\r\n\u003c/Project\u003e\r\n```\r\n\r\n### YAML Output Example\r\n\r\nYou can also output the aggregated configuration back into YAML format:\r\n\r\n```xml\r\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\r\n\r\n  \u003cTarget Name=\"AggregateConfigsToYAML\" BeforeTargets=\"PrepareForBuild\"\u003e\r\n    \u003cAggregateConfig \r\n      InputDirectory=\"Configs\"\r\n      OutputFile=\"$(MSBuildProjectDirectory)\\out\\output.yaml\"\r\n      OutputType=\"Yaml\" /\u003e\r\n  \u003c/Target\u003e\r\n\r\n\u003c/Project\u003e\r\n```\r\n\r\n### Additional Properties\r\n\r\nAt build time, you can inject additional properties into the top-level of your output configuration as key-value pairs. Conditionals and variables are supported.\r\n\r\nIn this example, two additional properties (`ResourceGroup` and `Environment`) are defined and will be included in the YAML output's top-level structure. This allows for dynamic property injection at build time.\r\n\r\n```xml\r\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\r\n\r\n  \u003cTarget Name=\"AggregateConfigsToYAML\" BeforeTargets=\"PrepareForBuild\"\u003e\r\n    \u003cItemGroup\u003e\r\n      \u003c!-- Define additional properties as key-value pairs --\u003e\r\n      \u003cAdditionalProperty Include=\"ResourceGroup\"\u003e\r\n        \u003cValue\u003eTestRG\u003c/Value\u003e\r\n      \u003c/AdditionalProperty\u003e\r\n      \u003cAdditionalProperty Include=\"Environment\"\u003e\r\n        \u003cValue\u003eProduction\u003c/Value\u003e\r\n      \u003c/AdditionalProperty\u003e\r\n    \u003c/ItemGroup\u003e\r\n\r\n    \u003c!-- Aggregate configuration into a YAML file --\u003e\r\n    \u003cAggregateConfig \r\n      InputDirectory=\"Configs\"\r\n      OutputFile=\"$(MSBuildProjectDirectory)\\out\\output.yaml\"\r\n      OutputType=\"Yaml\"\r\n      AdditionalProperties=\"@(AdditionalProperty)\" /\u003e\r\n  \u003c/Target\u003e\r\n\r\n\u003c/Project\u003e\r\n```\r\n\r\n#### Explanation:\r\n- **Additional Properties:** The `AdditionalProperty` items store key-value pairs (`ResourceGroup=TestRG` and `Environment=Production`). The key is set in the `Include` attribute, and the value is defined in a nested `\u003cValue\u003e` element.\r\n- **ItemGroup:** Groups the additional properties, which will later be referenced in the task as `@(AdditionalProperty)`.\r\n- **AggregateConfig Task:** This task collects the configurations from the `Configs` directory and aggregates them into a YAML output file. The `AdditionalProperties` item group is passed to the task, ensuring that the properties are injected into the top-level of the output.\r\n\r\n### Embedding Output Files as Resources\r\n\r\nYou can embed the output files (such as the generated JSON) as resources in the assembly. This allows them to be accessed from within your code as embedded resources.\r\n\r\n```xml\r\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\r\n\r\n  \u003cTarget Name=\"AggregateConfigs\" BeforeTargets=\"PrepareForBuild\"\u003e\r\n    \u003cAggregateConfig \r\n      InputDirectory=\"Configs\"\r\n      OutputFile=\"$(MSBuildProjectDirectory)\\out\\output.json\"\r\n      OutputType=\"Json\" /\u003e\r\n\r\n    \u003c!-- Embed output.json as a resource in the assembly --\u003e\r\n    \u003cItemGroup\u003e\r\n      \u003cEmbeddedResource Include=\"$(MSBuildProjectDirectory)\\out\\output.json\" /\u003e\r\n    \u003c/ItemGroup\u003e\r\n  \u003c/Target\u003e\r\n\r\n\u003c/Project\u003e\r\n```\r\n\r\nIn this example:\r\n- The generated output file `output.json` is embedded in the resulting assembly as a resource.\r\n- You can access this resource programmatically using the `System.Reflection` API.\r\n\r\n## Example YAML Input\r\n\r\nAssume you have the following YAML files in the `Configs` directory:\r\n\r\n```yaml\r\nresources:\r\n  - id: \"Resource1\"\r\n    type: \"Compute\"\r\n    description: \"Main compute resource\"\r\n```\r\n\r\n```yaml\r\nresources:\r\n  - id: \"Resource2\"\r\n    type: \"Storage\"\r\n    description: \"Storage resource\"\r\n```\r\n\r\n### Output JSON Example\r\n\r\n```json\r\n{\r\n  \"resources\": [\r\n    {\r\n      \"id\": \"Resource1\",\r\n      \"type\": \"Compute\",\r\n      \"description\": \"Main compute resource\",\r\n      \"source\": \"file1\"\r\n    },\r\n    {\r\n      \"id\": \"Resource2\",\r\n      \"type\": \"Storage\",\r\n      \"description\": \"Storage resource\",\r\n      \"source\": \"file2\"\r\n    }\r\n  ],\r\n  \"ResourceGroup\": \"TestRG\",\r\n  \"Environment\": \"Production\"\r\n}\r\n```\r\n\r\n### ARM Parameter Output Example\r\n\r\n```json\r\n{\r\n  \"$schema\": \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\",\r\n  \"contentVersion\": \"1.0.0.0\",\r\n  \"parameters\": {\r\n    \"resources\": {\r\n      \"type\": \"array\",\r\n      \"value\": [\r\n        {\r\n          \"id\": \"Resource1\",\r\n          \"type\": \"Compute\",\r\n          \"description\": \"Main compute resource\",\r\n          \"source\": \"file1\"\r\n        },\r\n        {\r\n          \"id\": \"Resource2\",\r\n          \"type\": \"Storage\",\r\n          \"description\": \"Storage resource\",\r\n          \"source\": \"file2\"\r\n        }\r\n      ]\r\n    },\r\n    \"ResourceGroup\": {\r\n      \"type\": \"string\",\r\n      \"value\": \"TestRG\"\r\n    },\r\n    \"Environment\": {\r\n      \"type\": \"string\",\r\n      \"value\": \"Production\"\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n## Accessing Embedded Resources in C# Assemblies\r\n\r\nEmbedding resources such as configuration files into your assembly allows you to package all necessary data within a single executable or library.\r\n\r\nIn the following example, we'll demonstrate how to read and deserialize an embedded resource at runtime.\r\n\r\n### Embedded resource\r\n\r\nConsider the following YML configuration files that you want to merge and embed into your assembly:\r\n\r\n**configs/global.yml**\r\n```yml\r\nenabled: true\r\n```\r\n\r\n**configs/prod.yml**\r\n```yml\r\nenvironment: Production\r\n```\r\n\r\n### Project file reference\r\n\r\nYour project should contain a reference similar to below:\r\n\r\n**application.csproj**\r\n```xml\r\n\u003cTarget Name=\"AggregateConfigs\" BeforeTargets=\"PrepareForBuild\"\u003e\r\n  \u003cAggregateConfig \r\n    InputDirectory=\"configs\"\r\n    OutputFile=\"out/output.json\"\r\n    OutputType=\"Json\" /\u003e\r\n\r\n  \u003cItemGroup\u003e\r\n    \u003cEmbeddedResource Include=\"out/output.json\" /\u003e\r\n  \u003c/ItemGroup\u003e\r\n\u003c/Target\u003e\r\n```\r\n\r\n### Reading the embedded resource\r\n\r\nTo access and deserialize the embedded JSON resource, use the following method:\r\n\r\n**application.cs**\r\n```csharp\r\nusing System;\r\nusing System.IO;\r\nusing System.Reflection;\r\nusing System.Text.Json;\r\n\r\npublic static T LoadFromEmbeddedResource\u003cT\u003e(string resourceName)\r\n{\r\n    var assembly = Assembly.GetExecutingAssembly();\r\n    using var stream = assembly.GetManifestResourceStream(resourceName)\r\n        ?? throw new FileNotFoundException($\"Resource '{resourceName}' not found in assembly.\");\r\n\r\n    return JsonSerializer.Deserialize\u003cT\u003e(stream, new JsonSerializerOptions\r\n    {\r\n        PropertyNameCaseInsensitive = true\r\n    }) ?? throw new InvalidOperationException(\"Failed to deserialize resource.\");\r\n}\r\n```\r\n\r\n### Defining the Configuration Class\r\n\r\nCreate a class that matches the structure of your configuration:\r\n\r\n```csharp\r\npublic class AppConfig\r\n{\r\n    public bool Enabled { get; set; }\r\n    public string Environment { get; set; }\r\n}\r\n```\r\n\r\n### Loading and Using the Configuration\r\n\r\nYou can now load and use the configuration data as follows:\r\n\r\n```csharp\r\nvar applicationConfig = LoadFromEmbeddedResource\u003cAppConfig\u003e(\"YourAssemblyName.out.output.json\");\r\n\r\nbool enabled = applicationConfig.Enabled; \r\nConsole.WriteLine($\"Enabled: {enabled}\"); // Outputs \"True\"\r\n\r\nstring environment = applicationConfig.Environment; \r\nConsole.WriteLine($\"Environment: {environment}\"); // Outputs \"Production\"\r\n```\r\n\r\n**Note:** Replace `\"YourAssemblyName.out.output.json\"` with the actual resource name, which typically includes the assembly name, output folder, and the output file name.\r\n\r\n### Finding the Correct Resource Name\r\n\r\nIf you're unsure about the exact resource name, you can retrieve all resource names in the assembly by adding the following code and inspecting the output:\r\n\r\n```csharp\r\nstring[] resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();\r\nforeach (var name in resourceNames)\r\n{\r\n    Console.WriteLine(name);\r\n}\r\n```\r\n\r\nThis will list all embedded resources, allowing you to confirm the correct name to use when loading the resource.\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License. See the [LICENSE](https://github.com/richardsondev/AggregateConfigBuildTask/blob/main/LICENSE) file for details.\r\n\r\n## Third-Party Libraries\r\n\r\nThis project leverages the following third-party libraries that are bundled with the package:\r\n\r\n- **[YamlDotNet](https://github.com/aaubry/YamlDotNet)**\\\r\n  __Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Antoine Aubry and contributors__\\\r\n  Used for YAML serialization and deserialization. YamlDotNet is distributed under the MIT License. For detailed information, refer to the [YamlDotNet License](https://github.com/aaubry/YamlDotNet/blob/master/LICENSE.txt).\r\n\r\n- **[YamlDotNet.System.Text.Json](https://github.com/IvanJosipovic/YamlDotNet.System.Text.Json)**\\\r\n  __Copyright (c) 2022 Ivan Josipovic__\\\r\n  Facilitates type handling for YAML serialization and deserialization, enhancing compatibility with System.Text.Json. This library is also distributed under the MIT License. For more details, see the [YamlDotNet.System.Text.Json License](https://github.com/IvanJosipovic/YamlDotNet.System.Text.Json/blob/main/LICENSE).\r\n\r\n## Contributing\r\n\r\nContributions are welcome! Feel free to submit issues or pull requests on [GitHub](https://github.com/richardsondev/AggregateConfigBuildTask).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardsondev%2Faggregateconfigbuildtask","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frichardsondev%2Faggregateconfigbuildtask","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardsondev%2Faggregateconfigbuildtask/lists"}