Skip to main content
Hero Background Image

Tips For Planning to Port a Contrib Module to Drupal 8

February 1, 2017

Having helped port a few contrib modules from Drupal 6 to 7, and then from 7 to 8, I'd like to share some tips and recommendations that may help others who are looking to port their modules to Drupal 8. While most articles on this topic focus on the coding – the new APIs, the new directory structures, etc – I'm going to focus on the project management and goal setting aspects of the port effort. In my opinion, the success of an OSS project upgrade can hinge more on these aspects rather than just the code changes, but they are rarely discussed.

1. Think Small

Most Drupal 7 modules have been around for many years. Drupal 7.0 itself was released in January 2011 and some contrib modules were pretty far along with their ports before that. Add in years of feature requests, bug fixing, and refactoring, and it's easy to see how a contemporary Drupal 7 contrib module could have a very large feature set. Which is great! All this functionality and flexibility has helped us build hundreds of thousands of sites However, there's no reason why the first stable release of the same module for Drupal 8 has to have all of the same functionality.

2. Brainstorm

All Drupal projects have a support channel called the issue queue. All issues created in the issue queue have an attribute to indicate which version they're relevant for, and this can be used to find the issues people have already created for the new port. Start off by reviewing the Drupal 8 issues for the project being worked on; this can be quickly done by looking at the project's issue queue, changing the "Version" field to "- 8.x issues -" and clicking "Search". Hey presto!

Review the issues currently available and then create new ones for anything that might be missed. This is a good time to make sure the old module's functionality is actually understood - there could be long forgotten functionality included that is no longer needed, so having a list of this will help.

It's also recommended at this point to have issues for rudimentary tasks like writing some initial documentation, one for writing some initial tests, and one for a quick code review. After that add some more for writing tests around specific functionality, one for testing against the next core minor release (API changes or additions might break the project), removing deprecated API usage, etc.

3. Plan Small 

While it can be tempting to say "everything must be fixed for 1.0", every module will have a basic set of functionality that without which there would be no point to the module. Look at the issues queue and decide how much of them absolutely must be in the final 8.x-1.0 release. Does it really need a huge amount of tests? Probably not, but it definitely should have at least one to make sure the site won't break when the module is enabled. Does it really need a huge amount of documentation? Probably not, but an initial README.txt file that provides a quick intro would be a huge help. Does it really need every option that was available in the Drupal 7 version?

Start small. Start with just the core, basic functionality, some tests and some documentation. That is what will become the 8.x-1.0 release.

It might be worth reviewing the list with others to make sure nothing has been forgotten. Remember that there will always be a 8.x-1.1 release, and a 8.x-1.2 release, even an 8.x-3.15 release after the module goes through two major rewrites and a bunch of additional fixes. The point is - 1.0 can be small.

4. Baby Steps

The 8.x-1.0 will be the first stable release, but it shouldn't be the first release.

Take the list of issues to be completed for 1.0 and split them up into small groups, preferably with some sort of sequential ordering. For example, a settings form doesn't have to exist before the config entities are being referenced as the system can use defaults. For each group of issues decide to create an associated beta release, e.g. "8.x-1.0-beta1", "8.x-1.0-beta2", "8.x-1.0-beta3" and so on. Each group should be kept small and contain about the same amount of work - if some issues end up being too all-encompassing feel free to split up the issue into smaller pieces.

It's worth mentioning that there should be a release candidate (8.x-1.0-rc1) before the final 1.0 release. Going from software engineering best practices, the first release candidate release should be functionally complete and any further changes before the 1.0 release should be focused on documentation, test writing and bug fixes; additional features can wait until after 1.0.

All told there could be a handful of releases or even a dozen or more depending on the size of the module - Metatag had twelve beta releases before it hit the magical 8.x-1.0!

One recommendation here - move the "write an initial test" issue to near the top of the list as having tests will help avoid regressions when other changes are being made. I've also found that having some tests can encourage other people to write more, so the test coverage will just grow over time!

5. Don't Plan Too Much

Remember that the first stable release doesn't have to have everything, so try to avoid the temptation of adding a ton of issues to the list just because the releases might seem "small." Once a module becomes stable more people will want to use it, which will lead to more collaboration, which might lead to suggestions and patches for improvements that were never thought of before. So don't feel every issue that's in the issue queue has to be assigned to a specific release.

6. Connect it All Up 

Drupal's issue queue, while it could use some improvements, has a few really useful features that people don't use enough. Two of these work really well when used together - the "Plan" category, and the issue "Parent" field. Here's what to do:

  • Create a new issue for the first beta release that was decided upon earlier.
  • Give the issue a name with a title like "Plan for [modulename] 8.x-1.0-beta1" and set the category field to "Plan".
  • Create a second issue for the next release after that, e.g. "Plan for [modulename] 8.x-1.0-beta2" and again set the category field to "Plan".
  • Go back to the "beta1" issue and update it to set the issue's "Parent" field to be the beta2 issue. This can be done by either typing in "Plan for [modulename] 8.x-1.0-beta1" or just pasting in its issue queue number, either way, the autocomplete form will help find the correct one.
  • Repeat for all of the releases that were planned out.

That creates the release issues and helps identify the end results, but the important piece remains. Go through the issues for each release and set their "Parent" field to point to the appropriate release.

When all is said and done, there should be a number of "Plan" issues, each with several other issues listed as their "children". There should also be a logical progression from beta releases through to the first release candidate and then final release.

7. Be Flexible

Lastly, it's worth keeping in mind that two things will happen while the work is being done:

  • People will report bugs. New bugs will need to be triaged and included in the plan along with the others.
  • Halfway, someone might realize that the plan as it currently stands is too broad, that the module doesn't really need all of those plugins, or it doesn't have to support five different remote APIs but instead three might be enough, whatever the case may be.

It is important to not stick absolutely rigidly to the plan as it was initially created. Instead, accept the realities of software development, that the plan may need to shift or, indeed, thrown out entirely.

If the overall plan included more than a few beta releases it may also be worth taking some time every few releases to make sure that the overall plan is still appropriate. We developers can often get tunnel vision and be stomping on a path that was started on ages ago, unaware that the path actually changed along the way, we were just too narrowly focused to notice.

Make a Good Start 

While perfection can be a nice goal to have in mind, remember that "better is the enemy of good." Start small, accept that there will be rough edges and that it can always be improved over time; in other words, release early, release often.

Good luck with your porting projects!