Deploy a Database Project DacPac using OctopusDeploy and PowerShell
In the past, I’ve had to write numerous collections of PowerShell scripts to deploy websites to various development servers. Octopus Deploy takes the pain out of that by providing a slick interface that lets you easily set up environments and get your code out to them.
One thing that it doesn’t handle out of the box is Database Projects. But it is possible.
Create the Package
Octopus packages are just NuGet packages. And the tool to create them is another NuGet package. All you need to do is add the OctoPack package to your project and then set the build parameter /p:RunOctoPack=true
and your package will be created.
At the moment, this package isn’t compatible with Database Projects so you’ll need to go through a couple of manual steps to reference it.
Download the Package
If you’re already using OctoPack in one of the other projects in your solution (such as your website), then you’ll already have it. If not, pull down the latest OctoPack to your packages folder using the Package Manager Console:
Reference it in your project
Right-click on your Database Project in Visual Studio and select “unload project”. Once that’s unloaded, right-click again and select “edit Database.sqlproj” (or the equivalent for whatever your project is called).
You’ll need to add in a few lines to reference OctoPack in there, so scroll to the bottom and enter the following just before the final </Project>
tag:
You’ll need to change the version number (3.0.41 above) to match the version that you’ve downloaded.
Once done, you can save and reload your project (right-click on the project file and select “Reload Project”).
Create the Publish Commands
The output of the Database Project is a DacPac file. We can run a deployment on this file using Microsoft.SqlServer.Dac.DacServices but we need something to trigger this build.
Octopus will run any PowerShell script found in the top level of the NuGet package. So, we’ll create a Deploy.ps1 file here and script our deployment inside of that.
This is what our file will look like:
On lines 1-21, we’re just checking for the parameters we’ll need to pass into the script when deploying the database:
- $dbName: the name of the database to targets
- $dbPublishProfile: the publish profile to use when deploying
- $dbUser: the database user to use
- $dbPassword: the password for the user being used
We can then add the Dac DLL reference to make the tools available.
Our deployment is going to be run directly on the target machine, so we can pull in DacServices using the local machine as our connection, giving it the DB user and password.
The next few lines set up some paths and output these to the logs for debugging:
Now we’re ready to load our DACPAC file…
…and the profile file…
…and use the services to deploy them:
Although our profile will already have a DB name specified in it, specifying it as a separate variable to pass in during deployment allows the same profile to be used for multiple targets.
Include the Script
We need to add this script, the DACPAC, and the profile file to our Octopus Deploy package. Since this is just a NuGet package, we can create a NuSpec file to specify what should be included.
Our Database.nuspec file looks like this:
We don’t set a target for the Deploy.ps1 file (line 12) so that it will sit in the top level of our package and be run by Octopus.
Now that’s in place, we can build our project and create our OctoPack file ready for deployment.
Set Up the Environment
We’ll be running the database deployment directly on the target machine, so we’ll need to install a Tentacle instance on there. If you’re already using Octopus for deployment, you’ll be familiar with this process. Or, you can go and refresh your memory using the Octopus Deploy docs.
Once created, we can add our target machine into our environment and tag it as a DB Server.
Now we’re ready to deploy our database.
Deploy the Package
First, we’ll go into our Octopus Deployment Process for our project and select “Add Step“.
Then we’ll select “Deploy a NuGet package” as our step type.
Lastly, we’ll enter the details of our step name and package details (in this example, I’m pulling the package from a TeamCity feed).
Parameters
Our Deploy.ps1 file requires 4 parameters to run:
- $dbName
- $dbPublishProfile
- $dbUser
- $dbPassword
We can provide these using Octopus’ Variables section in our project.
One of the best features of Octopus Deploy is the ability to set up different values for the same build parameter dependent on the environment or build step currently running.
We’ll set ours up for Dev and our Deploy DB step.
And now, when we run our deployment, our database will be pushed along with the code.