When your team charter is to support the infrastructure needs of many internal teams that are innovating quickly and releasing changes multiple times a day, it’s crucial to deliver as efficiently as possible. This team is tasked with providing trusted representative environments for testing to other teams in order to perform functional, integration, and performance validations that meet their product release timelines. This is done via a platform layer that promotes an automated, self-service capability for the teams that rely on it. But when you’re working to support an ever-moving target, some common pitfalls can occur.
The fast pace of work can lead to duplication of efforts, because teams are working in isolation and only doing the work that they need to benefit their own development. These teams may be implementing the same behavior in slightly different ways. Onboarding new team members becomes challenging, and developer productivity is impacted by the constant context switching required when there’s no set standard for contributing to different repos. A pitfall of such an effort is that, when a new feature is needed team wide, if each repository maintains its own implementation of the functionality, then the same feature change has to be propagated to each different repository. Imagine if, out of the 10 repositories owned by your team, the functionality is propagated to all repositories except the one repository that delivers artifacts to production!
That’s where inner sourcing comes in. Inner sourcing is the use of open source practices for software development inside the confines of a single organization. It can be a great tool to help break down silos, encourage internal collaboration, accelerate new engineer onboarding, and even identify opportunities to contribute code back to the open source world. Let’s look at a small case study of how inner sourcing is helping the team at Salesforce that’s responsible for providing a test environment platform for other teams across the company.
To work within our continuous delivery system, teams generate a deployment manifest file that tells the system what version of their service to deploy and and where to deploy it. Teams all have their own ways of doing this, and the manifest may be either a JSON or a YAML file, depending on their configuration. But since the creation of this file is a common need, why not standardize it?
Another similar requirement we have been seeing across our organization is having to interact with Git, since our tools need to trigger a multitude of interactions with Git. To name a few, our tools need to create PRs and add review comments to existing PRs for visibility automatically. With multiple projects needing this same set of functionalities, this is another strong contender to be moved to a common project, with all different teams simply consuming and building on top of it rather than reinventing the exact functionality in different ways. If a new interaction with Git is required, the consumer can contribute back to the common repository, adding this functionality across the teams and organizations.
The Test Environment Platform team consolidated these deployment functionalities — cloning repositories and creating PRs, generating deployment manifests, interacting with Slack etc. — and opened them up for consumption and collaboration. Teams are able to incorporate these centralized libraries through API calls or import statements. If a change needs to be made to the process, it can be made in the shared repo and delivered to all users at once. (To ensure regressions aren’t introduced by updates, teams are able to specify what version of the service they are using.) The shared module was created following both industry and internal best practice standards, mitigating the risk of team-specific biases getting baked in. Security policies can also be standardized when code is provided centrally. Inner sourcing this functionality frees teams up to focus on building and deploying their applications and services rather than maintaining infrastructure.
Documentation is crucial when it comes to inner sourced repositories, because it’s challenging to make sure the shared functionality is discoverable and that teams know how to implement it if they determine it will be useful for them. Documentation also helps individual engineers determine whether a piece of code they’re working on may be useful outside of their own use case and should therefore be contributed to the shared repo. Without good documentation, inner sourced projects can fizzle out if the main contributor leaves the company or moves to working on a new project.
Testing is another crucial piece of a successful inner sourced project. Complete unit and integration tests define the criteria for whether shared code is ready for consumption and help teams using it avoid issues at runtime. Having a well-defined test suite instills confidence in people absorbing the shared repository and also makes sure that addition of new features doesn’t break existing functionality. This becomes very important when multiple teams could be affected by a small error which slipped a developer’s notice. The tools we use ensure that we adhere to standard quality gates (such as minimum 80% code coverage, Sonarqube quality gates on code maintainability, etc.), thereby assuring the different teams building on top of our offerings that the repositories they are consuming are well tested. These metrics are visible publicly for transparency. When users contribute back to our projects, if benchmarks such as code coverage fall below a set minimum on the new code being added, we block the merges unless the user fixes this. This ensures that we stick to our promise of trust and customer success being delivered to our consumers.
Opening the shared repository up for feedback and collaboration makes it better for everyone using it. This is relatively common in open source, as well. It doesn’t have to be anything as formalized as a committee, but rather, any proposed change should be considered across all use cases by having a range of reviewers examine it before pushing the change.
Moving toward inner sourcing critical code components requires a cultural shift, but we’ve found it to be well worth the uphill climb for the benefits across productivity, standardization, and new team member onboarding. If you see a key functionality being implemented in multiple different ways as we did, or a piece of code that satisfies a common goal but is currently housed within a single team, why not try applying inner source practices to it and seeing what happens? Start small. GitHub’s introduction to inner source says,
“Pilot projects can help teams experiment with more open processes, democratize access to code, and document best practices before applying innersource more widely. Small successes can help show your internal community of developers how to make the most of their code and ship better software, faster.”
Inner source is also a great first step toward open source; if a project has the potential to be open sourced later, applying the same principles to it via inner source first makes it stronger.
For ourselves, we’ve been reaping the rewards of creating a centralized module for executing git operations from the get go. We currently have two different projects with org-wide visibility. Using a common repository that provides common functionality really accelerated our development cycle. Both projects simply imported the functionality they needed (manifest generation, creating automated PRs) and the only thing the developers had to be concerned about was building project-specific functionality on top of it without needing to worry about how to create PRs or generate manifests on their own. Our repo is also being used by other teams to now generate their manifests automatically, rather than having to generate one by themselves. And, what is even more exciting, is that we are seeing contribution requests as well, where consumers want to give back and add functionality that can benefit the tool! Inner sourcing has not only saved our team development cycles, but benefitted other teams as well, where they don’t have to spend time and effort on developing a common functionality.
There is still work to be done toward building a culture of inner source, and we’re excited to continue sharing the success of this project as an example of what can be achieved when we work together.