9
9
import traceback
10
10
import typing
11
11
from dataclasses import dataclass
12
- from typing import Literal , MutableMapping , cast
12
+ from typing import Literal , cast
13
13
from urllib .error import URLError
14
14
from uuid import uuid4
15
15
31
31
from conda_forge_tick .feedstock_parser import BOOTSTRAP_MAPPINGS
32
32
from conda_forge_tick .git_utils import (
33
33
DryRunBackend ,
34
+ DuplicatePullRequestError ,
34
35
GitCli ,
35
36
GitCliError ,
36
37
GitPlatformBackend ,
37
38
RepositoryNotFoundError ,
38
- comment_on_pr ,
39
- github3_client ,
40
39
github_backend ,
41
40
is_github_api_limit_reached ,
42
- push_repo ,
43
41
)
44
42
from conda_forge_tick .lazy_json_backends import (
45
43
LazyJson ,
72
70
)
73
71
74
72
from .migrators_types import MigrationUidTypedDict
73
+ from .models .pr_json import PullRequestData , PullRequestInfoSpecial , PullRequestState
75
74
76
75
logger = logging .getLogger (__name__ )
77
76
@@ -423,13 +422,20 @@ def _check_and_process_solvability(
423
422
return False
424
423
425
424
425
+ def get_spoofed_closed_pr_info () -> PullRequestInfoSpecial :
426
+ return PullRequestInfoSpecial (
427
+ id = str (uuid4 ()),
428
+ merged_at = "never issued" ,
429
+ state = "closed" ,
430
+ )
431
+
432
+
426
433
def run_with_tmpdir (
427
434
context : FeedstockContext ,
428
435
migrator : Migrator ,
429
436
git_backend : GitPlatformBackend ,
430
437
rerender : bool = True ,
431
438
base_branch : str = "main" ,
432
- dry_run : bool = False ,
433
439
** kwargs : typing .Any ,
434
440
) -> tuple [MigrationUidTypedDict , dict ] | tuple [Literal [False ], Literal [False ]]:
435
441
"""
@@ -448,7 +454,6 @@ def run_with_tmpdir(
448
454
git_backend = git_backend ,
449
455
rerender = rerender ,
450
456
base_branch = base_branch ,
451
- dry_run = dry_run ,
452
457
** kwargs ,
453
458
)
454
459
@@ -459,7 +464,6 @@ def run(
459
464
git_backend : GitPlatformBackend ,
460
465
rerender : bool = True ,
461
466
base_branch : str = "main" ,
462
- dry_run : bool = False ,
463
467
** kwargs : typing .Any ,
464
468
) -> tuple [MigrationUidTypedDict , dict ] | tuple [Literal [False ], Literal [False ]]:
465
469
"""For a given feedstock and migration run the migration
@@ -554,67 +558,64 @@ def run(
554
558
logger .warning ("Skipping migration due to solvability check failure" )
555
559
return False , False
556
560
557
- # This is needed because we want to migrate to the new backend step-by-step
558
- repo : github3 .repos .Repository | None = github3_client ().repository (
559
- context .git_repo_owner , context .git_repo_name
560
- )
561
-
562
- assert repo is not None
563
-
564
- feedstock_dir = str (context .local_clone_dir .resolve ())
565
-
566
- # TODO: Better annotation here
567
- pr_json : typing .Union [MutableMapping , None , bool ]
561
+ pr_data : PullRequestData | PullRequestInfoSpecial | None
562
+ """
563
+ The PR data for the PR that was created. The contents of this variable will be stored in the bot's database.
564
+ None means: We don't update the PR data.
565
+ """
568
566
if (
569
567
isinstance (migrator , MigrationYaml )
570
568
and not rerender_info .nontrivial_changes
571
569
and context .attrs ["name" ] != "conda-forge-pinning"
572
570
):
573
571
# spoof this so it looks like the package is done
574
- pr_json = {
575
- "state" : "closed" ,
576
- "merged_at" : "never issued" ,
577
- "id" : str (uuid4 ()),
578
- }
572
+ pr_data = get_spoofed_closed_pr_info ()
579
573
else :
580
- # push up
574
+ # push and PR
575
+ git_backend .push_to_repository (
576
+ owner = git_backend .user ,
577
+ repo_name = context .git_repo_name ,
578
+ git_dir = context .local_clone_dir ,
579
+ branch = branch_name ,
580
+ )
581
581
try :
582
- pr_json = push_repo (
583
- fctx = context ,
584
- feedstock_dir = feedstock_dir ,
585
- body = migration_run_data ["pr_body" ],
586
- repo = repo ,
587
- title = migration_run_data ["pr_title" ],
588
- branch = branch_name ,
582
+ pr_data = git_backend .create_pull_request (
583
+ target_owner = context .git_repo_owner ,
584
+ target_repo = context .git_repo_name ,
589
585
base_branch = base_branch ,
590
- dry_run = dry_run ,
586
+ head_branch = branch_name ,
587
+ title = migration_run_data ["pr_title" ],
588
+ body = migration_run_data ["pr_body" ],
589
+ )
590
+ except DuplicatePullRequestError :
591
+ # This shouldn't happen too often anymore since we won't double PR
592
+ logger .warning (
593
+ f"Attempted to create a duplicate PR for merging { git_backend .user } :{ branch_name } "
594
+ f"into { context .git_repo_owner } :{ base_branch } . Ignoring."
591
595
)
596
+ # Don't update the PR data
597
+ pr_data = None
592
598
593
- # This shouldn't happen too often any more since we won't double PR
594
- except github3 .GitHubError as e :
595
- if e .msg != "Validation Failed" :
596
- raise
597
- else :
598
- print (f"Error during push { e } " )
599
- # If we just push to the existing PR then do nothing to the json
600
- pr_json = False
601
- ljpr = False
602
-
603
- if pr_json and pr_json ["state" ] != "closed" and rerender_info .rerender_comment :
604
- comment_on_pr (
605
- pr_json ,
606
- rerender_info .rerender_comment ,
607
- repo ,
599
+ if (
600
+ pr_data
601
+ and pr_data .state != PullRequestState .CLOSED
602
+ and rerender_info .rerender_comment
603
+ ):
604
+ git_backend .comment_on_pull_request (
605
+ repo_owner = context .git_repo_owner ,
606
+ repo_name = context .git_repo_name ,
607
+ pr_number = pr_data .number ,
608
+ comment = rerender_info .rerender_comment ,
608
609
)
609
610
610
- if pr_json :
611
- ljpr = LazyJson (
612
- os .path .join ("pr_json" , str ( pr_json [ "id" ]) + " .json" ),
611
+ if pr_data :
612
+ pr_lazy_json = LazyJson (
613
+ os .path .join ("pr_json" , f" { pr_data . id } .json" ),
613
614
)
614
- with ljpr as __ljpr :
615
- __ljpr .update (** pr_json )
615
+ with pr_lazy_json as __edit_pr_lazy_json :
616
+ __edit_pr_lazy_json .update (** pr_data . model_dump ( mode = "json" ) )
616
617
else :
617
- ljpr = False
618
+ pr_lazy_json = False
618
619
619
620
# If we've gotten this far then the node is good
620
621
with context .attrs ["pr_info" ] as pri :
@@ -623,8 +624,7 @@ def run(
623
624
context .attrs , migrator_name , is_version = is_version_migration
624
625
)
625
626
626
- logger .info ("Removing feedstock dir" )
627
- return migration_run_data ["migrate_return_value" ], ljpr
627
+ return migration_run_data ["migrate_return_value" ], pr_lazy_json
628
628
629
629
630
630
def _compute_time_per_migrator (mctx , migrators ):
@@ -707,7 +707,6 @@ def _run_migrator_on_feedstock_branch(
707
707
migrator ,
708
708
fctx : FeedstockContext ,
709
709
git_backend : GitPlatformBackend ,
710
- dry_run ,
711
710
mctx ,
712
711
migrator_name ,
713
712
good_prs ,
@@ -723,9 +722,8 @@ def _run_migrator_on_feedstock_branch(
723
722
migrator = migrator ,
724
723
git_backend = git_backend ,
725
724
rerender = migrator .rerender ,
726
- hash_type = attrs .get ("hash_type" , "sha256" ),
727
725
base_branch = base_branch ,
728
- dry_run = dry_run ,
726
+ hash_type = attrs . get ( "hash_type" , "sha256" ) ,
729
727
)
730
728
finally :
731
729
fctx .attrs .pop ("new_version" , None )
@@ -758,6 +756,7 @@ def _run_migrator_on_feedstock_branch(
758
756
)
759
757
760
758
except (github3 .GitHubError , github .GithubException ) as e :
759
+ # TODO: pull this down into run() - also check the other exceptions
761
760
if hasattr (e , "msg" ) and e .msg == "Repository was archived so is read-only." :
762
761
attrs ["archived" ] = True
763
762
else :
@@ -1011,7 +1010,6 @@ def _run_migrator(
1011
1010
migrator = migrator ,
1012
1011
fctx = fctx ,
1013
1012
git_backend = git_backend ,
1014
- dry_run = dry_run ,
1015
1013
mctx = mctx ,
1016
1014
migrator_name = migrator_name ,
1017
1015
good_prs = good_prs ,
0 commit comments