Configuring Hudson/Jenkins for staging and production - deployment

How do I configure Hudson/Jenkins to production and staging deploy with the same configuration?
I have a build and deploy workflow configured in Jenkins to do production pushes. Now I need to use the same configuration to do a staging push, expect that couple of folder & DB names will change to reflect stage. I.e. Say from /var/prod/html to /var/stage/html and db from companyname_table to companyname_table_stage.
I don’t want to do a copy of the configuration since I may have to change the configuration in one place then I will have to make duplicate changes to every copy. Ideally I want to attempt this by passing some parameter

You could configure the project to be parameterized, and add a parameter specifying where to deploy to (i.e. staging or production). How you do this depends on what build system you are using. E.g. if you are using ant, the parameter will be exposed as an environment variable, so you could just have one variable saying whether its staging vs production, and then within the ant script you would set properties to /var/prod/html and companyname_table or /var/stage/html and companyname_table_stage depending on what that parameter is.
If for some reason you have build logic that couldn't change the property value based on the parameter, you would need separate parameters for the different values (e.g. one parameter for the db table and one parameter for the html location)
If you need separate projects for staging vs deploying, you could then have a project structure like this:
Project X: contains all the configuration and build/deploy logic
Project Stage-X: triggers a parameterized build of Project X, with the parameter set to the staging value
Project Deploy-X: triggers a parameterized build of Project X, with the parameter set to the production value
This also has the advantage that it is easy to add additional staging servers or deployment configurations, its just a matter of changing those parameter values.

Related

VSTS copy files to : filenames with variables

I am configuring VSTS build and release process.
I have a scenario where I have DEV and QA environments. I have different config files for each of the environments, think of the naming convention Test.Dev.Config
Test.QA.Config
In the "Copy files to" step of the build process, in the "contents" field, are you able to use the BuildConfiguration variable in order to tell the build process to copy the configuration files relevant to the BuildConfiguration:
so that the output of the package contains the Test.DEV.config files for the Dev build step and the Test.QA.config file for the QA build step.
I am basically testing out a options for config transforms in VSTS
Using a VSO variable combined with a string literal often doesn't work as expected within a task like File Copy. Also, you don't want to do that in every task that requires build configuration specific config file. What you can do instead, is to have a separate variable in your build definition that derives from BuildConfiguration variable like so:
Variable Value
BuildConfigFile *.$(BuildConfiguration).config
And then, within the File Copy task, you can directly use this variable as:
_PublishedWebsites\App_Config\$(BuildConfigFile)
For more details on defining one variable in terms of the other, refer this SO post.

How to manage A LOT of similar configurations in TFS

I have an ASP .Net MVC application with 4 different publishing profiles: dev, test, demo and prod.
These publising profiles are build using the same two steps: NuGet restore followed by an MSBuild. Then, they are deployed to lots of different servers: a few dev servers (one server dev per team), one test server, one demo server and several production servers.
msbuild /p:Configuration="$(Configuration)"
/p:PlatformTarget="any cpu"
/p:DeployOnBuild="True"
/p:DeployTarget="MsDeployPublish"
/p:MSDeployServiceURL="$(MSDeployServiceURL)"
/p:DeployIISAppPath="portal"
/p:CreatePackageOnPublish="False"
/p:MsDeployPublishMethod="WMSVC"
/p:AllowUntrustedCertificate="True"
/p:UserName="Deploy_User_For_TFS"
/p:Password="P#ssw0rd"
/p:AutoParameterizationWebConfigConnectionStrings=False
/p:ExcludeFilesFromDeployment="Cache"
Currently I have 4 TFS Build configurations (one for every publishing profile) and a file where I have all the possible values for MSDeployServiceURL parameter.
There are two issues with this approach:
When we had to add a new parameter AutoParameterizationWebConfigConnectionStrings we had to change it in 4 places instead of one.
We have to have a shared file as the source for the parameters. it is not easy to understand where which value should be copied and people often make mistakes.
So I have two questions:
Is there any way to have a one universal template where I can specify only my parameters Configuration and list of possible MSDeployServiceURLs and have everything else stay the same? Having such a template should fix problem #1.
Is there a way to define a drop-down like variable, where the value could not be typed in by the user, but should be selected from a pre-defined list of values?
Is there any way to have a one universal template where I can specify
only my parameters Configuration and list of possible
MSDeployServiceURLs and have everything else stay the same? Having
such a template should fix problem #1.
You could simplify such that the release configuration creates a templated publish profile. Then using TFS's release management, you could update the publish profile with the appropriate values. Based on your description, it seems like you are trying to combine both the compilation and the release.
For example, in TFS you could have one build (for example, MyApp-Release) that builds the code in the release configuration. As part of that process, it passes in placeholders for things like the deploy URL. For example, /p:MSDeployServiceURL="$(MSDeployServiceURL)" would be /p:MSDeployServiceURL="__MSDeployServiceURL__".
In the TFS release, you'd have a step that the replaces tokens (if you need one, you can use Colin's ALM Corner Custom Build Tasks) in the publish profile. The replace token task would then update the __MSDeployServiceURL__ with the value from an release environment variable with the same name (minus the underscores). So your release would have a dev, test, demo, and prod environment and for each environment, there would be a variable named MSDeployServerURL in each with a different value and a replace tokens step.

Pre-defined variable is empty in when creating VSTS release

I have a Service Fabric project set up with CD in VSTS. The CD process have been set up from the CD wizard in visual studio. So far so good but when the release is made I'm not getting any value from the pre-defined variable called Build.DefinitionName that I use for naming the releases.
This is how my Release name is configured: $(Build.DefinitionName)-$(date:yyyyMM).$(rev:r)
If we look in the release log there is no value for the variables:
[BUILD_DEFINITIONNAME] --> []
[RELEASE_ARTIFACTS_{Primary artifact alias}*_DEFINITIONNAME] --> []
*This value is populated correctly.
And according to the docs of primary artifact variables the two variables above should be the same.
As a result of this my releases are named $(Build.DefinitionName)-201702.7
If I use Build.BuildNumber instead. I get the correct value.
How can I get the variables populated?
Update
When creating the Build and Release definitions manually the $(Build.DefinitionName) gets populated correctly on the Release side. But the problem seems to appear when you use the CD wizard from Visual Studio. I might be missing something but the settings of the Build Definition are identical. Or there is some funky stuff going on with the CD wizard.
The solution is to create the release definition manually on web access and set Continuous Deployment.
On the build number is passed from Build to a release, there is no out of the box way to pass more variables between build and release.
However I write a ser of build tasks to do this: https://marketplace.visualstudio.com/items?itemName=nkdagility.variablehydration
It consists of two tasks, the first saves the specified variables to a json file, which you should put in the build output.
The second restores the variables you want. Especially useful if you have multiple source build for your release.

Generate different artifacts team city

I have a project which I want to deploy via team city but when it builds I want to generate a number of different artifacts.
In my app.config file I have an app setting called "platform" which I want to change the value of for each artifact. For example on build I would get three artifacts, dev, test, staging which would have had the "platform" setting changed to the corresponding value.
I have created the powershell script and run it successfully outside of team city, but I have not been able to work out how to set the file directory where the app.config exists within team city.
Is there a system variable I can use to target the current builds app.config file? Or is there a different / better way that I can accomplish what I want to do?
Thanks
Or is there a different / better way that I can accomplish what I want to do?
While this sort of question can lead to an argument over which is better... Based on what you have described, I believe that Octopus Deploy would be a good fit. Octopus Deploy integrates very nicely with TeamCity, and it handles the transformation configurations that are required to allow deployment to each of your environments, i.e. Dev, Test, and Staging. You would simply configure these as Environments within your Octopus Configuration, and during installation, Octopus can modify the configuration files as required, based on variables that you define.
I would recommand to create 3 build steps inside your TeamCity configuration :
Inside the Parameters tab, you can define configuration parameters. Just define here the 3 values : ie: PlatformDev, PlatformTest, PlatformStaging
Using Visual Studio Runner
You might be using Visual Studio runner type. So, here you can add specific values from MSBuild properties:
Dev Step:
Passing the parameter Dev, and executing your code
/p:CustomPlatform="%PlatformDev%"
Test Step:
Passing the parameter Test, and executing your code.
/p:CustomPlatform="%PlatformTest%"
Staging Step:
Passing the parameter Staging, and executing your code.
/p:CustomPlatform="%PlatformStaging%"
Then, the value CustomPlatform would be accessible inside your MSBuild scripts.
Using Powershell hand-made scripts
If you are using a powershell script to run your compilation/artifact creation, you can just add this CustomPlatform as a parameter of your script, and use it directly.
Using XSLT
Another way to do this might be to use XSLT to transform you app.config file, using a specific value.

CI and Deployment with TFS and Powershell

I am working on a CI process with automated deployment. TFS Build is building the solution, and it then uses an InvokeProcess task to kick off a Powershell script. The Powershell script deploys the database changes as a dacpac using sqlpackage, reporting services reports using the web service, fonts to the SSRS server, and the website itself to 1 or more web servers - the whole process uses a deployment configuration file to define drop paths, server ips, installation folders etc. There will be one of these per environment.
I would like to be able to build the solution and deploy to an internal server to run automated tests as part of the automated build. Once tests are completed, and the build has been manually checked, I'd then like to be able to kick off another Build definition which only has the deployment portion of the standard build template, which will simply take a build number or build drop location, and deploy the same build to a different environment (i.e. staging, prod etc.)
The issue I have is that I'm currently managing most of my web/app configuration using config file transformation - i.e. I have build definitions for Debug, Test, Prod etc. and then Web.Debug.config, Web.Test.config etc. I only want to carry out one build, and then deploy that same build to different environments, however at the moment the build will only generate configuration files for one environment - i.e. whatever the build configuration is.
Would the best approach be to generate all config files (or actually pre-createg complete config files for each environment), and then just choose the appropriate one for the specific deployment? Or should I store the env specific config in my deployment configuration file and update the appropriate keys using powershell when deploying?
What would be the normal/recommended approach here?
I'd suggest creating new Configurations for each target environment (e.g. by default you have Debug/Release, create some more). Then use the built-in web.config transforms, for non web-projects use Slow Cheetah
This will spit out pre-configured build outputs for each configuration you specify you want build (in your Build Definition).