From 2c6e18d6b26914499e205690beec2ee94dd1cb07 Mon Sep 17 00:00:00 2001 From: Z Chen <13544267+zijchen@users.noreply.github.com> Date: Wed, 25 Sep 2024 10:51:08 -0700 Subject: [PATCH] Add support for dotnet publish (#487) * Add support for dotnet publish * Fix test * Add condition to target override * Set property directly instead of importing BeforeCommon.targets --- src/Microsoft.Build.Sql/sdk/Sdk.props | 1 + src/Microsoft.Build.Sql/sdk/Sdk.targets | 16 ++- .../DotnetTestBase.cs | 47 +++++++- .../PackageReferenceTests.cs | 29 ----- .../Microsoft.Build.Sql.Tests/PublishTests.cs | 104 ++++++++++++++++++ 5 files changed, 161 insertions(+), 36 deletions(-) create mode 100644 test/Microsoft.Build.Sql.Tests/PublishTests.cs diff --git a/src/Microsoft.Build.Sql/sdk/Sdk.props b/src/Microsoft.Build.Sql/sdk/Sdk.props index 2dfff64..4b94526 100644 --- a/src/Microsoft.Build.Sql/sdk/Sdk.props +++ b/src/Microsoft.Build.Sql/sdk/Sdk.props @@ -15,6 +15,7 @@ netstandard2.1 @(SupportedTargetFramework->'%(Alias)') + publish diff --git a/src/Microsoft.Build.Sql/sdk/Sdk.targets b/src/Microsoft.Build.Sql/sdk/Sdk.targets index 83b798b..c1aa439 100644 --- a/src/Microsoft.Build.Sql/sdk/Sdk.targets +++ b/src/Microsoft.Build.Sql/sdk/Sdk.targets @@ -38,6 +38,12 @@ $(NoWarn),NU5128 + + + publish + $(OutputPath)$(PublishDirName)\ + + @@ -63,6 +71,12 @@ + + + + + + diff --git a/test/Microsoft.Build.Sql.Tests/DotnetTestBase.cs b/test/Microsoft.Build.Sql.Tests/DotnetTestBase.cs index 12bb3ae..f0df4d3 100644 --- a/test/Microsoft.Build.Sql.Tests/DotnetTestBase.cs +++ b/test/Microsoft.Build.Sql.Tests/DotnetTestBase.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.IO; using System.Text; +using Microsoft.Build.Construction; using Microsoft.SqlServer.Dac; using NUnit.Framework; using NUnit.Framework.Interfaces; @@ -36,10 +37,19 @@ protected string CurrentTestDataDirectory get { return Path.Combine(this.CommonTestDataDirectory, TestUtils.EscapeTestName(TestContext.CurrentContext.Test.Name)); } } + private string LocalNugetSource + { + get { return Path.Combine(this.WorkingDirectory, "pkg"); } + } + [SetUp] public void TestSetup() { EnvironmentSetup(); + + // Add pkg folder as a nuget source + RunGenericDotnetCommand($"nuget add source \"{LocalNugetSource}\" --name TestSource_{TestContext.CurrentContext.Test.Name}", out _, out string stdError); + Assert.AreEqual("", stdError, "Failed to add local nuget source: " + stdError); } [TearDown] @@ -85,8 +95,7 @@ protected void EnvironmentSetup() } // Copy SDK nuget package to Workingdirectory/pkg/ - string localNugetSource = Path.Combine(this.WorkingDirectory, "pkg"); - TestUtils.CopyDirectoryRecursive("../../../pkg", localNugetSource); + TestUtils.CopyDirectoryRecursive("../../../pkg", LocalNugetSource); // Copy common project files from Template to WorkingDirectory TestUtils.CopyDirectoryRecursive("../../../Template", this.WorkingDirectory); @@ -96,10 +105,6 @@ protected void EnvironmentSetup() { TestUtils.CopyDirectoryRecursive(this.CurrentTestDataDirectory, this.WorkingDirectory); } - - // Add pkg folder as a nuget source - RunGenericDotnetCommand($"nuget add source \"{localNugetSource}\" --name TestSource_{TestContext.CurrentContext.Test.Name}", out _, out string stdError); - Assert.AreEqual("", stdError, "Failed to add local nuget source: " + stdError); } /// @@ -294,6 +299,36 @@ protected void AddProjectReference(params string[] projects) ProjectUtils.AddItemGroup(this.GetProjectFilePath(), "ProjectReference", projects); } + /// + /// Add a package reference to a Nuget package. + /// + protected void AddPackageReference(string packageName, string version, string serverSqlcmdVariable = "", string databaseSqlcmdVariable = "", string databaseVariableLiteralValue = "", bool? suppressMissingDependenciesErrors = null) + { + ProjectUtils.AddItemGroup(this.GetProjectFilePath(), "PackageReference", new string[] { packageName }, (ProjectItemElement item) => { + item.AddMetadata("Version", version); + + if (!string.IsNullOrEmpty(serverSqlcmdVariable)) + { + item.AddMetadata("ServerSqlCmdVariable", serverSqlcmdVariable); + } + + if (!string.IsNullOrEmpty(databaseSqlcmdVariable)) + { + item.AddMetadata("DatabaseSqlCmdVariable", databaseSqlcmdVariable); + } + + if (!string.IsNullOrEmpty(databaseVariableLiteralValue)) + { + item.AddMetadata("DatabaseVariableLiteralValue", databaseVariableLiteralValue); + } + + if (suppressMissingDependenciesErrors.HasValue) + { + item.AddMetadata("SuppressMissingDependenciesErrors", suppressMissingDependenciesErrors.ToString()); + } + }); + } + /// /// Returns the full path to the sqlproj file used for this test. /// diff --git a/test/Microsoft.Build.Sql.Tests/PackageReferenceTests.cs b/test/Microsoft.Build.Sql.Tests/PackageReferenceTests.cs index fd92871..691d77c 100644 --- a/test/Microsoft.Build.Sql.Tests/PackageReferenceTests.cs +++ b/test/Microsoft.Build.Sql.Tests/PackageReferenceTests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; -using Microsoft.Build.Construction; using NUnit.Framework; namespace Microsoft.Build.Sql.Tests @@ -110,33 +109,5 @@ public void VerifyPackageReferenceToMasterAndGenerateCreateScript() this.VerifyDacPackage(); FileAssert.Exists(Path.Combine(this.GetOutputDirectory(), $"{DatabaseProjectName}_Create.sql")); } - - private void AddPackageReference(string packageName, string version, string serverSqlcmdVariable = "", string databaseSqlcmdVariable = "", string databaseVariableLiteralValue = "", bool? suppressMissingDependenciesErrors = null) - { - // Add a package reference to ReferenceProj version 5.5.5 - ProjectUtils.AddItemGroup(this.GetProjectFilePath(), "PackageReference", new string[] { packageName }, (ProjectItemElement item) => { - item.AddMetadata("Version", version); - - if (!string.IsNullOrEmpty(serverSqlcmdVariable)) - { - item.AddMetadata("ServerSqlCmdVariable", serverSqlcmdVariable); - } - - if (!string.IsNullOrEmpty(databaseSqlcmdVariable)) - { - item.AddMetadata("DatabaseSqlCmdVariable", databaseSqlcmdVariable); - } - - if (!string.IsNullOrEmpty(databaseVariableLiteralValue)) - { - item.AddMetadata("DatabaseVariableLiteralValue", databaseVariableLiteralValue); - } - - if (suppressMissingDependenciesErrors.HasValue) - { - item.AddMetadata("SuppressMissingDependenciesErrors", suppressMissingDependenciesErrors.ToString()); - } - }); - } } } \ No newline at end of file diff --git a/test/Microsoft.Build.Sql.Tests/PublishTests.cs b/test/Microsoft.Build.Sql.Tests/PublishTests.cs new file mode 100644 index 0000000..0119d07 --- /dev/null +++ b/test/Microsoft.Build.Sql.Tests/PublishTests.cs @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.IO; +using Microsoft.Build.Construction; +using NUnit.Framework; + +namespace Microsoft.Build.Sql.Tests +{ + [TestFixture] + public class PublishTests : DotnetTestBase + { + [Test] + public void VerifySimplePublish() + { + int exitCode = this.RunDotnetCommandOnProject("publish", out _, out string stdError); + + // Verify success + Assert.AreEqual(0, exitCode, "Publish failed with error " + stdError); + Assert.AreEqual(string.Empty, stdError); + this.VerifyDacPackage(); + this.VerifyPublishFolder(); + } + + [Test] + public void VerifyPublishWithNoBuild() + { + // Run build first + int exitCode = this.RunDotnetCommandOnProject("publish", out _, out string stdError); + Assert.AreEqual(0, exitCode, "Build failed with error " + stdError); + Assert.AreEqual(string.Empty, stdError); + this.VerifyDacPackage(); + + // Run publish with --no-build + exitCode = this.RunDotnetCommandOnProject("publish --no-build", out _, out stdError); + Assert.AreEqual(0, exitCode, "publish failed with error " + stdError); + Assert.AreEqual(string.Empty, stdError); + this.VerifyPublishFolder(); + } + + [Test] + public void VerifyPublishkWithIncludedFiles() + { + // Add a content file that is copied to output + string includedContent = Path.Combine(this.WorkingDirectory, "include_content.txt"); + File.WriteAllText(includedContent, "test"); + ProjectUtils.AddItemGroup(this.GetProjectFilePath(), "Content", new[] { includedContent }, (ProjectItemElement item) => + { + item.AddMetadata("CopyToOutputDirectory", "PreserveNewest"); + }); + + // Run dotnet publish + int exitCode = this.RunDotnetCommandOnProject("publish", out _, out string stdError); + + // Verify + Assert.AreEqual(0, exitCode, "Publish failed with error " + stdError); + Assert.AreEqual(string.Empty, stdError); + this.VerifyPublishFolder("include_content.txt"); + } + + [Test] + public void VerifyPublishWithProjectReference() + { + // Add a project reference to ReferenceProj, which should be copied to the publish directory + string tempFolder = TestUtils.CreateTempDirectory(); + TestUtils.CopyDirectoryRecursive(Path.Combine(this.CommonTestDataDirectory, "ReferenceProj"), tempFolder); + + this.AddProjectReference(Path.Combine(tempFolder, "ReferenceProj.sqlproj")); + + int exitCode = this.RunDotnetCommandOnProject("publish", out _, out string stdError); + + Assert.AreEqual(0, exitCode, "Publish failed with error " + stdError); + Assert.AreEqual(string.Empty, stdError); + this.VerifyDacPackage(); + this.VerifyPublishFolder("ReferenceProj.dacpac"); + } + + [Test] + public void VerifyPublishWithPackageReference() + { + // Add a package reference to master.dacpac, which should be copied to the publish directory + this.AddPackageReference(packageName: "Microsoft.SqlServer.Dacpacs.Azure.Master", version: "160.*"); + + int exitCode = this.RunDotnetCommandOnProject("publish", out _, out string stdError); + + Assert.AreEqual(0, exitCode, "Publish failed with error " + stdError); + Assert.AreEqual(string.Empty, stdError); + this.VerifyDacPackage(); + this.VerifyPublishFolder("master.dacpac"); + } + + /// + /// Verify dacpac is in the publish directory, along with any additional expected files. + /// + private void VerifyPublishFolder(params string[] additionalFiles) + { + string publishFolder = Path.Combine(this.GetOutputDirectory(), "publish"); + FileAssert.Exists(Path.Combine(publishFolder, $"{DatabaseProjectName}.dacpac")); + foreach (string file in additionalFiles) { + FileAssert.Exists(Path.Combine(publishFolder, file)); + } + } + } +} \ No newline at end of file