Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2d18146
added custom health check endpoint and updated metadataproviders to r…
seantleonard Feb 16, 2024
64a55fe
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Mar 2, 2024
239816e
update product version functions , update tests, add version to proje…
seantleonard Mar 8, 2024
63784e1
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Mar 8, 2024
91d96f6
update test comment
seantleonard Mar 8, 2024
2bcda1e
update formatting
seantleonard Mar 8, 2024
bfed980
Merge branch 'dev/sean/1971_version_health_endpt' of https://github.c…
seantleonard Mar 8, 2024
87ed99b
update pipeline to utilize Directory.Build.props for the major and mi…
seantleonard Mar 8, 2024
a89a79e
update path for Directory.Build.props, unforch, due to inability to e…
seantleonard Mar 8, 2024
5675aad
fix powershell script to parse the xml access properly, pull out the …
seantleonard Mar 8, 2024
dcd96c9
Merge branch 'dev/sean/1971_version_health_endpt' of https://github.c…
seantleonard Mar 9, 2024
7736a39
update failing tests , split out mssql because of unique processing f…
seantleonard Mar 9, 2024
8ef4435
add test checking health endpoint contents
seantleonard Mar 9, 2024
4d91936
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Mar 12, 2024
da8352f
Updated per pr feedback: remove bad character from powershell ise, up…
seantleonard Mar 12, 2024
2e4a755
Update to remove references to commit hash when querying ProductVersion
seantleonard Mar 12, 2024
4feea08
update CLI tests and CLI to always check for and return product versi…
seantleonard Mar 12, 2024
a59a8aa
Only CLI usage with --help, --version , or unknown verbs/options resu…
seantleonard Mar 13, 2024
fd417a2
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Mar 13, 2024
3909cf3
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Mar 18, 2024
d8e01b6
Remove usage of DAB_UNVERSIONED string. if fileVersionInfo.ProductVer…
seantleonard Mar 22, 2024
a9638f5
Merge branch 'dev/sean/1971_version_health_endpt' of https://github.c…
seantleonard Mar 22, 2024
2d789bd
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Mar 29, 2024
175d2d5
update test formatting. Datarows now have spacing to distinguish para…
seantleonard Mar 29, 2024
5d0e585
updated logger for healthreportresponsewriter and updated tests per p…
seantleonard Mar 29, 2024
5009b87
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Apr 1, 2024
d581e99
fix unit test with extra param and fix comment for accuracy.
seantleonard Apr 1, 2024
bbc08d9
Merge branch 'main' into dev/sean/1971_version_health_endpt
seantleonard Apr 1, 2024
7f04635
update test logic, displaynames, and comment summary to accurate port…
seantleonard Apr 1, 2024
397c920
Merge branch 'dev/sean/1971_version_health_endpt' of https://github.c…
seantleonard Apr 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .pipelines/templates/build-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ steps:
# generate the prerelease nuget version.
# We cannot set this in variables section above because $(isNugetRelease)
# is not available at pipeline compilation time.
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
[xml]$directoryBuildProps = Get-Content -Path $(Build.SourcesDirectory)/src/Directory.Build.props
# Get Version from Directory.Build.props
# When you access this XML property, it returns an array of elements (even if there's only one element with that name).
# To extract the actual value as a string, you need to access the first element of the array.
$version = $directoryBuildProps.Project.PropertyGroup.Version[0]
# Get Major and Minor version from the version extracted
$major = $version.Split([char]'.')[0]
$minor = $version.Split([char]'.')[1]
# store $major and $minor powershell variables into azure dev ops pipeline variables
Write-Host "##vso[task.setvariable variable=major]$major"
Write-Host "##vso[task.setvariable variable=minor]$minor"

- bash: |
echo IsNugetRelease = $ISNUGETRELEASE
echo IsReleaseCandidate = $ISRELEASECANDIDATE
Expand Down
2 changes: 0 additions & 2 deletions .pipelines/templates/variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
major: 0
minor: 11
# Maintain a separate patch value between CI and PR runs.
# The counter is reset when the minor version is updated.
patch: $[counter(format('{0}_{1}', variables['build.reason'], variables['minor']), 0)]
Expand Down
94 changes: 60 additions & 34 deletions src/Cli.Tests/EndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public void TestInitializingRestAndGraphQLGlobalSettings()
replaceEnvVar: true));

SqlConnectionStringBuilder builder = new(runtimeConfig.DataSource.ConnectionString);
Assert.AreEqual(ProductInfo.GetDataApiBuilderApplicationName(), builder.ApplicationName);
Assert.AreEqual(ProductInfo.GetDataApiBuilderUserAgent(), builder.ApplicationName);

Assert.IsNotNull(runtimeConfig);
Assert.AreEqual(DatabaseType.MSSQL, runtimeConfig.DataSource.DatabaseType);
Expand Down Expand Up @@ -771,22 +771,19 @@ public void TestMissingEntityFromCommand(

/// <summary>
/// Test to verify that help writer window generates output on the console.
/// Every test here validates that the first line of the output contains the product name and version.
/// </summary>
[DataTestMethod]
[DataRow("", "", new string[] { "ERROR" }, DisplayName = "No flags provided.")]
[DataRow("initialize", "", new string[] { "ERROR", "Verb 'initialize' is not recognized." }, DisplayName = "Wrong Command provided.")]
[DataRow("", "--version", new string[] { "Microsoft.DataApiBuilder 1.0.0" }, DisplayName = "Checking version.")]
[DataRow("", "--help", new string[] { "init", "add", "update", "start" }, DisplayName = "Checking output for --help.")]
public void TestHelpWriterOutput(string command, string flags, string[] expectedOutputArray)
{
using Process process = ExecuteDabCommand(
command,
flags
);
using Process process = ExecuteDabCommand(command, flags);

string? output = process.StandardOutput.ReadToEnd();
Assert.IsNotNull(output);
StringAssert.Contains(output, $"{Program.PRODUCT_NAME} {ProductInfo.GetProductVersion()}", StringComparison.Ordinal);
StringAssert.Contains(output, $"{Program.PRODUCT_NAME} {ProductInfo.GetProductVersion(includeCommitHash: true)}", StringComparison.Ordinal);

foreach (string expectedOutput in expectedOutputArray)
{
Expand All @@ -796,24 +793,25 @@ public void TestHelpWriterOutput(string command, string flags, string[] expected
process.Kill();
}

[DataRow("", "--version", DisplayName = "Checking dab version with --version.")]
[DataTestMethod]
public void TestVersionHasBuildHash(
string command,
string options
)
/// <summary>
/// When CLI is started via: dab --version, it should print the version number
/// which includes the commit hash. For example:
/// Microsoft.DataApiBuilder 0.12+2d181463e5dd46cf77fea31b7295c4e02e8ef031
/// </summary>
[TestMethod]
public void TestVersionHasBuildHash()
{
_fileSystem!.File.WriteAllText(TEST_RUNTIME_CONFIG_FILE, INITIAL_CONFIG);

using Process process = ExecuteDabCommand(
command: $"{command} ",
flags: $"--config {TEST_RUNTIME_CONFIG_FILE} {options}"
command: string.Empty,
flags: $"--config {TEST_RUNTIME_CONFIG_FILE} --version"
);

string? output = process.StandardOutput.ReadLine();
Assert.IsNotNull(output);

// Check that build hash is returned as part of version number
// Check that the build hash is returned as part of the version number.
string[] versionParts = output.Split('+');
Assert.AreEqual(2, versionParts.Length, "Build hash not returned as part of version number.");
Assert.AreEqual(40, versionParts[1].Length, "Build hash is not of expected length.");
Expand All @@ -822,21 +820,17 @@ string options
}

/// <summary>
/// Test to verify that the version info is logged for both correct/incorrect command,
/// and that the config name is displayed in the logs.
/// For valid CLI commands (Valid verbs and options) validate that the correct
/// version is logged (without commit hash) and that the config file name is printed to console.
/// </summary>
[DataRow("", "--version", false, DisplayName = "Checking dab version with --version.")]
[DataRow("", "--help", false, DisplayName = "Checking version through --help option.")]
[DataRow("edit", "--new-option", false, DisplayName = "Version printed with invalid command edit.")]
[DataRow("init", "--database-type mssql", true, DisplayName = "Version printed with valid command init.")]
[DataRow("add", "MyEntity -s my_entity --permissions \"anonymous:*\"", true, DisplayName = "Version printed with valid command add.")]
[DataRow("update", "MyEntity -s my_entity", true, DisplayName = "Version printed with valid command update.")]
[DataRow("start", "", true, DisplayName = "Version printed with valid command start.")]
[DataRow("init", "--database-type mssql", DisplayName = "Version printed with valid command init.")]
[DataRow("add", "MyEntity -s my_entity --permissions \"anonymous:*\"", DisplayName = "Version printed with valid command add.")]
[DataRow("update", "MyEntity -s my_entity", DisplayName = "Version printed with valid command update.")]
[DataRow("start", "", DisplayName = "Version printed with valid command start.")]
[DataTestMethod]
public void TestVersionInfoAndConfigIsCorrectlyDisplayedWithDifferentCommand(
public void ValidCliVerbsAndOptions_DisplayVersionAndConfigFileName(
string command,
string options,
bool isParsableDabCommandName)
string options)
{
_fileSystem!.File.WriteAllText(TEST_RUNTIME_CONFIG_FILE, INITIAL_CONFIG);

Expand All @@ -849,13 +843,45 @@ public void TestVersionInfoAndConfigIsCorrectlyDisplayedWithDifferentCommand(
Assert.IsNotNull(output);

// Version Info logged by dab irrespective of commands being parsed correctly.
// When DAB CLI (CommandLineParser) detects that usage of parsable verbs and options, CommandLineParser
// uses the options.Handler() method to display relevant info and process the command.
// All options.Handler() methods print the version without commit hash.
StringAssert.Contains(output, $"{Program.PRODUCT_NAME} {ProductInfo.GetProductVersion()}", StringComparison.Ordinal);
output = process.StandardOutput.ReadLine();
StringAssert.Contains(output, TEST_RUNTIME_CONFIG_FILE, StringComparison.Ordinal);

if (isParsableDabCommandName)
{
output = process.StandardOutput.ReadLine();
StringAssert.Contains(output, TEST_RUNTIME_CONFIG_FILE, StringComparison.Ordinal);
}
process.Kill();
}

/// <summary>
/// Validate that the DAB CLI logs the correct version (with commit hash) to the console
/// when invalid verbs, '--version', or '--help' are used.
/// Console Output:
/// Microsoft.DataApiBuilder 0.12+5009b8720409ab321fd8cd19c716835528c8385b
/// </summary>
[DataRow("", "--version", DisplayName = "Checking dab version with --version.")]
[DataRow("", "--help", DisplayName = "Checking version through --help option.")]
[DataRow("edit", "--new-option", DisplayName = "Version printed with invalid command edit.")]
[DataTestMethod]
public void InvalidCliVerbsAndOptions_DisplayVersionWithCommitHashAndConfigFileName(
string command,
string options)
{
_fileSystem!.File.WriteAllText(TEST_RUNTIME_CONFIG_FILE, INITIAL_CONFIG);

using Process process = ExecuteDabCommand(
command: $"{command} ",
flags: $"--config {TEST_RUNTIME_CONFIG_FILE} {options}"
);

string? output = process.StandardOutput.ReadLine();
Assert.IsNotNull(output);

// Version Info logged by dab irrespective of commands being parsed correctly.
// When DAB CLI (CommandLineParser) detects that usage includes --version, --help, or invalid verbs/options,
// CommandLineParser's default HelpWriter is used to display the version and help information.
// Because the HelpWriter uses fileVersionInfo.ProductVersion, the version includes the commit hash.
StringAssert.Contains(output, $"{Program.PRODUCT_NAME} {ProductInfo.GetProductVersion(includeCommitHash: true)}", StringComparison.Ordinal);

process.Kill();
}
Expand All @@ -882,7 +908,7 @@ public async Task TestExitOfRuntimeEngineWithInvalidConfig(
);
string? output = await process.StandardOutput.ReadLineAsync();
Assert.IsNotNull(output);
StringAssert.Contains(output, $"{Program.PRODUCT_NAME} {ProductInfo.GetProductVersion()}", StringComparison.Ordinal);
StringAssert.Contains(output, $"{Program.PRODUCT_NAME} {ProductInfo.GetProductVersion(includeCommitHash: true)}", StringComparison.Ordinal);

output = await process.StandardOutput.ReadLineAsync();
Assert.IsNotNull(output);
Expand Down
2 changes: 1 addition & 1 deletion src/Config/RuntimeConfigLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ internal static string GetConnectionStringWithApplicationName(string connectionS
return connectionString;
}

string applicationName = ProductInfo.GetDataApiBuilderApplicationName();
string applicationName = ProductInfo.GetDataApiBuilderUserAgent();

// Create a StringBuilder from the connection string.
SqlConnectionStringBuilder connectionStringBuilder;
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Services/OpenAPI/OpenApiDocumentor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Azure.DataApiBuilder.Core.Parsers;
using Azure.DataApiBuilder.Core.Services.MetadataProviders;
using Azure.DataApiBuilder.Core.Services.OpenAPI;
using Azure.DataApiBuilder.Product;
using Azure.DataApiBuilder.Service.Exceptions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Writers;
Expand All @@ -30,7 +31,6 @@ public class OpenApiDocumentor : IOpenApiDocumentor
private OpenApiResponses _defaultOpenApiResponses;
private OpenApiDocument? _openApiDocument;

private const string DOCUMENTOR_VERSION = "PREVIEW";
private const string DOCUMENTOR_UI_TITLE = "Data API builder - REST Endpoint";
private const string GETALL_DESCRIPTION = "Returns entities.";
private const string GETONE_DESCRIPTION = "Returns an entity.";
Expand Down Expand Up @@ -132,8 +132,8 @@ public void CreateDocument()
{
Info = new OpenApiInfo
{
Version = DOCUMENTOR_VERSION,
Title = DOCUMENTOR_UI_TITLE,
Version = ProductInfo.GetProductVersion(),
Title = DOCUMENTOR_UI_TITLE
},
Servers = new List<OpenApiServer>
{
Expand Down
1 change: 1 addition & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<PropertyGroup>
<Nullable>enable</Nullable>
<BaseOutputPath>..\out</BaseOutputPath>
<Version>0.12</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand Down
53 changes: 30 additions & 23 deletions src/Product/ProductInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,51 @@ namespace Azure.DataApiBuilder.Product;

public static class ProductInfo
{
public const string DEFAULT_VERSION = "0.0.0";
public const string DAB_APP_NAME_ENV = "DAB_APP_NAME_ENV";
public static readonly string DEFAULT_APP_NAME = $"dab_oss_{ProductInfo.GetProductVersion()}";
public static readonly string ROLE_NAME = "DataApiBuilder";
public static readonly string DAB_USER_AGENT = $"dab_oss_{GetProductVersion()}";
public static readonly string CLOUD_ROLE_NAME = "DataApiBuilder";

/// <summary>
/// Reads the product version from the executing assembly's file version information.
/// Returns the Product version in Major.Minor.Patch format without a commit hash.
/// FileVersionInfo.ProductBuildPart is used to represent the Patch version.
/// FileVersionInfo is used to retrieve the version information from the executing assembly
/// set by the Version property in Directory.Build.props.
/// FileVersionInfo.ProductVersion includes the commit hash.
/// </summary>
/// <returns>Product version if not null, default version 0.0.0 otherwise.</returns>
public static string GetProductVersion()
/// <param name="includeCommitHash">If true, returns the version string with the commit hash</param>
/// <returns>Version string without commit hash: Major.Minor.Patch
/// Version string with commit hash: Major.Minor.Patch+COMMIT_ID"</returns>
public static string GetProductVersion(bool includeCommitHash = false)
{
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
string? version = fileVersionInfo.ProductVersion;

return version ?? DEFAULT_VERSION;
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(fileName: assembly.Location);

string versionString;

// fileVersionInfo's ProductVersion is nullable, while PoductMajorPart, ProductMinorPart, and ProductBuildPart are not.
// if ProductVersion is null, the other properties will be 0 since they do not return null.
if (includeCommitHash && fileVersionInfo.ProductVersion is not null)
{
versionString = fileVersionInfo.ProductVersion;
}
else
{
versionString = fileVersionInfo.ProductMajorPart + "." + fileVersionInfo.ProductMinorPart + "." + fileVersionInfo.ProductBuildPart;
}

return versionString;
}

/// <summary>
/// It retrieves the user agent for the DataApiBuilder by checking the value of
/// DAB_APP_NAME_ENV environment variable. If the environment variable is not set,
/// it returns a default value indicating connections from open source.
/// </summary>
/// <returns>Returns the value in the environment variable DAB_APP_NAME_ENV, when set.
/// Otherwise, returns user agent string: dab_oss_Major.Minor.Patch</returns>
public static string GetDataApiBuilderUserAgent()
{
return Environment.GetEnvironmentVariable(DAB_APP_NAME_ENV) ?? DEFAULT_APP_NAME;
}

/// <summary>
/// Returns the application name to be used for database connections for the DataApiBuilder.
/// It strips the hash value from the user agent string to only return the application name and the version.
/// The method serves as a means of identifying the source of connections made through the DataApiBuilder.
/// </summary>
public static string GetDataApiBuilderApplicationName()
{
string dabVersion = ProductInfo.GetDataApiBuilderUserAgent();
int hashStartPosition = dabVersion.LastIndexOf('+');
return hashStartPosition != -1 ? dabVersion[..hashStartPosition] : dabVersion;
return Environment.GetEnvironmentVariable(DAB_APP_NAME_ENV) ?? DAB_USER_AGENT;
}
}

Loading