rr-wfm / MSBuild.Sdk.SqlProj

An MSBuild SDK that provides similar functionality to SQL Server Data Tools (.sqlproj) projects
MIT License
414 stars 47 forks source link

[Question] Is there a way to set up the project to only build if source files change? #63

Open kevcrooks opened 4 years ago

kevcrooks commented 4 years ago

At the moment, if I set up the project then run a build it will say "1 succeeded".

If I run the build again without changing any files, I'd like the build to be skipped (i.e. "1 up-to-date" instead of "1 succeeded" in Visual Studio)

Is there a way to do this, or is it not possible, because we always need to reproduce the dacpac file?

jeffrosenberg commented 4 years ago

We do currently support incremental builds. I'm not sure about what controls the specific verbiage coming out of MSBuild, but if no files are changed, the project isn't re-built.

jmezach commented 4 years ago

@kevcrooks It should not recreate the dacpac file on every build, but I do believe that Visual Studio still reports 1 succeeded instead of 1 up-to-date. I'm not entirely sure why that is. Perhaps the way we've implemented it doesn't match with the expectations that Visual Studio has.

Is this a problem for you? If so I would like to understand why. We shouldn't be "waisting" resources if that's your concern.

kevcrooks commented 4 years ago

Thank you, I'll check this, the main reason I'd like this is so I can add a dotnet publish to our Database as a post-build step (before my dependent projects), but I think it was getting into a build loop because the dotnet publish was doing another build.

I may not be doing this the best way, but I noticed that I was previously using 1.6.0, so I'll see if this works now I'm on 1.8.1 - please let me know if there's a better way for me to go about a publish as part of the build though

kevcrooks commented 4 years ago

I've just checked and I'm seeing the same on 1.8.1.

The main thing I'd like is to be able to deploy the Database as part of a build - but only if the build has changed (so I'm not needing to deploy every time). At the moment I've tried adding:

dotnet publish --no-build --no-restore --no-dependencies

as a post-build step, but this is triggering a recurring set of builds.

My backup plan is to create a separate project that only calls dotnet publish as a build step, and make all my other projects dependent on that one instead, but I wanted to check if there's a nicer way to do this? And also this has the issue of deploying the Database every time, even if the files haven't changed.

jeffrosenberg commented 4 years ago

@jmezach looking at the incremental build docs again, I think the difference here is that what's being skipped is our CoreCompile target, not the entire build. I'm not sure whether there's a way to actually skip the entire build, though, because we need some of the earlier targets in the build to generate the list of inputs to check.

jmezach commented 4 years ago

If you're doing a dotnet publish and the .dacpac hasn't been build yet, it should do a dotnet build for you. If the .dacpac has been build and none of the source files have changed it should just use the existing .dacpac that's already there.

If that's not the case, please let us know because then there might be a bug.

jmezach commented 4 years ago

@jeffrosenberg Hmm, maybe that could be resolved by making the Build target dependent on the targets we need and then put the Inputs and Outputs on that target instead.

kevcrooks commented 4 years ago

@jmezach do you know if there's a workaround I can do on my end in the meantime - to get a build/publish to from the project only when the files change (I.e. so that any other project depending on it will run the build/publish step as part of its build, but only when needed)?

jmezach commented 4 years ago

@kevcrooks It looks like you're specifically experiencing an issue with projects that depend on each other. We currently don't support project references yet (see #40) so I'm wondering how you've set things up. Could you share some of the relevant sections of your project file(s)?

kevcrooks commented 4 years ago

@jmezach apologies I don't think I explained quite right.

My SqlProj doesn't need any dependencies, but I have a separate (e.g. console app) project that I'd like to depend on the SqlProj project, so that when I build my console app, the SqlProj project will dotnet build and dotnet publish if needed.

Here's some sample projects I've set up: One issue I'm having is that the post-build publish step doesn't work, since it will cause the project to build in a loop, so I'd like a way around this:

<Project Sdk="MSBuild.Sdk.SqlProj/1.8.1">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <SqlServerVersion>Sql130</SqlServerVersion>
        <TargetServerName>(localdb)\mssqllocaldb</TargetServerName>
        <TargetDatabaseName>TestDB</TargetDatabaseName>
    </PropertyGroup>
    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
      <Exec Command="dotnet publish --no-build --no-restore --no-dependencies" />
    </Target>
</Project>
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Database1.csproj" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="FSharp.Data.SqlClient" Version="2.0.6" />
  </ItemGroup>

</Project>

The reason I'd like to have another project depend on the SqlProj, is that there's an F# connector will link to a live localhost DB to provide intellisense. But this requires the most up-to-date version, i.e. I need to perform dotnet publish when theSqlProj changes.

Ideally I'd like to not do a deployment on every build, but just when I've changed something in the SqlProj, if you have a way to do this?

jmezach commented 4 years ago

Ah, I think I understand what you want now. Basically you're looking for incremental publish (on top of incremental build) in that the publish is only performed if the .dacpac has actually changed. We already support incremental build, so I guess we could have the .dacpac as an Inputs on the Publish target.

But we'd also need an Outputs and I'm not quite sure what the best way would be to implement that. To do it correctly we'd need to check the actual database to see when that has last been updated which isn't trivial to do. Or perhaps we could write a file to the obj folder on each publish and we use that as the Outputs. That way it wouldn't republish the database if that file is newer (or the same) as the .dacpac. I think that'll work, but it won't account for any changes made to the actual database of course.

@ErikEJ @jeffrosenberg Would love to hear your thoughts on this design?

jeffrosenberg commented 4 years ago

I'm not convinced we would want to add an incremental publish step here, since as you said, we'd really need to check the actual database, which I think is too heavyweight an approach. One thing I'd like to point out here is that by its nature, the publish step is already incremental -- it reads the state of the database and applies only those updates needed.

I think what the OP really wants is to not bother moving on to the publish step at all based on whether a new build is needed. I think that means updating our incremental build to skip the entire build rather than just a single target, so that MSBuild views the build as "skipped", rather than "successful". No idea whether @jmezach's suggestion from last week will work for that, but it's worth a try.

In the meantime, @kevcrooks, I think the only viable "workaround" here is to just run the publish every time. I understand that's not ideal for you, but because of the way the publish works, if there's nothing to be done that step will just become a no-op.

jeffrosenberg commented 4 years ago

To clarify my comments above, my concern about the proposed design is that the last-updated time of the .dacpac file isn't necessarily a good way to judge whether a publish is needed -- we would really need to check the database. For example, what if the user is trying to publish to multiple environments? The first publish would succeed, but each subsequent publish would be skipped as not needed.

ErikEJ commented 4 years ago

Agree on "publish every time" - that is how DaxFX works - "desired state configuration"

kevcrooks commented 4 years ago

I think what the OP really wants is to not bother moving on to the publish step at all based on whether a new build is needed. I think that means updating our incremental build to skip the entire build rather than just a single target, so that MSBuild views the build as "skipped", rather than "successful". No idea whether @jmezach's suggestion from last week will work for that, but it's worth a try.

In the meantime, @kevcrooks, I think the only viable "workaround" here is to just run the publish every time. I understand that's not ideal for you, but because of the way the publish works, if there's nothing to be done that step will just become a no-op.

@jeffrosenberg yes that's correct, it's what I'm aiming for. However dotnet publish as a post-build step won't work at the moment until your suggestion with the incremental build is done. At the moment a publish triggers a build, which in turn triggers a publish (if set as a post-build step) and so on... so I may need to wait until the incremental build fix is complete to get this?

jmezach commented 4 years ago

I guess we could try the suggestion I made earlier and ship that as a beta version for @kevcrooks to try out. I'm fairly busy at the moment though, so I don't know when I'll have the time to make that change, so if there's anyone else who has time for this let me know and then I'll assign the issue.

jeffrosenberg commented 4 years ago

@jmezach I can give it a try today or tomorrow. If that doesn't work, I don't know how much additional time I can commit to playing around with this, but I'll give your suggestion a try and see what happens!

jmezach commented 4 years ago

@jeffrosenberg That would be awesome. I've assigned the issue to you for now. If it doesn't work let us know and we'll have another look at it.

jeffrosenberg commented 4 years ago

So far, I've managed to get the binlog to show that the Build step is skipped, but it hasn't resolved the problem of a circular reference when targeting the PostBuildEvent. I have a few more thoughts, so I'm going to stick with it for a bit longer, but might be a couple of days before I can get back to it.

jeffrosenberg commented 4 years ago

@kevcrooks I'm looking more closely at the MSBuild documentation, and I don't think <Target Name="PostBuild" AfterTargets="PostBuildEvent"> will work the way you expect it to. Based on the target build order, I believe your post-build publish step will run every time:

Before the target is executed, its Inputs attribute and Outputs attribute are compared. If MSBuild determines that any output files are out of date with respect to the corresponding input file or files, then MSBuild executes the target. Otherwise, MSBuild skips the target.

After the target is executed or skipped, any other target that lists it in an AfterTargets attribute is run. [Emphasis mine]

After quite a bit of testing, I believe the only way we can avoid this infinite loop is to remove the Publish target's dependence on Build. I could be open to that, because I think having a project file set up like this (a build with a post-build publish action) is pretty common and will lead many people into this sort of loop. On the other hand, if we don't double-check that Build has run before Publish, we risk the publish having unexpected effects, as expected changes won't be published if the user hasn't explicitly run Build first.

I'm not too familiar with dotnet build conventions, so I'm not sure what makes the most sense. Either way, I think a couple of sentences of documentation about the build order would be helpful. @jmezach @ErikEJ any thoughts about the Publish target's dependence on Build?

Regardless of what we decide on that, there is one change I tested while working on this that I think I'd like to send a PR for -- moving the incremental build Inputs and Outputs from the CoreCompile target to the Build target. (EDIT: I played around with this a little more and I've changed my mind, apparently when doing this the CoreCompile target still runs)

kevcrooks commented 4 years ago

@jeffrosenberg Yes you're right, I've just tested with the following app, and dotnet build runs both the pre-build and post-build steps every time. (However there's no infinite build loop in this example, because it's able to detect everything is up-to-date) EDIT: The code below just runs powershell, but I checked it avoids the infinite loop when the post-build step contains dotnet publish too

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="powershell Write-Host &quot;post-build&quot;" />
  </Target>

  <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="powershell Write-Host &quot;pre-build&quot;" />
  </Target>

</Project>

However from Visual Studio, once it detects that the project is "1 up-to-date" it doesn't run the pre- or post-builds after the first time: image

image

Most of the time I'll be using Visual Studio (and my motivation was to avoid unnecessary deployments when developing), so I think as long as we can get the "1 up-to-date" fix for Visual Studio builds then that would work great for me.

And although the post-build publish would always happen with dotnet build, at least it would only happen once (without the build loop), so it would work fine on our build server too.

jmezach commented 4 years ago

@jeffrosenberg I'm not entirely sure that we actually need the Publish target to depend on the Build target. We could perhaps just check if the output file exists (and fix #68 in the process ;)) and throw an error if it doesn't instructing people to run a dotnet build first.

Also, I'm not sure about this, but it might be that dotnet will implicitly run build before a publish. That might be something that is build into dotnet itself. I believe it does the same thing with restore when you run build. This is just conjecture on my part though, I haven't verified that ;).

jmezach commented 4 years ago

Just tried what I described above, but it does seem that if we remove the dependency on the Build target the dotnet publish command doesn't run dotnet build behind the scenes. Interestingly there is a --no-build argument for dotnet publish which would suggest it does do the build implicitly (since it works similarly to --no-restore). I guess I'll have to do some more digging to see what's going on.

jmezach commented 4 years ago

Looks like the up-to-date check is actually a Visual Studio feature that is separate from the MSBuild logic. I found this document that describes this feature. We might be able to implement that, although I'm not sure if this will solve the problem at hand.

jeffrosenberg commented 4 years ago

Nice catch, that definitely explains what we're seeing

jmezach commented 4 years ago

We should probably add a separate issue for tracking the implementation of the Visual Studio up-to-date-check. I might be able to throw something together this weekend and ship a beta version. Then we can ask @kevcrooks to evaluate whether it solves this issue. If it does that's nice, if it doesn't we can keep this open and explore further options.

kevcrooks commented 4 years ago

Thanks @jmezach, yes happy to test any beta version next week

jmezach commented 4 years ago

@kevcrooks I've just uploaded a beta version that should fix the up-to-date check issue (for which I've created a separate issue, see #74). Could you give that a try and see if this also resolves your issue? Should be just a matter of editing your .csproj and swapping out the version number in the Sdk attribute on the <Project> element. Please let us know how that goes.

kevcrooks commented 4 years ago

@kevcrooks I've just uploaded a beta version that should fix the up-to-date check issue (for which I've created a separate issue, see #74). Could you give that a try and see if this also resolves your issue? Should be just a matter of editing your .csproj and swapping out the version number in the Sdk attribute on the <Project> element. Please let us know how that goes.

@jmezach I just tried the following version: <Project Sdk="MSBuild.Sdk.SqlProj/1.9.0-beta.5.g60d0950ebe"> with the post-build:

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="dotnet publish --no-build --no-restore --no-dependencies" />
  </Target>

but I didn't notice any difference in behaviour (the build was looping continuously still) - was this the beta version you meant?

jmezach commented 4 years ago

@kevcrooks Yes, that seems to be the correct version. So I guess that just implementing the fast up-to-date check doesn't solve your issue then.

I had a look at what dotnet publish does behind the scenes, but it seems that the --no-build flag doesn't actually do anything. Looking at the source code it seems to have the same behaviour as --no-restore. So I can understand why the loop is happening, because dotnet publish will just run the Publish target which has a dependency on the Build target.

One thing you could try perhaps is to have your PostBuild target call the Publish target using <CallTarget>. That way you stay within the same MSBuild process so it should have figured out that the Build target has already run and shouldn't run it again.

brettrowberry commented 4 years ago

FYI I’m extremely interested in this workflow!

jmezach commented 4 years ago

@kevcrooks Have you managed to give the suggested solution a try yet? If that works it might be worthwhile to make this a built-in (toggle-able) feature.

kevcrooks commented 4 years ago

@jmezach apologies just come back to this, but I'll try the workaround today or tomorrow.

Do you know if it's possible to fix the underlying issue of the project build loop in VS? If it's possible to match the behaviour of a standard console app where, when dotnet publish is in the post-build step, it will detect there is "1 up-to-date" so this doesn't have a build loop. As above, with this console app, doing a dotnet build from the command line will always run the post- and pre-build steps, but won't do an infinite loop, so if this behaviour can be matched with the sqlproj, that would be ideal for me?

I'll definitely try this though, as if it gets what we need in the meantime that will be good

jmezach commented 4 years ago

@kevcrooks Would you mind sharing a binary log of running a dotnet build on your console app that has that post-build step to run dotnet publish? I honestly wouldn't know what the difference would be between a console app and a sqlproj so I'll need some more details to figure out what's going on.

You can get the binary log by running dotnet build /bl which should give you an msbuild.binlog file. Please note that the file includes all your environment variables.

kevcrooks commented 4 years ago

@jmezach I can't share the binlog unfortunately, but I've included more details to recreate as it's just two csproj files that I'm using: For the console app:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <Compile Include="Program.fs" />
    </ItemGroup>

    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <Exec Command="powershell Write-Host &quot;post-build&quot;&#xD;&#xA;dotnet publish --no-build" />
    </Target>

    <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
        <Exec Command="powershell Write-Host &quot;pre-build&quot;" />
    </Target>

</Project>

For the SqlProj:

<Project Sdk="MSBuild.Sdk.SqlProj/1.8.1">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <SqlServerVersion>Sql130</SqlServerVersion>
    <TargetServerName>(localdb)\mssqllocaldb</TargetServerName>
    <TargetDatabaseName>MainDB3</TargetDatabaseName>
  </PropertyGroup>

    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <Exec Command="powershell Write-Host &quot;post-build&quot;&#xD;&#xA;dotnet publish --no-build" />
    </Target>
    <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
        <Exec Command="powershell Write-Host &quot;pre-build&quot;" />
    </Target>

</Project>

You can use the above project files to recreate, and if the behaviour of the console app can be matched, this will work fine for me. I think the problem comes from the SqlProj thinking that there needs to be a build when there doesn't.

Console app From Visual Studio image

SqlProj from Visual Studio (has an infinite loop) image

Console app dotnet build image

SqlProj dotnet build (this is stuck in a loop) Ideally this would match the behaviour for the console app as well. image

I'll try your suggested solution as well in the meantime, thanks again

Note: The --no-build part of the post-build is required for the console app, since if I remove this, there is an infinite build loop for the console app too

kevcrooks commented 3 years ago

@jmezach I wanted to check if you think the change we need might be possible? We're looking to migrate to this if possible, but need to know that it would be able to work in a pipeline as discussed in the repro before we do? Because of the environment variables, I can't share the bin file but I think the info above should be enough detail to reproduce on your end?

jmezach commented 3 years ago

@kevcrooks I'm still wondering if you've tried the <CallTarget> workaround I described in this comment. I still think that'll solve your issue.

kevcrooks commented 3 years ago

@jmezach I set the target as I think you mean, but I get an error in VS with a "There is a circular dependency in the target dependency graph..." I used the same csproj files as above for a console app and the SqlProj, but edited the SqlProj file to this:

<Project Sdk="MSBuild.Sdk.SqlProj/1.8.1">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <SqlServerVersion>Sql130</SqlServerVersion>
        <TargetServerName>(localdb)\mssqllocaldb</TargetServerName>
        <TargetDatabaseName>TestDB</TargetDatabaseName>
    </PropertyGroup>
    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <CallTarget Targets="Publish"></CallTarget>
    </Target>
</Project>

Can you let me know the corrections to this SqlProj file that should work using the CallTarget in the suggestion?

kevcrooks commented 3 years ago

The closest I was able to get after a bit more playing around was this

<Project Sdk="MSBuild.Sdk.SqlProj/1.8.1">
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <SqlServerVersion>Sql130</SqlServerVersion>
        <TargetServerName>(localdb)\mssqllocaldb</TargetServerName>
        <TargetDatabaseName>TestDB</TargetDatabaseName>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
      <WarningLevel>3</WarningLevel>
    </PropertyGroup>
    <Target Name="MyPublishAfterBuildTarget" AfterTargets="Build">
        <CallTarget Targets="Publish"></CallTarget>
    </Target>
</Project>

This has the behaviour that it will always publish when building from VS and the command line (but at least without a circular dependency). I think this is because of the bug mentioned before that (if I remove the extra Target), VS always tries a build, i.e. "1 succeeded" instead of "1 up-to-date".

I think that if this underlying issue can be fixed, then the target here might have the behaviour we need.

Unfortunately I'll not be able to do more testing on this without a fix. We would be very keen to migrate in the future if this can get sorted though, so please do update me if a fix gets published, and thank you for your ideas this far.

kevcrooks commented 3 years ago

@jmezach I was just able to come back to this again, and with fresh eyes I'm almost able to get a workflow that will suit us.

Unfortunately I'm now having a problem where the project will not build when it should do.

I've set up a basic template project with a single table in Visual Studio. When I update the table and do a build in Visual studio it says: ========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ========== even though the .sql file for the table has changed. (Note that dotnet build in the command line works correctly).

Is there a way to get Visual Studio to match the dotnet build behaviour - i.e. detect that because the .sql file has changed, the project is not "up-to-date"?

If I can get this part working, I think that gives us a good workflow, so I can post our final solution as the answer.

jmezach commented 3 years ago

Hmm, not sure why that doesn't work as expected. Could you try these debugging suggestions and post the output here so we can have a look at what's going on?

kevcrooks commented 3 years ago

@jmezach Here's the verbose output with a project containing a single table, if I edit e.g. the name of a field in the Table.sql file.

I found that this happens because I don't need need these lines to explicitly reference the .sql file in the .csproj any more:

    <ItemGroup>
        <Compile Include="Table.sql" />
    </ItemGroup>

However if do include these lines in the .csproj file, then all works as expected, so this is probably a good enough work-around for us. But if there is a fix to avoid needing to do this, that would be great too.

This is the log, if I change a .sql file, without including the lines above - the project doesn't detect a change, so doesn't build:

Build started...
1>FastUpToDate: Adding UpToDateCheckBuilt outputs: (Database1)
1>FastUpToDate:     'C:\Users\kevcr\source\repos\Database1\obj\Debug\netstandard2.0\Database1.dacpac' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\source\repos\Database1\bin\Debug\netstandard2.0\Database1.dacpac' (Database1)
1>FastUpToDate: Adding project file inputs: (Database1)
1>FastUpToDate:     'C:\Users\kevcr\source\repos\Database1\Database1.csproj' (Database1)
1>FastUpToDate: Adding newest import input: (Database1)
1>FastUpToDate:     'C:\Users\kevcr\source\repos\Database1\Database1.csproj' (Database1)
1>FastUpToDate: Adding ResolvedCompilationReference inputs: (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.MemoryMappedFiles.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tools.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.Encoding.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Requests.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Pipes.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Debug.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Console.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.IsolatedStorage.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ServiceModel.Web.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.NetworkInformation.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.SecureString.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.Extensions.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Transactions.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Security.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.TraceSource.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Tasks.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Timer.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XPath.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.RegularExpressions.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.CompilerServices.VisualC.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Sockets.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Concurrent.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XPath.XDocument.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.TextWriterTraceListener.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Web.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.FileSystem.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Json.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.Writer.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ValueTuple.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Calendars.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.UnmanagedMemoryStream.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Xml.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\Microsoft.Win32.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Parallel.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XDocument.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.Composition.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Specialized.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Process.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Numerics.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Ping.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlSerializer.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Overlapped.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Extensions.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.EventBasedAsync.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.Linq.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tracing.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.Client.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Contracts.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Claims.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Data.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.NameResolution.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\mscorlib.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Http.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Principal.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.ReaderWriter.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.ZipFile.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.DriveInfo.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Numerics.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Thread.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Core.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.AppContext.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Algorithms.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Tasks.Parallel.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Text.Encoding.Extensions.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Handles.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.ThreadPool.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Windows.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Data.Common.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.ResourceManager.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Dynamic.Runtime.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Reflection.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.TypeConverter.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Extensions.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ObjectModel.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.FileVersionInfo.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.Serialization.Formatters.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.Reader.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.NonGeneric.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Csp.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Expressions.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.RuntimeInformation.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Encoding.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Watcher.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlDocument.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebHeaderCollection.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Primitives.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Queryable.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.X509Certificates.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.Serialization.dll' (Database1)
1>FastUpToDate:     'C:\Users\kevcr\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.StackTrace.dll' (Database1)
1>FastUpToDate: No inputs are newer than earliest output 'C:\Users\kevcr\source\repos\Database1\obj\Debug\netstandard2.0\Database1.dacpac' (22/04/2021 10:38:55). (Database1)
1>FastUpToDate: Project is up to date. (Database1)
1>FastUpToDate: Up to date check completed in 5.3 ms (Database1)
========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
jmezach commented 3 years ago

Hmm, looks like the fast-up-to-date check only looks at Compile items and not Content items. I guess we could change the SDK to use Compile as the build action instead of Content, but that would be a breaking change. Alternatively we could investigate whether we can influence the fast-up-to-date check to (also) look at Content. Maybe that would be as easy as adding < UpToDateCheckInput Include="@(Content)" /> to the SDK somewhere.

RyanThomas73 commented 3 years ago

I haven't looked through how your defining your inputs / outputs yet so I'm just going off of what I've read in this thread so far...

For modifying the fast up-to-date check values I recommend defining a custom set name that matches your inputs (e.g. @(Content)) to the output it should be compared against (e.g. a computed hash of the inputs, the output dacpac, etc)

<ItemGroup>
    <UpToDateCheckInput Include="@(SqlProjectFilesToCheckForChanges)" Set="SqlProjectFiles" />
    <!-- OR -->
    <UpToDateCheckInput Include="@(Content)" Set="SqlProjectFiles" />

    <UpToDateCheckOutput Include="$(GeneratedSqlProjectHashFile)" Set="SqlProjectFiles" />
    <!-- OR -->
    <UpToDateCheckOutput Include="$(PathToGeneratedDacpacFile)" Set="SqlProjectFiles" />
</ItemGroup>

Also, if you want to be able to short-circuit your incremental build in one of the earlier targets OR if someone has a need to implement their own custom target that only runs when the schema/project input files have changed the out-of-the-box hash tasks might be a relatively easy way to achieve this.

<!-- your.file.targets -->
<!-- Subsitute @(SqlProjectFilesToCheckForChanges) with @(Content) or whatever item set you need -->
<PropertyGroup>
    <GeneratedSqlProjectCacheFile>$(IntermediateOutputPath)$(MSBuildProjectFile).sqlprojectfiles.cache<GeneratedSqlProjectCacheFile>
</PropertyGroup>

<ItemGroup>
    <UpToDateCheckInput Include="@(SqlProjectFilesToCheckForChanges)" Set="SqlProjectFiles" />
    <UpToDateCheckOutput Include="$(GeneratedSqlProjectCacheFile)" Set="SqlProjectFiles" />
</ItemGroup>

<Target Name="_CreateSqlProjectCacheFile"
        Inputs="@(SqlProjectFilesToCheckForChanges)" 
        Outputs="$(GeneratedSqlProjectCacheFile)">

    <!-- Get the hash value for each of the input files -->
    <GetFileHash Files="@(SqlProjectFilesToCheckForChanges)">
        <Output TaskParameter="Items" ItemName="SqlProjectFilesWithHashValue" />
    </GetFileHash>

    <!-- Generate a combined hash for the input files -->
    <!-- You can also combine specific project/msbuild settings with the @(SqlProjectFilesWithHashValue) if there's more you need to key off of -->
    <Hash ItemsToHash="@(SqlProjectFilesWithHashValue->'%(FileHash)')">
        <Output TaskParameter="HashResult" PropertyName="_SqlProjectFilesCombinedHash" />
    </Hash>

    <!-- Write the updated .cache file only if the value has changed ->
    <WriteLinesToFile Lines="$(_SqlProjectFilesCombinedHash)" File="$(GeneratedSqlProjectCacheFile)" Overwrite="True" WriteOnlyWhenDifferent="True" />

    <ItemGroup>
        <FileWrites Include="$(GeneratedSqlProjectCacheFile)" />

        <!-- If you wanted to, you could configure it and let the .cache file flow through to the consuming projects as well -->
        <!-- Then they could key off of it in more advanced ways like reading the hash value and comparing it to a value for the last time they deployed the database to determine if they need to re-deploy -->
        <Content Include="$(GeneratedSqlProjectCacheFile)">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
    </ItemGroup>
</Target>

<PropertyGroup>
    <_YourCoreCompileDependsOn>$(_YourCoreCompileDependsOn);_CreateSqlProjectCacheFile</_YourCoreCompileDependsOn>
<PropertyGroup>

<!-- All of your later targets can then use the .cache file as the input to compare against their respective output -->
<Target Name="_YourCoreCompile"
             BeforeTargets="whatever"
             DependsOn="$(_YourCoreCompileDependsOn)"
             Inputs="$(GeneratedSqlProjectCacheFile)"
             Outputs="$(PathToGeneratedDacpacOrWhateverYourOutputsAre)">
   <!-- your target logic -->
</Target>
// Consuming project
<Project Sdk="Microsoft.NET.Sdk">
    <ItemGroup>
         <ProjectReference Include="..\path\to\DatabaseSdkProject.csproj" ReferenceOutputAssembly="False"  />
    </ItemGroup>

   <Target Name="PublishIfDatabaseHasChanges"
                 Inputs="..\path\to\the\cachefile"
                 Outputs="..\path\to\the\cachefile\for\the\most\recent\time\you\deployed">
        <!-- your public logic -->

        <WriteLinesToFile Lines="$(_SqlProjectFilesCombinedHash)" File="..\path\to\the\cachefile\for\the\most\recent\time\you\deployed" Overwrite="True" 
    </Target>
</Project>
ErikEJ commented 4 months ago

@jeffrosenberg @jmezach It looks to me like this works as expected with the latest dotnet SDK and the latest VS - can we close this?

jmezach commented 4 months ago

How do we know exactly that it works with the latest SDK and VS? Have I missed something? But yes, if it works now I don't see a need to keep this open.

ErikEJ commented 4 months ago

@jmezach I just did some manual testing, but maybe I did not cover all possible cases

bheemvennapureddy commented 3 months ago

I still see this error

➜  Business git:(disable_sql_rules) ✗ dotnet build src/WinchkDatabase/WinchkDatabase.csproj
MSBuild version 17.8.5+b5265ef37 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  Using target framework net8.0 to run DacpacTool
  CAPSHistoryDatabase -> /Users/bheemvennapureddy/github/Business/src/CAPSHistoryDatabase/bin/Debug/CAPSHistoryDatabase.dacpac
  Using target framework net8.0 to run DacpacTool
  WinchkDatabase -> /Users/bheemvennapureddy/github/Business/src/WinchkDatabase/bin/Debug/WinchkDatabase.dacpac
  MSBuild version 17.8.5+b5265ef37 for .NET
    Using target framework net8.0 to run DacpacTool
    CAPSHistoryDatabase -> /Users/bheemvennapureddy/github/Business/src/CAPSHistoryDatabase/bin/Debug/CAPSHistoryDatabase.dacpac
    Using target framework net8.0 to run DacpacTool
    WinchkDatabase -> /Users/bheemvennapureddy/github/Business/src/WinchkDatabase/bin/Debug/WinchkDatabase.dacpac
    MSBuild version 17.8.5+b5265ef37 for .NET
      Using target framework net8.0 to run DacpacTool
      CAPSHistoryDatabase -> /Users/bheemvennapureddy/github/Business/src/CAPSHistoryDatabase/bin/Debug/CAPSHistoryDatabase.dacpac
      Using target framework net8.0 to run DacpacTool
      WinchkDatabase -> /Users/bheemvennapureddy/github/Business/src/WinchkDatabase/bin/Debug/WinchkDatabase.dacpac
      MSBuild version 17.8.5+b5265ef37 for .NET
        Using target framework net8.0 to run DacpacTool
        CAPSHistoryDatabase -> /Users/bheemvennapureddy/github/Business/src/CAPSHistoryDatabase/bin/Debug/CAPSHistoryDatabase.dacpac
        Using target framework net8.0 to run DacpacTool
        WinchkDatabase -> /Users/bheemvennapureddy/github/Business/src/WinchkDatabase/bin/Debug/WinchkDatabase.dacpac
        MSBuild version 17.8.5+b5265ef37 for .NET
^CAttempting to cancel the build...
    Attempting to cancel the build...
  Attempting to cancel the build...
      Attempting to cancel the build...
/Users/bheemvennapureddy/github/Business/src/WinchkDatabase/WinchkDatabase.csproj(16,5): warning MSB5021: Terminating the task executable "bash" and its child processes because the build was canceled.

Build FAILED.

/Users/bheemvennapureddy/github/Business/src/WinchkDatabase/WinchkDatabase.csproj(16,5): warning MSB5021: Terminating the task executable "bash" and its child processes because the build was canceled.
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:06.54
➜  Business git:(disable_sql_rules) ✗ 

with the below csproj

<Project Sdk="MSBuild.Sdk.SqlProj/2.7.2">
  <Import Project="..\..\common.project.props" />
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <SqlServerVersion>Sql150</SqlServerVersion>
    <SuppressTSqlWarnings>71558,71502,71562</SuppressTSqlWarnings>
    <TargetName>WinchkDatabase</TargetName>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <RunSqlCodeAnalysis>True</RunSqlCodeAnalysis>
    <CodeAnalysisRules>-SqlServer.Rules.SRN*;-SqlServer.Rules.SRD*;-Microsoft.Rules.Data.SR*;-SqlServer.Rules.SRP*</CodeAnalysisRules>
    <TargetServerName>(LocalDB)\MSSQLLocalDB</TargetServerName>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="dotnet publish --no-build --no-restore --no-dependencies" />
  </Target>

  <ItemGroup>
    <None Include="SchemaComparisons\SchemaComparison.scmp" />
    <None Include="shared.publish.xml" />
    <None Include="SchemaComparisons\FromCashMoneyToProject.scmp" />
    <None Include="SchemaComparisons\FromSRC18_06.scmp" />
    <None Include="shared.publish.xml" />
    <None Include="local.publish.xml" />
    <None Include="SchemaComparisons\FromSrcToProject.scmp" />
    <None Include="SchemaComparisons\FromProjectToLocalDb.scmp" />
    <None Include="SchemaComparisons\FromCM18_06.scmp" />
  </ItemGroup>
  <ItemGroup>
    <PreDeploy Include="Scripts\Script.PreDeployment.sql" />
    <PostDeploy Include="Scripts\Script.PostDeployment.sql" />
    <None Include="package.nuspec">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Private>true</Private>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Content Remove="Scripts\Script.PreDeployment.sql" />
    <Content Remove="Scripts\Script.PostDeployment.sql" />
    <Content Remove="Scripts\Post-Deployment\2429.0-PostDeployment.sql" />
    <Content Remove="Scripts\Pre-Deployment\2429.0-PreDeployment.sql" />
    <RefactorLog Include="WinchkDatabase.refactorlog" />
  </ItemGroup>
  <ItemGroup>
    <SqlCmdVariable Include="AccountingDatabase">
      <DefaultValue>AccountingDatabase</DefaultValue>
      <Value>$(SqlCmdVar__8)</Value>
    </SqlCmdVariable>
    <SqlCmdVariable Include="AppLogDatabase">
      <DefaultValue>AppLogDatabase</DefaultValue>
      <Value>$(SqlCmdVar__15)</Value>
    </SqlCmdVariable>
    <SqlCmdVariable Include="BankCard">
      <DefaultValue>BankCard</DefaultValue>
      <Value>$(SqlCmdVar__13)</Value>
    </SqlCmdVariable>
    <SqlCmdVariable Include="CAPSHistoryDatabase">
      <DefaultValue>CAPSHistory</DefaultValue>
      <Value>$(SqlCmdVar__14)</Value>
    </SqlCmdVariable>
    <SqlCmdVariable Include="CustomerScoringDatabase">
      <DefaultValue>CustomerScoring</DefaultValue>
      <Value>$(SqlCmdVar__6)</Value>
    </SqlCmdVariable>
    <SqlCmdVariable Include="InternalAuditDatabase">
      <DefaultValue>InternalAudit</DefaultValue>
      <Value>$(SqlCmdVar__1)</Value>
    </SqlCmdVariable>
    <SqlCmdVariable Include="SqlReportServer">
      <DefaultValue>SQLRPT</DefaultValue>
      <Value>$(SqlCmdVar__9)</Value>
    </SqlCmdVariable>
  </ItemGroup>
  <ItemGroup>
      <ProjectReference Include="../CAPSHistoryDatabase/CAPSHistoryDatabase.csproj" DatabaseSqlCmdVariable="CAPSHistoryDatabase"/>
    </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.SqlServer.Dacpacs.Master" Version="150.1.1" DacpacName="master" DatabaseVariableLiteralValue= "master" />
    <PackageReference Include="Microsoft.SqlServer.Dacpacs.Msdb" Version="150.0.0" DacpacName="msdb" DatabaseVariableLiteralValue= "msdb"/>
    <PackageReference Include="Database.AppLog" Version="$(InHousePackageVersionSpec)" DacpacName="AppLogDatabase" DatabaseSqlCmdVariable="AppLogDatabase"/>
    <PackageReference Include="Database.CustomerScoring" Version="$(InHousePackageVersionSpec)" DacpacName="CustomerScoringDatabase"  DatabaseSqlCmdVariable="CustomerScoringDatabase"/>
    <PackageReference Include="Database.InternalAudit" Version="$(InHousePackageVersionSpec)" DacpacName="InternalAuditDatabase" DatabaseSqlCmdVariable="InternalAuditDatabase"/>
    <PackageReference Include="Database.HotelCardifornia" Version="1.0.*" DacpacName="HotelCardifornia.Database" DatabaseSqlCmdVariable="BankCard"/>
  </ItemGroup>
</Project>
jmezach commented 3 months ago

@bheemvennapureddy That looks more like a circular dependency issue unrelated to this issue?

bheemvennapureddy commented 3 months ago

@jmezach you mean to say that each of these projects has a circular dependency on the other? I don't think they are Winck has a dependency with Caps but there not other way around