Is there a way to add custom rebasing logic?


I’m working as part of a team on a project which uses Craft CMS.

Our workflow is to rebase and merge, sometimes squashing, sometimes not.

Craft stores a set of configuration files which describe the various defined content types, and this is used as part of its mechanism for setting up its database.

When a developer makes changes to the CMS structure, these configuration files are updated. Usually even if multiple developers are working on things there are no conflicts in this set of files and things merge easily, with one exception: a “last modified” timestamp, which the CMS uses to judge whether it needs to read the config files, look for changes, and apply them.

The CMS provides a CLI command which updates this timestamp to the current time, and even resolves git conflict markers around it if they exist.

The problem

When we have multiple MRs open which touch the project config and therefore this timestamp, merging one always introduces conflicts with all others.

They’re trivial to resolve manually individually, but it’s a real pain. We have to wait for one to finish merging along with the associated CI tasks, then manually fix the conflict in the next, wait for the OK from CI, then wait for the merge and merge-related CI, then manually fix the next, and so on.

What I would like

I would like to automate this.

I don’t know if it’d be a CI thing, or a bot, or some script that I can put somewhere in the Gitlab CE configuration, or something else.

This is how I imagine it working:

  • It’s triggered somehow when an open non-draft MR finds that it is now in conflict with its target branch.

  • It starts to rebase itself on the target branch. When rebasing stops due to a conflict, we check whether the config file with the timestamp is the only one in conflict. If not, we abort.

  • We run the Craft-provided CLI command which updates the timestamp and resolves its conflict markers. We check if there are still conflicts. If there are, we abort.

  • We continue to the next commit, until we’ve aborted or the rebase is complete.

  • If the rebase completed, we force-push (with the flags to protect against clobbering new work which appeared in the mean time).

My question

Is the above possible? How would I get started?