Skip to content

Commit 036141e

Browse files
Fix merge conflicts
2 parents b2f87b5 + 15fcfa5 commit 036141e

34 files changed

Lines changed: 844 additions & 125 deletions

.pipelines/dwsql-pipelines.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Licensed under the MIT License.
33

44
# DwSql Integration Testing Pipeline config is split into two jobs:
5-
# 1) LinuxTests -> Run SQL Server 2019 in Linux Docker Image
5+
# 1) LinuxTests -> Run SQL Server 2025 in Linux Docker Image
66
# 2) WindowsTests -> Run LocalDB preinstalled on machine
77

88
trigger:
@@ -159,8 +159,8 @@ jobs:
159159
# The variable setting on the pipeline UI sets the connection string
160160
# for the linux job above.
161161
data-source.connection-string: Server=(localdb)\MSSQLLocalDB;Persist Security Info=False;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=30;TrustServerCertificate=True;
162-
InstallerUrl: https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi
163-
SqlVersionCode: '15.0'
162+
InstallerUrl: https://download.microsoft.com/download/dea8c210-c44a-4a9d-9d80-0c81578860c5/ENU/SqlLocalDB.msi
163+
SqlVersionCode: '17.0'
164164

165165
steps:
166166
- task: CmdLine@2

.pipelines/mssql-pipelines.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Licensed under the MIT License.
33

44
# MsSql Integration Testing Pipeline config is split into parallel jobs:
5-
# 1) linux (disabled) -> Run SQL Server 2019 in Linux Docker Image
5+
# 1) linux (disabled) -> Run SQL Server 2025 in Linux Docker Image
66
# 2) windows_combined -> GraphQL, REST, Unit, HotReload, OpenApi, Auth, Telemetry, Caching on LocalDB
77
# 3) windows_configuration -> Configuration tests on LocalDB (with schema init)
88

@@ -176,7 +176,7 @@ jobs:
176176
# The variable setting on the pipeline UI sets the connection string
177177
# for the linux job above.
178178
data-source.connection-string: Server=(localdb)\MSSQLLocalDB;Persist Security Info=False;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=30;TrustServerCertificate=True;
179-
InstallerUrl: https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi
179+
InstallerUrl: https://download.microsoft.com/download/dea8c210-c44a-4a9d-9d80-0c81578860c5/ENU/SqlLocalDB.msi
180180
SqlVersionCode: '17.0'
181181

182182
steps:
@@ -199,7 +199,7 @@ jobs:
199199
# The variable setting on the pipeline UI sets the connection string
200200
# for the linux job above.
201201
data-source.connection-string: Server=(localdb)\MSSQLLocalDB;Persist Security Info=False;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=30;TrustServerCertificate=True;
202-
InstallerUrl: https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi
202+
InstallerUrl: https://download.microsoft.com/download/dea8c210-c44a-4a9d-9d80-0c81578860c5/ENU/SqlLocalDB.msi
203203
SqlVersionCode: '17.0'
204204

205205
steps:

CODEOWNERS

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
# review when someone opens a pull request.
44
* @Aniruddh25 @aaronburtle @anushakolan @jerrynixon @RubenCerna2079 @souvikghosh04 @sourabh1007 @vadeveka @Alekhya-Polavarapu @rusamant @stuartpa
55

6-
code_of_conduct.md @jerrynixon
7-
contributing.md @jerrynixon
8-
license.txt @jerrynixon
9-
readme.md @jerrynixon
10-
security.md @jerrynixon
11-
support.md @jerrynixon
6+
CODE_OF_CONDUCT.md @jerrynixon @croblesm
7+
CONTRIBUTING.md @jerrynixon @croblesm
8+
LICENSE.txt @jerrynixon @croblesm
9+
README.md @jerrynixon @croblesm
10+
SECURITY.md @jerrynixon @croblesm
11+
support.md @jerrynixon @croblesm

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Data API builder (DAB) is an open-source, no-code tool that creates secure, full
3636

3737
| | REST | GraphQL | MCP |
3838
| :-----------: | :--: | :-----: | :---------: |
39-
| **Supported** | Yes | Yes | Coming soon |
39+
| **Supported** | Yes | Yes | Yes |
4040

4141
## Getting started
4242

@@ -312,4 +312,4 @@ Nitro (formerly Banana Cake Pop by ChilliCream, Inc.) may optionally store work
312312

313313
### Trademarks
314314

315-
This project may use trademarks or logos. Use of Microsoft trademarks must follow Microsoft’s [Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks). Use of third-party marks is subject to their policies.
315+
This project may use trademarks or logos. Use of Microsoft trademarks must follow Microsoft’s [Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks). Use of third-party marks is subject to their policies.

src/Cli.Tests/ConfigureOptionsTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ public void TestUpdateEnabledForRestSettings(bool updatedEnabledValue)
418418
[DataRow("/updatedPath", DisplayName = "Update REST path to /updatedPath.")]
419419
[DataRow("/updated_Path", DisplayName = "Ensure underscore is allowed in REST path.")]
420420
[DataRow("/updated-Path", DisplayName = "Ensure hyphen is allowed in REST path.")]
421+
[DataRow("/api/v2", DisplayName = "Ensure multi-segment paths are allowed in REST path.")]
421422
public void TestUpdatePathForRestSettings(string updatedPathValue)
422423
{
423424
// Arrange -> all the setup which includes creating options.

src/Cli.Tests/EndToEndTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,12 @@ public void TestUpdateDepthLimitInGraphQLRuntimeSettings(string depthLimit, bool
343343
[DataRow("/updatedPath", true, DisplayName = "Success in updated GraphQL Path to /updatedPath.")]
344344
[DataRow("/updated-Path", true, DisplayName = "Success in updated GraphQL Path to /updated-Path.")]
345345
[DataRow("/updated_Path", true, DisplayName = "Success in updated GraphQL Path to /updated_Path.")]
346+
[DataRow("/api/v2", true, DisplayName = "Success in updated GraphQL Path to multi-segment path /api/v2.")]
346347
[DataRow("updatedPath", false, DisplayName = "Failure due to '/' missing.")]
347348
[DataRow("/updated Path", false, DisplayName = "Failure due to white spaces.")]
348349
[DataRow("/updated.Path", false, DisplayName = "Failure due to reserved char '.'.")]
349350
[DataRow("/updated@Path", false, DisplayName = "Failure due reserved chars '@'.")]
350-
[DataRow("/updated/Path", false, DisplayName = "Failure due reserved chars '/'.")]
351+
[DataRow("/api//v2", false, DisplayName = "Failure due to empty path segment.")]
351352
public void TestUpdateGraphQLPathRuntimeSettings(string path, bool isSuccess)
352353
{
353354
// Initialize the config file.
@@ -405,11 +406,12 @@ public void TestUpdateHostCorsOriginsRuntimeSettings(string path, bool isSuccess
405406
[DataRow("/updatedPath", true, DisplayName = "Successfully updated Rest Path to /updatedPath.")]
406407
[DataRow("/updated-Path", true, DisplayName = "Successfully updated Rest Path to /updated-Path.")]
407408
[DataRow("/updated_Path", true, DisplayName = "Successfully updated Rest Path to /updated_Path.")]
409+
[DataRow("/api/v2", true, DisplayName = "Successfully updated Rest Path to multi-segment path /api/v2.")]
408410
[DataRow("updatedPath", false, DisplayName = "Failure due to '/' missing.")]
409411
[DataRow("/updated Path", false, DisplayName = "Failure due to white spaces.")]
410412
[DataRow("/updated.Path", false, DisplayName = "Failure due to reserved char '.'.")]
411413
[DataRow("/updated@Path", false, DisplayName = "Failure due reserved chars '@'.")]
412-
[DataRow("/updated/Path", false, DisplayName = "Failure due reserved chars '/'.")]
414+
[DataRow("/api//v2", false, DisplayName = "Failure due to empty path segment.")]
413415
public void TestUpdateRestPathRuntimeSettings(string path, bool isSuccess)
414416
{
415417
// Initialize the config file.

src/Cli.Tests/ValidateConfigTests.cs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ public void TestCleanup()
4040
Environment.SetEnvironmentVariable($"database-type", null);
4141
Environment.SetEnvironmentVariable($"sp_param1_int", null);
4242
Environment.SetEnvironmentVariable($"sp_param2_bool", null);
43+
44+
// Set output back to the default for other tests.
45+
Console.SetOut(new StreamWriter(Console.OpenStandardOutput())
46+
{
47+
AutoFlush = true
48+
});
49+
Console.SetError(new StreamWriter(Console.OpenStandardError())
50+
{
51+
AutoFlush = true
52+
});
4353
}
4454

4555
/// <summary>
@@ -294,9 +304,6 @@ public void ValidateConfigSchemaWhereConfigReferencesEnvironmentVariables()
294304
Assert.IsFalse(
295305
condition: loggerOutput.Contains("Failed to validate config against schema due to"),
296306
message: "Unexpected errors encountered when validating config schema in RuntimeConfigValidator::ValidateConfigSchema(...).");
297-
Assert.IsTrue(
298-
condition: loggerOutput.Contains("The config satisfies the schema requirements."),
299-
message: "RuntimeConfigValidator::ValidateConfigSchema(...) didn't communicate successful config schema validation.");
300307
}
301308

302309
/// <summary>
@@ -405,6 +412,37 @@ public void TestValidateNonRootZeroEntitiesWithInvalidConnectionString()
405412
Assert.IsFalse(isValid);
406413
}
407414

415+
/// <summary>
416+
/// Tests that logs related to suppressed messages do not appear.
417+
/// </summary>
418+
[TestMethod]
419+
public async Task TestValidateSuppressedLogsDoNotAppear()
420+
{
421+
// Arrange
422+
StringWriter writer = new();
423+
Console.SetOut(writer);
424+
425+
string config = AddPropertiesToJson(INITIAL_CONFIG, SINGLE_ENTITY);
426+
427+
((MockFileSystem)_fileSystem!).AddFile(
428+
path: TEST_RUNTIME_CONFIG_FILE,
429+
mockFile: config);
430+
ValidateOptions validateOptions = new(TEST_RUNTIME_CONFIG_FILE);
431+
432+
// Act
433+
Utils.LoggerFactoryForCli = Utils.GetLoggerFactoryForCli();
434+
ConfigGenerator.IsConfigValid(validateOptions, _runtimeConfigLoader!, _fileSystem!);
435+
436+
// Assert
437+
string loggerOutput = writer.ToString();
438+
Assert.IsTrue(
439+
condition: !loggerOutput.Contains("REST path:"),
440+
message: "RuntimeConfigValidator should not contain any messages indicating REST path for individual entities");
441+
Assert.IsTrue(
442+
condition: !loggerOutput.Contains("REST calls are disabled for the entity:"),
443+
message: "RuntimeConfigValidator should not contain any messages related to REST calls for individual entities");
444+
}
445+
408446
/// <summary>
409447
/// Validates that a root config (with data-source-files pointing to children)
410448
/// that has no data-source and no entities is considered structurally valid

src/Cli/Commands/ValidateOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public int Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSy
3838
}
3939
else
4040
{
41-
logger.LogError("Config is invalid.");
41+
logger.LogInformation("Config is invalid.");
4242
}
4343

4444
return isValidConfig ? CliReturnCode.SUCCESS : CliReturnCode.GENERAL_ERROR;

src/Cli/ConfigGenerator.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3166,8 +3166,6 @@ public static bool IsConfigValid(ValidateOptions options, FileSystemRuntimeConfi
31663166
return false;
31673167
}
31683168

3169-
_logger.LogInformation("Validating config file: {runtimeConfigFile}", runtimeConfigFile);
3170-
31713169
RuntimeConfigProvider runtimeConfigProvider = new(loader);
31723170

31733171
if (!runtimeConfigProvider.TryGetConfig(out RuntimeConfig? _))
@@ -3196,14 +3194,21 @@ public static bool IsConfigValid(ValidateOptions options, FileSystemRuntimeConfi
31963194
bool mcpEnabled = config.IsMcpEnabled;
31973195
if (mcpEnabled)
31983196
{
3197+
bool missingFields = false;
31993198
foreach (KeyValuePair<string, Entity> entity in config.Entities)
32003199
{
32013200
if (entity.Value.Fields == null || !entity.Value.Fields.Any())
32023201
{
3203-
_logger.LogWarning($"Entity '{entity.Key}' is missing 'fields' definition while MCP is enabled. " +
3204-
"It's recommended to define fields explicitly to ensure optimal performance with MCP.");
3202+
missingFields = true;
3203+
_logger.LogDebug($"Entity '{entity.Key}' is missing 'fields' definition while MCP is enabled.");
32053204
}
32063205
}
3206+
3207+
if (missingFields)
3208+
{
3209+
_logger.LogWarning("One or more entities are missing `fields` definition while MCP is enabled. " +
3210+
"It's recommended to define fields explicitly to ensure optimal performance with MCP.");
3211+
}
32073212
}
32083213

32093214
// Warn if Unauthenticated provider is used with authenticated or custom roles

src/Cli/Utils.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ public static bool IsURIComponentValid(string? uriComponent)
205205
uriComponent = uriComponent.Substring(1);
206206
}
207207

208-
return !RuntimeConfigValidatorUtil.DoesUriComponentContainReservedChars(uriComponent);
208+
// The path may contain multiple '/'-separated segments (e.g. 'api/v2'); validate each segment.
209+
return !RuntimeConfigValidatorUtil.DoesUriPathContainReservedChars(uriComponent);
209210
}
210211

211212
/// <summary>

0 commit comments

Comments
 (0)