Photo by Mark de Jong on Unsplash

Automatic dependencies updates for frontend services

Our path to Renovate

Mirek Stanek
Published in
5 min readNov 24, 2021

--

Building software is like building LEGO bricks. Most tech solutions are the compositions of open source libraries, public APIs, or 3rd party libraries that we can plug directly into our code. This modularity is one of the biggest growth drivers in the world of technology. The company can focus on its core competencies while using external services created by experts in their domains.
Azimo is no different here — in our tech stack, we use external SDKs (like Onfido to verify people’s identities), frameworks/runtimes — Node.js, Angular, React, or open-source libraries (like RxJS or RxSwift for reactive code). With all of these, we can focus entirely on building financial services that are fast, cheap, and available to all and don’t try to tackle problems already solved.

Having countless external dependencies is invaluable in terms of building your product. But it leads to new challenges. Being on top of all of the changes and bug fixes released under new versions is one of them.

Let’s look closer at one of our microservices responsible for serving our main page — azimo.com. It is an SSR (server-side rendering) web application, built on top of Node.js, containerized with Docker, and hosted on AWS infrastructure. But Node and Docker aren’t the only dependencies we use. This particular service uses 90+ dependencies (or more than 3000, when we include dependencies of these dependencies 🤯). Among them, there are big ones, like React, Redux, RxJS, Bootstrap. But we also use single-purpose projects like UUID or cookie-parser, tools like web-vitals, and our internal libraries.

Keep them all up to date

Keeping all of the things up to date is essential, period. The longer you wait with updates, the bigger is the list of changes. On the one hand, your app uncovers more bugs and vulnerabilities; on the other, there are more breaking changes in public interfaces to which you need to adapt your code.

To make this process more convenient, we integrated the repository with Renovate. This tool creates Merge Requests with dependencies updates — either a single library’s bump with breaking changes or a bundled update with minor versions. It has some neat features too, like rebasing when conflicts appear or doing auto-merge. Each Merge Request has release notes fetched from the updated dependency. You can also compare source code changes between your version and the newest one.

For more, check to Renovate documentation.

Example Merge Requests created by Renovate

Very cool automation, isn’t it? But this is not the end of the story. Integrations like Renovate or Dependabot require some preparation. Otherwise, you may end up with tens of open Merge Requests, production failures, and constant feeling that most dependencies are not up to date.

When we integrated Renovate with our main page microservice for the first time, we got 40+ MRs within one week (and another 20 in the following one). It wouldn’t be possible for a small team like ours to handle so many changes if we hadn’t prepared our project for that.
Here are our quality standards which make the updating process seamless.

Quality standards

Crash free

Over the years, our web engineering team invested a lot of time to ensure our web app was stable. Nowadays, most of the time, we keep our crash-free ratio at >99.9% level. Stability metric is essential not only from the user experience perspective. Some of our crashes aren’t even visible in the customer’s journey. They just generate noise in crashlytics tools. But keeping its level as low as possible will make it possible to spot anomalies during the lifetime of our product. Thanks to that, it’s much easier to identify the root cause, such as a dependency update.

Crash-free metrics for our main page app

Process automation

Another thing is process automation. What Renovate does for us is create MRs with an updated package.json file. It’s not very sophisticated automation, is it? But more important things happen later. Our Merge Request pipelines have some of these steps:

  • Lint checks and unit tests
  • Test coverage report
  • Visual regression tests
  • Deployment

It means that Renoved doesn’t only update packages versions (you could do the same with npm commands) but also runs all of the checks against this update. With this information, it’s much easier to decide what can be merged instantly and which changes require more attention from our side.

Testing coverage

The part of process automation are tests. Over the years, we put a lot of effort into ensuring that tests cover a significant part of our codebase. The microservice responsible for our landing page is currently covered on >80% level. Moreover, 100% of our UI components are described in Storybook and covered with UI regression tests. Even the most minor changes in the user interface need to be reviewed and approved during the code review process. If any dependencies updates affect our UI, we will very likely see it in Merge Request reports.

Example report from our UI regression tests

Integration with Renovate is an important improvement to our product development process. It will help us to keep our tech stack up-to-date, free of bugs, and secure. We plan to adopt it across all of our microservices in the following months. But this integration wouldn’t be beneficial without some groundwork we did in last years — high crash-free with some monitoring around that or process automations, including multi-level testing.

Thanks to all of that, in the last quarter only, our relatively small web engineering team could merge more than 100 updates for dependencies, making our landing page even more stable, secure, and up to date.

Statistics from the Renovate adoption in main page microservice

Acknowledgments

Building this kind of integration wouldn’t be possible without the hard work of our Web and DevOps engineering teams. The biggest credits go to Artur Kania, Tech Lead for Web Engineering, and DevOps Engineer Bartek Grzybowski. Both built the foundation for the integrations described in this article.

Towards financial services available to all

We’re working throughout the company to create faster, cheaper, and more available financial services all over the world, and here are some of the techniques that we’re utilizing. There’s still a long way ahead of us, and if you’d like to be part of that journey, check out our careers page.

--

--

Mirek Stanek

I empower leaders through practice 🛠️💡✨. Site Leader and Director of Engineering at Papaya Global. Ex-Head of Engineering at Azimo.