Skip to content

Execute repo-controlled script during the "rebase" step, before pushing to the CI

In Mesa we have code formatting checks, and they currently prevent merging badly formatted code into the main branch.

This is all nice and well, but people who haven't configured their editor to auto-format the code get a bad experience: they send their MR to @marge-bot, Marge rebases, sends to the CI, the CI fails, Marge tells the dev that the CI failed, and the dev has to look at the CI to see that the formatting is bad and do the whole dance again after fixing it. This is especially bad for new contributors.

It would be a much better user experience if Marge could just do the formatting itself and add a commit at the end, after rebasing and just before pushing to the CI, so that it's transparent for the user. (just before pushing also means that any commit added will be pushed intact, meaning its hash can be used as a something that will exist in the permanent git history, and can for instance be added to .git-blame-ignore-revs)

Since project-defined operations like these can require more tools to be available and we cannot rely on those in Marge deployments, I'm thinking of doing this with a container: it would contain whatever is needed, and marge would simply look for a config file in the repo, and if it's found download the image it specifies and run the command; the only dependency that is added is podman or docker.

For instance, in our case a basic version of this would be:

.marge-bot/pre-push.yml:

image: foo/bar:v3
script: |
  meson setup build

  # format C & C++ code
  ninja -C build clang-format

  # format Rust code
  shopt -s globstar
  rustfmt src/**/lib.rs

  if ! git diff --quiet
  then
    # commit any changes needed
    git config user.email code-format-fix@mesa-project.local
    git config user.name 'code format fixup script'
    git commit -am 'code format automatic fixup'
    git rev-parse HEAD >> .git-blame-ignore-revs
  fi

(we might want to make it smarter by eg. using git autofixup, but once it's under the project's control we can make whatever improvement we want)

When Marge sees this file in the project, it would read these two keys (as $image and $script below), and run:

podman run --rm --volume "$repo":/code --workdir /code "$image" sh -c "$script"

If the command fails, its output is included in the Marge error message (necessary for debugging), which as a bonus also mean this can be used by projects that want to have extra checks in there and exit 1 if they need to stop the merge.


Does this sound like a reasonable plan? If so I'll start working on this and post an MR once I have a working prototype.