Skip to content

Commit

Permalink
Add a label to keep a PR rebased
Browse files Browse the repository at this point in the history
  • Loading branch information
Matyrobbrt committed Dec 14, 2024
1 parent aecb6a3 commit fb36890
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/main/graphql/com/github/api/fragments.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ fragment IssueInfo on Issue {

fragment PullRequestInfo on PullRequest {
mergeable
mergeStateStatus
number
permalink
title
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/net/neoforged/automation/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ public record RepoConfiguration(Boolean enabled, @JsonDeserialize(contentUsing =
labelHandlers = labelHandlers == null ? Map.of() : labelHandlers;
}
public static final RepoConfiguration DEFAULT = new RepoConfiguration(true, Map.of(), null, null);

@Nullable
public <T extends LabelHandler> T getLabelOfType(String label, Class<T> type) {
var handler = labelHandlers.get(label);
return type.isInstance(handler) ? (T) handler : null;
}
}

private static final ObjectMapper MAPPER = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER).enable(YAMLGenerator.Feature.LITERAL_BLOCK_STYLE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
import com.github.api.GetPullRequestQuery;
import com.github.api.GetPullRequestsQuery;
import com.github.api.fragment.PullRequestInfo;
import com.github.api.type.MergeStateStatus;
import com.github.api.type.MergeableState;
import com.github.api.type.PullRequestState;
import net.neoforged.automation.Configuration;
import net.neoforged.automation.util.GHAction;
import net.neoforged.automation.util.Label;
import net.neoforged.automation.webhook.impl.GitHubEvent;
import net.neoforged.automation.webhook.impl.MultiEventHandler;
import net.neoforged.automation.webhook.impl.WebhookHandler;
import net.neoforged.automation.webhook.label.KeepRebasedHandler;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.github.GHPullRequestReview;
import org.kohsuke.github.GHPullRequestReviewState;
Expand All @@ -28,7 +31,7 @@
import java.util.concurrent.TimeUnit;

public final class MergeConflictCheckHandler implements MultiEventHandler {
private static final long PR_BASE_TIME = 3;
public static final long PR_BASE_TIME = 3;
private static final ScheduledThreadPoolExecutor SERVICE = new ScheduledThreadPoolExecutor(1);
private static final Set<String> IN_PROGRESS_REPOS = Collections.synchronizedSet(new HashSet<>());

Expand Down Expand Up @@ -97,6 +100,19 @@ public static MergeableState checkConflict(GitHub gitHub, PullRequestInfo info)
final int number = info.number();
final GHRepository repo = gitHub.getRepository(info.repository().nameWithOwner());
final GHPullRequest pr = repo.getPullRequest(number);

// If the PR is mergeable but behind and it has a keep-rebased label, we shall rebase it
if (state == MergeableState.MERGEABLE && info.mergeStateStatus() == MergeStateStatus.BEHIND) {
var conf = Configuration.get(repo);
for (PullRequestInfo.Node node : info.labels().nodes()) {
if (conf.getLabelOfType(node.name(), KeepRebasedHandler.class) != null) {
pr.updateBranch();
break;
}
}
return state;
}

if (hasLabel && state == MergeableState.MERGEABLE) {
// We don't have conflicts but the PR has the label... remove it.
Label.NEEDS_REBASE.remove(pr);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.neoforged.automation.webhook.label;

import com.github.api.GetPullRequestQuery;
import com.github.api.type.MergeableState;
import net.neoforged.automation.webhook.handler.MergeConflictCheckHandler;
import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHLabel;
import org.kohsuke.github.GHUser;
import org.kohsuke.github.GitHub;
import org.kohsuke.github.GitHubAccessor;

public class KeepRebasedHandler implements LabelHandler {
@Override
public void onLabelAdded(GitHub gitHub, GHUser actor, GHIssue issue, GHLabel label) throws Exception {
while (MergeConflictCheckHandler.checkConflict(gitHub, GitHubAccessor.graphQl(gitHub, GetPullRequestQuery.builder()
.owner(issue.getRepository().getOwnerName())
.name(issue.getRepository().getName())
.number(issue.getNumber())
.build())
.repository()
.pullRequest().fragments().pullRequestInfo()) == MergeableState.UNKNOWN) {
Thread.sleep(MergeConflictCheckHandler.PR_BASE_TIME * 1000);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
public interface LabelHandler {
Map<String, Class<? extends LabelHandler>> TYPES = Map.of(
"lock", LockLabelHandler.class,
"merge", MergeLabelHandler.class
"merge", MergeLabelHandler.class,
"keep-rebased", KeepRebasedHandler.class
);

default void onLabelAdded(GitHub gitHub, GHUser actor, GHIssue issue, GHLabel label) throws Exception {
Expand Down

0 comments on commit fb36890

Please sign in to comment.