@@ -629,14 +629,15 @@ def test_unrelated_same_namespace_record_is_not_a_dependency(tmp_path, monkeypat
629629
630630
631631# ---------------------------------------------------------------------------
632- # detect_default_branch
632+ # detect_default_branch / get_merge_base / get_base_pdl_changes
633633# ---------------------------------------------------------------------------
634634
635635
636- def _make_proc (returncode : int , stdout : str = "" ) -> MagicMock :
636+ def _make_proc (returncode : int , stdout : str = "" , stderr : str = "" ) -> MagicMock :
637637 m = MagicMock ()
638638 m .returncode = returncode
639639 m .stdout = stdout
640+ m .stderr = stderr
640641 return m
641642
642643
@@ -658,6 +659,34 @@ def test_detect_default_branch_fallback_to_master(monkeypatch):
658659 assert bsv .detect_default_branch () == "master"
659660
660661
662+ def test_get_merge_base_returns_sha (monkeypatch ):
663+ monkeypatch .setattr (subprocess , "run" ,
664+ lambda * a , ** kw : _make_proc (0 , "abc123def456\n " ))
665+ assert bsv .get_merge_base ("refs/remotes/origin/acryl-main" ) == "abc123def456"
666+
667+
668+ def test_get_merge_base_failure_exits (monkeypatch ):
669+ monkeypatch .setattr (subprocess , "run" ,
670+ lambda * a , ** kw : _make_proc (1 , stderr = "not a git repo" ))
671+ with pytest .raises (SystemExit ):
672+ bsv .get_merge_base ("refs/remotes/origin/acryl-main" )
673+
674+
675+ def test_get_base_pdl_changes_returns_files (monkeypatch ):
676+ monkeypatch .setattr (subprocess , "run" ,
677+ lambda * a , ** kw : _make_proc (0 , "a/Foo.pdl\n b/Bar.pdl\n " ))
678+ result = bsv .get_base_pdl_changes ("deadbeef" , "refs/remotes/origin/acryl-main" )
679+ assert result == ["a/Foo.pdl" , "b/Bar.pdl" ]
680+
681+
682+ def test_get_base_pdl_changes_failure_exits (monkeypatch ):
683+ monkeypatch .setattr (subprocess , "run" ,
684+ lambda * a , ** kw : (_ for _ in ()).throw (
685+ subprocess .CalledProcessError (1 , "git" , stderr = "err" )))
686+ with pytest .raises (SystemExit ):
687+ bsv .get_base_pdl_changes ("deadbeef" , "refs/remotes/origin/acryl-main" )
688+
689+
661690# ---------------------------------------------------------------------------
662691# Version bump scenarios (via main())
663692#
@@ -668,17 +697,23 @@ def test_detect_default_branch_fallback_to_master(monkeypatch):
668697# ---------------------------------------------------------------------------
669698
670699
671- def _run_main (tmp_path , monkeypatch , changed_files , base_content_by_path ):
700+ def _run_main (tmp_path , monkeypatch , changed_files , base_content_by_path , * ,
701+ base_pdl_changes = None ):
672702 """
673703 Run main() with filesystem and git calls mocked out.
674704
675- changed_files — list of Path objects treated as "changed"
705+ changed_files — list of Path objects treated as "changed" on this branch
676706 base_content_by_path — dict mapping str(path) → content string on base branch,
677707 or None to simulate a new file not present on base
708+ base_pdl_changes — list of str paths changed on the base branch since
709+ divergence (default: empty — no conflict)
678710 """
679711 monkeypatch .setenv ("PDL_ROOTS" , str (tmp_path ))
680712 monkeypatch .setattr (sys , "argv" , ["bump_schema_versions.py" , "--base-branch" , "master" ])
681- monkeypatch .setattr (bsv , "get_changed_pdl_files" , lambda _branch : [str (f ) for f in changed_files ])
713+ monkeypatch .setattr (bsv , "get_merge_base" , lambda _ref : "deadbeef" )
714+ monkeypatch .setattr (bsv , "get_base_pdl_changes" ,
715+ lambda _base , _ref : base_pdl_changes or [])
716+ monkeypatch .setattr (bsv , "get_changed_pdl_files" , lambda _ref : [str (f ) for f in changed_files ])
682717 monkeypatch .setattr (bsv , "get_file_at_branch" ,
683718 lambda path , _branch : base_content_by_path .get (path ))
684719 return bsv .main ()
@@ -730,14 +765,48 @@ def test_version_bump_new_file_stays_at_1(tmp_path, monkeypatch):
730765 assert bsv .get_schema_version (aspect .read_text ()) == 1
731766
732767
768+ def test_conflicting_pdl_on_base_branch_exits_with_error (tmp_path , monkeypatch ):
769+ # Base ref is current AND the same PDL changed on both branches → block at stage 2
770+ base_content = aspect_pdl ("myAspect" )
771+ aspect = write_pdl (tmp_path , "com/linkedin/dataset/MyAspect.pdl" , base_content )
772+
773+ rc = _run_main (
774+ tmp_path , monkeypatch ,
775+ changed_files = [aspect ],
776+ base_content_by_path = {str (aspect ): base_content },
777+ base_pdl_changes = [str (aspect )], # same file changed on base
778+ )
779+
780+ assert rc == 1
781+ assert bsv .get_schema_version (aspect .read_text ()) == 1 # untouched
782+
783+
784+ def test_unrelated_base_pdl_changes_do_not_block (tmp_path , monkeypatch ):
785+ # A different PDL changed on the base branch — should not block this branch's bump
786+ base_content = aspect_pdl ("myAspect" )
787+ aspect = write_pdl (tmp_path , "com/linkedin/dataset/MyAspect.pdl" , base_content )
788+
789+ rc = _run_main (
790+ tmp_path , monkeypatch ,
791+ changed_files = [aspect ],
792+ base_content_by_path = {str (aspect ): base_content },
793+ base_pdl_changes = ["com/linkedin/other/Unrelated.pdl" ], # different file on base
794+ )
795+
796+ assert rc == 0
797+ assert bsv .get_schema_version (aspect .read_text ()) == 2 # bumped normally
798+
799+
733800def test_version_bump_dry_run_does_not_write (tmp_path , monkeypatch ):
734801 base_content = aspect_pdl ("myAspect" )
735802 aspect = write_pdl (tmp_path , "com/linkedin/dataset/MyAspect.pdl" , base_content )
736803 original = aspect .read_text ()
737804
738805 monkeypatch .setenv ("PDL_ROOTS" , str (tmp_path ))
739806 monkeypatch .setattr (sys , "argv" , ["bump_schema_versions.py" , "--base-branch" , "master" , "--dry-run" ])
740- monkeypatch .setattr (bsv , "get_changed_pdl_files" , lambda _branch : [str (aspect )])
807+ monkeypatch .setattr (bsv , "get_merge_base" , lambda _ref : "deadbeef" )
808+ monkeypatch .setattr (bsv , "get_base_pdl_changes" , lambda _base , _ref : [])
809+ monkeypatch .setattr (bsv , "get_changed_pdl_files" , lambda _ref : [str (aspect )])
741810 monkeypatch .setattr (bsv , "get_file_at_branch" , lambda path , _branch : base_content )
742811
743812 rc = bsv .main ()
0 commit comments