Pull Requests (or whatever their equivalents are called in your favorite Git distribution) are a norm. Most of us adopted them as the primary way of reviewing and accepting changes that will ultimately be deployed to production. They work hand-in-hand with feature branches.
A common (and recommended) workflow is to create a new branch for each feature or a change we want to release. Once we create a branch dedicated to a feature or a change, we work locally or in DevPods until we are satisfied with the outcome. From there on, we make a pull request which should execute a set of automated steps that will deploy the preview and validate it. If all the steps are successful, we might have some manual actions like code review. Once finished, we merge the pull request and that, as you already saw, results in yet another round of automated tests that end with the deployment to one or more environments (those set to receive new releases automatically). Finally, the last step is to promote a release to production whenever we feel we’re ready (unless the promotion to production is set to be automatic). Hopefully, the whole process from creating a branch all the way until it is deployed to permanent environments (e.g., staging, production) is measured in days or even hours.
So, a high-level process of a lifecycle of an application usually contains the steps that follow.
- Create a feature branch
- Work on the feature locally or through DevPods
- Create a pull request when the feature is ready
- Deploy the preview
- Execute a set of automated validations that will confirm that the pull request works as expected
- Review and approve the pull request
- Create, deploy, and validate a new release in permanent environments (e.g., staging)
- Promote the release to production (unless that part is automated as well)

The high-level process of a lifecycle of an application
In your case, there might be variations to the process. Still, at a very high level, the process works reasonably well and is widely adopted. The problem is that the process based on feature branches is in stark contrast to how we were developing applications in the past.
A long time ago in a galaxy far, far away, we used to have long application lifecycles, cumbersome and mostly manual processes, and an infinite number of gates with silly approval mechanisms. That reflected in our branching strategies. We’d have project or development branches that lived for months. Moving from one environment to another usually meant merging from one branch to another (e.g., from development to staging to integration to pre-production to production). We do not live in 1999 anymore, and those practices are today obsolete.
We split projects into features. We reduced lifecycles from months to weeks to days to hours. And, more importantly, we learned that it is pointless to test one set of binaries and deploy another to production. All that resulted in feature branches model. Each feature gets a branch, and each branch is merged back to master. There’s nothing in between. There are no staging, integration, pre-production and other branches. The reason for that lies in the process that tells us that we should build something only once and move the same artifact through environments. With such an approach, there is no reason for the existence of all those branches. You develop in a feature branch, you merge it to the master, you build the artifacts as part of the merge process, and you move them through environments until they reach production. Even that can be questioned, and many are now pushing directly to the master branch without feature or any other branches and without pull requests. We won’t go that far, and I’ll assume that, if you do want to push directly to master, you should be able to adapt the process we’ll use. What I do NOT expect you to do is create a complicated branching schema only because you’re used to it. Move on and travel forward from whichever year you live into the present time (2019 at the time of this writing).
The present is feature branches, GitOps, and Kubernetes. Jenkins X unites the three into an easy to use bundle.
The DevOps 2.6 Toolkit: Jenkins X
The article you just read is an extract from The DevOps 2.6 Toolkit: Jenkins X.
The book is still in progress, and I do not yet have a clearly defined scope. I write about tech I’m working with and that interests me the most. Right now, that’s Jenkins X.
You can get the book from LeanPub. If you do, you’ll get updates whenever a new chapter is finished. At the same time, you can get more actively involved and send me your comments, suggestions for the next topics, bug reports, and so on. I’d love to hear back from you.
Is this article related to Continous Integration/Continuous Delivery? If it is please take the effort to understand the meaning of them.
This article is not directly related to CI/CD, but how we deal with pull requests and associated environments.