Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add merge-conflict notifications #1856

Merged
merged 5 commits into from
Nov 23, 2024
Merged

Conversation

ehuss
Copy link
Contributor

@ehuss ehuss commented Nov 8, 2024

This adds a new handler which will post comments on PRs when there is a merge conflict. I have appreciated this feature in homu, and I think it would be helpful for repositories that are not using homu.

A high-level overview:

  • There is a new [merge-conflict] conflg table to enable the feature. It supports labels just like homu.
  • There are two separate events that it listens to:
    • A push to a repo branch will trigger a scan through all open PRs for PRs that have new conflicts.
    • A push to a PR, which either adds a conflict or resolves an existing conflict. This also includes opening/reopening PRs.
  • State is stored in the database so that only one conflict comment is posted.
    • After the conflict is resolved, the comment will be hidden.
  • This is complicated by the fact that the mergeable status of a PR is updated both lazily and asynchronously. That is, GitHub doesn't bother computing it until you ask for it, which it then returns null. Then, GitHub has an async background task which computes the value. There is no notification (AFAIK) when that is done, so we just poll again after a delay.

@Urgau
Copy link
Member

Urgau commented Nov 18, 2024

Full support for having merge conflict warnings, love it ❤️.

On a more technical note, have you been able to test it?

@ehuss
Copy link
Contributor Author

ehuss commented Nov 18, 2024

Yes, here was my test plan:

  • PR operations:
    • ✓ Normal PR open
    • ✓ PR open with a conflict
    • ✓ PR reopen with a conflict
    • ✓ Push to PR that generates a conflict
      • Verify it works synchronously, and with the unknown rescan delay.
    • ✓ Resolving a conflict in a PR hides the comment
      • ✓ And then getting a new conflict will post a new comment, which will also get hidden properly
  • Push to branch from a PR
    • ✓ "possibly" should be filled out correctly
    • ✓ Doesn't warn on PRs for other branches
    • ✓ Doesn't warn on mergeable PRs
    • ✓ Doesn't warn on the PR that was just closed (is there a race between merging and closing the PR?)
    • ✓ Verify unknown scan works correctly
    • ✓ Verify graphql pagination works correctly
    • ✓ Doesn't post a comment to a PR that already has a comment
  • ✓ Push to a branch without a PR, should use SHA in "possibly" message
  • ✓ Labels get set correctly

src/handlers/merge_conflict.rs Outdated Show resolved Hide resolved
// Spawn since this can trigger a lot of work.
tokio::task::spawn(async move {
// See module note about locking.
let gh = GithubClient::new_from_env();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we need a new client vs. using the existing ctx.github client? Seems like that should be Cloneable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, that sounds good! For some reason I was just assuming it wasn't cloneable (or maybe I was concerned about how the connection pooling would work?).

// row-lock held between the time it is loaded and the save call below.
// The `post_comment` call should normally be pretty fast, so races should
// be rare. If they happen too often, consider adding some locking
// mechanism here.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a lock held, actually on the full table? load(...) starts with LOCK TABLE issue_data and presumably that's kept until the transaction ends (which happens in save).

.execute("LOCK TABLE issue_data", &[])

Do we think we need more?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember what I was thinking at the time. I saw the LOCK TABLE call, but for some reason was thinking there was something else. I can't think of what it is now, and the lock is clearly held in the IssueData, so I removed the comment. Thanks for pointing that out!

@Mark-Simulacrum
Copy link
Member

Generally onboard with landing mostly as-is, a few questions/comments.

ehuss and others added 4 commits November 23, 2024 09:12
Co-authored-by: Mark Rousskov <[email protected]>
I don't remember what I was thinking at the time. It looks like the
transaction is stored in IssueData, so the lock should persist.
The client is already cloneable and should reuse the connection pool.
Personal preference, felt better this way.
@ehuss ehuss merged commit d7d4bab into rust-lang:master Nov 23, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants