diff --git a/README.md b/README.md index e20a2356..8f299163 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ dotnet new sqlproj -s Sql130 You should now have a project file with the following contents: ```xml - + - netstandard2.0 + netstandard2.1 Sql130 @@ -55,11 +55,12 @@ You should now have a project file with the following contents: ``` -Then run a `dotnet build` and you'll find a .dacpac file with the same name as your project file in the `bin\Debug\netstandard2.0` folder. If you want to change the name of the `.dacpac` file you can set the `` property in your project file to something else. +Then run a `dotnet build` and you'll find a .dacpac file with the same name as your project file in the `bin\Debug\netstandard2.1` folder. If you want to change the name of the `.dacpac` file you can set the `` property in your project file to something else. > Note: For PackageReferences this SDK currently assumes that the `.dacpac` file has the same name as the package. If you plan to create a NuGet package out of your project (see [below](#packaging-support)) then make sure that `` matches the ID of your package. -> Note: Ensure you **do not** change the `TargetFramework` element from `netstandard2.0` to anything else. Otherwise, you will see errors like `The "CopyRefAssembly" task was not given a value for the required parameter "SourcePath"`. +> Note: Ensure you **do not** change the `TargetFramework` element from `netstandard2.1 +` to anything else. Otherwise, you will see errors like `The "CopyRefAssembly" task was not given a value for the required parameter "SourcePath"`. ## Editing the Project file The project file can have extension `.csproj` or `.fsproj`. @@ -94,9 +95,9 @@ If you already have a SSDT (.sqlproj) project in your solution, you can keep tha There are a lot of properties that can be set on the model in the resulting `.dacpac` file which can be influenced by setting those properties in the project file using the same name. For example, the snippet below sets the `RecoveryMode` property to `Simple`: ```xml - + - netstandard2.0 + netstandard2.1 Simple SqlAzure @@ -112,7 +113,7 @@ Like `.sqlproj` projects `MSBuild.Sdk.SqlProj` supports controlling T-SQL build Treating warnings as errors can be optionally enabled by adding a property `TreatTSqlWarningsAsErrors` to the project file: ```xml - + True ... @@ -124,7 +125,7 @@ Treating warnings as errors can be optionally enabled by adding a property `Trea To suppress specific warnings from being treated as errors, add a comma-separated list of warning codes to `SuppressTSqlWarnings` property in the project file: ```xml - + 71558,71502 True @@ -136,7 +137,7 @@ To suppress specific warnings from being treated as errors, add a comma-separate You can suppress warnings for a specific file by adding `SuppressTSqlWarnings` for this file: ```xml - + ... @@ -156,7 +157,7 @@ Support for pre- and post-deployment scripts has been added in version 1.1.0. Th To include these scripts into your `.dacpac` add the following to your `.csproj`: ```xml - + ... @@ -173,7 +174,7 @@ It is important to note that scripts in the `Pre-Deployment` and `Post-Deploymen By default the pre- and/or post-deployment script of referenced packages (both [PackageReference](#package-references) and [ProjectReference](#project-references)) are not run when using `dotnet publish`. As of version 1.11.0 this can be optionally enabled by adding a property `RunScriptsFromReferences` to the project file as in the below example: ```xml - + True ... @@ -189,7 +190,7 @@ By default the pre- and/or post-deployment script of referenced packages (both [ Especially when using pre- and post-deployment scripts, but also in other scenario's, it might be useful to define variables that can be controlled at deployment time. This is supported using SQLCMD variables, added in version 1.1.0. These variables can be defined in your project file using the following syntax: ```xml - + ... @@ -213,9 +214,9 @@ Especially when using pre- and post-deployment scripts, but also in other scenar `MSBuild.Sdk.SqlProj` supports referencing NuGet packages that contain `.dacpac` packages. These can be referenced by using the `PackageReference` format familiar to .NET developers. They can also be installed through the NuGet Package Manager in Visual Studio. ```xml - + - netstandard2.0 + netstandard2.1 @@ -227,9 +228,9 @@ Especially when using pre- and post-deployment scripts, but also in other scenar It will assume that the `.dacpac` file is inside the `tools` folder of the referenced package and that it has the same name as the NuGet package. Referenced packages that do not adhere to this convention will be silently ignored. However, you have the ability to override this convention by using the `DacpacName` attribute on the `PackageReference` (introduced in version 2.5.0). For example: ```xml - + - netstandard2.0 + netstandard2.1 Sql160 @@ -244,9 +245,9 @@ This will add a reference to the `tools\SomeOtherDacpac.dacpac` file inside the By default, the package reference is treated as being part of the same database. For example, if the reference package contains a `.dacpac` that has a table and a stored procedure and you would `dotnet publish` the project the table and stored procedure from that package will be deployed along with the contents of your project to the same database. If this is not desired, you can add the `DatabaseVariableLiteralValue` item metadata to the `PackageReference` specifying a different database name: ```xml - + - netstandard2.0 + netstandard2.1 @@ -261,9 +262,9 @@ You can also use SQLCMD variables to set references, similar to the behavior of >Note: Don't forget to define appropriate [SQLCMD variables](#sqlcmd-variables) ```xml - + - netstandard2.0 + netstandard2.1 @@ -302,9 +303,9 @@ sqlpackage Microsoft has recently released NuGet packages containing the definitions of the `master` and `msdb` databases. This is useful if you want to reference objects from those databases within your own projects without getting warnings. To reference these, you'll need to use at least version 2.5.0 of MSBuild.Sdk.SqlProj as you'll need to use the `DacpacName` feature for package references described above. For example: ```xml - + - netstandard2.0 + netstandard2.1 160 @@ -322,9 +323,9 @@ For other variants of SQL Server / Azure SQL Database there are dedicated packag Similar to package references you can also reference another project by using a `ProjectReference`. These references can be added manually to the project file or they can be added through Visual Studio. For example, consider the following example: ```xml - + - netstandard2.0 + netstandard2.1 @@ -336,9 +337,9 @@ Similar to package references you can also reference another project by using a This will ensure that `MyOtherProject` is built first and the resulting `.dacpac` will be referenced by this project. This means you can use the objects defined in the other project within the scope of this project. If the other project is representing an entirely different database, you can also use `DatabaseVariableLiteralValue` or SQLCMD variables on the `ProjectReference` similar to `PackageReference`: ```xml - + - netstandard2.0 + netstandard2.1 @@ -370,9 +371,9 @@ In order to solve circular references between databases that may have been incor `SuppressMissingDependenciesErrors` to both [Package References](#package-references) and [ProjectReferences](#project-references)): ```xml - + - netstandard2.0 + netstandard2.1 @@ -392,7 +393,7 @@ In order to solve circular references between databases that may have been incor You'll need to set the `PackageProjectUrl` property in the `.csproj` like this: ```xml - + ... your-project-url @@ -464,7 +465,7 @@ To further customize the deployment process, you can use the following propertie In addition to these properties, you can also set any of the [documented](https://docs.microsoft.com/dotnet/api/microsoft.sqlserver.dac.dacdeployoptions) deployment options. These are typically set in the project file, for example: ```xml - + ... True @@ -487,7 +488,7 @@ Most of those properties are simple values (like booleans, strings and integers) Instead of using `dotnet publish` to deploy changes to a database, you can also have a full SQL script generated that will create the database from scratch and then run that script against a SQL Server. This can be achieved by adding the following to the project file: ```xml - + True True @@ -507,20 +508,22 @@ The database name for the create script gets resolved in the following manner: Starting with version 2.7.0 of the SDK, there is support for running static code analysis during build. The SDK includes the following sets of rules: - Microsoft.Rules ([1](https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd193411(v=vs.100)), [2](https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd193246(v=vs.100)) and [3](https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd172117(v=vs.100))) -- [SqlServer.Rules](https://github.com/tcartwright/SqlServer.Rules/blob/master/docs/table_of_contents.md) -- [Smells](https://github.com/davebally/TSQL-Smells) Static code analysis can be enabled by adding the `RunSqlCodeAnalysis` property to the project file: ```xml - + + + netstandard2.1 True -SqlServer.Rules.SRD0006;-Smells.* ``` +> Notice that the target framework should be set to `netstandard2.1` if you add additional NuGet-based rules. + A xml file with the analysis results is created in the output folder. The optional `CodeAnalysisRules` property allows you to disable individual rules or groups of rules. @@ -530,7 +533,7 @@ Any rule violations found during analysis are reported as build warnings. Individual rule violations or groups of rules can be configured to be reported as build errors as shown below. ```xml - + True +!SqlServer.Rules.SRN0005;+!SqlServer.Rules.SRD* @@ -538,16 +541,24 @@ Individual rule violations or groups of rules can be configured to be reported a ``` -You can also bring your own rules. For an example of custom rules, see [this repository](https://github.com/ErikEJ/SqlServer.Rules). +You can also build your own rules. For an example of how to build a custom rule, see [this blog post](https://erikej.github.io/dacfx/dotnet/2024/04/04/dacfx-rules.html). + +To publish your own custom rules, pack your rule .dll in a NuGet package as shown in the rule project file [here](https://github.com/ErikEJ/SqlServer.Rules/blob/master/SqlServer.Rules/SqlServer.Rules.csproj). -To use custom rules, place the rule .dll files in a `Rules` folder in the project, and add them as Content items: +We know of the following public rules NuGet packages, that you can add to your project. ```xml - + + ``` +They are based on these older repositories: + +- [SqlServer.Rules](https://github.com/tcartwright/SqlServer.Rules/blob/master/docs/table_of_contents.md) +- [Smells](https://github.com/davebally/TSQL-Smells) + ## Integrations `MSBuild.Sdk.SqlProj` integrates with a number of other technologies and tools. Here are some examples: @@ -556,7 +567,7 @@ To use custom rules, place the rule .dll files in a `Rules` folder in the projec - [dotnet-sqltest](https://github.com/cagrin/dotnet-sqltest) - Command line tool for running tSQLt unit tests from MSBuild.Sdk.SqlProj projects. -- [EF Core Power Tools](https://marketplace.visualstudio.com/items?itemName=ErikEJ.EFCorePowerTools&ssr=false#overview) - Visual Studio extension that can generate an Entity Framework Core DbContext and model classes directly from your `MSBuild.Sdk.SqlProj` project. +- [EF Core Power Tools](https://marketplace.visualstudio.com/items?itemName=ErikEJ.EFCorePowerTools&ssr=false#overview) - Visual Studio extension that can generate an Entity Framework Core DbContext and model classes, and various diagrams directly from your `MSBuild.Sdk.SqlProj` project. ## Workaround for parser errors (SQL46010) This project relies on the publicly available T-SQL parser which may not support all T-SQL syntax constructions. Therefore, you might encounter a SQL46010 error if you have a script file that contains unsupported syntax. If that happens, there's a couple of workarounds you can try: diff --git a/src/DacpacTool/BuildOptions.cs b/src/DacpacTool/BuildOptions.cs index 3f8b488a..cc3adc63 100644 --- a/src/DacpacTool/BuildOptions.cs +++ b/src/DacpacTool/BuildOptions.cs @@ -22,6 +22,7 @@ public class BuildOptions : BaseOptions public bool RunCodeAnalysis { get; set; } public string CodeAnalysisRules { get; set; } + public FileInfo[] CodeAnalysisAssemblies { get; set; } public bool WarnAsError { get; set; } public string SuppressWarnings { get; set; } public FileInfo SuppressWarningsListFile { get; set; } diff --git a/src/DacpacTool/DacpacTool.csproj b/src/DacpacTool/DacpacTool.csproj index ca2cf296..40d77225 100644 --- a/src/DacpacTool/DacpacTool.csproj +++ b/src/DacpacTool/DacpacTool.csproj @@ -16,11 +16,7 @@ - - - - - + diff --git a/src/DacpacTool/PackageAnalyzer.cs b/src/DacpacTool/PackageAnalyzer.cs index 8fb374d6..7635a942 100644 --- a/src/DacpacTool/PackageAnalyzer.cs +++ b/src/DacpacTool/PackageAnalyzer.cs @@ -22,33 +22,29 @@ public PackageAnalyzer(IConsole console, string rulesExpression) BuildRuleLists(rulesExpression); } - public void AddRulesFile(FileInfo inputFile) - { - ArgumentNullException.ThrowIfNull(inputFile); - - // Make sure the file exists - if (!inputFile.Exists) - { - throw new ArgumentException($"Unable to find rules file {inputFile}", nameof(inputFile)); - } - - if (inputFile.Directory.Name.Equals("rules", StringComparison.OrdinalIgnoreCase) - && inputFile.Extension.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) - { - CopyAdditionalRulesFile(inputFile); - } - } - - public void Analyze(TSqlModel model, FileInfo outputFile) + public void Analyze(TSqlModel model, FileInfo outputFile, FileInfo[] analyzers) { ArgumentNullException.ThrowIfNull(model); ArgumentNullException.ThrowIfNull(outputFile); + ArgumentNullException.ThrowIfNull(analyzers); _console.WriteLine($"Analyzing package '{outputFile.FullName}'"); try { var factory = new CodeAnalysisServiceFactory(); - var service = factory.CreateAnalysisService(model); + var settings = new CodeAnalysisServiceSettings(); + + if (analyzers.Length == 0) + { + _console.WriteLine("DacpacTool warning SQLPROJ0001: No additional rules files found, consider adding more rules via PackageReference - see the readme here: https://github.com/rr-wfm/MSBuild.Sdk.SqlProj."); + } + else + { + _console.WriteLine("Using additional analyzers: " + string.Join(", ", analyzers.Select(a => a.FullName))); + settings.AssemblyLookupPath = string.Join(';', analyzers.Select(a => a.DirectoryName)); + } + + var service = factory.CreateAnalysisService(model, settings); if (_ignoredRules.Count > 0 || _ignoredRuleSets.Count > 0) { @@ -125,16 +121,5 @@ private static string GetOutputFileName(FileInfo outputFile) } return outputFileName + ".CodeAnalysis.xml"; } - - private void CopyAdditionalRulesFile(FileInfo rulesFile) - { - var destPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); - - var dest = Path.Combine(destPath, rulesFile.Name); - - rulesFile.CopyTo(dest, overwrite: true); - - _console.WriteLine($"Adding additional rules file from '{rulesFile.FullName}' to '{dest}'"); - } } } diff --git a/src/DacpacTool/PackageBuilder.cs b/src/DacpacTool/PackageBuilder.cs index 9dcbdbd1..43c2e913 100644 --- a/src/DacpacTool/PackageBuilder.cs +++ b/src/DacpacTool/PackageBuilder.cs @@ -78,13 +78,6 @@ public bool AddInputFile(FileInfo inputFile) throw new ArgumentException($"Unable to find input file {inputFile}", nameof(inputFile)); } - // Skip custom rules files, they will be added to the tools folder later by the analyzer - if (inputFile.Directory.Name.Equals("rules", StringComparison.OrdinalIgnoreCase) - && inputFile.Extension.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - _console.WriteLine($"Adding {inputFile.FullName} to the model"); try diff --git a/src/DacpacTool/Program.cs b/src/DacpacTool/Program.cs index 29f18c05..a182ff53 100644 --- a/src/DacpacTool/Program.cs +++ b/src/DacpacTool/Program.cs @@ -33,6 +33,7 @@ static async Task Main(string[] args) new Option(new string[] { "--runcodeanalysis", "-an" }, "Run static code analysis"), new Option(new string[] { "--codeanalysisrules", "-ar" }, "List of rules to suppress in format '-Microsoft.Rules.Data.SR0001;-Microsoft.Rules.Data.SR0008'"), + new Option(new string[] { "--codeanalysisassemblies", "-aa" }, "Custom code analysis rule assemblies to use"), new Option(new string[] { "--warnaserror" }, "Treat T-SQL Warnings As Errors"), new Option(new string[] { "--generatecreatescript", "-gcs" }, "Generate create script for package"), @@ -206,13 +207,7 @@ private static int BuildDacpac(BuildOptions options) { var analyzer = new PackageAnalyzer(new ActualConsole(), options.CodeAnalysisRules); - foreach (var line in File.ReadLines(options.InputFile.FullName)) - { - FileInfo inputFile = new FileInfo(line); // Validation occurs in AddRulesFile - analyzer.AddRulesFile(inputFile); - } - - analyzer.Analyze(packageBuilder.Model, options.Output); + analyzer.Analyze(packageBuilder.Model, options.Output, options.CodeAnalysisAssemblies ?? Array.Empty()); } return 0; diff --git a/src/MSBuild.Sdk.SqlProj.Templates/templates/sqlproj/sqlproj.csproj b/src/MSBuild.Sdk.SqlProj.Templates/templates/sqlproj/sqlproj.csproj index 18b7c0ab..dc21a380 100644 --- a/src/MSBuild.Sdk.SqlProj.Templates/templates/sqlproj/sqlproj.csproj +++ b/src/MSBuild.Sdk.SqlProj.Templates/templates/sqlproj/sqlproj.csproj @@ -1,11 +1,18 @@ - netstandard2.0 + netstandard2.1 #{SqlServerVersion} #{CodeAnalysis} + + + + + + + diff --git a/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets b/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets index 4598709d..0a2170a4 100644 --- a/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets +++ b/src/MSBuild.Sdk.SqlProj/Sdk/Sdk.targets @@ -229,6 +229,7 @@ @(PostDeploy->'--postdeploy %(Identity)', ' ') @(RefactorLog->'--refactorlog %(Identity)', ' ') -an + @(Analyzer->'-aa "%(Identity)"', ' ') -ar "$(CodeAnalysisRules)" --debug --warnaserror @@ -236,7 +237,7 @@ -tdn "$(TargetDatabaseName)" -spw "$(SuppressTSqlWarnings)" -spl "$(IntermediateOutputPath)$(MSBuildProjectName).WarningsSuppression.txt" - dotnet "$(DacpacToolExe)" build $(OutputPathArgument) $(MetadataArguments) $(SqlServerVersionArgument) $(InputFileArguments) $(ReferenceArguments) $(SqlCmdVariableArguments) $(BuildPropertyArguments) $(DeployPropertyArguments) $(PreDeploymentScriptArgument) $(PostDeploymentScriptArgument) $(RefactorLogScriptArgument) $(TreatTSqlWarningsAsErrorsArgument) $(SuppressTSqlWarningsArgument) $(WarningsSuppressionListArgument) $(DebugArgument) $(GenerateCreateScriptArgument) $(TargetDatabaseNameArgument) $(RunSqlCodeAnalysisArgument) $(CodeAnalysisRulesArgument) + dotnet "$(DacpacToolExe)" build $(OutputPathArgument) $(MetadataArguments) $(SqlServerVersionArgument) $(InputFileArguments) $(ReferenceArguments) $(SqlCmdVariableArguments) $(BuildPropertyArguments) $(DeployPropertyArguments) $(PreDeploymentScriptArgument) $(PostDeploymentScriptArgument) $(RefactorLogScriptArgument) $(TreatTSqlWarningsAsErrorsArgument) $(SuppressTSqlWarningsArgument) $(WarningsSuppressionListArgument) $(DebugArgument) $(GenerateCreateScriptArgument) $(TargetDatabaseNameArgument) $(RunSqlCodeAnalysisArgument) $(CodeAnalysisRulesArgument) $(CodeAnalysisAssemblyLookupPathsArgument) diff --git a/test/DacpacTool.Tests/DacpacTool.Tests.csproj b/test/DacpacTool.Tests/DacpacTool.Tests.csproj index e45c0a5b..92fa53e7 100644 --- a/test/DacpacTool.Tests/DacpacTool.Tests.csproj +++ b/test/DacpacTool.Tests/DacpacTool.Tests.csproj @@ -8,6 +8,18 @@ 9.0 + + + Always + + + Always + + + Always + + + diff --git a/test/DacpacTool.Tests/PackageAnalyzerTests.cs b/test/DacpacTool.Tests/PackageAnalyzerTests.cs index 7d9a9d87..caffa77c 100644 --- a/test/DacpacTool.Tests/PackageAnalyzerTests.cs +++ b/test/DacpacTool.Tests/PackageAnalyzerTests.cs @@ -1,4 +1,6 @@ -using System.IO; +using System; +using System.Collections.Generic; +using System.IO; using System.Linq; using Microsoft.SqlServer.Dac.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -21,10 +23,10 @@ public void RunsAnalyzer() var packageAnalyzer = new PackageAnalyzer(_console, null); // Act - packageAnalyzer.Analyze(result.model, result.fileInfo); + packageAnalyzer.Analyze(result.model, result.fileInfo, CollectAssemblyPaths()); // Assert - testConsole.Lines.Count.ShouldBe(15); + testConsole.Lines.Count.ShouldBe(16); testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'"); testConsole.Lines.ShouldContain($"proc1.sql(1,47): Warning SRD0006 : SqlServer.Rules : Avoid using SELECT *."); @@ -32,6 +34,8 @@ public void RunsAnalyzer() testConsole.Lines.ShouldContain($"Successfully analyzed package '{result.fileInfo.FullName}'"); } + + [TestMethod] public void RunsAnalyzerWithSupressions() { @@ -42,10 +46,10 @@ public void RunsAnalyzerWithSupressions() var packageAnalyzer = new PackageAnalyzer(_console, "-SqlServer.Rules.SRD0006;-Smells.SML005;-SqlServer.Rules.SRD999;+!SqlServer.Rules.SRN0002;"); // Act - packageAnalyzer.Analyze(result.model, result.fileInfo); + packageAnalyzer.Analyze(result.model, result.fileInfo, CollectAssemblyPaths()); // Assert - testConsole.Lines.Count.ShouldBe(13); + testConsole.Lines.Count.ShouldBe(14); testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'"); testConsole.Lines.Any(l => l.Contains("SRD0006")).ShouldBeFalse(); @@ -64,10 +68,10 @@ public void RunsAnalyzerWithWildcardSupressions() var packageAnalyzer = new PackageAnalyzer(_console, "-SqlServer.Rules.SRD*"); // Act - packageAnalyzer.Analyze(result.model, result.fileInfo); + packageAnalyzer.Analyze(result.model, result.fileInfo, CollectAssemblyPaths()); // Assert - testConsole.Lines.Count.ShouldBe(13); + testConsole.Lines.Count.ShouldBe(14); testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'"); testConsole.Lines.Any(l => l.Contains("SRD")).ShouldBeFalse(); @@ -84,10 +88,10 @@ public void RunsAnalyzerWithWarningsAsErrors() var packageAnalyzer = new PackageAnalyzer(_console, "+!SqlServer.Rules.SRD0006"); // Act - packageAnalyzer.Analyze(result.model, result.fileInfo); + packageAnalyzer.Analyze(result.model, result.fileInfo, CollectAssemblyPaths()); // Assert - testConsole.Lines.Count.ShouldBe(15); + testConsole.Lines.Count.ShouldBe(16); testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'"); testConsole.Lines.ShouldContain($"proc1.sql(1,47): Error SRD0006 : SqlServer.Rules : Avoid using SELECT *."); @@ -105,18 +109,41 @@ public void RunsAnalyzerWithWarningsAsErrorsUsingWildcard() var packageAnalyzer = new PackageAnalyzer(_console, "+!SqlServer.Rules.SRD*"); // Act - packageAnalyzer.Analyze(result.model, result.fileInfo); + packageAnalyzer.Analyze(result.model, result.fileInfo, CollectAssemblyPaths()); // Assert - testConsole.Lines.Count.ShouldBe(15); + testConsole.Lines.Count.ShouldBe(16); + testConsole.Lines.Count(l => l.Contains("Using additional analyzers: ")).ShouldBe(1); testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'"); + testConsole.Lines.ShouldNotContain("DacpacTool warning SQLPROJ0001: No additional rules files found, consider adding more rules via PackageReference - see the readme here: https://github.com/rr-wfm/MSBuild.Sdk.SqlProj."); testConsole.Lines.ShouldContain($"proc1.sql(1,47): Error SRD0006 : SqlServer.Rules : Avoid using SELECT *."); testConsole.Lines.ShouldContain($"-1(1,1): Error SRD0002 : SqlServer.Rules : Table does not have a primary key."); testConsole.Lines.Count(l => l.Contains("): Error ")).ShouldBe(2); testConsole.Lines.ShouldContain($"Successfully analyzed package '{result.fileInfo.FullName}'"); } + [TestMethod] + public void RunsAnalyzerWithoutAdditionalAnalyzers() + { + // Arrange + var testConsole = (TestConsole)_console; + testConsole.Lines.Clear(); + var result = BuildSimpleModel(); + var packageAnalyzer = new PackageAnalyzer(_console, null); + + // Act + packageAnalyzer.Analyze(result.model, result.fileInfo, Array.Empty()); + + // Assert + testConsole.Lines.Count.ShouldBe(16); + + testConsole.Lines[1].ShouldBe("DacpacTool warning SQLPROJ0001: No additional rules files found, consider adding more rules via PackageReference - see the readme here: https://github.com/rr-wfm/MSBuild.Sdk.SqlProj."); + testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'"); + testConsole.Lines.Count(l => l.Contains("): Error ")).ShouldBe(0); + testConsole.Lines.ShouldContain($"Successfully analyzed package '{result.fileInfo.FullName}'"); + } + private static (FileInfo fileInfo, TSqlModel model) BuildSimpleModel() { var tmodel = new TestModelBuilder() @@ -128,5 +155,15 @@ private static (FileInfo fileInfo, TSqlModel model) BuildSimpleModel() return (new FileInfo(packagePath), model); } + + private FileInfo[] CollectAssemblyPaths() + { + var result = new List(); + var path = Path.GetDirectoryName(Path.Combine(System.Reflection.Assembly.GetAssembly(typeof(PackageAnalyzerTests)).Location)); + result.Add(new FileInfo(Path.Combine(path, "SqlServer.Rules.dll"))); + result.Add(new FileInfo(Path.Combine(path, "TSQLSmellSCA.dll"))); + + return result.ToArray(); + } } } diff --git a/test/DacpacTool.Tests/SqlServer.Dac.dll b/test/DacpacTool.Tests/SqlServer.Dac.dll new file mode 100644 index 00000000..09d9b6c7 Binary files /dev/null and b/test/DacpacTool.Tests/SqlServer.Dac.dll differ diff --git a/test/TestProjectWithAnalyzers/Rules/SqlServer.Rules.dll b/test/DacpacTool.Tests/SqlServer.Rules.dll similarity index 50% rename from test/TestProjectWithAnalyzers/Rules/SqlServer.Rules.dll rename to test/DacpacTool.Tests/SqlServer.Rules.dll index e3b9fab3..163c94ae 100644 Binary files a/test/TestProjectWithAnalyzers/Rules/SqlServer.Rules.dll and b/test/DacpacTool.Tests/SqlServer.Rules.dll differ diff --git a/test/DacpacTool.Tests/TSQLSmellSCA.dll b/test/DacpacTool.Tests/TSQLSmellSCA.dll new file mode 100644 index 00000000..ed71901d Binary files /dev/null and b/test/DacpacTool.Tests/TSQLSmellSCA.dll differ diff --git a/test/TestProjectWithAnalyzers/Rules/SqlServer.Dac.dll b/test/TestProjectWithAnalyzers/Rules/SqlServer.Dac.dll deleted file mode 100644 index 6ea8cd1f..00000000 Binary files a/test/TestProjectWithAnalyzers/Rules/SqlServer.Dac.dll and /dev/null differ diff --git a/test/TestProjectWithAnalyzers/TestProjectWithAnalyzers.csproj b/test/TestProjectWithAnalyzers/TestProjectWithAnalyzers.csproj index 7d49d0aa..7d170a01 100644 --- a/test/TestProjectWithAnalyzers/TestProjectWithAnalyzers.csproj +++ b/test/TestProjectWithAnalyzers/TestProjectWithAnalyzers.csproj @@ -2,16 +2,15 @@ - netstandard2.0 + netstandard2.1 Sql150 - True -SqlServer.Rules.SRD0006;-Smells.*;+!SqlServer.Rules.SRN0002 + true - - - - + + + \ No newline at end of file