Giter VIP home page Giter VIP logo

homu's Introduction

Homu

Hommando

Homu is a bot that integrates with GitHub and your favorite continuous integration service such as Travis CI, Appveyor or Buildbot.

Why is it needed?

Let's take Travis CI as an example. If you send a pull request to a repository, Travis CI instantly shows you the test result, which is great. However, after several other pull requests are merged into the master branch, your pull request can still break things after being merged into master. The traditional continuous integration solutions don't protect you from this.

In fact, that's why they provide the build status badges. If anything pushed to master is completely free from any breakage, those badges will not be necessary, as they will always be green. The badges themselves prove that there can still be some breakages, even when continuous integration services are used.

To solve this problem, the test procedure should be executed just before the merge, not just after the pull request is received. You can manually click the "restart build" button each time before you merge a pull request, but Homu can automate this process. It listens to the pull request comments, waiting for an approval comment from one of the configured reviewers. When the pull request is approved, Homu tests it using your favorite continuous integration service, and only when it passes all the tests, it is merged into master.

Note that Homu is not a replacement of Travis CI, Buildbot or Appveyor. It works on top of them. Homu itself doesn't have the ability to test pull requests.

Influences of bors

Homu is largely inspired by bors. The concept of "tests should be done just before the merge" came from bors. However, there are also some differences:

  1. Stateful: Unlike bors, which intends to be stateless, Homu is stateful. It means that Homu does not need to retrieve all the information again and again from GitHub at every run. This is essential because of GitHub's rate limiting. Once it downloads the initial state, the following changes are delivered with the Webhooks API.
  2. Pushing over polling: Homu prefers pushing wherever possible. The pull requests from GitHub are retrieved using Webhooks, as stated above. The test results from Buildbot are pushed back to Homu with the HttpStatusPush feature. This approach improves the overall performance and the response time, because the bot is informed about the status changes immediately.

And also, Homu has more features, such as rollup, try, and the Travis CI & Appveyor support.

Usage

How to install

$ sudo apt-get install python3-venv python3-wheel
$ python3 -m venv .venv
$ . .venv/bin/activate
$ pip install -U pip
$ git clone https://github.com/rust-lang/homu.git
$ pip install -e homu

How to configure

In the following instructions, HOST refers to the hostname (or IP address) where you are running your custom homu instance. PORT is the port the service is listening to and is configured in web.port in cfg.toml. NAME refers to the name of the repository you are configuring homu for.

  1. Copy cfg.sample.toml to cfg.toml. You'll need to edit this file to set up your configuration. The following steps explain where you can find important config values.

  2. Create a GitHub account that will be used by Homu. You can also use an existing account. In the developer settings, go to "OAuth Apps" and create a new application:

    • Make note of the "Client ID" and "Client Secret"; you will need to put them in your cfg.toml.
    • The OAuth Callback URL should be http://HOST:PORT/callback.
    • The homepage URL isn't necessary; you could set http://HOST:PORT/.
  3. Go back to the developer settings of the GitHub account you created/used in the previous step. Go to "Personal access tokens". Click "Generate new token" and choose the "repo" and "user" scopes. Put the token value in your cfg.toml.

  4. Add your new GitHub account as a Collaborator to the GitHub repo you are setting up homu for. This can be done in repo (NOT user) "Settings", then "Collaborators". Enable "Write" access.

    4.1. Make sure you login as the new GitHub account and that you accept the collaborator invitation you just sent!

  5. Add a Webhook to your repository. This is done under repo (NOT user) "Settings", then "Webhooks". Click "Add webhook", then set:

    • Payload URL: http://HOST:PORT/github
    • Content type: application/json
    • Secret: The same as repo.NAME.github.secret in cfg.toml
    • Events: click "Let me select individual events", then pick Issue comments, Pull requests, Pushes, Statuses, Check runs
  6. Add a Webhook to your continuous integration service, if necessary. You don't need this if using Travis/Appveyor.

    • Buildbot

      Insert the following code to the master.cfg file:

      from buildbot.status.status_push import HttpStatusPush
      
      c['status'].append(HttpStatusPush(
         serverUrl='http://HOST:PORT/buildbot',
         extra_post_params={'secret': 'repo.NAME.buildbot.secret in cfg.toml'},
      ))
  7. Go through the rest of your cfg.toml and uncomment (and change, if needed) parts of the config you'll need.

How to run

$ . .venv/bin/activate
$ homu

homu's People

Contributors

aidanhs avatar alexcrichton avatar ashcrow avatar barosl avatar bryanburgers avatar camelid avatar centril avatar cgwalters avatar edunham avatar eh2406 avatar flip1995 avatar frewsxcv avatar gankra avatar huonw avatar indirect avatar jlebon avatar johntitor avatar jyn514 avatar kellda avatar kennytm avatar larsbergstrom avatar manishearth avatar mark-simulacrum avatar marmeladema avatar nilstrieb avatar oliviacrain avatar pietroalbini avatar ralfjung avatar valloric avatar xanewok avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

homu's Issues

Allow try builds after approval

Currently, once a pull request has been approved r+, it can not be tried.

There are times when we want to do a timer run, even after r+ing the merge request, so it would be great if we could still @bors try after approval.

cc @Centril

Ignore leading "@" in "r=@user"

Currently, our two bots need to be commanded like r? @user but bors r=user. I have been tripped by this, and so did others.

Would be nice if bors could just strip the leading @ when encountering bors r=@user.

Custom name for rollup branch in homu queue interface

When you make rollups, a branch named rollup is created for you. This usually works well. However, sometimes I want to do some planning of several rollups in sequence. Then the interface doesn't work so well because if you already have a rollup branch available, it will force-push to that one killing your already in-progress rollup PR.

Instead, it would be good if I could assign a name to the rollup PR myself, e.g. rollup_alpha and rollup_beta, using an input textbox.

Additionally, I think it would be nice if the default behavior were to generate a unique name for that rollup in the input box (can be done client side or server side... not so important). The rare use case of force-pushing to an existing branch can still be supported by changing the name yourself to rollup.

cc @pietroalbini

Bors re-executes command when comment gets edited

When editing a GH comment that contains a @bors command, the command gets re-evaluated. This is confusing when it is a bors r+ (as bors complains about double-approval) and can cost a lot of CI time when it is a bors retry.

IMO it would be much less surprising if bors ignored edit events, and only considered new comments.

Messages on unmergeable PR should be more rollup-aware.

Seeing this is not very informative when #N is a rollup PR:

The latest upstream changes (presumably #N) made this pull request unmergeable. Please resolve the merge conflicts.

Assuming there is a way to get the list of files in the diff without getting the whole diff, from the github API (or maybe the diffs are cheap?), it might be possible to quickly check, for rollup PRs, which of the rolled-up PRs had any of the files that now conflict.

Automate the r=me idiom

Oftentimes reviewers will write something like r=me with green travis.
It would be good to automate this sort of thing such that a reviewer can write:

@bors r=me

and then bors will r+ once travis is actually green.
That way, you don't need any other reviewer to intervene or to delegate bors privileges.

can't unapprove my own PRs

People need to be able to r- their own PRs.

Use case:

I make a PR that updates clippy.
The PR is r+ed and prioritized.
In the meantime another rollup merges and breaks clippy again.
Now the clippy-pr needs to be updated again to a working version of clippy since it won't pass CI otherwise but I cannot prevent it from being tested and potentially waste 3 hours of CI time since I cannot r- PRs I authored.

rust-lang/rust#61298 (comment)

Restarting homu when the tree is closed bricks the web UI

We had to restart the production homu instance while the tree was closed, and once we restarted it the web UI raised this exception:

Traceback (most recent call last):                                                                                              
  File "/usr/local/bin/bottle.py", line 862, in _handle                                                                         
    return route.call(**args)                                                                                                   
  File "/usr/local/bin/bottle.py", line 1742, in wrapper                                                                        
    rv = callback(*a, **ka)                                                                                                     
  File "/homu/homu/server.py", line 75, in index                                                                                
    for label in sorted(g.repos)])                                                                                              
  File "/usr/local/lib/python3.6/dist-packages/jinja2/asyncsupport.py", line 76, in render                                      
    return original_render(self, *args, **kwargs)                                                                               
  File "/usr/local/lib/python3.6/dist-packages/jinja2/environment.py", line 1008, in render                                     
    return self.environment.handle_exception(exc_info, True)                                                                    
  File "/usr/local/lib/python3.6/dist-packages/jinja2/environment.py", line 780, in handle_exception                            
    reraise(exc_type, exc_value, tb)                                                                                            
  File "/usr/local/lib/python3.6/dist-packages/jinja2/_compat.py", line 37, in reraise                                          
    raise value.with_traceback(tb)                                                                                              
  File "/homu/homu/html/index.html", line 26, in top-level template code                                                        
    <li><a href="queue/{{repo.repo_label}}">{{repo.repo_label}}</a> {% if repo.treeclosed >= 0 %} [TREE CLOSED] {% endif %}</li>
jinja2.exceptions.UndefinedError: 'github3.repos.repo.Repository object' has no attribute 'treeclosed'                          

To "fix" the issue I had to reopen the tree and then restart homu again. We should properly fix this.

Handling fixup commits

Hello

I find the git fixup commits quite useful.

For those who are not used to them, this is how it works:

  • I create a pull request.
  • There are some nitpicks in the review.
  • The nitpicks don't deserve a full commit to fix. But I also don't want to rebase the branch during the review, as that makes reviewing a bit harder. I want to just push a little commit with the fixes. This can be created by git commit -a --fixup=THE-COMMIT-TO-BE-FIXED.
  • After the whole review is concluded, I do git rebase --interactive --autosquash THE-BRANCH_COMMIT. This'll squash the fixup commits into the commits they fix up. Note that this doesn't necessarily squash the whole branch into one commit.

However, such flow seems to be advanced and @bors/homu doesn't know about it. Which leads to two disadvantages:

  • There's another round with the reviewer (they have to tell me it is time to do the rebase).
  • It can happen by accident that a branch with fixups gets approved (rust-lang/rust#61421).

I was thinking if there's a way to improve the support for this (and make the flow more known, because I believe it has advantages). I wonder about three different options:

  • The bot could refuse to proceed if a fixup message is present in the branch with an explanation message, handling the second point.
  • The bot could refuse to proceed, but remember the approval. If the rebased branch is pushed and has empty diff against the not squashed, it could remember the approval and proceed then (but I don't know, this may be hard to implement).
  • The bot could actually perform the rebase. But I'm not sure this is desirable (because then it loses eg. gpg signatures on the commit) and there could be conflicts to resolve during the rebase.

What do you think?

Clearer rollup intention marking

Right now, reviewers have the option to rollup a PR which notifiers the roller-upper (e.g. @Centril or @Manishearth) that this PR is ~always safe to include into a rollup PR.

However, this is a rather blunt instrument. There are a bunch of other PRs that I will attempt to include into a rollup that are not @bors rolluped.

There are also PRs that should never be included into a rollup. It would be nice to get such a notification in the queue interface. E.g. @bors never-rollup. These PRs should probably get p=1 if no higher prio is assigned. To make this visible in the homu web interface, a new column could be added at the end. Otherwise, you could color the rollup-intention with:

  • green: always rollup
  • nothing: maybe rollup
  • red: never rollup

(or other colors...)

Stop showing completed try builds

The UI for rust-lang/rust frequently fills up with numerous "success" at the top of the page.

There's sort of two bugs here. First, we don't currently keep whether a build is try or r+ in the DB, AFAICT, which means that these aren't displayed as success (try) after bors reboots.

The easy fix here is to just never show successful builds -- I'm not sure that they are important enough to be so prominent in the UI, since there's nothing that can really be done with them.

Incorrect labels after "bors r- retry"

Doing bors r- retry (e.g. because we realized a PR would fail but is already being tested, so we want it to be removed from the queue and the active job to be stopped) leaves the PR with incorrect labels: the PR is still labeled "waiting for bors". This also happen when first doing "bors r-" and then in another comment doing "bors retry". See rust-lang/rust#66995 (comment) for an example.

I guess "bors retry" fails to detect that the PR is not actually queued any more, and thus incorrectly sets the "waiting for bors" label.

Add More Links In The Dashboard

I was surprised that on the dashboard, that only the PR number links to the PR. It would be nice if I could also just click on the title of the PR and have that redirect me to the PR like does on GitHub.

Another nice to have would also being able to click on the head ref, and people's names but that feels less important.

Screenshot 2020-05-08 at 10 33 21

Add `@bors perf` command or similar

The typical workflow when having to get perf data for a commit is

@bors try

(wait until bors posts that it is done)

@rust-timer build SHA

(wait until that is done)

It would be great if bors would have a command like perf, that would work basically exactly the same as try, except that the "try build done" message would invoke the rust-timer bot the same way that we currently have to do manually (yay, bots calling bots). So, no human interaction should be needed, after doing @bors perf, until the final perf results are in.

Cc @Mark-Simulacrum

Ignore commands in quotes

There is another edge case in homu command handling: when an user replies to a comment via email by default the parent command is quoted, and the old parser code tried to handle it. We should ignore commands when the line starts with >, to hopefully catch quoted emails, or if the new parser already handles this a test should be added.

Example: rust-lang/rust#61540 (comment)

Add support for viewing travis status from PR list view

Part of #25

Would be nice if the PR list view could show the various status checks that show up at the bottom of the PR for approved PRs. We should use the GH status hook (which we already use) to store status check results for every PR.

This would make rollups much easier: Pick every travis-pass PR that is rollup=always, pick some rollup=maybe, and no rollup=never.

"Testing commit" message should link the Azure pipeline of the test

Now that rust-lang uses Azure pipelines exclusively, the "Testing commit ..." message of bors could link the Azure pipeline of the test.

Also, currently, when looking at the queue and clicking on a PR that's currently being tested, the pipeline of the test is not linked there either.

bors argument parsing does not report errors

I recently issued the command @bors r+ rollup+, because I have seen plenty of cases where one has to add a + after a command to make it happen. Not so for rollup, it seems, but bors also did not complain. Can we get error messages when there is a word+ or word- but bors does not actually recognize this as a command?

Link the "tree is currently closed" message to the treeclosed request

When receiving the treeclosed message:

🌲 The tree is currently closed for pull requests below priority 1500, this pull request will be tested once the tree is reopened

It would be nice if the comment linked to where the treeclosed request was made. This link should already be available, as it's shown elsewhere:

click on treeclosed link at the top of Homu queue page and it redirected me to the comment that closed the tree

Does not always detect conflicts

Recently I had several cases where a PR started having conflicts with master, but homu failed to report that. Most recently, this happened in rust-lang/rust#71946.

This used to work more reliably, and it is quite useful as otherwise I as PR author have no idea that a rebase is needed.

[meta] Autorollups

We should eventually automate rollups, with failures pinging humans.

Steps:

  • Add rollup levels (#22)
  • Add travis status indicators to the list view (#26)
  • Add a subsystem that picks a bag of approved non-never-rollup PRs, balancing travis-pass rollup=always and rollup=maybe counts based on some heuristics

422 Update is not a fast forward

I've been lucky enough to hit "422 Update is not a fast forward" twice in the past two weeks. Not sure if it makes sense to file an issue here (feel free to close). Cross referencing:

My recent encounters:

Doesn't seem to happen too often: https://github.com/rust-lang/rust/pulls?utf8=%E2%9C%93&q=is%3Apr+%22update+is+not+a+fast+forward%22+

From what little I've read, I see other projects having similar problems, and some people concluding that the GitHub API can take a while to update (up to 30 seconds?) due to caching. I'm not too familiar with how homu works, but maybe a longer retry might help?

No user docs

There are no docs here about which commands @bors supports, how to use it, etc.

Remove support for bors commands in review comments

There are 3 types of comments that can be made related to a pull request:

  1. Issue comments, which – despite their name – are comments made directly in the pull request. Most of our @bors commands are made here.
  2. Review comments, which are comments made on the code diff of a merge request
  3. Commit comments, which are comments made on the commit itself (and we do not support in @bors).

I wrote a script to go through all of our pull requests to quantify how many bors commands appear in review comments. Here are the results:

Repo Review comment commands
rust-lang/cargo 0
rust-lang/rust-clippy 0
rust-lang-nursery/compiler-builtins 0
rust-lang-nursery/crater 0
rust-lang/hashbrown 0
rust-lang/libc 0
rust-lang/regex 0
rust-lang/rls 0
rust-lang/rust 1
rust-lang/rustlings 0
rust-lang/rustup.rs 0

So, the only time this feature has been used (that I can find; I won't rule out that my code was not 100% perfect) was this 5 Dec 2018 comment.

In the spirit that the easiest code to maintain is no code, I propose that we remove support for this rarely used feature. The total cost of supporting it is pretty low, but the utility of this function appears even lower (one use in 5 years).

I believe it would mostly come down to removing the following two parts of the code:

homu/homu/main.py

Lines 1507 to 1522 in df43bc0

for comment in pull.iter_comments():
if comment.original_commit_id == pull.head.sha:
parse_commands(
comment.body,
comment.user.login,
repo_label,
repo_cfg,
state,
my_username,
db,
states,
sha=comment.original_commit_id,
command_src=comment.to_json()['html_url'],
# FIXME switch to `comment.html_url`
# after updating github3 to 1.3.0+
)

homu/homu/server.py

Lines 372 to 402 in df43bc0

if event_type == 'pull_request_review_comment':
action = info['action']
original_commit_id = info['comment']['original_commit_id']
head_sha = info['pull_request']['head']['sha']
if action == 'created' and original_commit_id == head_sha:
pull_num = info['pull_request']['number']
body = info['comment']['body']
username = info['sender']['login']
state = g.states[repo_label].get(pull_num)
if state:
state.title = info['pull_request']['title']
state.body = info['pull_request']['body']
if parse_commands(
body,
username,
repo_label,
repo_cfg,
state,
g.my_username,
g.db,
g.states,
realtime=True,
sha=original_commit_id,
command_src=info['comment']['html_url'],
):
state.save()
g.queue_handler()

Refuse to create rollups with unapproved PRs

Currently, it is fairly easy to accidentally create a rollup containing an unapproved PR: all it takes is a wrong click in the long column of checkboxes on the left.

Would it be possible to disable/remove those checkboxes for PRs that are not actually enqueued, or else at least warn before creating a rollup that contains an unapproved PR?

Add timer to Bors queue page

It would be pretty useful to display the time a PR has been testing for on the queue page. Probably in brackets after pending (or in place of), maybe in a different colour. Keeping it live with JavaScript would be a bonus.

critical: a try build can trigger a merge to master

It appears that sometimes, the result of a try build can trigger a merge to master. This seems to occur when the PR is approved between when the try build is started and when the Homu gets notified that the try build finished.

See: rust-lang/rust#61763 (comment)

Potential steps to reproduce (haven't tried this yet, but it fits with what happened on the referenced issue comment):

  1. Start a try build (e.g. @botname try)
  2. Approve the build (e.g. @botname r+)
  3. Wait until the try build succeeds

Ignores commands in PR description

In some cases, a PR goes through bors as a matter of process but doesn't actually need any review -- for example this miri PR. In that case it would be nice if we could just have a bors command in the PR description, instead of having to submit the PR and then add a comment with the comment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.