There is a new version of this approach:
http://thoai-nguyen.blogspot.com.au/2012/10/deploy-dot-NET-window-service-TeamCity-Updated.html
Deploy window services from TeamCity is such a pain since you don't have something like WebDeploy as deploying a web application. Optopus is a product on the market to do it but I don't want to pay for this simple task. So here is the way I did.
Tool: powershell, window commands, wget, 7zip
Prerequisite: TeamCity server and the remote server have to be configured to use Remote Commands in Windows PowerShell
1/ Config both servers follow the above link. TeamCity server has to be a trusted client to the remote server and vice versa
2/ Download wget and put somewhere on the remote server such as C:\DeploymentScripts\wget.exe
3/ Download and install 7zip on remote server where you installed your windows service.
4/ Write deployment script and put somewhere on the remote server such as C:\DeploymentScripts\MyApp\deploy.bat
It can be a powershell script but I decided to use a batch file for simplicity.
Basically, the script when triggered, will
- Use wget to download the latest artifact from TeamCity.
- Use 7zip to extract the artifact, copy it to a temporary folder.
- Save the artifact to Artifacts folder
- Backup the whole current service folder
- Stop target window service
- Copy over new files and old configuration files
- Start target window service
- Clean up
Here is the script, replace some value in the script to match your requirement.
@echo off:: Deployment scripts for my window service SETLOCAL :: 0/ --------- Set some local variables SET Environment.ExecutingFolder="C:\DeploymentScripts\MyApp" SET Environment.7zip="C:\Program Files (x86)\7-Zip\7z.exe" SET Environment.Wget="C:\DeploymentScripts\wget.exe" SET TeamCity.User=van SET TeamCity.Password=vanpassword SET TeamCity.BuildTypeId=bt19 SET TeamCity.Artifact=MyAppService.{build.number}.zip SET TeamCity.Branch=Default Branch SET MyApp.TargetFolderName=MyApp.Service SET MyApp.TargetFolderPath=C:\WhereMyAppInstalled\%MyApp.TargetFolderName% SET MyApp.ServiceName=MyAppServiceName SET MyApp.ImageName=MyApp.Service.exe CD /D %Environment.ExecutingFolder% ECHO 1/ --------- Get latest artifact from TeamCity, MyApp %TeamCity.Branch% ----------------- bt19: build type ID for MyApp on %TeamCity.Branch% %Environment.Wget% -q --http-user=%TeamCity.User% --http-password=%TeamCity.Password% --auth-no-challenge http://my.teamcity.url.com/repository/download/%TeamCity.BuildTypeId%/.lastSuccessful/%TeamCity.Artifact% REN *.zip* *.zip ECHO Found following artifact DIR /B *zip ECHO 2/ --------- Extract the artifact to folder __Temp --------------- %Environment.7zip% e -y -o__Temp *.zip ECHO 3/ --------- Store the artifact ------------------ MOVE /Y *.zip Artifacts\ ECHO 4/ --------- Backup current service folder --------------- for %%a in (%MyApp.TargetFolderPath%) do set Temp.LastDate=%%~ta SET Temp.LastDate=%Temp.LastDate:~6,4%-%Temp.LastDate:~0,2%-%Temp.LastDate:~3,2% %Temp.LastDate:~11,2%%Temp.LastDate:~14,2%%Temp.LastDate:~17,2% ECHO Last deployment: %Temp.LastDate% ECHO Now backup files to folder %MyApp.TargetFolderName%.%Temp.LastDate% XCOPY /E /I /H /R /Y %MyApp.TargetFolderPath% "%MyApp.TargetFolderName%.%Temp.LastDate%" ECHO 5/ --------- Stop %MyApp.ServiceName% service --------------- net stop %MyApp.ServiceName% ECHO Wait 15 seconds ping 1.1.1.1 -n 1 -w 15000 > nul ECHO Try to kill the process %MyApp.ImageName% if it's still running TASKKILL /F /FI "IMAGENAME eq %MyApp.ImageName%" /T > nul ECHO 6/ --------- Deploy new files & copy over old configs ---------------------- XCOPY /E /H /R /Y __Temp %MyApp.TargetFolderPath% COPY /Y "%MyApp.TargetFolderName%.%Temp.LastDate%\*.config" %MyApp.TargetFolderPath% ECHO 7/ --------- Start %MyApp.ServiceName% service --------------- net start %MyApp.ServiceName% ECHO 8/ --------- Cleanup --------------------------------- RD /S /Q __Temp ENDLOCAL
5/ Open powershell as Administrator on TeamCity server and execute following command:
read-host -assecurestring | convertfrom-securestring | out-file C:\Users\Administrator\MyAppSecurePassword.txt
Then enter the password for the remote server. The secure password will be stored in the above file. It will then be used by TeamCity for future powershell commands against the remote server.
6/ Go to TeamCity management website, add a new project with 1 step that will execute the following powershell command:
$username = "Administrator" $password = cat C:\Users\Administrator\MyAppSecurePassword.txt | convertto-securestring $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password $serverNameOrIp = "xxx.xxx.xxx.xxx" Invoke-command -computername $serverNameOrIp -ScriptBlock {C:\DeploymentScripts\MyApp\deploy.bat} -Credential $cred
Notes:
- Administrator is the Admin username on the remote server
- C:\Users\Administrator\MyAppSecurePassword.txt is the secure file that store the secure password we created at step 5.
- serverNameOrIp value has to be changed to the remote server's ip address where you installed the windows service
So after the code is checked in and successfully built, we can trigger the deployment by clicking "Run" from the above created project. The deploy.bat script above can be triggered anytime from the remote server for testing purpose. It's simple enough to read and modify when more steps need to be involved.
Cheers
0 comments:
Post a Comment