Generate different artifacts team city - powershell

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.

Related

Azure Webjobs app.config Release Transformations

I have a webjob and a webapp (both separate projects), I would like to build one artifact for all environments and do the transformations during the release step rather than build, as that way I have to create an artifact per environment. So I am creating two separate artifacts (one for webapp and one for webjob) per environment and applying the xml transforms during publish to the app service, now everything works fine, except that the transformed file for the webjob is placed in the root directory of the webapp, which is not what I intend to do. I would like the file to be placed as app_data\jobs\continous\myjob\myjob.exe.config
I've seen the slow cheeta and CTT transforms, but those are out of the scope of this question as they do transform only on build.
You can use Kudu api to run the commands to copy or delete files.
More information about how to call kudu api during build/relase, you can refer to: How to access Kudu in Azure using power shell script
You should transform during build and your transformation should happen as tokens in the build rather than actual target values. Then in deployment you can replace the token values with actual target environment values. That is the proper approach for packaging and deployment of any application type.
Steps should be
In build tokenize the configurations with transformation (use this extension task)
Package tokenized configurations as build output
At deployment apply target values to tokens (use replace tokens task comes with marketplace extension, which replaces values of defined configs with release variable values by mapping names automatically. in other words token should be the parameter name)
Here is an example done on a windows service. But it is applicable for webjobs (have tested this) as well and it is the proper solution.

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.

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).

Configuring Hudson/Jenkins for staging and production

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.