We are working on automation of deployment using Jenkins. We have different environments – DEV, UAT, PROD. In SVN, we are tagging each release and placing same binaries in DEV, UAT, PROD. The artifacts already contains config files w.r.t each environment but I am not understanding why we are storing binaries in environment folder again. Are there any scenarios where deployment might be different for different environments.
C# – In which cases build artifacts will be different in different environments
asp.netccontinuous integrationdeploymentrelease
Related Solutions
Normally the higher the deployment process is automated, the lower risk there will be. To achieve better automation, i think command line procedures (with different modes, for example, interactive v.s. quiet mode) could be a good option:
I believe you won't have many environments (DEV/QA/UAT/PROD/etc.) and they are already fixed. So a fixed xslt transformation could be defined and included in your project, for example, call it web.config.xslt, in which, a list of configuration sections per environment could be defined (or a switch-case conditional configuration)
use MSBuild to build the solution, and output the built files to a newwork location (preferably accessible to all developers), and at the end, transform web.config based on web.config.xslt and produce a couple of config files: web.Dev.config, web.QA.config, web.UAT.config and web.Prod.config
give an option at the command line, say which environment the user wants to deploy, then batch copy all the files to the desired server (of course, you have to allow these folders shared and accessible to the deployer) and at the end copy the corresponding web.[ENV].config file as web.config to destination folder
other bit and pieces (such as versioning, DLL signing and etc.) could also be included and automated through out the MSBuild process.
all these steps could be stored in a predefined solution level file, let's say it mySolution.BuildRelease.proj (all up to you) and set MSbuild (or your self-defined bat file, which calls MSBuild and your own console app) as the default app to open it.
of course, if some of the processes could not be done using command line, you might want to try write a console application and call it during MSBuild.
if you are fancy with interactive approaches, you may also define a html app (hta) to wrap up the process
I'm going to suggest you move to a slightly more complex but far more flexible system. Basically, I recommend you shift away from SVN branches that are linked to environments. We used this for several years and had no serious problems.
- If you don't already have one, install a repository product like Nexus.
- Write deployment jobs for Jenkins that deploy a numbered version to Nexus, but do not deploy to the DEV, UAT or PROD hosts. This job will tag all files with the version number, and put the versioned .war file into Nexus. Assuming you use Maven or Gradle as your build tool, this is out of the box functionality for Jenkins.
- Write deployment jobs for Jenkins that ask the user for a version number and target host. These are simply jobs that use SVN checkouts augmented by bash scripts that Jenkins will execute. You will need to add a few Jenkins plugins to make life easier (e.g Setenv to set variables visible to the whole job)
- Install a second Jenkins instance for use of DEVOPS. This will host jobs that deploy a particular version to the the higher environments. This is mainly for security if developers are not allowed to do deployments to some environments.
- Your use of SVN will change. We simply used the trunk for development, and branches for each deployed version. You only need to create version branches on demand (branch from tag). You typically will also create an occasional branch to try out a new feature.
- Put up a white board in a prominent position that lists what versions are currently in each environment.
So what will this give you?
- You don't need to do a code merge when moving between environments, as branches are no longer linked to environments.
- You can quickly regress any environment to a different version. This is great for chasing obscure bugs.
- Insist that defect reports include the version number. This gives good traceability of when the defect was fist detected.
There are a few fish hooks.
- Your code must be written so that the same .war file will run in any environment. This means all configuration data must be stored as environment variables and/or JNDI variables. You can also use configuration files that are separately controlled and versioned (typically by DEVOPS). The actual location of these files will be specified by an environment or JNDI variable.
- You will need to setup certificate-based trust between Jenkins and the target deployment machines. This is necessary so that you can use SSH to move files to the target hosts and execute commands on the target host - SSH does not support username/password authentication from a script.
I realise this may be quite a change for your team, so good luck!
Best Answer
There are a number of scenarios where your deployment could be different per environment:
There could be lots of others, but it's hard to say without more info on your specific project.
As for storing binaries, it is fairly common to store build artifacts somewhere, but I'd recommend using an actual artifact repository rather than a "source code repository" like SVN. You'd have build jobs that create the artifacts (release or in-progress) and put into the repository. Then you'd have other jobs that deploy the artifacts to servers. You can combine them, but that gets to be a lot on one job and you start losing granularity.
(Aside: I've got some experience using Maven, Nexus, and Jenkins for C# webservices... but that's some real craziness for most .NET developers. But once you've got Maven working for you in .NET-land -- instead of against you -- then you gain some neat benefits.)