@@ -91,6 +91,7 @@ public class GitHubPROrigin implements Origin<GitRevision> {
9191 public static final String GITHUB_PR_NUMBER_LABEL = "GITHUB_PR_NUMBER" ;
9292 public static final String GITHUB_BASE_BRANCH = "GITHUB_BASE_BRANCH" ;
9393 public static final String GITHUB_BASE_BRANCH_SHA1 = "GITHUB_BASE_BRANCH_SHA1" ;
94+ public static final String GITHUB_PR_USE_MERGE = "GITHUB_PR_USE_MERGE" ;
9495 public static final String GITHUB_PR_TITLE = "GITHUB_PR_TITLE" ;
9596 public static final String GITHUB_PR_URL = "GITHUB_PR_URL" ;
9697 public static final String GITHUB_PR_BODY = "GITHUB_PR_BODY" ;
@@ -274,8 +275,9 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
274275 Set <String > requiredLabels = gitHubPrOriginOptions .getRequiredLabels (requiredLabelsField );
275276 Set <String > retryableLabels = gitHubPrOriginOptions .getRetryableLabels (retryableLabelsField );
276277 int prNumber = (int )prData .getNumber ();
278+ boolean actuallyUseMerge = this .useMerge ;
277279
278- if (!gitHubPrOriginOptions . forceImport && !requiredLabels .isEmpty ()) {
280+ if (!forceImport () && !requiredLabels .isEmpty ()) {
279281 int retryCount = 0 ;
280282 Set <String > requiredButNotPresent ;
281283 do {
@@ -311,8 +313,7 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
311313
312314 // check if check runs are ready if applicable
313315 checkRequiredCheckRuns (api , project , prData );
314- if (!gitHubPrOriginOptions .forceImport
315- && branch != null && !Objects .equals (prData .getBase ().getRef (), branch )) {
316+ if (!forceImport () && branch != null && !Objects .equals (prData .getBase ().getRef (), branch )) {
316317 throw new EmptyChangeException (String .format (
317318 "Cannot migrate http://github.com/%s/pull/%d because its base branch is '%s', but"
318319 + " the workflow is configured to only migrate changes for branch '%s'" ,
@@ -325,7 +326,7 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
325326 ImmutableList <Review > reviews = api .getReviews (project , prNumber );
326327 ApproverState shouldMigrate =
327328 reviewState .shouldMigrate (reviews , reviewApprovers , prData .getHead ().getSha ());
328- if (!gitHubPrOriginOptions . forceImport && !shouldMigrate .shouldMigrate ()) {
329+ if (!forceImport () && !shouldMigrate .shouldMigrate ()) {
329330 String rejected = "" ;
330331 if (!shouldMigrate .rejectedReviews ().isEmpty ()) {
331332 rejected = String .format ("\n The following reviews were ignored because they don't meet "
@@ -353,13 +354,11 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
353354 labels .putAll (GITHUB_PR_REVIEWER_OTHER , others );
354355 }
355356
356- if (!gitHubPrOriginOptions .forceImport
357- && requiredState == StateFilter .OPEN && !prData .isOpen ()) {
357+ if (!forceImport () && requiredState == StateFilter .OPEN && !prData .isOpen ()) {
358358 throw new EmptyChangeException (String .format ("Pull Request %d is not open" , prNumber ));
359359 }
360360
361- if (!gitHubPrOriginOptions .forceImport
362- && requiredState == StateFilter .CLOSED && prData .isOpen ()) {
361+ if (!forceImport () && requiredState == StateFilter .CLOSED && prData .isOpen ()) {
363362 throw new EmptyChangeException (String .format ("Pull Request %d is open" , prNumber ));
364363 }
365364
@@ -372,23 +371,31 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
372371 // Prefix the branch name with 'refs/heads/' since some implementations of
373372 // GitRepository need the whole reference name.
374373 .add (String .format ("refs/heads/%s:" + LOCAL_PR_BASE_BRANCH , prData .getBase ().getRef ()));
375- if (useMerge ) {
376- if (prData .isMergeable () == null ) {
374+
375+ if (actuallyUseMerge ) {
376+ if (Boolean .TRUE .equals (prData .isMergeable ())) {
377+ refSpecBuilder .add (String .format ("%s:%s" , asMergeRef (prNumber ), LOCAL_PR_MERGE_REF ));
378+ } else if (forceImport ()) {
379+ console .warnFmt (
380+ "PR %d is not mergeable, but continuing with PR Head instead because of %s" ,
381+ prNumber ,
382+ GeneralOptions .FORCE );
383+ actuallyUseMerge = false ;
384+ } else if (prData .isMergeable () == null ) {
377385 throw new CannotResolveRevisionException (
378386 String .format (
379387 "Cannot find a merge reference for Pull Request %d."
380388 + " GitHub might still be generating it." ,
381389 prNumber ));
382- } else if (! prData . isMergeable ()) {
390+ } else {
383391 throw new CannotResolveRevisionException (
384392 String .format (
385393 "Cannot find a merge reference for Pull Request %d."
386394 + " It might have a conflict with head." ,
387395 prNumber ));
388- } else {
389- refSpecBuilder .add (String .format ("%s:%s" , asMergeRef (prNumber ), LOCAL_PR_MERGE_REF ));
390396 }
391397 }
398+
392399 ImmutableList <String > refspec = refSpecBuilder .build ();
393400 try (ProfilerTask ignore = generalOptions .profiler ().start ("fetch" )) {
394401 getRepository ()
@@ -399,7 +406,7 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
399406 refspec ,
400407 partialFetch );
401408 } catch (CannotResolveRevisionException e ) {
402- if (useMerge ) {
409+ if (actuallyUseMerge ) {
403410 throw new CannotResolveRevisionException (
404411 String .format ("Cannot find a merge reference for Pull Request %d, even though GitHub"
405412 + " reported that this merge reference should exist." , prNumber ), e );
@@ -409,7 +416,7 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
409416 }
410417 }
411418
412- String refForMigration = useMerge ? LOCAL_PR_MERGE_REF : LOCAL_PR_HEAD_REF ;
419+ String refForMigration = actuallyUseMerge ? LOCAL_PR_MERGE_REF : LOCAL_PR_HEAD_REF ;
413420 GitRevision gitRevision = getRepository ().resolveReference (refForMigration );
414421
415422 String headPrSha1 = getRepository ().resolveReference (LOCAL_PR_HEAD_REF ).getSha1 ();
@@ -427,6 +434,7 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
427434 labels .put (GitModule .DEFAULT_INTEGRATE_LABEL , integrateLabel );
428435 labels .put (GITHUB_BASE_BRANCH , prData .getBase ().getRef ());
429436 labels .put (GITHUB_PR_HEAD_SHA , headPrSha1 );
437+ labels .put (GITHUB_PR_USE_MERGE , Boolean .toString (actuallyUseMerge ));
430438
431439 String mergeBase = getRepository ().mergeBase (refForMigration , LOCAL_PR_BASE_BRANCH );
432440 labels .put (GITHUB_BASE_BRANCH_SHA1 , mergeBase );
@@ -444,7 +452,7 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
444452 gitRevision .getSha1 (),
445453 // TODO(malcon): Decide the format to use here:
446454 /*reviewReference=*/ null ,
447- useMerge ? asMergeRef (prNumber ) : asHeadRef (prNumber ),
455+ actuallyUseMerge ? asMergeRef (prNumber ) : asHeadRef (prNumber ),
448456 labels .build (),
449457 url );
450458
@@ -453,7 +461,7 @@ private GitRevision getRevisionForPR(String project, PullRequest prData)
453461
454462 private void checkRequiredCheckRuns (GitHubApi api , String project , PullRequest prData )
455463 throws ValidationException , RepoException {
456- if (gitHubPrOriginOptions . forceImport || requiredCheckRuns .isEmpty ()) {
464+ if (forceImport () || requiredCheckRuns .isEmpty ()) {
457465 return ;
458466 }
459467 try (ProfilerTask ignore = generalOptions .profiler ()
@@ -477,7 +485,7 @@ private void checkRequiredCheckRuns(GitHubApi api, String project, PullRequest p
477485
478486 private void checkRequiredStatusContextNames (GitHubApi api , String project , PullRequest prData )
479487 throws ValidationException , RepoException {
480- if (gitHubPrOriginOptions . forceImport || requiredStatusContextNames .isEmpty ()) {
488+ if (forceImport () || requiredStatusContextNames .isEmpty ()) {
481489 return ;
482490 }
483491 try (ProfilerTask ignore = generalOptions .profiler ()
@@ -520,8 +528,8 @@ public Reader<GitRevision> newReader(Glob originFiles, Authoring authoring)
520528 partialFetch ,
521529 patchTransformation ,
522530 describeVersion ,
523- /*configPath=*/ null ,
524- /*workflowName=*/ null ) {
531+ /*configPath=*/ null ,
532+ /*workflowName=*/ null ) {
525533
526534 /** Disable rebase since this is controlled by useMerge field. */
527535 @ Override
@@ -569,7 +577,10 @@ public Endpoint getFeedbackEndPoint(Console console) throws ValidationException
569577 @ Override
570578 public ChangesResponse <GitRevision > changes (@ Nullable GitRevision fromRef , GitRevision toRef )
571579 throws RepoException , ValidationException {
572- if (!useMerge ) {
580+ checkCondition (
581+ toRef .associatedLabels ().containsKey (GITHUB_PR_USE_MERGE ),
582+ "Cannot determine whether 'use_merge' was set." );
583+ if (toRef .associatedLabel (GITHUB_PR_USE_MERGE ).contains ("false" )) {
573584 return super .changes (fromRef , toRef );
574585 }
575586 GitLogEntry merge =
@@ -645,6 +656,10 @@ public ImmutableSetMultimap<String, String> describe(Glob originFiles) {
645656 return builder .build ();
646657 }
647658
659+ private boolean forceImport () {
660+ return generalOptions .isForced () || gitHubPrOriginOptions .forceImport ;
661+ }
662+
648663 /**
649664 * Only migrate PR in one of the following states:
650665 */
0 commit comments