@@ -83,6 +83,7 @@ describe('create-release-branch (functional)', () => {
83
83
private : true ,
84
84
workspaces : [ 'packages/*' ] ,
85
85
scripts : { foo : 'bar' } ,
86
+ packageManager :
'[email protected] ' ,
86
87
} ) ;
87
88
expect (
88
89
await environment . readJsonFileWithinPackage ( 'a' , 'package.json' ) ,
@@ -195,6 +196,7 @@ describe('create-release-branch (functional)', () => {
195
196
private : true ,
196
197
workspaces : [ 'packages/*' ] ,
197
198
scripts : { foo : 'bar' } ,
199
+ packageManager :
'[email protected] ' ,
198
200
} ) ;
199
201
expect (
200
202
await environment . readJsonFileWithinPackage ( 'a' , 'package.json' ) ,
@@ -640,6 +642,263 @@ describe('create-release-branch (functional)', () => {
640
642
) ;
641
643
} ) ;
642
644
645
+ it ( 'updates the dependency version in package "b" when package "a" version is bumped' , async ( ) => {
646
+ await withMonorepoProjectEnvironment (
647
+ {
648
+ packages : {
649
+ $root$ : {
650
+ name : '@scope/monorepo' ,
651
+ version : '1.0.0' ,
652
+ directoryPath : '.' ,
653
+ } ,
654
+ a : {
655
+ name : '@scope/a' ,
656
+ version : '1.0.0' ,
657
+ directoryPath : 'packages/a' ,
658
+ } ,
659
+ b : {
660
+ name : '@scope/b' ,
661
+ version : '2.0.0' ,
662
+ directoryPath : 'packages/b' ,
663
+ } ,
664
+ } ,
665
+ workspaces : {
666
+ '.' : [ 'packages/*' ] ,
667
+ } ,
668
+ } ,
669
+ async ( environment ) => {
670
+ await environment . updateJsonFileWithinPackage ( 'b' , 'package.json' , {
671
+ dependencies : {
672
+ '@scope/a' : '1.0.0' ,
673
+ } ,
674
+ } ) ;
675
+ const constraintsProContent = `
676
+ % All packages must have a name and version defined.
677
+ \\+ gen_enforced_field(_, 'name', null).
678
+ \\+ gen_enforced_field(_, 'version', null).
679
+
680
+ % All version ranges used to reference one workspace package in another workspace package's \`dependencies\` or \`devDependencies\` must match the current version of that package.
681
+ gen_enforced_dependency(Pkg, DependencyIdent, CorrectDependencyRange, DependencyType) :-
682
+ DependencyType \\= 'peerDependencies',
683
+ workspace_has_dependency(Pkg, DependencyIdent, _, DependencyType),
684
+ workspace_ident(DepPkg, DependencyIdent),
685
+ workspace_version(DepPkg, DependencyVersion),
686
+ atomic_list_concat(['^', DependencyVersion], CorrectDependencyRange),
687
+ Pkg \\= DepPkg. % Ensure we do not add self-dependency
688
+
689
+ % Entry point to check all constraints.
690
+ workspace_package(Pkg) :-
691
+ package_json(Pkg, _, _).
692
+
693
+ enforce_all :-
694
+ workspace_package(Pkg),
695
+ enforce_has_name(Pkg),
696
+ enforce_has_version(Pkg),
697
+ (package_json(Pkg, 'dependencies', Deps) -> enforce_dependencies(Pkg, Deps) ; true).
698
+
699
+ enforce_has_name(Pkg) :-
700
+ package_json(Pkg, 'name', _).
701
+
702
+ enforce_has_version(Pkg) :-
703
+ package_json(Pkg, 'version', _).
704
+
705
+ enforce_dependencies(_, []).
706
+ enforce_dependencies(Pkg, [DepPkg-DepVersion | Rest]) :-
707
+ workspace_package(DepPkg),
708
+ package_json(DepPkg, 'version', DepVersion),
709
+ enforce_dependency_version(Pkg, DepPkg),
710
+ enforce_dependencies(Pkg, Rest).
711
+
712
+ enforce_dependency_version(Pkg, DepPkg) :-
713
+ package_json(Pkg, 'dependencies', Deps),
714
+ package_json(DepPkg, 'version', DepVersion),
715
+ member(DepPkg-DepVersion, Deps).
716
+
717
+ update_dependency_version(Pkg, DepPkg) :-
718
+ package_json(Pkg, 'dependencies', Deps),
719
+ package_json(DepPkg, 'version', DepVersion),
720
+ \\+ member(DepPkg-DepVersion, Deps),
721
+ Pkg \\= DepPkg, % Ensure we do not add self-dependency
722
+ set_package_json(Pkg, 'dependencies', DepPkg, DepVersion).
723
+ ` ;
724
+
725
+ await environment . writeFile ( 'constraints.pro' , constraintsProContent ) ;
726
+ await environment . runTool ( {
727
+ releaseSpecification : {
728
+ packages : {
729
+ a : 'major' ,
730
+ b : 'intentionally-skip' ,
731
+ } ,
732
+ } ,
733
+ } ) ;
734
+
735
+ expect (
736
+ await environment . readJsonFileWithinPackage ( 'a' , 'package.json' ) ,
737
+ ) . toStrictEqual ( {
738
+ name : '@scope/a' ,
739
+ version : '2.0.0' ,
740
+ } ) ;
741
+ expect (
742
+ await environment . readJsonFileWithinPackage ( 'b' , 'package.json' ) ,
743
+ ) . toStrictEqual ( {
744
+ name : '@scope/b' ,
745
+ version : '2.0.0' ,
746
+ dependencies : { '@scope/a' : '^2.0.0' } ,
747
+ } ) ;
748
+ } ,
749
+ ) ;
750
+ } ) ;
751
+
752
+ it ( 'updates the yarn lock file' , async ( ) => {
753
+ await withMonorepoProjectEnvironment (
754
+ {
755
+ packages : {
756
+ $root$ : {
757
+ name : '@scope/monorepo' ,
758
+ version : '1.0.0' ,
759
+ directoryPath : '.' ,
760
+ } ,
761
+ a : {
762
+ name : '@scope/a' ,
763
+ version : '1.0.0' ,
764
+ directoryPath : 'packages/a' ,
765
+ } ,
766
+ b : {
767
+ name : '@scope/b' ,
768
+ version : '2.0.0' ,
769
+ directoryPath : 'packages/b' ,
770
+ } ,
771
+ } ,
772
+ workspaces : {
773
+ '.' : [ 'packages/*' ] ,
774
+ } ,
775
+ } ,
776
+ async ( environment ) => {
777
+ await environment . updateJsonFileWithinPackage ( 'b' , 'package.json' , {
778
+ dependencies : {
779
+ '@scope/a' : '1.0.0' ,
780
+ } ,
781
+ } ) ;
782
+ const constraintsProContent = `
783
+ % All packages must have a name and version defined.
784
+ \\+ gen_enforced_field(_, 'name', null).
785
+ \\+ gen_enforced_field(_, 'version', null).
786
+
787
+ % All version ranges used to reference one workspace package in another workspace package's \`dependencies\` or \`devDependencies\` must match the current version of that package.
788
+ gen_enforced_dependency(Pkg, DependencyIdent, CorrectDependencyRange, DependencyType) :-
789
+ DependencyType \\= 'peerDependencies',
790
+ workspace_has_dependency(Pkg, DependencyIdent, _, DependencyType),
791
+ workspace_ident(DepPkg, DependencyIdent),
792
+ workspace_version(DepPkg, DependencyVersion),
793
+ atomic_list_concat(['^', DependencyVersion], CorrectDependencyRange),
794
+ Pkg \\= DepPkg. % Ensure we do not add self-dependency
795
+
796
+ % Entry point to check all constraints.
797
+ workspace_package(Pkg) :-
798
+ package_json(Pkg, _, _).
799
+
800
+ enforce_all :-
801
+ workspace_package(Pkg),
802
+ enforce_has_name(Pkg),
803
+ enforce_has_version(Pkg),
804
+ (package_json(Pkg, 'dependencies', Deps) -> enforce_dependencies(Pkg, Deps) ; true).
805
+
806
+ enforce_has_name(Pkg) :-
807
+ package_json(Pkg, 'name', _).
808
+
809
+ enforce_has_version(Pkg) :-
810
+ package_json(Pkg, 'version', _).
811
+
812
+ enforce_dependencies(_, []).
813
+ enforce_dependencies(Pkg, [DepPkg-DepVersion | Rest]) :-
814
+ workspace_package(DepPkg),
815
+ package_json(DepPkg, 'version', DepVersion),
816
+ enforce_dependency_version(Pkg, DepPkg),
817
+ enforce_dependencies(Pkg, Rest).
818
+
819
+ enforce_dependency_version(Pkg, DepPkg) :-
820
+ package_json(Pkg, 'dependencies', Deps),
821
+ package_json(DepPkg, 'version', DepVersion),
822
+ member(DepPkg-DepVersion, Deps).
823
+
824
+ update_dependency_version(Pkg, DepPkg) :-
825
+ package_json(Pkg, 'dependencies', Deps),
826
+ package_json(DepPkg, 'version', DepVersion),
827
+ \\+ member(DepPkg-DepVersion, Deps),
828
+ Pkg \\= DepPkg, % Ensure we do not add self-dependency
829
+ set_package_json(Pkg, 'dependencies', DepPkg, DepVersion).
830
+ ` ;
831
+ await environment . writeFile ( 'constraints.pro' , constraintsProContent ) ;
832
+ const outdatedLockfile = `
833
+ # This file is generated by running "yarn install" inside your project.
834
+ # Manual changes might be lost - proceed with caution!
835
+
836
+ __metadata:
837
+ version: 6
838
+
839
+ "@scope/a@^1.0.0, @scope/a@workspace:packages/a":
840
+ version: 0.0.0-use.local
841
+ resolution: "@scope/a@workspace:packages/a"
842
+ languageName: unknown
843
+ linkType: soft
844
+
845
+ "@scope/b@workspace:packages/b":
846
+ version: 0.0.0-use.local
847
+ resolution: "@scope/b@workspace:packages/b"
848
+ dependencies:
849
+ "@scope/a": ^1.0.0
850
+ languageName: unknown
851
+ linkType: soft
852
+
853
+ "@scope/monorepo@workspace:.":
854
+ version: 0.0.0-use.local
855
+ resolution: "@scope/monorepo@workspace:."
856
+ languageName: unknown
857
+ linkType: soft` ;
858
+ await environment . writeFile ( 'yarn.lock' , outdatedLockfile ) ;
859
+ await environment . runTool ( {
860
+ releaseSpecification : {
861
+ packages : {
862
+ a : 'major' ,
863
+ b : 'intentionally-skip' ,
864
+ } ,
865
+ } ,
866
+ } ) ;
867
+
868
+ const updatedLockfile = `# This file is generated by running "yarn install" inside your project.
869
+ # Manual changes might be lost - proceed with caution!
870
+
871
+ __metadata:
872
+ version: 6
873
+
874
+ "@scope/a@^2.0.0, @scope/a@workspace:packages/a":
875
+ version: 0.0.0-use.local
876
+ resolution: "@scope/a@workspace:packages/a"
877
+ languageName: unknown
878
+ linkType: soft
879
+
880
+ "@scope/b@workspace:packages/b":
881
+ version: 0.0.0-use.local
882
+ resolution: "@scope/b@workspace:packages/b"
883
+ dependencies:
884
+ "@scope/a": ^2.0.0
885
+ languageName: unknown
886
+ linkType: soft
887
+
888
+ "@scope/monorepo@workspace:.":
889
+ version: 0.0.0-use.local
890
+ resolution: "@scope/monorepo@workspace:."
891
+ languageName: unknown
892
+ linkType: soft
893
+ ` ;
894
+
895
+ expect ( await environment . readFile ( 'yarn.lock' ) ) . toStrictEqual (
896
+ updatedLockfile ,
897
+ ) ;
898
+ } ,
899
+ ) ;
900
+ } ) ;
901
+
643
902
it ( 'does not update the versions of any packages that have been tagged with intentionally-skip' , async ( ) => {
644
903
await withMonorepoProjectEnvironment (
645
904
{
@@ -691,6 +950,7 @@ describe('create-release-branch (functional)', () => {
691
950
version : '2.0.0' ,
692
951
private : true ,
693
952
workspaces : [ 'packages/*' ] ,
953
+ packageManager :
'[email protected] ' ,
694
954
} ) ;
695
955
expect (
696
956
await environment . readJsonFileWithinPackage ( 'a' , 'package.json' ) ,
0 commit comments