Now I’m all for making my life easier and one thing that makes life easier for me is having a single process that I can run to install\update all my favourite utility stored procedures quickly and on all my SQL Servers.
I’ve done this a few different ways in the past but this time I got thinking about GitHub. We keep all our utility procs in a GitHub repository so wouldn’t it be cool if we could just access those scripts directly from GitHub and run them on multiple SQL Servers? This could be especially useful if I wanted to install or update these procs on an offsite customer’s Server where I might not easily have access to all my scripts.
I’m the first person to admin that I’m a bit of a noob when it comes to PowerShell but it seemed the best place to go to to get this done. The following scripts go out to your GitHub repository, pullback the scripts and run them on your specified SQL instances. I’ve purposely avoided using POSH-Git in these scripts as I wanted them to be something that could be run without the need to install Git.
Run A Single Specific Script On SQL1 and SQL2
$ScriptURL should be set to the URL of the raw script
Add-PSSnapin SqlServerCmdletSnapin120 Add-PSSnapin SqlServerProviderSnapin120 #set variables $ScriptURL="https://raw.githubusercontent.com/SQLUndercover/UndercoverToolbox/master/sp_restorescript.sql" $SQLInstances = "SQL1,SQL2" $DefaultDatabase = "master" ForEach ($SQLInstance in $SQLInstances.Split(",")) { echo "Running Scripts on " $SQLInstance $ScriptFromGit = Invoke-WebRequest $ScriptURL Invoke-Sqlcmd -Query $ScriptFromGit.Content -ServerInstance $SQLInstance -database $DefaultDatabase }
Run All Scripts From Specified Repository
$GitRepository should be set to the URL or the repository or folder within the repository that holds your scripts
Add-PSSnapin SqlServerCmdletSnapin120 Add-PSSnapin SqlServerProviderSnapin120 #set variables $GitRepository = "https://github.com/SQLUndercover/UndercoverToolbox" $SQLInstances = "SQL1,SQL2" $DefaultDatabase = "master" ForEach ($SQLInstance in $SQLInstances.Split(",")) { echo "Running Scripts on " $SQLInstance #get all sql files from GIT repository $files = (Invoke-WebRequest $GitRepository).Links | ? href -like *.sql #loop through all files and run them into SQL foreach ($file in $files.href) { $ScriptURL = ("https://raw.githubusercontent.com" + $file.Replace("/blob/","/")) echo "Running " $ScriptURL $ScriptFromGit = Invoke-WebRequest $ScriptURL Invoke-Sqlcmd -Query $ScriptFromGit.Content -ServerInstance $SQLInstance -database $DefaultDatabase } }
The above scrip will run all the scripts in the repository and in no particular order. What do we do if we only want to run in specific scripts or to run them in a certain order. In that case I decided to add a manifest file. This is just a text file that contains the scripts that you want to run and the order that they should be run. It a simple text file which lists the name of each script on a separate line, in the order that you want them run.
Run Scrips As Specified in the Manifest
$GitManifestURL is the URL of the raw manifest file
Add-PSSnapin SqlServerCmdletSnapin120 Add-PSSnapin SqlServerProviderSnapin120 #set variables $GitRepository = "https://github.com/SQLUndercover/UndercoverToolbox" $GitManifestURL = "https://raw.githubusercontent.com/SQLUndercover/UndercoverToolbox/master/Manifest.txt" $SQLInstances = "SQL1,SQL2" $DefaultDatabase = "master" ForEach ($SQLInstance in $SQLInstances.Split(",")) { echo "Running Scripts on " $SQLInstance #get manifest $Manifest = (Invoke-WebRequest $GitManifestURL).Content #loop through prereqs in order of the manifest and run them into SQL #foreach ($PreRec In $Manifest) ForEach ($Script in $Manifest.Split("`r`n")) { $ScriptURL = ($GitRepository + "/" + $Script) echo "Running " $ScriptURL $ScriptFromGit = Invoke-WebRequest $ScriptURL Invoke-Sqlcmd -Query $ScriptFromGit.Content -ServerInstance $SQLInstance -database $DefaultDatabase } }
Thanks for reading and I love to hear from you if you’ve got a different way of doing this 🙂
Looks like this would be useful for an “All Databases on a given Azure ‘server’ ” scenario. Server stays the same, but the database changes. We’ve had a need to run scripts for each database on an instance and this would help. Have to open/close a connection for each one due to the way Azure SQL works.
LikeLiked by 1 person
That’s a cracking thought! 🙂
I wrote it as a way to loop through multiple servers, I never thought of looping through databases in Azure in the same way. Nice thinking 🙂
LikeLike
Is there any way to do this with a login/password for a private github repo?
LikeLike
That’s a really good question and to be honest, I’m not actually sure. I’d imagine that there should be a way to pass credentials through. I’ll have to look into it.
LikeLike
This was my immediate thought as well – this would be ideal running from a Private Repo, as I’ve been wanting to apply this method to other areas of infrastructure as well, with lots of possibilities with PowerShell.
LikeLike
Sorry I am new to GITHUB, I want to understand where to keep this file and from where this file is calling file.
I have a repository, and in my project will run few sql script in each sprint, I want to do automate the deployment through GITHUB.
Note: my organization is not ready to buy any tools. I am using Enterprise GITHUB.
It helps me lot if you explain how can i do this in GITHUB.
LikeLike
This is great! Is it possible for the PowerShell script to pick up only the changed .SQL file and deploy at the server. How to go about it?
LikeLike
This is great! I am looking at implementing this, but do you have a sample manifest file? Sorry, still learning github.
LikeLike
Hi Tim,
For the scripts on this post, the manifest file just needs to be a simple text file with the filenames on a different line.
We use a similar idea for the auto updates on our Undercover Catalogue and Inspector tools, although the manifests for these also holds a little extra information around version numbers on top of just the filename.
https://github.com/SQLUndercover/UndercoverToolbox/blob/master/SQLUndercoverCatalogue/Updates/Manifest.csv
LikeLike
Having issue with Enterprise Github:
Invoke-WebRequest : The request was aborted: The connection was closed unexpectedly.
At line:34 char:18
+ $ScriptFromGit = Invoke-WebRequest $ScriptURL
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Any ideas?
LikeLike