Harald S. Fianbakken on January 10th, 2012
Whatever IDE you are using, or language for that matter, deploying files to different servers can be really boring (and repetative).
In many cases your IDE has built-in support for deployment – but usually just for one server – and little flexible. The deployment/publishing features within your IDE does not always match the structure you require from your structure.
I’ve often had the need to be able to :
- Update my files from SVN
- Copy certain files from a base location to different remote locations
- Be able to specify / ignore certain files (e.g. test – files from my solution that only makes sense on local development environment)
- Upload the same files and structure to multiple servers.
As I hate manual work, I wrote this script where you can configure the following:
- SVNRoot – Base folder for svn updates / checkouts
- Folders (from this base) that will be scanned for files
- File patterns to be scanned (recursively from the above folders) – E.g *.aspx, *.ascx, *.dll
- File patterns to be ignored (e.g. all files containing _Test_aspx).
- Folder patterns to be ignored (all files in these folders will be ignored)
- Web.config for deployment (if needed for webservers)
- Target servers – multiple ftp servers for uploading
- Ftp user and password for deployment
If something else than FTP should be used for transferring, it should be fairly easy to rewrite this script.
Script explained (Download script and configure it):
- Updates your SVNRoot directory (svn) – requires SVN to be installed
- Start-Upload is called (main-method for starting the process)
- Iterates your configured folders
- For each folder : Scans for the configured filetypes (recursively) – removes the folders that should be ignored
- If file is valid (should not be ignored), constructs a relative path based on SVNRoot and base of the folder it’s within and uploads the file by calling Upload-File ($localFile, $relativeDestination).
- For each file that should be uploads – executes a System.Net.WebClient.UploadFile (PUT) to each of the configured servers
Should be fairly easy to configure and adjust for other systems than FTP. Note that the FTP solution here requires the folder structure to be present on the FTP servers. If not, the script will just show an error message for each file that could not be uploaded through the webclient.
# Simple publishing script
# Author: Harald S. Fianbakken <harald@Fianbakken.com>
# Why: Cause I'm to lazy to checkout files and upload them to respective servers
# NB: Folder structure must be present on FTP server - Make sure to do this in advance
# If not present, the WebClient will fail for each file trying to be uploaded.
# BEGIN SCRIPT CONFIGURATION
# Root folder where files are checked in / out
$SVNRoot = "C:\VS\Fianbakken\MyProject\Fianbakken.CoreProjects\"
# This is usually the targets you'd want to configure
# Files are fetched from these directories according the the pattern specified below
$baseFolders = "${SVNRoot}Fianbakken.FrontEnd\Fianbakken.FrontEnd.Main", "${SVNRoot}Fianbakken.FrontEnd\Fianbakken.FrontEnd.Main\Content"
# What file types to we wish to upload - Disable all irrelevant files for faster deployment
$filesToUpload = "*.dll", "*.ascx", "*.aspx", "*.css", "*.js"
# If you just want to test the script or upload single file uncomment the following and replace with a valid filename
#$filesToUpload = "Bootstrap.js"
# Should configuration file be deployed (performs iis-reset!)
$deployConfig = $false;
$configToUpload = "$SVNRoot\Doc\Web.Config"
$configDeploymentTarget ="/Web.Config" # Root path of server
# Folders will be ignored (and all its contents)
# NB: These are relative paths (relative to each baseFolder)
$foldersToIgnore = "/obj/", "/Content/"
# What files (and patterns) to skip. Each item will be matched with contains (wilcard)
# This will make all files containing _Test_.aspx to be ignored (not uploaded)
$filesToIgnore = "_Test_.aspx"
# FTP settings where files are to be uploaded
$ftpUser = "myuser"
$ftpPassword = "blabla"
$targetServers = "publish.Fianbakken.com", "cms.Fianbakken.com"
$targetBaseFolder = "www.Fianbakken.com"
# END SCRIPT CONFIGURATION
# DO NOT MODIFY BELOW THIS LINE
# TODO - Could parse SVN response to only update these files!
svn update $SVNRoot
$connections = @{}
$client = New-Object System.Net.WebClient
function Get-FtpUrl($relativeFilePath, $server){
$url = "ftp://${ftpUser}:${ftpPassword}@$server/${targetBaseFolder}${relativeFilePath}"
return $url
}
function Upload-File($localFile, $relativeDestination){
$targetServers | % {
$url = Get-FtpUrl -relativeFilePath $relativeDestination -server $_
$outstring = $url.Replace($ftpPassword, "********")
Write-Host -ForegroundColor Green "Uploading $localFile to $_ "
Write-Host -ForegroundColor Gray " |-- PUT $outstring"
$data = $client.UploadFile($url, $localFile);
}
# To Download, use DownloadFile $dest, $lcoal
}
# Fetches files for uploading and does the magic
function Start-Upload(){
if($deployConfig){
Write-Host -ForegroundColor Green "Uploading configuration file!"
Upload-File -localFile $configToUpload -remoteDestination $configDeploymentTarget
}
# Done with config
$baseFolders | % {
if($_ -ne $null){
$base = $_;
$items = gci -Include $filesToUpload -Recurse -Path $base;
$items | % {
if($_ -ne $null){
# Fix paths , make it relative
$theFile = $_.Fullname;
$relativePath = $theFile.Replace($base, "");
$relativePath = $relativePath.Replace("\", "/");
$ignore = $false;
# Is there any folders which should be ignored in this list
$foldersToIgnore | % {
if($relativePath.StartsWith($_)){
$ignore = $true;
}
}
# Is there any of the files that should be ignored - only matching filenames
$filesToIgnore | % {
if($relativePath.EndsWith($_)){
$ignore = $true;
}
}
if(!$ignore){
Upload-File -localFile $theFile -relativeDestination $relativePath
}
} # End item ne null
} # End items
} # End if
} # end base
}
# Finally execute the method to start
Start-Upload
Tags: ASP.NET, AUTOMATED DEPLOYMENT, Powershell, SVN