@@ -353,7 +353,7 @@ private string BuildLocalApp([CallerMemberName] string testName = "TestName", st
353
353
public async Task EndToEnd_MultiProjectSolution ( )
354
354
{
355
355
ILogger logger = _loggerFactory . CreateLogger ( nameof ( EndToEnd_MultiProjectSolution ) ) ;
356
- DirectoryInfo newSolutionDir = new ( Path . Combine ( TestSettings . TestArtifactsDirectory , $ "CreateNewImageTest_EndToEnd_MultiProjectSolution" ) ) ;
356
+ DirectoryInfo newSolutionDir = new ( Path . Combine ( TestSettings . TestArtifactsDirectory , nameof ( EndToEnd_MultiProjectSolution ) ) ) ;
357
357
358
358
if ( newSolutionDir . Exists )
359
359
{
@@ -431,6 +431,82 @@ public async Task EndToEnd_MultiProjectSolution()
431
431
commandResult . Should ( ) . HaveStdOutContaining ( "Pushed image 'consoleapp:latest'" ) ;
432
432
}
433
433
434
+ /// <summary>
435
+ /// Tests that a multi-project solution with a library that targets multiple frameworks can be published.
436
+ /// This is interesting because before https://github.com/dotnet/sdk/pull/47693 the container targets
437
+ /// wouldn't be loaded for multi-TFM project evaluations, so any calls to the PublishContainer target
438
+ /// for libraries (which may be multi-targeted even when referenced from a single-target published app project) would fail.
439
+ /// It's safe to load the target for libraries in a multi-targeted context because libraries don't have EnableSdkContainerSupport
440
+ /// enabled by default, so the target will be skipped.
441
+ /// </summary>
442
+ [ DockerAvailableFact ]
443
+ public async Task EndToEnd_MultiProjectSolution_with_multitargeted_library ( )
444
+ {
445
+ ILogger logger = _loggerFactory . CreateLogger ( nameof ( EndToEnd_MultiProjectSolution_with_multitargeted_library ) ) ;
446
+ DirectoryInfo newSolutionDir = new ( Path . Combine ( TestSettings . TestArtifactsDirectory , nameof ( EndToEnd_MultiProjectSolution_with_multitargeted_library ) ) ) ;
447
+
448
+ if ( newSolutionDir . Exists )
449
+ {
450
+ newSolutionDir . Delete ( recursive : true ) ;
451
+ }
452
+
453
+ newSolutionDir . Create ( ) ;
454
+
455
+ // Create solution with projects
456
+ new DotnetNewCommand ( _testOutput , "sln" , "-n" , nameof ( EndToEnd_MultiProjectSolution_with_multitargeted_library ) )
457
+ . WithVirtualHive ( )
458
+ . WithWorkingDirectory ( newSolutionDir . FullName )
459
+ . Execute ( )
460
+ . Should ( ) . Pass ( ) ;
461
+
462
+ new DotnetNewCommand ( _testOutput , "web" , "-n" , "WebApp" )
463
+ . WithVirtualHive ( )
464
+ . WithWorkingDirectory ( newSolutionDir . FullName )
465
+ . Execute ( )
466
+ . Should ( ) . Pass ( ) ;
467
+
468
+ new DotnetCommand ( _testOutput , "sln" , "add" , Path . Combine ( "WebApp" , "WebApp.csproj" ) )
469
+ . WithWorkingDirectory ( newSolutionDir . FullName )
470
+ . Execute ( )
471
+ . Should ( ) . Pass ( ) ;
472
+
473
+ new DotnetNewCommand ( _testOutput , "classlib" , "-n" , "Library" )
474
+ . WithVirtualHive ( )
475
+ . WithWorkingDirectory ( newSolutionDir . FullName )
476
+ . Execute ( )
477
+ . Should ( ) . Pass ( ) ;
478
+
479
+ new DotnetCommand ( _testOutput , "sln" , "add" , Path . Combine ( "Library" , "Library.csproj" ) )
480
+ . WithWorkingDirectory ( newSolutionDir . FullName )
481
+ . Execute ( )
482
+ . Should ( ) . Pass ( ) ;
483
+
484
+ // Set TFMs for Library - use current toolset + NS2.0 for compatibility
485
+ // also set IsPublishable to false
486
+ using ( FileStream stream = File . Open ( Path . Join ( newSolutionDir . FullName , "Library" , "Library.csproj" ) , FileMode . Open , FileAccess . ReadWrite ) )
487
+ {
488
+ XDocument document = await XDocument . LoadAsync ( stream , LoadOptions . None , CancellationToken . None ) ;
489
+ var tfmNode =
490
+ document
491
+ . Descendants ( )
492
+ . First ( e => e . Name . LocalName == "TargetFramework" ) ;
493
+ var propertyGroupNode = tfmNode . Parent ! ;
494
+ tfmNode . Remove ( ) ;
495
+ propertyGroupNode . Add ( new XElement ( "TargetFrameworks" , $ "{ ToolsetInfo . CurrentTargetFramework } ;netstandard2.0") ) ;
496
+ propertyGroupNode . Add ( new XElement ( "IsPublishable" , "false" ) ) ;
497
+ stream . SetLength ( 0 ) ;
498
+ await document . SaveAsync ( stream , SaveOptions . None , CancellationToken . None ) ;
499
+ }
500
+
501
+ // Publish
502
+ CommandResult commandResult = new DotnetCommand ( _testOutput , "publish" , "/t:PublishContainer" , "-bl" )
503
+ . WithWorkingDirectory ( newSolutionDir . FullName )
504
+ . Execute ( ) ;
505
+
506
+ commandResult . Should ( ) . Pass ( ) ;
507
+ commandResult . Should ( ) . HaveStdOutContaining ( "Pushed image 'webapp:latest'" ) ;
508
+ }
509
+
434
510
[ DockerAvailableTheory ( ) ]
435
511
[ InlineData ( "webapi" , false ) ]
436
512
[ InlineData ( "webapi" , true ) ]
@@ -1012,7 +1088,7 @@ public void EndToEndMultiArch_RemoteRegistry()
1012
1088
. And . HaveStdOutContaining ( $ "Pushed image '{ imageX64 } ' to registry '{ registry } '.")
1013
1089
. And . HaveStdOutContaining ( $ "Pushed image '{ imageArm64 } ' to registry '{ registry } '.")
1014
1090
. And . HaveStdOutContaining ( $ "Pushed image index '{ imageIndex } ' to registry '{ registry } '.") ;
1015
-
1091
+
1016
1092
// Check that the containers can be run
1017
1093
// First pull the image from the registry for each platform
1018
1094
ContainerCli . PullCommand (
@@ -1029,7 +1105,7 @@ public void EndToEndMultiArch_RemoteRegistry()
1029
1105
imageFromRegistry )
1030
1106
. Execute ( )
1031
1107
. Should ( ) . Pass ( ) ;
1032
-
1108
+
1033
1109
// Run the containers
1034
1110
ContainerCli . RunCommand (
1035
1111
_testOutput ,
0 commit comments