De-forking a Puppet module

A couple of years ago, the team I’m on forked a Puppet module called "mrepo" that is used for creating and managing RPM-based repository mirrors. We recently had an issue arise with using the module, and I happened to notice that the upstream of our fork is now Vox Pupuli and that they had made several improvements that we could benefit from. Those changes, combined with knowing the quality work Vox Pupuli does on all of their modules, made me wonder what it would take to get off our fork and back on to the upstream version.

To suss that out, I looked at the closed pull requests to see what kind of changes we had made since forking from the original repository. Based on what I saw there, all we had really done was:

  • add one parameter and an optional bit to an ERB template
  • added a regex validation for an architecture we use that the upstream doesn't

That seemed simple enough, and the diffs of each pull request were quite small, so I decided to actually try and submit our changes as a pull request.

I set about working on my pull request initially by just submitting it as-is to see what shook out ... turns out that when you are two years behind on commits that doesn't exactly work. At that point, it was time to do what I should have done in the first place: rebase my changes on the current upstream version. Here's what that looks like from a git perspective:

Create a branch in the fork:

Squash the six commits that made up our local mods into a single commit:

I still wanted to make sure that credit was given where it was due even though I was squashing all of the commits into one, so I made note of the names and email addresses in the original messages and added a Co-authored-by line for each to the new commit message.

Pull in the history from upstream:

Rebase local changes onto the current upstream code:

The rebase step included resolving some merge conflicts from where things diverged between the two code bases over the last couple of years. After completing the rebase, I ended up adding some additional changes to our code based on work that had happened upstream. At this stage my single commit's message now looked like this:

I felt pretty good about these changes after a good bit of testing via CI on the PR and doing noop runs on our server that uses this module, so I commented on the PR that it was ready for review.

Later that same day, Tim Meusel of Vox Pupuli (aka bastelfreak [1] [2]) merged my PR. The changes were even pushed up to the Forge that same day!

After the new version was pushed up to the Forge, I archived the fork of the repo and updated the Puppetfile in our control repository.

Unfortunately, it seems one thing was missed when I added types to everything. 23 days after all of the work above was completed, another user chimed in to say that the new version had an error in it: I had set the parameter metadata to only accept strings when it should actually accept both strings and arrays. We chatted back and forth a little and they posted another pull request to correct the issue. A reviewer of the fix rightly indicated that

Variant[Enum['yum','apt','repomd','repoview'],Array[Enum['yum','apt','repomd','repoview']]] $metadata = 'repomd' 

was a little too convoluted to have in the parameter section of a manifest and asked the author to create a type instead. The result was the creation of types/metadata.pp:

After that, the PR author was able to make the parameter definition much simpler:

And that's it ... with work done over 3 days (including doing unrelated things) plus helping review a bug report a few weeks later, all of the additions that we used internally are now available to the community at large AND we no longer have to be the sole maintainers of a module. This is absolutely a win-win scenario in my mind. As a bonus, the Vox Pupuli community now has another party with a vested interest in helping maintain one of their many modules, so this is really a win-win-win!

Gene Liverman is a senior site reliability engineer at Puppet.

Learn more

Puppet sites use proprietary and third-party cookies. By using our sites, you agree to our cookie policy.