1

We have 3 environments:

  • Staging - where all developer pull requests get merged for quality assurance testing
  • Release - After quality assurance testing, staging pull requests are merged into the release branch and are available for acceptance testing
  • Main - Once accepted, the release pull requests are merged into the Main branch for production release.

In the above case, when deployment occurs in a bunch, it works fine, but when we want to do continuous deployment, it gets blocked.

Example: Feature 1, 2, 3 are ready for QAing on staging and staging is merged into release. Now acceptance testers accepted only feature 3 and reworked feature 1 & 2. In this case until feature 1 & 2 gets fixed, the entire deployment is blocked.

A solution to this is: Cherry-pick the commit for feature 3 and push it to the main.

This is very complex when there are multiple commits and there might be merged commits with staging as well. Also, it is very time consuming.

Is there any way to automate or speed up this process to achieve continuous deployment for the pull requests that get accepted?

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • 1
    Have you guys looked into using feature flags? They allow you to deploy code into production while essentially letting it remain "dormant" for some or all users, whether the code is in-progress/technically complete but not yet accepted. – Ben Wong Feb 20 '23 at 04:46

2 Answers2

0

Do not merge integration branches (branches where you integrate multiple feature branches together): as you are describing, it becomes very complex to get the right set of features in each of them.

Integration branches (QA, staging, release) are long-lived branches you are merging to, not from.

Merge feature branches to QA, then merge those same feature branches (but only the ones that are ready) to staging.
And merge only the ones ready to release.

I have described that process before as gitworkflow (one word)


That being said, integration branches, as commented by Daniel Mann, should not represent deployment stages.

A deployment is orthogonal to source control, and take one fixed state of the code to deploy the same artifact through a series of stages.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I would recommend against using branches per environment as it violates the "build once" principle -- any testing you're doing in QA is being completely invalidated the second you merge a **completely different** set of features to staging. As @BenWong recommended, making use of feature toggling allows for you to build and test a single, continuously-integrated version of your application from a single branch. – Daniel Mann Feb 20 '23 at 05:48
  • 2
    @DanielMann I fully agree. I was simply recommending a merge strategy for integration branches in general. – VonC Feb 20 '23 at 05:54
  • For years now I've been struggling with whether it's called "gitworkflow" or "[gitworkflows](https://git-scm.com/docs/gitworkflows)" (plural). Maybe this settles it, though the plural comes up in searches better... – TTT Feb 20 '23 at 15:21
  • 1
    @TTT yes, to my knowledge, it is git workflow. No plural form. – VonC Feb 20 '23 at 15:36
  • @TTT As in https://github.com/rocketraman/gitworkflow – VonC Feb 20 '23 at 19:03
  • Even in the About section of that link, it says "gitworkflows" and references the hackernoon article, which also uses "gitworkflows" in at least one place. Hehe. (Maybe we just need to coin a new term for it that can index better in search engines.) Though I will start using "gitworkflow" singular from now on. – TTT Feb 20 '23 at 19:13
  • 2
    @DanielMann although I agree with your statement in general, in "gitworkflow", the idea is to have preliminary integration testing done off to the side, on a throwaway branch which might also have its own test environment associated with it. This throwaway branch is typically called `next` and gets reset periodically to `main` or similar. This serves as a "pretty good" starting point for working out the kinks prior to merging it into a long lived branch. This concept is oftentimes "in addition to", rather than "instead of", other strategies, including those using feature flags. – TTT Feb 21 '23 at 17:32
0

This question is tagged with Git Flow, and based on that it appears your staging branch is probably intended to act like the develop branch in Git Flow, but you are using it slightly differently.

In Git Flow, the develop branch is intended to be like the master or main branch in other flows, in the sense that you merge your code into develop when you can assume you are pretty sure that code is ready to go to production. From there the release branch is used to verify that you were right with that assumption. The release branch is created for the pending release, and is used to do extra testing, just in case. The release branch simply gives you a branch to make bug fixes if needed, while other features are merged into develop for the next release after the pending one. This simultaneous development of new features without needing code freezes, while the pending release is being hardened, is the main benefit of using Git Flow. However, unless that release hardening cycle is very short (say, perhaps less than a few hours but very likely less than a day), Git Flow doesn't typically align well with CI/CD practices.

It turns out you aren't using your staging branch the way Git Flow intends the develop branch to be used. If you haven't decided which features you want to include in the upcoming release, then they aren't ready to be merged into develop yet; you need to figure that out a different way, or, consider that perhaps Git Flow may not be the best workflow for you. You could use feature flags (meaning everything is merged into develop, but a config can be toggled on the release branch to determine what is turned on), or you could simply revert merges into develop or even on the release branch. In your exact situation where 3 features made their way into release and you decided at that point that you only wish to release one of them, I would recommend simply reverting the 2 merges for the undesired features. You can always add them back in later (by reverting the revert commits, or re-writing the commit IDs and re-merging them).

Note if your situation isn't really an exception and happens often, then I highly recommend using gitworkflow as mentioned in VonC's answer. Note it doesn't even have to be an "either or" decision. In one of the large repos I work out of in my organization, we actually use both: we have a next branch where we do integration testing, and once those features are validated in the test environment we merge them into develop over in our Git Flow strategy. The most important thing to remember with "gitworkflow" is that you should reset the next branch periodically to your main development branch, which is typically main in some flows, but might be staging or develop if you're using a hybrid model.

TTT
  • 22,611
  • 8
  • 63
  • 69