Production deployment workflow for web client app

Renas Sitdikov
Flatstack Thoughts
Published in
6 min readJan 25, 2022

--

I worked on a small team (5–7 devs) on the outsource project, and we were developing API + web client app. Both API and client app should be regularly released. In this article you can find how we organized this release workflow for web client app.

There are different workflows possible, the described bellow is the one that we chose, and every team member knows how to do it and can be responsible for the process.

This article will be very helpful for beginners and for those who want to expand their responsibility. Here are no code examples, the article describes principles.

Why better to know how to do it for every person on the team?

It can be very useful

Even if you are beginner you can quickly become responsible for that are out of your scope.

You can cover your colleagues and the whole project

As a rule lead developer are responsible for production deployment process but they are also can be responsible for many different activity such as mentoring, interviewing, long calls with customers and etc. But regular deployment should not down, and maybe you can help to proceed it.

There is a chance you stay alone in the project

Anything can happen, vacations, sudden sickness or even your customer will decrease the number of stacks but regular release of the product is still important, and nobody care that you never did it.

What branches to use?

Let’s review all possible branches and they role on development and deployment.

Feature branches

Any task requires development in isolated place such as feature branch created from main development (master) branch. After reviewing and approving the destination of this branch the same as origin — main development (master) branch.

master (main, dev, integration, staging) — main development branch

All completed tasks’ branches are merging here. This branch should be protected — unapproved branches can’t be merged. Any changes automatically deploying to the staging app. If any new changes added to production branch — master should be updated.

release*

This is a special branch between master and production mostly need for QA. It’s creating from main development (master) branch and merging to the production branch. Why we not just merge master into production? - you can ask me. Well, it’s also works until you have no QA. Sometimes QA needs to check more than one day, and if QA will test staging app better to not merge features here and devs can be blocked. So release app which automatically deployed from any change occurred in release* branch is isolated place to check your future production version. As a best practice better to create new branch in every release version and name it as like “release-1.13.0” — it prevents confusing with another release versions. The versioning in this example are very common:

  • first digit (1.13.0) — is a major version that should be changed in case of major changes (for example changes that breaks the API)
  • second digit (1.13.0) — is a minor version that should be changed after minor changes (for example change that don’t break the API or regular releases)
  • and third digit (1.13.0) — is a patch version — it changing after bug fixes

Hotfix to release

It’s a very common branch with feature branches but it’s creating from the current release* branch and merging after approving back to release* branch. This branch is needed to make quick fixes after when QA found bugs while testing current release.

Production branch

This is a main branch of the project. Break downs and bugs should be minimal here (ideally to be zero). Of course, it should be protected as master. This branch is a result of our work, it deploys to production environment where it’s used by our customers.

Hotfix to production

We do everything to avoid bugs on production, but they happen sometimes, and we should quickly fix it. This branch is a mix of feature and release branch. The origin and destination is production. It should be named as last release + patch (release-1.13.1 because our last release is 1.13.0). Like to regular release branch it automatically deploys to release environment and should be tested by QA.

Revert feature

So this is a hotfix branch in case if fixing of the bug is complicated and need a lot of time, better to revert a feature which cause this bug and deploy without it. Everything you need is a “git revert”, but don’t forget to revert this revert on master to continue fixing bug there.

Perfect timeline

Let’s wrap it to a week and we will see the timeline:

Monday

  • Finish merging new features to master
  • Create release* branch from master
  • Make sure that API developing team made the same
  • QA can start testing the release

Tuesday

  • Review QA’s feedback
  • If something needs to be fixed — fix it as hotfix to release and QA start testing again
  • If everything ok — we can perform Wednesday operations

Wednesday

Ideally on this day there should not be any bugs on release.

  • Make sure API team deployed to production first
  • We can deploy if no bugs

Thursday

This is a backup day to deploy in case of we or API team didn’t deployed

Friday

Please, no 🙂 Better make some tasks that will decrease the technical debt. Release it on Monday, and then create a new one.

If you will do it — be ready for “funny weekend”. Releasing on Friday is always under the pressure, so it’s very simple to pass some bugs to production. Calm down, and release it on Monday.

Step by step

  • Merge features to master (use squash)
  • Create release* branch from master
  • QA tests release environment
  • Make hotfixes to release, and test it again
  • Release to production (use merge commit)
  • Update master from production (use merge commit)
  • QA tests production environment (if possible)
  • Release hotfixes to production (use squash)
  • But QA tests before it
  • Update master from production (use merge commit)

Conflict when updating master

In case of conflicts between master and production you can not just solve it in master branch because it protected. Here are five steps to do it like a boss:

  • Create branch from production
  • Locally merge master to created branch
  • Resolve conflicts
  • Create PR to master
  • Merge it after approves (better to use merge commit)

Squash vs merge commit

Everything wrote above will work fine by using only merge commit. Using squash prettifies the development history. It will look like one feature — one PR — one commit. It is because when you merge by squashing it collects all you commits in PR and convert it into one. On opposite side merge commit just transfers all your commits.

Squash is very convinient to merging one feature:

  • feature branch → master
  • hotfix → release*
  • hotfix (patch) release* → production

Merge commit is good when we merge the number of features (squash is not recommended here):

  • release* → production
  • production → master

Schema

Additionally to the perfect timeline here is a visual schema:

Finally

And finally as overview everything that we should understand after reading this article:

  • Branches: feature branches, master, release*, production
  • Versioning [major].[minor].[patch(bugfix)]
  • Perfect timeline and schema
  • Do not deploy on Fridays!
  • Correctly understand difference between squash and merge commit

--

--