Pushing the Limits of Continuous Integration: Releasing to Production on Every Change

How composable architectures paving the way to perform atomic releases

Ashan Fernando
Bits and Pieces

--

Reducing the lead time from development to production is essential in modern software development. Many software processes, like Kanban, are geared toward this.

Yet, releasing to production for every change is still challenging. We must ensure that even the slightest change to the codebase does not break existing functionality. However, executing automated tests for the entire codebase may exhaust your CI.

How can we push the limits of CI/CD and release each change into production in a stable way?

Modular Builds and Tests — With Composable Architecture

The fundamental challenge here is that it's difficult to predict its impact when we modify the code in a codebase, as source control will show only the added and modified files. And the files we modify and tests we write don’t have a clear connection. Therefore, to be safe, we have to execute all the automated tests before performing a release.

Imagine how long it will take to execute thousands of tests in a large, complex code base, even for the slightest code change. It may take hours. Therefore, traditionally releasing at least a few features together (or daily) is realistic instead of pushing every change into production.

The most famous attempts to address this problem are Microservices and Microfrontend architecture styles. These styles promote breaking a large codebase into multiple pieces with clear boundaries to keep code complexity in each piece to a minimum.

But can we do better in creating more granular level of boundaries that are easy to test in isolation and understand the impact of a modification?

Introducing Composable Architecture

Composable architectures help break a large code base into a collection of components wired together to build the final application. The fundamental unit of composable architecture is the Bit component.

This completely changes how we implement platform engineering across the organization.

Reinvent platform engineering for a highly modular codebase

Instead of working on a large codebase, our changes are within the bounds of components. When we modify one or more components, we can identify its impact and dependency chain. We can even build the modified components using Ripple CI (CI platform optimized to build and test components in parallel).

Ripple CI, building components

Therefore, using a component-based architecture, the entire development and test lifecycle is encapsulated within components, allowing running efficient builds and tests against only the changed components for faster and more efficient release into production.

Full Transparency — Easy to Assess Impact of Changes

Transparency in the CI process is crucial for large teams. It enables developers to quickly assess the impact of their changes and understand how they fit into the broader project. Bit supports this transparency by providing a clear overview of each component, its API, a preview (for UI components), its dependencies, and the latest test results.

Bit platform CI, Component Hosting and Dependency Graph

For example, if you build a design system using Bit, you can see all these in action with complete transparency across the components you change to improve developer and designer collaboration. The main advantage is that the same underlying ecosystem and tooling can be extended and consistently used from the frontend to the backend.

When a developer modifies a component, the Bit dependency graph can show which parts of the application are affected, propagate the change and show its test results. This makes it easier to identify potential issues before they reach production, ensuring that every change is safe and that the team can confidently push updates rapidly.

Component-Based Feature Toggles — For Granular Control

Feature toggling is a powerful technique that allows teams to merge code into production without making it immediately available to all users. Sometimes, you may not be able to complete the entire feature, but you can still push it by adding a toggle. This allows your teammate to collaborate and get the latest updates, avoiding big-bang code merges that take hours to resolve conflicts. This strategy is also effective in a CI environment where changes are continuously pushed to production.

You can extend the feature toggling into components, where you know precisely which components are modified when reactivating a toggle. This allows you to test the impacted features of a toggle and test them before and after releasing it to production. You can get to know most of this information at build time, a luxury for stability when releasing changes often and fast into production.

Now, you can decide which version of the component you want to use within the toggle, making it easier to carry out AB testing and canary releases at a more granular level.

"dependencies": {
"component-v1": "npm:your-component-package@1.0.0",
"component-v2": "npm:your-component-package@2.0.0"
}
import React from 'react';
import ComponentV1 from 'component-v1';
import ComponentV2 from 'component-v2';

const App = () => {
// Check for a query parameter to decide the component version
const newFeature = FEATURE_FLAG_VARIABLE;

return (
<div>
{newFeature ? <ComponentV2 /> : <ComponentV1 />}
</div>
);
};

export default App;

This means new or updated components can be deployed and conditionally activated based on various criteria, such as user roles, geographic locations, or other business rules. This granular control over feature release processes enables teams to experiment and roll out changes incrementally, reducing the traditional risk associated with deploying new features.

Standardizing JS Development: Templates, Code Reuse, Uniform QA, and Enforced Conventions

Standardization is vital to maintaining quality and efficiency, especially in large teams working on complex projects.

Imagine your developers know precisely how to create a new React component with a predefined skeleton and the standards they must maintain regarding code styles, interfaces, unit tests, etc.

We can improve productivity and consistency across code bases by simplifying and eliminating subjectivity and unnecessary decision-making for repetitive tasks in favor of standardization.

Component-based architecture using Bit takes standardization to new heights. You can define custom templates for component creation, create reusable components for your CI build tasks for code linting and evaluate other code styling rules.

Enhance dev experience for better quality and consistency for faster releases

Even if you use the default component generators, you can save hundreds of hours in a shorter time span.

Component generators in Bit

Since you store all your components in the bit platform, you can access them across applications, projects, and teams. This also helps you build robust, tested and hardened code over time.

Bit also ensures that every component is tested and meets quality standards before it’s used in production. This approach streamlines the QA process, making it an integral part of development rather than a separate, often bottlenecked, stage.

All these together help implement high quality and visibility into code, allowing for faster releases.

Conclusion

The dream of releasing every change into production is becoming a reality for teams with the right tools and methodologies. By embracing efficient builds/tests, ensuring complete transparency, utilizing component-based feature toggling, and standardizing development practices, teams can push the limits of continuous integration like never before.

Bit stands out as a pivotal tool in this journey, offering a platform that supports composable design, encourages efficient CI practices, and fosters a culture of transparency and quality. As teams adopt these advanced CI practices, the ability to release every change into production at scale is not just a possibility but a practical, achievable goal.

Thanks for reading! If you have any questions or suggestions, feel free to add them to the comments below.

--

--