One of the most critical moments in development is when a new website or feature gets pushed to production. In this post I will share with you 10 tips that helped us get our deployment "under control" without having to spend our precious time in evenings and weekends to fix the release.
1) Setup continuous delivery
- Avoid manual releases and find a tool to configure continuous delivery. Our preferred tool is Visual Studio Release Management. The tool allows you to configure the enviroments (DTAP) with each their own specific variables and tasks that need to be executed. Typical tasks include copying / deleting / archiving / extracting files, publishing packages, running tests and powershell scripts.
- The prerequisite of a succesful release is that the code compiles and all tests are passed. It is recommend to use web application projects.
- It is also recommend to get the build time as fast as possible. Remove unnecessary files (modules) from the project.
- Environment specific variables can be configured in config files like the web.config. Best practise here is to use web.config transformations. This will ensure that every environment can have it's own set (e.g. debug enabled on development but disabled on production). The goal is to automate deployment without having to change the configs manually after a release. If all fails we typically use powershell scripts to apply some additional magic :)
- Decide on how to verion your application from the start of the project. You can avoid a lot of discussion if the team talks about the same release version number (e.g. 1.0).
2) Keep everything in sync (except content)
- Add every environment specific Kentico configuration (objects, global settings, site domain aliases and licenses) in development and roll it out (via continuous integration, staging or export/import packages) accross all environments. If everything is configured the same on all environments, it will be much easier to deploy (hence you can simply override it) but also when you want to troubleshoot and identify the differences (see also tip 10).
- If it is needed to use environment specific settings, first check for existing web.config application keys otherwise fall back to site settings.
- Be careful when you consider using Kentico Continuous Integration, Staging or Export/Import for synchronization. All of these features will not support continuous deployment for the full 100%. Our preferred solution is to create release packages using Export/Import.
3) Enable caching on all environments
- We recommend enabling caching on development with the same specs as required on production. This will force developers to implement and test working with cache dependencies.
4) Tweak the content structure
- One of the easiest way to deploy the content structure (set of page types) is when you reduce and avoid the release of content. Our recommendation is to create page types based on the required page templates. Therefor every page type will have it's own unique page template (1-to-1 relation). This will typically introduce a parent/child hierarchy (overview/detail pages) and allow the editors to only add items that are desired. Example: homepage and news overview can be placed underneath root, news items can be placed underneath news overview but not underneath the homepage.
- The additional benefit of creating all those specific page types is that you can easily apply role based permissions. For example you could configure certain roles to not be able to delete level 1 content, which typically breaks the site if it's not there.
- Avoid usage of the page tab because automatic deployment of content is very hard and will most likely result in manual work. Try to put that type of content in the form tab.
- Additionally if editors need to tweak specific settings (e.g. number of items to be shown in a list in the sidebar), add fields to the page type and use macros to inject the values in the web parts. The benefit of this approach (especially within portal engine) is that you can easily roll the updated content structure out as you are totally in control of the functionality.
- The downside to this approach is that can increase the number of page types needed. To workaround this we typically recommend having one mother page type (metadata) that contains all generic fields (title, description, teaser and date) and have all other page types inherit from it. The page types will only contain unique fields to provide additional configuration.
5) In case of widgets...
- Try to add them in the design tab in combination with the widget actions web part. This will allow editors to reset the view to the original form. The benefit here is that the page template can be easily rolled out.
- When it's placed in the content (page tab or inline) it will be tough to update them, especially when macros are added as default values. If no action is taken, the widgets will have to be removed and readded. An alternative is to script the update and modify the widget defintion which is stored in a complex XML structure. The recommendation here is to use custom Kentico settings for the properties that need to be set via macros. If a macro needs to be changed, you can simply update the setting and it will be applied to all widgets.
6) Feature isolation
- When developing new functionality, it is best practise to implement feature toggles (e.g. web.config application settings). This will allow you to disable features while they are still in development. Using the application settings you can enable features on some of the environments and disable it on the others. The feature toggle is a key aspect of continuous delivery, as it allows you to quickly roll out new versions of the software where unfinished work is still disabled/locked.
7) Develop custom modules
- In case of custom functionality we recommend creating custom modules and deploy them as NuGet packages. Custom modules are perfect for storing custom data (preferred over custom tables) and allow you to store custom settings and even create a custom user interface.
8) Script it out!
- Whenever you need to release functionality that cannot be staged or packaged we recommend to script it and use a custom module loader to execute the code on application start. Typical examples include content manipulation or when a feature cannot be packaged using Export/Import.
9) Apply release driven development
- I am a big fan of what I'd like to call "release driven development". This concept forces our developers to think upfront on how they will ensure that their changes are being deployed from one environment (local dev) to the next one (stable dev). In our way-of-work (part of the definition of done) we have incorporated that the developers check each others work right after deployment to the stable development environment. Basically this consists out of doing code reviews using TFS and Visual Studio and ensuring the feature is deployed and works correctly. Only when the developer verifies the correctness of the feature, the release is approved to be deployed to the next (test) environment.
10) If all fails...
- Take a look at Compare for Kentico, a Kentico module that will allow you to visually compare accross installations and synchronize the differences with the click of a button. You can start with a 30-day free trial.