@@ -553,6 +553,148 @@ describe('CargoWorkspace plugin', () => {
553553 }
554554 ) ;
555555 } ) ;
556+ it ( 'handles non-root workspace path via cargo-workspace-path' , async ( ) => {
557+ const candidates : CandidateReleasePullRequest [ ] = [
558+ buildMockCandidatePullRequest (
559+ 'crates/packages/rustA' ,
560+ 'rust' ,
561+ '1.1.2' ,
562+ {
563+ component : 'pkgA' ,
564+ updates : [
565+ buildMockPackageUpdate (
566+ 'crates/packages/rustA/Cargo.toml' ,
567+ 'packages/rustA/Cargo.toml'
568+ ) ,
569+ ] ,
570+ }
571+ ) ,
572+ ] ;
573+ stubFilesFromFixtures ( {
574+ sandbox,
575+ github,
576+ fixturePath : fixturesPath ,
577+ files : [ ] ,
578+ flatten : false ,
579+ targetBranch : 'main' ,
580+ inlineFiles : [
581+ [ 'crates/Cargo.toml' , '[workspace]\nmembers = ["packages/rustA"]' ] ,
582+ [
583+ 'crates/packages/rustA/Cargo.toml' ,
584+ '[package]\nname = "pkgA"\nversion = "1.1.1"\n\n[dependencies]\ntracing = "1.0.0"' ,
585+ ] ,
586+ ] ,
587+ } ) ;
588+ sandbox
589+ . stub ( github , 'findFilesByGlobAndRef' )
590+ . withArgs ( 'crates/packages/rustA' , 'main' )
591+ . resolves ( [ 'crates/packages/rustA' ] ) ;
592+ plugin = new CargoWorkspace (
593+ github ,
594+ 'main' ,
595+ {
596+ 'crates/packages/rustA' : {
597+ releaseType : 'rust' ,
598+ } ,
599+ } ,
600+ {
601+ cargoWorkspacePath : 'crates' ,
602+ }
603+ ) ;
604+ const newCandidates = await plugin . run ( candidates ) ;
605+ expect ( newCandidates ) . lengthOf ( 1 ) ;
606+ const rustCandidate = newCandidates . find (
607+ candidate => candidate . config . releaseType === 'rust'
608+ ) ;
609+ expect ( rustCandidate ) . to . not . be . undefined ;
610+ const updates = rustCandidate ! . pullRequest . updates ;
611+ assertHasUpdate ( updates , 'crates/packages/rustA/Cargo.toml' ) ;
612+ assertHasUpdate ( updates , 'crates/Cargo.lock' ) ;
613+ } ) ;
614+ it ( 'walks dependency tree with non-root workspace path' , async ( ) => {
615+ const candidates : CandidateReleasePullRequest [ ] = [
616+ buildMockCandidatePullRequest (
617+ 'crates/packages/rustA' ,
618+ 'rust' ,
619+ '1.1.2' ,
620+ {
621+ component : 'pkgA' ,
622+ updates : [
623+ buildMockPackageUpdate (
624+ 'crates/packages/rustA/Cargo.toml' ,
625+ 'packages/rustA/Cargo.toml'
626+ ) ,
627+ ] ,
628+ }
629+ ) ,
630+ ] ;
631+ stubFilesFromFixtures ( {
632+ sandbox,
633+ github,
634+ fixturePath : fixturesPath ,
635+ files : [ ] ,
636+ flatten : false ,
637+ targetBranch : 'main' ,
638+ inlineFiles : [
639+ [
640+ 'crates/Cargo.toml' ,
641+ '[workspace]\nmembers = ["packages/rustA", "packages/rustB", "packages/rustC"]' ,
642+ ] ,
643+ [
644+ 'crates/packages/rustA/Cargo.toml' ,
645+ '[package]\nname = "pkgA"\nversion = "1.1.1"\n\n[dependencies]\ntracing = "1.0.0"' ,
646+ ] ,
647+ [
648+ 'crates/packages/rustB/Cargo.toml' ,
649+ '[package]\nname = "pkgB"\nversion = "2.2.2"\n\n[dependencies]\npkgA = { version = "1.1.1", path = "../pkgA" }' ,
650+ ] ,
651+ [
652+ 'crates/packages/rustC/Cargo.toml' ,
653+ '[package]\nname = "pkgC"\nversion = "3.3.3"\n\n[dependencies]\npkgB = { version = "2.2.2", path = "../pkgB" }' ,
654+ ] ,
655+ ] ,
656+ } ) ;
657+ sandbox
658+ . stub ( github , 'findFilesByGlobAndRef' )
659+ . withArgs ( 'crates/packages/rustA' , 'main' )
660+ . resolves ( [ 'crates/packages/rustA' ] )
661+ . withArgs ( 'crates/packages/rustB' , 'main' )
662+ . resolves ( [ 'crates/packages/rustB' ] )
663+ . withArgs ( 'crates/packages/rustC' , 'main' )
664+ . resolves ( [ 'crates/packages/rustC' ] ) ;
665+ plugin = new CargoWorkspace (
666+ github ,
667+ 'main' ,
668+ {
669+ 'crates/packages/rustA' : {
670+ releaseType : 'rust' ,
671+ } ,
672+ 'crates/packages/rustB' : {
673+ releaseType : 'rust' ,
674+ } ,
675+ 'crates/packages/rustC' : {
676+ releaseType : 'rust' ,
677+ } ,
678+ } ,
679+ {
680+ cargoWorkspacePath : 'crates' ,
681+ }
682+ ) ;
683+ const newCandidates = await plugin . run ( candidates ) ;
684+ expect ( newCandidates ) . lengthOf ( 1 ) ;
685+ const rustCandidate = newCandidates . find (
686+ candidate => candidate . config . releaseType === 'rust'
687+ ) ;
688+ expect ( rustCandidate ) . to . not . be . undefined ;
689+ const updates = rustCandidate ! . pullRequest . updates ;
690+ // pkgA is directly released
691+ assertHasUpdate ( updates , 'crates/packages/rustA/Cargo.toml' , RawContent ) ;
692+ // pkgB depends on pkgA, should be bumped
693+ assertHasUpdate ( updates , 'crates/packages/rustB/Cargo.toml' , RawContent ) ;
694+ // pkgC depends on pkgB, should be transitively bumped
695+ assertHasUpdate ( updates , 'crates/packages/rustC/Cargo.toml' , RawContent ) ;
696+ assertHasUpdate ( updates , 'crates/Cargo.lock' ) ;
697+ } ) ;
556698 it ( 'handles packages with invalid version' , async ( ) => {
557699 const candidates : CandidateReleasePullRequest [ ] = [
558700 buildMockCandidatePullRequest ( 'packages/rustA' , 'rust' , '1.1.2' , {
0 commit comments