dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.22k stars 1.35k forks source link

MSBuild BuildContributor-related parameter for specifying directory path #6615

Closed DanielLoth closed 3 years ago

DanielLoth commented 3 years ago

Hi everyone,

Background

I've recently been looking into adopting Microsoft.SqlServer.Dac.Deployment.BuildContributor and Microsoft.SqlServer.Dac.Deployment.DeploymentContributor.

Initially I was exploring them at home in my personal time, and more recently this week I've been working with a colleague to determine how we might operationalise a BuildContributor within a CICD pipeline.

The key issue is that we would like to develop the BuildContributor, check in code changes, and subsequently deploy it for use on a build server agent (ephemeral Team City build agent).

We can conceivably place the BuildContributor DLL files straight into the appropriate Extensions folder. For example:

C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\150\Extensions

However the challenge with deployments to a build server agent is that other processes on that server might be using the previous version of the DLL that we wish to deploy, thereby blocking or stalling a deployment.

Ideally, we'd be able to deploy to an arbitrary directory, update an environment variable to point to that arbitrary directory, and then pass that environment variable's value to msbuild on the command line.


Example ideal sequence of events

Firstly, we'd build our BuildContributor code using our CICD pipeline.

Secondly, once the build is confirmed 'good', we'd ideally deploy it to a target. We still need to work through how exactly this will work, but it'd most likely involve periodically checking for, and pulling, an updated version of a package.

At that point, we need to unpackage the DLL and drop the contents somewhere. In my view that would ideally be a path such as:

C:\MyBuildContributors\4d2f4565-0769-48f1-b2b5-bb6d7377e4b9

Being a newly created directory, the unpackaging will always succeed immediately (so long as there's adequate disk space).

Next we'd set, or update, an environment variable. For example, we might set an environment variable named BUILD_CONTRIBUTOR_HOME to the value C:\MyBuildContributors\4d2f4565-0769-48f1-b2b5-bb6d7377e4b9.

And finally, we'd be able to use it with msbuild like so:

%MSBUILD% %ProjectFile% ^
    /t:Build ^
    /p:Configuration=Release ^
    /p:BuildContributors="MyBuildContributor" ^
    /p:BuildContributorPaths=%BUILD_CONTRIBUTOR_HOME%

Research into the DeploymentContributor support revealed that the sqlpackage tool has support for specifying an arbitrary directory path to search for contributors in via the AdditionalDeploymentContributorPaths parameter:

%SQLPACKAGE% ^
    /Action:Script ^
    /SourceFile:%DacpacFilePath% ^
    /TargetServerName:%TargetServerName% ^
    /TargetDatabaseName:%DatabaseName% ^
    ...
    /p:AdditionalDeploymentContributors="MyDeploymentPlanModifier" ^
    /p:AdditionalDeploymentContributorPaths="%BUILD_CONTRIBUTOR_HOME%"

Workarounds for others who may encounter this problem

One workaround that we discovered was that we could create a Symbolic Link within the Extensions directory. This would allow us to discover a BuildContributor DLL in whichever arbitrary directory the SymLink pointed to.

One challenge with this is that you must create the SymLink in a command line terminal that has administrator privileges.


Request

I was wondering if the msbuild development team might consider implementing this as a new feature? Essentially a parameter named BuildContributorPaths or similar that can be used in the manner described above.


Thank you for taking your time to read this.

Kind regards, Daniel Loth

rainersigwald commented 3 years ago

To be clear, you're talking about doing something like what's described here? https://docs.microsoft.com/sql/ssdt/walkthrough-extend-database-project-build-to-generate-model-statistics?view=sql-server-ver15

I suspect this can be done with no new work at the MSBuild layer, but it might require work at the SQL layer. That doc suggests changes to the VS directory that most project extensibility doesn't require.

DanielLoth commented 3 years ago

Yes, that's correct. I'm looking at using it for tasks at build time such as:

rainersigwald commented 3 years ago

It looks like this is entirely controlled by the .sqlproj team, and not by MSBuild itself. Can you please open a feedback ticket for this?

After it's created, that will open an internal bug which will be routed to the right team. If you post the link here we may be able to help that process go faster.

I took a quick look at the MSBuild logic they're using and it looks like they just pass $(BuildContributors) to their SqlBuildTask. I guess it uses the name of the contributor to find and load the DLL somehow.

I agree that you should be able to use these features without modifying your Visual Studio installation, and I can be very clear on that in the internal bug that will be generated by your feedback.

I'm going to close this because we can't fix it but please do link the feedback item.

DanielLoth commented 3 years ago

Hi @rainersigwald, thank you for taking the time to investigate.

I've raised a request here: https://developercommunity.visualstudio.com/t/Add-support-for-p:BuildContributorPaths/1460247

I've written an abridged version in that request ticket, and referred them to this issue for a more concrete example of how the new parameter might be used.

rainersigwald commented 3 years ago

Routed and commented on the request, thanks!

DanielLoth commented 3 years ago

Hi @rainersigwald,

I hope you're well.

I was wondering if you could provide any news on this one. The request raised on the Developer Community website hasn't really moved since July, so I thought I might reach out here.

Is this change likely to progress in the near future?