From a Day to 17 Minutes: How we’ve dealt with slow build times

From a Day to 17 Minutes: How we’ve dealt with slow build times

The problem of a long deployment process isn't just the waiting; it's how this waiting seeps into every part of the development process, fundamentally changing how teams work. Test builds are less frequent and bigger in scope. This leads to slower turnaround times on feedback and testing. Release cycles are long and there is less space for experimentation and prototyping.

 

We experienced this in full fashion with 8 hour deployment times with a decent amount of manual work. Here's how we finally took action to significantly reduce the time it took.

Common pains of shipping electron app

acreom first started as a web app, and deploying it was simple. But when we decided to support other platforms by creating an Electron version, we saw that things started to move much slower. 

Distributing desktop versions of our app became a tough and tedious task. We would spend an entire day just getting the versions ready for release. It was not only time-consuming, but also highlighted several issues we faced, such as managing different platform requirements and ensuring consistent performance across all of them. 

Building the Frontend for Different Operating Systems

For the frontend part of our app, we use Vue+Nuxt. However, when we work with Electron, we don't use Nuxt's feature for server-side rendering. Instead, we build the frontend as a single page app, which means it's made up of static files like HTML, CSS, and JavaScript. It's important to note that we create a separate build for each operating system because there are some differences in how the app works on each one, such as the way users log in, deep links, and file management.

We are also building a tiny executable called acreom-assistant that is running a local language model for parsing dates. This executable is packaged with electron. You can learn more about how we ship it.

App Signing and Distribution Across Different Platforms

To make sure our app runs on Windows without triggering the SmartScreen warning, it has to be digitally signed. This process involves getting a certificate, which comes on a physical USB token (a USB drive with a private key on it). These tokens are bought from certificate authorities and cost around $300 a year. Because of this, the app's build process needs to happen on a computer that has this USB token plugged in, which we ended up doing manually on one of our developer's Windows computers.

For macOS, to avoid users having to manually allow the app in the Privacy & Security settings, the app must also be signed and then notarized by Apple. Notarization requires an Apple Developer account, which costs $100 annually. Fortunately, we had an old MacBook Pro that we dedicated to the tasks of building, signing, and notarizing the app.

When Apple released computers with the new M1 chips, we had to adapt again. We added another MacBook to our setup because we use ZeroMQ for communication between the Electron app and the Acreom-assistant, and ZeroMQ has some native bindings that required adjustments for the M1 architecture.

Linux was a bit different; it was the only platform for which we set up the build and distribution process to run automatically through GitHub actions from the beginning. This approach for Linux was much simpler compared to the manual processes required for Windows and macOS, making it our "golden" platform in terms of ease of deployment.

Sharing Builds: Adapting to M1 Challenges on GitHub

The last step for each platform's build process is to upload the app to our GitHub releases repository. We automated this step from the beginning, but when we started creating builds for the new M1 chip Macs, we had to add a manual step. This involved merging files needed for the auto-updater to work with the M1 builds

Making dev team happy with faster deployments

Originally, it took us a whole day to get the builds ready for users. We had a dedicated machine to run the non-automated build, then we had to upload the builds to a shared folder, and send each other messages that the build was done. Repeating this many steps made the whole process painfully slow. That’s when we started with automation and moving the pipeline to the cloud, which didn't work out that well at first.

Automated internal builds for testing

We ship our products across multiple platforms. This includes web, desktop (like Windows, MacOS, Linux), and mobile devices (iOS and Android). We use the same steps for each platform, using continuous deployment to share our work with our team and the users. 

Every time we add a new branch, GitHub Actions automatically makes an inside version of our app and puts it in a Google Cloud Platform bucket, which the team has access to and can try them out. Each feature has a specific Discord Forum, where we discuss and explore ideas.  

Quick beta builds on web

Our approach for web apps mirrors our desktop apps. We deploy each branch to a unique URL (e.g., [branchname].preview.acreom.com) using Netlify. We share some early versions of our projects hosted on Netlify with our Discord community. To protect user data, these test builds connect to a staging backend and database, instead of the production environment. While they aren't fully ready for release, they are prepared for users to explore, envision how they could use them, and share their feedback on Discord.

Results on the way we’re building

Having this in place helped us tremendously iterating on our product. To show a real example after all the improvements: We knew there was something wrong with our sidebar so we've made an effort to improve doing a series of explorations with clear goals. We did 4-6 builds within 2 weeks, iterating on various parts. We explored and discussed what worked well and what didn’t. During that time, we have learnt everything - tradeoffs and consequences of decisions, so that we could confidently ship a good thing. If deployment time would take us day a week, our team couldn’t be focusing on solving user problems. We’ve talked about some of our learnings in common mistakes of building a productivity tool. But it also resulted in some unexpected benefits.

More demos over discussions 

Faster deploy times helped us rediscover an old mantra - show, don’t tell. Rapid prototyping and iterating on the end result is the best way to explore ideas. We don't have to spend hours talking about ideas in meetings without anything concrete to look at. The prototypes we do are often very basic and just good enough to communicate an idea, even if some parts are broken. They also encourage us to take action. It's hard not to try something when it doesn't cost much, while learning a lot from it. If we can build something in a day, we don't spend too much time talking about it. 

More options to choose from

Having multiple options and ideas makes it easier to pick the best one. Rapid prototypes leave you with a catalog of possible solutions clearly demonstrating its pros and cons. After that you have a rough understanding of costs and tiniest details of the implementation. 

Targeted user feedback

Shipping things quickly means you can share more with your users. Keeping in touch with your users is key to showing how you are solving their problems. Not everyone will test your prototype, but somebody will be interested to try out and help you to shape it. Talk to people, show them how you're solving their problems, and you might end up with a group of fans willing to help you.