How Do We Serve New Frontend Developments to Our QAs for Testing
It might be challenging to separate, develop and test tasks meaningfully and painlessly. I will try to explain our practices to follow development process using git and how we serve our developments to QA’s for testing purposes.
We practically have 3 different environments for our applications:
- dev/local
- staging
- production
We are using feature based branch names on git and giving names like FEAT-1, FEAT-2 that are equal to Jira tasks. Our feature development lifecycle was like:
- Complete development
- Open a merge request to the main branch
- Review code
- Apply reviews if any necessary
- Merge feature into the main branch
- Deploy application to the staging environment
- Perform manual and automation tests (by QAs)
- Open a bug if any defects are found (by QAs)
- Reapply from the first step
- If everything is OK then production deployment phase starts (I skip its details)
Problem of This Approach
A merge request will be merged into main branch after code review step is done. We may have more than one new commits that are merged into main branch since latest deployment. We faced this kind of situations countless times. When we have main branch in this situation and if we have to release a bugfix, hotfix or an urgent thing, the problem begins.
Why? Because we have untested commits in main branch and we can’t deploy them yet. To solve the problem we may create a new branch from latest deployed commit and develop necessary fix and deploy it. But we have to break our deployment rule, because we want to keep main branch equals production. Doing it in this way we need to deploy another branch to production and we won’t have this latest fix in main branch. A lot of pain wait us when we want to include the latest fix into main branch.
Should we include it into main branch with cherry-pick or should we do it with merge? We will most probably encounter code conflicts during the solution. I know it can be resolvable but we believe that all these struggles are unnecessary. I like to solve problems in a way that I don’t have to think about the same problem over and over again. So, there should be more elegant ways.
Solution
Since we are doing our developments feature-based, why don’t we serve our application in the same way on staging environment? By doing this we will be able to test features independently. When the test of a feature is done, we can merge it into main branch. It doesn’t matter anymore we need to deploy hotfix or urgent feature because we have tested and ready-to-deploy commits in main branch. We can separately develop new necessary fix/feature and apply same code review/test/merge process on it too.
Our new feature development lifecycle is like:
- Complete development
- Open a merge request to the main branch
- Review code
- Apply reviews if any necessary
- Deploy branch to the staging environment without merging it into main branch
- Perform manual and automation tests (by QAs)
- Open a bug if any defects are found (by QAs)
- Fix bug if found and commit into the same feature branch and push
- Reapply from the step-3
- If there is no bug and QAs says “Test is OK” then merge feature branch into main branch
Thus, main branch will always be ready-to-deploy and clean. If you need to add hotfix/feature into your application, the only thing you need to do is creating a new branch from main branch. So you are ready to go without thinking anything. (We might still have backend-dependent features which we didn’t deploy yet in our main branch, we have feature-toggle feature to handle this kind of situations but this is the subject of another post)
If you have dependent features need to be tested together, it is easy-to-do task. Let’s say you have FEAT-1 and FEAT-2 branches but you need to test them together, just create a new branch and merge both of them into it. e.g. In combination-of-FEAT-1-FEAT-2 branch. Follow the above steps starting from step-5. Follow the above steps starting from step-3 if any conflict occurs. You don’t need FEAT-1 and FEAT-2 branches anymore.
How We Applied the Solution
As you can guess there are some ways to do it. You may try to apply devops solution and create new environment for each branch to realize this but you will need more resources and it will be relatively complex.
Our colleagues from another team implemented a solution by using istio but it was also too complex to me. We need to learn many of its concepts and configurations and we thought it is time consuming. I always consider reinventing the wheel in such cases. I believe it is arguably more challenging, instructive and satisfying. We mostly go with custom solutions.
Disclaimer: I do not suggest to do things from scratch on your own all the time. Especially if technical know-how of team is not enough, in the strict deadline circumstances, if there is mature and robust solution exists out there somewhere, and if you don’t want to hear complaints from your spouse about lack of time to see each other :) and so on…
Application We Developed
We developed an application called branch-up to apply the solution above. This application is working based on webhooks. Basically whenever a merge request is open/updated/merged, a webhook will be triggered. Consequently, the branch-up application pulls the latest commit of source branch from the remote repository, builds it and deploys the UI under specific branch name.
Branch-up flow;
- Create a merge request from any branch to main branch (which is called master in our project)
- Branch-up will start the process automatically for source branch (*1)
- Source branch will be pulled
- Pulled code will be built
- Built code will be deployed and served via branch-up.trendyol.com/source-branch
- Deployed branch can be tested now
1. If the merge request just created is not in draft mode. You can see in below image, PT-58 is in draft mode. It means that it is in code review phase for developers, and not ready to test for QAs. Thus, we know which branch is at which phase without looking at Jira.
Conclusion
By doing this we gained ability to test branches independently. After each successful test, we are merging tested branch into main branch. Thus, the main branch only contains production-ready deployable codes. Whenever we need to deploy the application we will be able to do this.
Since using this solution;
From developers’ side, we are freed from the burden of branch management. Thanks to clean main branch we no longer think about how to fix the warnings and urgent errors that we need to fix.
From QAs’ side, we are able to test branches task-oriented. And also we can compare the branch with previous version before merge, because /master
endpoint contains previous version of application. (Also we still have staging environment for this)
We can say that as a negative affect, we need to do last one test on stage environment after merging all features to check that is there any problem.
Thank you for reading!
Please leave a comment and feel free to share if you like it.