Skip to content

feat: Add LoadFromConfiguration for appsettings.json support#416

Merged
JusterZhu merged 3 commits into
masterfrom
issue/410-loadfromconfiguration
May 25, 2026
Merged

feat: Add LoadFromConfiguration for appsettings.json support#416
JusterZhu merged 3 commits into
masterfrom
issue/410-loadfromconfiguration

Conversation

@JusterZhu
Copy link
Copy Markdown
Collaborator

Summary

Adds .LoadFromConfiguration(IConfiguration) to GeneralUpdateBootstrap for loading settings from appsettings.json, environment variables, or any IConfiguration source.

Usage

// From top-level IConfiguration
new GeneralUpdateBootstrap()
    .LoadFromConfiguration(builder.Configuration)
    .LaunchAsync();

// Code overrides config
new GeneralUpdateBootstrap()
    .LoadFromConfiguration(builder.Configuration)
    .Option(UpdateOptions.Silent, true)
    .LaunchAsync();

Supported config keys

All UpdateOptions (AppType, DiffMode, Silent, MaxConcurrency, EnableResume, etc.) and Configinfo fields (UpdateUrl, AppSecretKey, InstallPath, etc.) are mapped.

appsettings.json example

{
  "GeneralUpdate": {
    "AppType": "Client",
    "UpdateUrl": "https://update.example.com",
    "Silent": true,
    "MaxConcurrency": 5
  }
}

Closes #410

Adds .LoadFromConfiguration(IConfiguration) to GeneralUpdateBootstrap
for loading settings from appsettings.json, environment variables,
or any IConfiguration source.

- Reads UpdateOptions (AppType, DiffMode, Silent, MaxConcurrency, etc.)
- Reads Configinfo fields (UpdateUrl, AppSecretKey, InstallPath, etc.)
- Code .Option() calls override configuration values (code > config)
- Added PackageReference to Microsoft.Extensions.Configuration.Abstractions

Closes #410
Copilot AI review requested due to automatic review settings May 25, 2026 11:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds GeneralUpdateBootstrap.LoadFromConfiguration(IConfiguration) to support loading UpdateOptions and Configinfo-backed fields from appsettings.json / environment variables / any IConfiguration source, plus introduces a new dependency on Microsoft.Extensions.Configuration.Abstractions.

Changes:

  • Added LoadFromConfiguration(IConfiguration config, string section = "GeneralUpdate") to map common configuration keys onto UpdateOptions and _configInfo.
  • Added helper methods for setting options/fields from configuration keys.
  • Added Microsoft.Extensions.Configuration.Abstractions package reference to GeneralUpdate.Core.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj Adds Configuration.Abstractions package reference to enable IConfiguration-based loading.
src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs Introduces LoadFromConfiguration and key-to-option/config field mapping logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +199 to +204
public GeneralUpdateBootstrap LoadFromConfiguration(Microsoft.Extensions.Configuration.IConfiguration config, string section = "GeneralUpdate")
{
if (config == null) return this;

var sec = config.GetSection(section);

Comment on lines +186 to +187
/// Values set via <c>.Option()</c> or <c>.SetConfig()</c> before this call
/// are preserved (code has higher priority than config).
Comment on lines +221 to +234
TrySetConfigField(sec, "UpdateUrl", v => _configInfo.UpdateUrl = v);
TrySetConfigField(sec, "AppSecretKey", v => _configInfo.AppSecretKey = v);
TrySetConfigField(sec, "AppName", v => _configInfo.AppName = v);
TrySetConfigField(sec, "MainAppName", v => _configInfo.MainAppName = v);
TrySetConfigField(sec, "InstallPath", v => _configInfo.InstallPath = v);
TrySetConfigField(sec, "ClientVersion", v => _configInfo.ClientVersion = v);
TrySetConfigField(sec, "UpgradeClientVersion", v => _configInfo.UpgradeClientVersion = v);
TrySetConfigField(sec, "ProductId", v => _configInfo.ProductId = v);
TrySetConfigField(sec, "ReportUrl", v => _configInfo.ReportUrl = v);
TrySetConfigField(sec, "UpdateLogUrl", v => _configInfo.UpdateLogUrl = v);
TrySetConfigField(sec, "Bowl", v => _configInfo.Bowl = v);
TrySetConfigField(sec, "Scheme", v => _configInfo.Scheme = v);
TrySetConfigField(sec, "Token", v => _configInfo.Token = v);
TrySetConfigField(sec, "DriverDirectory", v => _configInfo.DriverDirectory = v);
Comment on lines +205 to +216
// UpdateOptions — only set if key exists in config
TrySetOptionIfMissing(sec, "AppType", v => Option(UpdateOptions.AppType, Enum.Parse<AppType>(v)));
TrySetOptionIfMissing(sec, "DiffMode", v => Option(UpdateOptions.DiffMode, Enum.Parse<DiffMode>(v)));
TrySetOptionIfMissing(sec, "Silent", v => Option(UpdateOptions.Silent, bool.Parse(v)));
TrySetOptionIfMissing(sec, "SilentAutoInstall", v => Option(UpdateOptions.SilentAutoInstall, bool.Parse(v)));
TrySetOptionIfMissing(sec, "SilentPollIntervalMinutes", v => Option(UpdateOptions.SilentPollIntervalMinutes, int.Parse(v)));
TrySetOptionIfMissing(sec, "MaxConcurrency", v => Option(UpdateOptions.MaxConcurrency, int.Parse(v)));
TrySetOptionIfMissing(sec, "EnableResume", v => Option(UpdateOptions.EnableResume, bool.Parse(v)));
TrySetOptionIfMissing(sec, "RetryCount", v => Option(UpdateOptions.RetryCount, int.Parse(v)));
TrySetOptionIfMissing(sec, "RetryIntervalSeconds", v => Option(UpdateOptions.RetryInterval, TimeSpan.FromSeconds(double.Parse(v))));
TrySetOptionIfMissing(sec, "VerifyChecksum", v => Option(UpdateOptions.VerifyChecksum, bool.Parse(v)));
TrySetOptionIfMissing(sec, "DownloadTimeout", v => Option(UpdateOptions.DownloadTimeout, int.Parse(v)));
Comment on lines +240 to +245
private void TrySetOptionIfMissing(Microsoft.Extensions.Configuration.IConfigurationSection sec, string key, Action<string> setter)
{
var v = sec[key];
if (!string.IsNullOrEmpty(v))
setter(v);
}
Comment on lines +37 to +39
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />

JusterZhu added 2 commits May 25, 2026 19:48
Overload reads a Configinfo JSON file. Filename-only resolves
relative to current directory; relative/absolute paths used as-is.
Uses source-generated JSON to stay AOT-compatible.

Closes #410
@JusterZhu JusterZhu merged commit 2bfdf3b into master May 25, 2026
3 checks passed
@JusterZhu JusterZhu deleted the issue/410-loadfromconfiguration branch May 25, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add LoadFromConfiguration for appsettings.json support

2 participants