Get Changesets Associated With Build - powershell

In TFS (2013 Update 4) I am trying to write a PowerShell script to copy modified SQL files that are tied to a build. I can get and copy the appropriate files if I know the changeset number, which will often be enough (I can use the TF_BUILD_SOURCEGETVERSION environment variable when the build is triggered by a merge). However, occasionally there will be a handful of changesets that are associated with the build in TFS.
Using the Build Number, how do I get a list of Changesets?

You need to use your build number to find the previous build number. You will then have both a start changeset (from previous build) to current changeset (current build).
You can then walk the gap with the API and find all the intervening changesets.

So I've done this in my last engagement, in essence we solved it by doing a get of all SQL related files EVERY build and produce a csv file that contained information about each file, name, version, and most importantly and MD5 hash of the file. Then with each deployment we create/update/insert into a special deployment table in our DB all SQL "run" against that DB. Then our build script is really just producing the csv file but our deployment script has the intelligence and checks to see if anything as changed in the csv file vs. the target DB and only applies changes (new SQL, changed SQL with new MD5). So we essentially use two scripts. I can't share the scripts but you have the idea. Also I would look at this article by Alexander
Automating SQL Server Database Deployments: Scripting Details where he explains a lot about db migration.

Related

Create SQL script from commits since last build

As a DevOps engineer, I want our developers to be able to place SQL scripts in a SQL Server Database Project folder and have the VSTS build agent prepare all scripts committed since the last successful build.
The reason I'm looking for only files since the last successful build is because I only want these scripts to run once. If they are built into a post-deployment script, they will be run every time the database is deployed. Most of these scripts are data changes and not schema changes.
I found this Build last commited [sic] SQL Script VSTS, but the solution applied to a Git repository for latest committed changes instead of a generic solution or TFVC equivalent.
Do I need to look into Visual Studio pre-build events? SQL Server Database Project post-deployment scripts? VSTS build agent task to search for and copy latest files to another location?
If they are built into a post-deployment script, they will be run every time the database is deployed.
The solution to this problem is to make the scripts idempotent. If data needs to be inserted, check if it's there before inserting it.
Sounds like what you really want is DBUP, it tracks which scripts have been ran and runs them via a console application.
https://dbup.readthedocs.io/en/latest/
https://marketplace.visualstudio.com/items?itemName=johanclasson.UpdateDatabaseWithDbUp

Track changes in configuration tables and create automated scripts to deploy them other envionments

In the product that I work on, there are many configuration tables. I need to find a way to track configuration changes (hopefully with some kind of version/changeset number), deploy the configuration changes to other environments using the changeset number and if needed rollback particular configuration based on changeset number.
I am wondering how can I do that?
One solution that I think could work is to write a script(s) to take all the configurations from all the config tables and create Json file(s). I can then check-in that file(s) to tfs or github to maintain versioning and write another script(s) to load that configuration file(s) in any environment.

Multiple Database Solution VSTS Release Definition

I am looking for help creating a release definition in VSTS to deploy database changes for a solution that targets 7 databases in a Data Warehouse/BI environment.
My solution is under TFVC in VSTS that contains 17 database projects targeting 7 databases, some databases have multiple projects due to cross database joins and reuse of a database objects in projects via database references. If the cross database joins weren't there this problem would be a lot easier to solve but it will take time to eradicate these.
When any change is committed the solution is built and the dacpacs generated are kept as artifacts for release.
My release definition is not particularly smart which consists of a PowerShell script that iterates over each dacpacs which generates a deployment report followed by a deployment. Whilst this works it does have its problem:
The deployments are done in alphabetical order, so if a changeset involves numerous databases it's possible the deployment will fail as something referenced in one database may not yet exist in another.
The deployments are made against each database regardless of what has changed, so creating a view in one database means that all of them have compare/deployment done against them which isn't necessary. Something like this would take seconds to create outside of the CI/CD process which currently takes 30 minutes for the build, release to test then live.
How can I make the release definition smarter?

Prevent msdeploy from syncing unchanged files after TFS Build?

When doing a get-latest from TFS, all timestamps are set to the time at which the get operation was executed. When doing running msdeploy to perform a sync, the timestamps in the source are compared with the timestamps on the target server. Of course, this means that with TFS + msdeploy, every file will be pushed to the target servers after every build, unless
You use incremental builds
You have only a single build agent in the build controller's pool.
If the build definition is set to do Clean builds, or if you want to utilize multiple build agents, then this no longer works.
This topic comes up all the time, and once every couple of years I cast out new lines in case something has changed. This could be fixed in a couple of different ways:
TFS sets timestamps on workspace files to the last checkin time.
TFS sets timestamps on workspace files to the last modified time from the files themselves when they were last checked in.
msdeploy uses some content-based comparison method (e.g. MD5) to compare files, rather than timestamp comparisons.
Something else?
I never know where to go to search for this stuff since both of these teams are pretty opaque--the webdeploy team in particular. Is this a problem that has been solved yet?
The TFS and visual Studio teams are entirely transparent and you can submit feature requests through http://visualstudio.uservoice.com and bugs through http://connect.microsoft.com.
However all files within a server workspace are set to the date the file was last modified on the server. Local workspaces physically compare the file contents to determin changes. You can change from local workspace to server workspace in the workspace properties.
In the end, we got around this by writing a powershell script to wrap the .cmd file produced by the Web Publishing Pipeline, and passing the -useChecksum flag in the command that invokes the .cmd script. Since the boilerplate .cmd created by WPP allows for passing additional arguments to msdeploy, we were able to accomplish this with a line like the following.
& "MyProject.cmd" /u:agent /p:P#ssw0rd /m:$ComputerName /y -useChecksum
In this way, even though TFS is creating workspaces with timestamps set to the get-latest time, msdeploy is now instructed to use checksums instead.

Script to Compare TFS labels in a folder

I have several branches in TFS (dev, test, stage) and when I merge changes into the test branch I want an automated script to find all the updated SQL files based on the labels and deploy them to the SQL database.
Currently I manually use compare in TFS source control explorer to get the files that are changed and use a custom powershell script to deploy to the database.
I am looking for a script that would copy the changed sql files to a repository so that my powershell will do the rest.
Any help would be appreciated.
Thanks
Nit