What is a deployment pipeline is an automated manifestation of your process for getting software from version control into the hands of your users. It does not imply that no human interaction with the system through the release process, but instead ensures that the error-prone and complex steps are automated, reliable, and repeatable.
Goal: A deployment pipeline should allow you to create, test, deploy complex system of higher quality and at a significantly lower cot and risk than we could otherwise have done.
Deploy to any environment (Testing, Staging, Production, etc) with a click of a button
Repeatable deployment (deploy a previous version easily)
Minimum Stages of pipeline
The commit stage
Asserts that the system works at the technical. Meaning that it compiles, passes a suite of commit tests, and runs code analysis, creates binaries and prepare a test database for use by later stages. Commit tests are primarily unit tests, but should also include a small select of other types of tests such as BDD or integration tests to give a higher level of confidence that the build is working properly. The stage should take less than five minutes and definitely less than 10 minutes. Its purpose is to give quick feedback to the developer that something is not working and needs to be fixed before moving on to the next task.
Automated acceptance test stages
Asserts that the system works at the functional and nonfunctional level, and that it behaviorally meets the needs of its users and the specifications of the customers.
Manual test stages
Asserts that the system is usable and fulfills its requirements, detects any defects not caught by automated tests, and verifies that it provides value to its users. Typically, this would include exploratory testing environments, integration environments, and UAT (user acceptance testing).
Delivers the system to users, either as packaged software or by deploying it into a production or staging environment (a staging environment is a testing environment identical to the production environment)
The process starts with the developers committing changes into their version control system. At this point, the continuous integration management system responds to the commit by triggering a new instance of our pipeline. This first (commit) stage of the pipeline compiles the code, runs unit tests, performs code analysis, and creates installers. If the unit tests all pass and the code is up to scratch, we assemble the executable code into binaries and store them in an artifact repository.
A application is comprised of three parts:
- Keep the deployment pipeline efficient, so the team gets feedback as soon as possible.
- Build upon foundations known to be sound.
- Keep binary files independent from configuration information
- Keep configuration information in one place
Best PracticesOnly build your binaries once - the binaries are the .NET assemblies and should only be compiled once in the Commit stage. The later stages use these binaries. Building at each stage or even for testing, code analysis, etc. is considered an anti-pattern.
Deploy the same binaries to all environments. For example, the same binaries used in UAT should be used in production. This can be used by using hashes of the binaries to verify they are the same.
Store the binaries in a file system, not version control.
Configuration Data is not included in the binaries and should be kept separately. - Configuration data is data that is different between the environments such as ip address, urls, database connection strings, external services, etc. It can also include data that changes behavior of the application.
Use Configuration files and store in source control - Each environment should have its specific settings stored in a configuration file that is specific to that environment. This correct file can be determined by looking at the hostname of the local server if one server or in multi-server environments through the use of environment variable supplied to the deployment script. Alternatively the data could be stored in a database as well.
Binaries must be deployable to every environment
Deploy the same way to every environment - this ensures that the deployment process is tested effectively.
Test configuration settings - check to see if external services are actually available when deploying, Ideally if the service is not available the installation should not be.
Smoke test - after an installation run some very basic scenario to make sure the external services are accessible. Check particularly sensitive urls, hosts, etc, make sure certain pages come up that depend on configured information work .
Locked down environments - Production should only be changed once proper change management has been used for approval of the change. The same should be for test environments, but the approval process is easier.
Each change should propagate through the pipeline instantly - the first stage (commit) should be triggered upon every check-in and each stage should trigger the next one immediately upon successful completion of the previous one. The system needs to be smart enough to check for new changes before running tests. For example, if three people check-in before an integration test finishes the latest changes should be bundled into what is tested in the integration tests. For manually triggered stages (later ones) they need to wait for user interaction.
If any part of the pipeline fails, stop the line -