From 9a160c7b1d64cf50e86f40f3d635ae6395e4f551 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 14 Jan 2026 04:49:48 +0000
Subject: [PATCH 1/5] Initial plan
From 0056297f46b434e41a2760237688747b71584fd7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 14 Jan 2026 04:57:28 +0000
Subject: [PATCH 2/5] Add data-source.health.name CLI parameter support
Co-authored-by: JerryNixon <1749983+JerryNixon@users.noreply.github.com>
---
src/Cli/Commands/ConfigureOptions.cs | 5 +++++
src/Cli/ConfigGenerator.cs | 18 ++++++++++++++++++
.../DatasourceHealthOptionsConvertorFactory.cs | 3 ++-
3 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/src/Cli/Commands/ConfigureOptions.cs b/src/Cli/Commands/ConfigureOptions.cs
index 11dca2a4eb..299a791e2d 100644
--- a/src/Cli/Commands/ConfigureOptions.cs
+++ b/src/Cli/Commands/ConfigureOptions.cs
@@ -28,6 +28,7 @@ public ConfigureOptions(
string? dataSourceOptionsContainer = null,
string? dataSourceOptionsSchema = null,
bool? dataSourceOptionsSetSessionContext = null,
+ string? dataSourceHealthName = null,
int? depthLimit = null,
bool? runtimeGraphQLEnabled = null,
string? runtimeGraphQLPath = null,
@@ -80,6 +81,7 @@ public ConfigureOptions(
DataSourceOptionsContainer = dataSourceOptionsContainer;
DataSourceOptionsSchema = dataSourceOptionsSchema;
DataSourceOptionsSetSessionContext = dataSourceOptionsSetSessionContext;
+ DataSourceHealthName = dataSourceHealthName;
// GraphQL
DepthLimit = depthLimit;
RuntimeGraphQLEnabled = runtimeGraphQLEnabled;
@@ -150,6 +152,9 @@ public ConfigureOptions(
[Option("data-source.options.set-session-context", Required = false, HelpText = "Enable session context. Allowed values: true (default), false.")]
public bool? DataSourceOptionsSetSessionContext { get; }
+ [Option("data-source.health.name", Required = false, HelpText = "Identifier for data source in health check report.")]
+ public string? DataSourceHealthName { get; }
+
[Option("runtime.graphql.depth-limit", Required = false, HelpText = "Max allowed depth of the nested query. Allowed values: (0,2147483647] inclusive. Default is infinity. Use -1 to remove limit.")]
public int? DepthLimit { get; }
diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs
index 648edc1950..fd01827c60 100644
--- a/src/Cli/ConfigGenerator.cs
+++ b/src/Cli/ConfigGenerator.cs
@@ -684,6 +684,24 @@ private static bool TryUpdateConfiguredDataSourceOptions(
dbOptions.Add(namingPolicy.ConvertName(nameof(MsSqlOptions.SetSessionContext)), options.DataSourceOptionsSetSessionContext.Value);
}
+ // Handle health.name option
+ if (options.DataSourceHealthName is not null)
+ {
+ // If there's no existing health config, create one with the name
+ if (datasourceHealthCheckConfig is null)
+ {
+ datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(enabled: null, name: options.DataSourceHealthName);
+ }
+ else
+ {
+ // Update the existing health config with the new name
+ datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(
+ enabled: datasourceHealthCheckConfig.Enabled,
+ name: options.DataSourceHealthName,
+ thresholdMs: datasourceHealthCheckConfig.UserProvidedThresholdMs ? datasourceHealthCheckConfig.ThresholdMs : null);
+ }
+ }
+
dbOptions = EnumerableUtilities.IsNullOrEmpty(dbOptions) ? null : dbOptions;
DataSource dataSource = new(dbType, dataSourceConnectionString, dbOptions, datasourceHealthCheckConfig);
runtimeConfig = runtimeConfig with { DataSource = dataSource };
diff --git a/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs b/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
index d8286ff7a0..8862645f73 100644
--- a/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
+++ b/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
@@ -114,7 +114,8 @@ public HealthCheckOptionsConverter(DeserializationVariableReplacementSettings? r
public override void Write(Utf8JsonWriter writer, DatasourceHealthCheckConfig value, JsonSerializerOptions options)
{
- if (value?.UserProvidedEnabled is true)
+ // Write the health object if enabled was explicitly provided OR if name is set OR if threshold was explicitly provided
+ if (value?.UserProvidedEnabled is true || value?.Name is not null || value?.UserProvidedThresholdMs is true)
{
writer.WriteStartObject();
writer.WritePropertyName("enabled");
From 77cdd247c67aaf324c29abb4b1383c292e011dbe Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 14 Jan 2026 05:06:18 +0000
Subject: [PATCH 3/5] Add tests for data-source.health.name CLI parameter
Co-authored-by: JerryNixon <1749983+JerryNixon@users.noreply.github.com>
---
src/Cli.Tests/ConfigureOptionsTests.cs | 97 ++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/src/Cli.Tests/ConfigureOptionsTests.cs b/src/Cli.Tests/ConfigureOptionsTests.cs
index 073f349a67..27d9dec08e 100644
--- a/src/Cli.Tests/ConfigureOptionsTests.cs
+++ b/src/Cli.Tests/ConfigureOptionsTests.cs
@@ -926,6 +926,103 @@ public void TestFailureWhenAddingSetSessionContextToMySQLDatabase()
Assert.IsFalse(isSuccess);
}
+ ///
+ /// Tests adding data-source.health.name to a config that doesn't have a health section.
+ /// This method verifies that the health.name can be added to a data source configuration
+ /// that doesn't previously have a health section.
+ /// Command: dab configure --data-source.health.name "My Data Source"
+ ///
+ [TestMethod]
+ public void TestAddDataSourceHealthName()
+ {
+ // Arrange
+ SetupFileSystemWithInitialConfig(INITIAL_CONFIG);
+
+ ConfigureOptions options = new(
+ dataSourceHealthName: "My Data Source",
+ config: TEST_RUNTIME_CONFIG_FILE
+ );
+
+ // Act
+ bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);
+
+ // Assert
+ Assert.IsTrue(isSuccess);
+ string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
+ Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? config));
+ Assert.IsNotNull(config.DataSource);
+ Assert.IsNotNull(config.DataSource.Health);
+ Assert.AreEqual("My Data Source", config.DataSource.Health.Name);
+ Assert.IsTrue(config.DataSource.Health.Enabled); // Default value
+ }
+
+ ///
+ /// Tests updating data-source.health.name on a config that already has a health section.
+ /// This method verifies that the health.name can be updated while preserving other health settings.
+ /// Command: dab configure --data-source.health.name "Updated Name"
+ ///
+ [DataTestMethod]
+ [DataRow("New Name", DisplayName = "Update health name with a simple string")]
+ [DataRow("This is the value", DisplayName = "Update health name with the example from the issue")]
+ public void TestUpdateDataSourceHealthName(string healthName)
+ {
+ // Arrange - Config with existing health section
+ string configWithHealth = @"
+ {
+ ""$schema"": ""test"",
+ ""data-source"": {
+ ""database-type"": ""mssql"",
+ ""connection-string"": ""testconnectionstring"",
+ ""health"": {
+ ""enabled"": false,
+ ""threshold-ms"": 2000
+ }
+ },
+ ""runtime"": {
+ ""rest"": {
+ ""enabled"": true,
+ ""path"": ""/api""
+ },
+ ""graphql"": {
+ ""enabled"": true,
+ ""path"": ""/graphql"",
+ ""allow-introspection"": true
+ },
+ ""host"": {
+ ""mode"": ""development"",
+ ""cors"": {
+ ""origins"": [],
+ ""allow-credentials"": false
+ },
+ ""authentication"": {
+ ""provider"": ""StaticWebApps""
+ }
+ }
+ },
+ ""entities"": {}
+ }";
+ SetupFileSystemWithInitialConfig(configWithHealth);
+
+ ConfigureOptions options = new(
+ dataSourceHealthName: healthName,
+ config: TEST_RUNTIME_CONFIG_FILE
+ );
+
+ // Act
+ bool isSuccess = TryConfigureSettings(options, _runtimeConfigLoader!, _fileSystem!);
+
+ // Assert
+ Assert.IsTrue(isSuccess);
+ string updatedConfig = _fileSystem!.File.ReadAllText(TEST_RUNTIME_CONFIG_FILE);
+ Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(updatedConfig, out RuntimeConfig? config));
+ Assert.IsNotNull(config.DataSource);
+ Assert.IsNotNull(config.DataSource.Health);
+ Assert.AreEqual(healthName, config.DataSource.Health.Name);
+ // Verify existing health settings are preserved
+ Assert.IsFalse(config.DataSource.Health.Enabled);
+ Assert.AreEqual(2000, config.DataSource.Health.ThresholdMs);
+ }
+
///
/// Sets up the mock file system with an initial configuration file.
/// This method adds a config file to the mock file system and verifies its existence.
From ab532b2e34c20e04df22547047feb56826e38bef Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 14 Jan 2026 05:13:44 +0000
Subject: [PATCH 4/5] Improve comments based on code review feedback
Co-authored-by: JerryNixon <1749983+JerryNixon@users.noreply.github.com>
---
src/Cli/ConfigGenerator.cs | 3 ++-
.../Converters/DatasourceHealthOptionsConvertorFactory.cs | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs
index fd01827c60..9cfdb506fa 100644
--- a/src/Cli/ConfigGenerator.cs
+++ b/src/Cli/ConfigGenerator.cs
@@ -688,13 +688,14 @@ private static bool TryUpdateConfiguredDataSourceOptions(
if (options.DataSourceHealthName is not null)
{
// If there's no existing health config, create one with the name
+ // Note: passing enabled: null uses the default value (true) from the base constructor
if (datasourceHealthCheckConfig is null)
{
datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(enabled: null, name: options.DataSourceHealthName);
}
else
{
- // Update the existing health config with the new name
+ // Update the existing health config with the new name while preserving other settings
datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(
enabled: datasourceHealthCheckConfig.Enabled,
name: options.DataSourceHealthName,
diff --git a/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs b/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
index 8862645f73..9c08cf4d81 100644
--- a/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
+++ b/src/Config/Converters/DatasourceHealthOptionsConvertorFactory.cs
@@ -114,7 +114,10 @@ public HealthCheckOptionsConverter(DeserializationVariableReplacementSettings? r
public override void Write(Utf8JsonWriter writer, DatasourceHealthCheckConfig value, JsonSerializerOptions options)
{
- // Write the health object if enabled was explicitly provided OR if name is set OR if threshold was explicitly provided
+ // Write the health object if any of these conditions are met:
+ // - enabled was explicitly provided by the user
+ // - name property has a value
+ // - threshold was explicitly provided by the user
if (value?.UserProvidedEnabled is true || value?.Name is not null || value?.UserProvidedThresholdMs is true)
{
writer.WriteStartObject();
From 211e1d6d070b525b01a3cb2e7e4b1ca71fe95c8a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 14 Jan 2026 05:20:50 +0000
Subject: [PATCH 5/5] Improve code clarity based on review feedback
Co-authored-by: JerryNixon <1749983+JerryNixon@users.noreply.github.com>
---
src/Cli/ConfigGenerator.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs
index 9cfdb506fa..658a871b53 100644
--- a/src/Cli/ConfigGenerator.cs
+++ b/src/Cli/ConfigGenerator.cs
@@ -688,7 +688,7 @@ private static bool TryUpdateConfiguredDataSourceOptions(
if (options.DataSourceHealthName is not null)
{
// If there's no existing health config, create one with the name
- // Note: passing enabled: null uses the default value (true) from the base constructor
+ // Note: passing enabled: null triggers the base constructor logic that sets Enabled = true
if (datasourceHealthCheckConfig is null)
{
datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(enabled: null, name: options.DataSourceHealthName);
@@ -696,10 +696,12 @@ private static bool TryUpdateConfiguredDataSourceOptions(
else
{
// Update the existing health config with the new name while preserving other settings
+ // Preserve threshold only if it was explicitly set by the user
+ int? thresholdToPreserve = datasourceHealthCheckConfig.UserProvidedThresholdMs ? datasourceHealthCheckConfig.ThresholdMs : null;
datasourceHealthCheckConfig = new DatasourceHealthCheckConfig(
enabled: datasourceHealthCheckConfig.Enabled,
name: options.DataSourceHealthName,
- thresholdMs: datasourceHealthCheckConfig.UserProvidedThresholdMs ? datasourceHealthCheckConfig.ThresholdMs : null);
+ thresholdMs: thresholdToPreserve);
}
}