owned this note
owned this note
Published
Linked with GitHub
# `homu` rewrite
The Rust BORS clone [`homu`](https://github.com/rust-lang/homu) is crucial to the daily development of Rust infrastructure (compiler, miri, clippy etc.).
Sadly, the code of `homu` is quite old and messy, it is currently basically unmaintainable and it is very difficult to implement new features for it.
It also probably contains a lot of legacy code for CI systems that aren't used anymore (e.g. Travis).
It would be nice if we could rewrite `homu` (preferably in Rust), with the following goals:
1. Make the code more maintainable/testable.
- Writing it in Rust should by itself improve maintainability and readability vs the current Python code that is *very* dynamically typed.
- Prepare/extend the test suite for `homu`.
2. Get rid of legacy systems, tailor the code for the current GitHub CI.
- In the process, possibly change some of the workflows to be better integrated with GitHub.
3. Implement new feature requests (once the rewrite is done) that are now stuck ([homu issue list](https://github.com/rust-lang/homu/issues)).
## What does `homu` do?
First, it would be nice to document what does `homu` do at its current state:
- Web server
- `homu` provides a [web server](https://bors.rust-lang.org/).
- Displays basic help (which GH commands are available).
- Displays current merge [queue](https://bors.rust-lang.org/queue/rust).
- Allows creating rollup PRs.
- Synchronizes PR state on startup.
- GitHub integration
- The server also has webhooks for GH events.
- Reads commands from GitHub comments on PRs.
- Merge queue
- Downloads information about PRs and commits, creates merge commits, schedules tests and performs the actual merges.
- Handles PR priority and tree closing.
- Database
- Stores information about current PR states, repositories, closed trees, priorities etc.
- Uses SQLite.
- Configuration
- Configured through a TOML file.
## What do we want to keep/change?
- Web server
- We need to reimplement the backend, but the frontend can probably stay the same for now.
- Database
- We can provide an interface that will let us abstract the DB, and then implement backends e.g. for SQLite, DynamoDB or others.
## Alternatives to a full rewrite
Use existing tools:
- [bors-ng](https://github.com/bors-ng/bors-ng)
- A lot of momentum and activity, active development (+).
- Written in Elixir (-), probably wouldn't be friendly to `rustc` developers for maintenance.
- As any other tool, it's opinionated and doesn't necessarily match the commands used currently by `homu`. Compare: https://bors.tech/documentation/ vs https://bors.rust-lang.org/. Things like `treeclosed` seem to be missing. We could add them, but the tool is used by a lot of users and it's unclear whether we could fit its needs (and get our changes in) for the specific use cases of rustc (clippy, miri, ...) projects.
- [bors-rs](https://github.com/bors-rs/bors)
- Written in Rust (+).
- Seems similar in scope and features to homu (+).
- Unmaintained (-).
- Implemented as a GitHub App (could be moved to a self-deployed app).
- [original bors](https://github.com/graydon/bors)
- Unmaintained, written in Python, wouldn't improve the current situation (- - -).
If we adapt an existing tool, we would probably either need to fork it to add commands that are currently offered by `homu`, or generalize it enough so that we can add custom commands to it.
There seem to be two ways forward:
- Use and integrate bors-ng.
- Rewrite `homu` in Rust (while potentially taking some code from `bors-rs`).
### More detailed comparison of `homu` vs `bors-ng` commands
Note: aliases (like `r+` vs `merge`) are not included, only commands that
differ semantically.
| `homu` | `bors-ng` | Description |Do we need it?|
|--------------|---------------------|:-----------:|:-:|
|`r+`|`r+`|Reviewed, merge|x|
|`r+ <SHA>`|N/A|Reviewed, merge with SHA guard||
|`r+ p=<prio>`|`r+ p=<prio>`|Set PR priority, merge|x|
|`r=<name>`|`r=<list of names>`|Reviewed by `name`(s), merge|x|
|`r-`|`r-`|Cancel merge|x|
|`p=<prio>`|`p=<prio>`|Set PR priority|x|
|`try`|`try`|Try build|x|
|N/A (?)|`try-`|Cancel a try build||
|`delegate+`|`delegate+`|Delegate rights to PR author|x|
|`delegate=<name>`|`delegate=<list of names>`|Delegate to specific user(s)||
|`delegate-`|N/A|Undelegate PR author||
|`rollup=never`|`single on`|Disable rollup/batching|x|
|`rollup=always`|`single off`|Enable/force rollup/batching|x|
|`rollup=iffy`|N/A|`iffy` rollup||
|`rollup=maybe`|N/A|`maybe` rollup||
|`rollup-`|N/A|Unmark as rollup||
|`squash`|N/A|Squash before merge||
|`squash-`|N/A|No squash before merge||
|`force`|N/A|Stop all builds, move to next PR||
|`treeclosed=<prio>`|N/A|Close tree for PRs below `<prio>`||
|`treeclosed-`|N/A|Undo tree closure||
|`clean`|N/A|Clean up previous build results||
|`retry`|N/A|Retry build (?)||
|N/A|`retry`|Retry previous command||
There are also some other debug/maintenance commands like `ping`.