I put together this diagram to show the workflow I like to use for building, testing, and deploying applications.
There are 4 stages:
A developer checks out source code into his local environment. He builds the source code and runs the automated unit tests to verify it is working. He then makes changes that can be viewed and tested interactively in his local setup. When his changes are tested and completed, he checks them back in.
With git, this would involve a pull and a push — but not a push to master. Every developer should have a remote repository that functions as a backup. This could in theory be a branch, but I don’t like proliferation of branches. Consistent naming makes it easier to keep track of what should be merged.
The developer then sends a merge request to the central project repository from his own repo. So you have something that looks like:
pull request from fijiaaron/feature_branch to project/feature_branch
The central project repository then pulls the changeset from the developer’s repo and does whatever automated and manual checks deemed necessary.
These could include code reformatting, style checks, static analysis, code coverage, code reviews, etc. The project is built from scratch and unit tests are run.
If all checks pass, a package is built and pushed to the artifact repository. If not, it is rejected and the developer is notified. The developers master (or feature) branch still contains his commit, but the central repo remains untainted.
The artifact repository could be your git repo (but probably shouldn’t be) or a package tool such as maven’s artifactory, nuget, or an RPM repository. It doesn’t matter as long as the packages are well named and versioned — and you have a way of keeping track of versions and a way to promote them (a simple database of artifact->version->promotion status).
The central source repository should be tagged for each package version created.
Formal system testing occurs next. I thought about naming this step “QA” to distinguish it from developer testing, but quality is everyone’s job, right?
At this stage, the source code is left behind, and a known good artifact is downloaded and deployed to a test environment. Automated and/or manual tests are run that exercise the full system as it runs in a production-like environment. How production-like is a decision best made by you.
At the end of the system test stage, the decision is made to promote it as ready for production or not.
Note that there can be several levels or stages of testing that run sequentially or in parallel. This allows for a deployment pipeline that might include an environment with mocked services, ones for formal QA and stakeholder acceptance, performance & security testing, and staging environments. The main idea is that there is a flag that denotes an artifact (or collection of artifacts) as ready for production deployment at the end of it.
This is the final stage, and it’s really just another section in the deployment pipeline that happens to be the final one — or ones if you roll out in stages to some customers (eg. a beta site or A/B testing.)