RFC: Add support for custom commit titles

Summary: Introduce a new configuration property to define a commit title template.

I allow this RFC document to be modified and redistributed under the terms of the CC-BY-NC-SA 3.0 license.

Motivation

My team uses the conventional commits specification (conventionalcommits .org) for our commit messages and we use GitCop (gitcop .com) to police that users adhere to these rules. We also only merge PRs using Bors, but Bors's hardcoded commit titles do not comply to the same rules.

I would like to have a way for us to specify what the commit title should look like when Bors creates a merge commit. This feature has also been mentioned in issue 637 and discussed in How to change the commit message format?.

Guide-level explanation

I propose to introduce a new configuration property: commit_title.

The commit_title configuration property can be used to define a custom template for the commit title, that Bors applies to generate the commit message of new merge commits. The commit_title can be configured in your bors.toml configuration file.

For example, let's say you'd like Bors to merge all PRs with the commit title merge pull request. Simply add the following to your bors.toml configuration file.

commit_title = "merge pull request"

It is also possible to refer to the PR's unique identifier using a reserved keyword in the commit_title.

For example, let's say you'd like Bors to merge a PR with id #8 using the commit title merge: #8. Just add the following to your bors.toml configuration file.

commit_title = "merge: ${PR_REFS}"

If you do not specify a commit_title, it defaults to:

commit_title = "Merge ${PR_REFS}"

Reference-level explanation

The commit_title is defined in the following BNF:

<commit_title> ::= <segment> | <commit_title> <segment>
<segment> ::= <prefix> <pr_refs> <suffix>
<prefix> ::= "" | <string>
<pr_refs> ::= "" | "${PR_REFS}"
<suffix> ::= "" | <string>
<string> ::= ... # any non empty string

This grammar means that the commit_title can contain:

  • any non-empty string
  • as many ${PR_REFS} references as you'd like, and in any index in the string

All occurrences of the ${PR_REFS} keyword are replaced by the string of pr references. This is generated in the following manner:

For every PR that will be merged with this commit:
   take the identifier (i.e. `xref`)
   prepend the char `#`
   join with space char in between

For the set of PR identifiers [1,2,3,4] this would result in: #1 #2 #3 #4.

Drawbacks

Why should we not do this?

  • It adds an additional config property and a reserved keyword to maintain.
  • It might lead to unforeseen bugs.

Rationale and alternatives

  • Why is this design the best in the space of possible designs?
    It allows for flexibility and is backwards compatible
  • What other designs have been considered and what is the rationale for not choosing them?
    I have not yet considered other designs
  • What is the impact of not doing this?
    Some users might feel they can't use a tool like Bors if they can't have this feature, although unlikely.

Prior art

  • For feature RFC's: What other CI/CD systems implement anything similar to this one? What do they do well? What do they do poorly? If this proposal is similar to what one of them already does, did you change anything, and why or why not? Why would the user pick bors over just using that other thing instead?

Rultor does not support this feature. I don't know any other tools that do the same.

  • Also for feature RFC's: How does this feature you're proposing complement the software development lifecycle of real teams? Compare what you're implementing to things that they're doing by hand, or using other tools. Please make sure that this feature is likely to be used by more than one project.

Other users have requested this feature.

  • For process RFC's: What do other major open-source projects do? Focus on ones that make their environment welcome to marginalized groups. If they have a reputation for being mean, we don't want to copy them.

NA

  • What lessons can we learn from what other communities have done here? Why do they do what they do? Why is it applicable to bors, or why isn't it?

NA

  • Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background.

NA

Unresolved questions

  • What parts of the design do you expect to resolve through the RFC process before this gets accepted?

Specify and commit to a grammar and naming of the config property

  • What parts of the design do you expect to resolve through the implementation of this feature before deployment?

NA

  • What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?

Commit body customisation
Additional reserved keywords for PR summary and description

Future possibilities

Commit body customisation
Additional reserved keywords for PR summary and description

See also

If this RFC already has a draft Pull Request, link to it here:

Since no discussion has started yet, I'd like to add some design choices to consider:

An alternative to that grammar could be something along the lines of:

<commit_title> ::= <string> | <prefix> <pr_refs> <suffix>
<prefix> ::= "" | <string>
<pr_refs> ::= "" | "${PR_REFS}"
<suffix> ::= "" | <string>
<string> ::= ... # any non empty string

This would restrict the number of times the ${PR_REFS} keyword can be used in a commit_title.


Other choices are the naming of:

  • commit_title: alternatives I see could work commit_title_template or title_template
  • ${PR_REFS}: alternatives I see could work {{PR_REFS}}, <PR_REFS> or just PR_REFS or even PR_IDs

Of course, I am open to other suggestions. Please let me know what you think

The name probably should have “template” in it.

As for whether the PRs should be allowed to appear more than once? Yeah, they should.

One other thing I might consider is extensibility. Maybe you should arrange to have $ escaped with a backlash, and have unknown variables error out instead of being silently used verbatim? That way, new variables can be added without being a breaking change.

The name probably should have “template” in it.

Agreed. However, it might not be a good idea to just name it title_template, since it might not be clear what title (i.e. commit or PR) is meant. commit_template is also not correct, since it only concerns the title of the commit message. Options I see:

commit_title_template = "Merge ${PR_REFS}"
[commit]
title_template = "Merge ${PR_REFS}"

WDYT?

have unknown variables error out instead of being silently used verbatim

I like that idea, we should definitely have some way to escape variables. I just wouldn't escape it with a backslash. I think the ${x} is a good enough keyword signifying token, but I'm open to other ideas. So far the options are:

  • ${x}
  • {{x}}
  • <x>
  • \${x]

It might also be possible to do something like \\x escaping, but that get's complicated quickly because it's not clear when the variable stops and the static text starts. I don't have a strong preference for any option.

Probably the best choice.

I don't think I want backslash to be part of the normal variable syntax. Probably, a good choice would be the first one, ${x}. because it would be easy to make it a literal by adding a syntax like $$, so that:

# The default, results in "Merge #99"
commit_title_template = "Merge ${PR_REFS}"
# A custom choice, results in "Merge #99 [semver:1]"
commit_title_template = "Merge ${PR_REFS} [semver:1]"
# A custom choice with a literal dollar sign, produces "$merge #99"
commit_title_template = "$$merge ${PR_REFS}"
# This one produces an error, something like "Error: invalid variable FOO"
commit_title_message = "Merge ${PR_REFS} ${FOO}"

I don't want to use backslashes, because that would conflict with TOML and be really annoying.

@notriddle Thanks. That all makes sense.

I'm not allowed to edit the original post anymore, so I'm unable to update the RFC. Could you perhaps update it, or is it fine that these design choices are only mentioned in these discussions?