Skip to content

Commit f541139

Browse files
committed
Added component validation for deployment/testing components. Fixed MsDeployPublisher.
1 parent 964bcb3 commit f541139

File tree

12 files changed

+174
-9
lines changed

12 files changed

+174
-9
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.
2+
3+
using PostSharp.Engineering.BuildTools.Docker;
4+
using System.Collections.Generic;
5+
6+
namespace PostSharp.Engineering.BuildTools.Build;
7+
8+
public interface IBuildComponent
9+
{
10+
bool VerifyContainerRequirements( BuildContext context, ContainerRequirements requirements );
11+
12+
IEnumerable<IBuildComponent> Children { get; }
13+
}

src/PostSharp.Engineering.BuildTools/Build/Model/Product.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.
22

33
using JetBrains.Annotations;
4+
using Microsoft.VisualStudio.Services.Common;
45
using PostSharp.Engineering.BuildTools.BillOfMaterials;
56
using PostSharp.Engineering.BuildTools.Build.Bumping;
67
using PostSharp.Engineering.BuildTools.Build.Files;
@@ -153,6 +154,36 @@ public TimeSpan BuildTimeout
153154
ExportsToTeamCityDeploy: true,
154155
RequiresUpstreamCheck: true ) );
155156

157+
public IEnumerable<IBuildComponent> GetBuildComponents()
158+
{
159+
HashSet<IBuildComponent> components = new();
160+
161+
foreach ( var configuration in this.Configurations.All )
162+
{
163+
AddComponents( configuration.PublicPublishers );
164+
AddComponents( configuration.PrivatePublishers );
165+
AddComponents( configuration.Swappers );
166+
}
167+
168+
return components;
169+
170+
void AddComponents( IEnumerable<IBuildComponent>? newComponents )
171+
{
172+
if ( newComponents == null )
173+
{
174+
return;
175+
}
176+
177+
foreach ( var component in newComponents )
178+
{
179+
if ( components.Add( component ) )
180+
{
181+
AddComponents( component.Children );
182+
}
183+
}
184+
}
185+
}
186+
156187
public ImmutableArray<string> DefaultArtifactRules { get; } = ImmutableArray<string>.Empty;
157188

158189
/// <summary>

src/PostSharp.Engineering.BuildTools/Build/Publishing/InvalidatingS3Publisher.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using JetBrains.Annotations;
44
using PostSharp.Engineering.BuildTools.Build.Model;
5+
using PostSharp.Engineering.BuildTools.Docker;
56
using PostSharp.Engineering.BuildTools.Utilities;
67
using System;
78
using System.Collections.Generic;

src/PostSharp.Engineering.BuildTools/Build/Publishing/MsDeployPublisher.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.
22

3+
using JetBrains.Annotations;
34
using PostSharp.Engineering.BuildTools.Build.Model;
5+
using PostSharp.Engineering.BuildTools.Docker;
46
using PostSharp.Engineering.BuildTools.Utilities;
57
using System;
68
using System.Collections.Generic;
@@ -15,6 +17,7 @@ namespace PostSharp.Engineering.BuildTools.Build.Publishing
1517
/// <summary>
1618
/// A <see cref="Publisher"/> that uses <c>MSDeploy</c> to deploy a web site.
1719
/// </summary>
20+
[PublicAPI]
1821
public class MsDeployPublisher : ArtifactPublisher
1922
{
2023
private readonly ImmutableArray<MsDeployConfiguration> _configurations;
@@ -57,6 +60,13 @@ private static bool QueryPublishProfile(
5760
return true;
5861
}
5962

63+
public override bool VerifyContainerRequirements( BuildContext context, ContainerRequirements requirements )
64+
{
65+
return base.VerifyContainerRequirements( context, requirements )
66+
&& requirements.RequireComponent<VisualStudioBuildToolsComponent>( context, out var vs )
67+
&& vs.RequireVSComponent( context, "Microsoft.VisualStudio.Component.WebDeploy" );
68+
}
69+
6070
public override SuccessCode PublishFile(
6171
BuildContext context,
6272
PublishSettings settings,
@@ -73,7 +83,7 @@ public override SuccessCode PublishFile(
7383
}
7484

7585
context.Console.WriteMessage( $"Publishing {file} to {publishProfile.PublishUrl}{packageConfiguration.VirtualDirectory}." );
76-
86+
7787
var exe = @"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";
7888

7989
var iisWebApplicationName = packageConfiguration.VirtualDirectory == null

src/PostSharp.Engineering.BuildTools/Build/Publishing/Publisher.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,27 @@
22

33
using JetBrains.Annotations;
44
using PostSharp.Engineering.BuildTools.Build.Model;
5+
using PostSharp.Engineering.BuildTools.Docker;
6+
using System.Collections.Generic;
7+
using System.Linq;
58

69
namespace PostSharp.Engineering.BuildTools.Build.Publishing
710
{
811
/// <summary>
912
/// An abstract publisher class used in <see cref="PublishCommand"/> to publish artifacts or execute publishing step.
1013
/// </summary>
1114
[PublicAPI]
12-
public abstract class Publisher
15+
public abstract class Publisher : IBuildComponent
1316
{
1417
/// <summary>
1518
/// When set to false, the publisher will not publish pre-release artifacts. Default is true.
1619
/// </summary>
1720
public bool PublishPrerelease { get; init; } = true;
1821

22+
public virtual bool VerifyContainerRequirements( BuildContext context, ContainerRequirements requirements ) => true;
23+
24+
IEnumerable<IBuildComponent> IBuildComponent.Children => [];
25+
1926
protected abstract bool Publish(
2027
BuildContext context,
2128
PublishSettings settings,

src/PostSharp.Engineering.BuildTools/Build/Swapping/AppServiceSwapper.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using JetBrains.Annotations;
44
using PostSharp.Engineering.BuildTools.Build.Model;
5+
using PostSharp.Engineering.BuildTools.Docker;
56
using PostSharp.Engineering.BuildTools.Utilities;
67

78
namespace PostSharp.Engineering.BuildTools.Build.Swapping
@@ -59,5 +60,9 @@ protected override SuccessCode ExecuteCore(
5960

6061
return AzHelper.Run( context, args, settings.Dry ) ? SuccessCode.Success : SuccessCode.Error;
6162
}
63+
64+
public override bool VerifyContainerRequirements( BuildContext context, ContainerRequirements requirements )
65+
=> base.VerifyContainerRequirements( context, requirements )
66+
&& requirements.RequireComponent<AzureCliComponent>( context );
6267
}
6368
}

src/PostSharp.Engineering.BuildTools/Build/Swapping/Swapper.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
using JetBrains.Annotations;
44
using PostSharp.Engineering.BuildTools.Build.Model;
55
using PostSharp.Engineering.BuildTools.Build.Testing;
6+
using PostSharp.Engineering.BuildTools.Docker;
7+
using System.Collections.Generic;
68

79
namespace PostSharp.Engineering.BuildTools.Build.Swapping
810
{
911
/// <summary>
1012
/// A swapper is some logic that swaps a deployment slot (typically a staging one) onto another deployment slop (typically the production one).
1113
/// </summary>
1214
[PublicAPI]
13-
public abstract class Swapper
15+
public abstract class Swapper : IBuildComponent
1416
{
1517
/// <summary>
1618
/// When set to false, the swapper will not swap when the product is pre-release. Default is true.
@@ -42,5 +44,9 @@ protected abstract SuccessCode ExecuteCore(
4244
SwapSettings settings,
4345
BuildConfigurationInfo configuration,
4446
BuildArguments buildArguments );
47+
48+
public virtual bool VerifyContainerRequirements( BuildContext context, ContainerRequirements requirements ) => true;
49+
50+
IEnumerable<IBuildComponent> IBuildComponent.Children => this.Testers;
4551
}
4652
}
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.
22

33
using PostSharp.Engineering.BuildTools.Build.Model;
4+
using PostSharp.Engineering.BuildTools.Docker;
5+
using System.Collections.Generic;
46

57
namespace PostSharp.Engineering.BuildTools.Build.Testing;
68

7-
public abstract class Tester
9+
public abstract class Tester : IBuildComponent
810
{
911
public abstract SuccessCode Execute(
1012
BuildContext context,
1113
string artifactsDirectory,
1214
BuildArguments buildArguments,
1315
bool dry );
16+
17+
public virtual bool VerifyContainerRequirements( BuildContext context, ContainerRequirements requirements ) => true;
18+
19+
IEnumerable<IBuildComponent> IBuildComponent.Children => [];
1420
}

src/PostSharp.Engineering.BuildTools/Build/Testing/VsTestTester.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.
22

33
using PostSharp.Engineering.BuildTools.Build.Model;
4+
using PostSharp.Engineering.BuildTools.Docker;
45
using PostSharp.Engineering.BuildTools.Utilities;
6+
using System;
57
using System.Collections.Generic;
68
using System.IO;
79
using System.IO.Compression;
@@ -39,7 +41,16 @@ public override SuccessCode Execute(
3941
var packagePath = Path.Combine( artifactsDirectory, this.TestPackageName.ToString( buildArguments ) );
4042
ZipFile.ExtractToDirectory( packagePath, tempDirectory );
4143

42-
var exe = @"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\TestPlatform\vstest.console.exe";
44+
var vsDir = Environment.GetEnvironmentVariable( "VSINSTALLDIR" );
45+
46+
if ( string.IsNullOrEmpty( vsDir ) )
47+
{
48+
context.Console.WriteError( "The VSINSTALLDIR environment variable is not defined." );
49+
50+
return SuccessCode.Fatal;
51+
}
52+
53+
var exe = Path.Combine( vsDir, @"Common7\IDE\Extensions\TestPlatform\vstest.console.exe" );
4354

4455
var argsList = new List<string>();
4556

@@ -74,5 +85,12 @@ public override SuccessCode Execute(
7485
Directory.Delete( tempDirectory, true );
7586
}
7687
}
88+
89+
public override bool VerifyContainerRequirements( BuildContext context, ContainerRequirements requirements )
90+
{
91+
return base.VerifyContainerRequirements( context, requirements )
92+
&& requirements.RequireComponent<VisualStudioBuildToolsComponent>( context, out var vs )
93+
&& vs.RequireVSComponent( context, "Microsoft.VisualStudio.Component.TestTools.BuildTools" );
94+
}
7795
}
7896
}

src/PostSharp.Engineering.BuildTools/Docker/ContainerRequirements.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using PostSharp.Engineering.BuildTools.Utilities;
77
using System;
88
using System.Collections.Generic;
9+
using System.Diagnostics.CodeAnalysis;
910
using System.IO;
1011
using System.Linq;
1112

@@ -62,6 +63,19 @@ void Add( ContainerComponent c )
6263
}
6364
}
6465

66+
// Validate publishers and testers.
67+
var hasMissingRequirement = false;
68+
69+
foreach ( var buildComponent in context.Product.GetBuildComponents() )
70+
{
71+
hasMissingRequirement = !buildComponent.VerifyContainerRequirements( context, this );
72+
}
73+
74+
if ( hasMissingRequirement )
75+
{
76+
return false;
77+
}
78+
6579
// Order components.
6680
var orderedComponents = allComponents.OrderBy( x => x ).ToList();
6781

@@ -87,4 +101,23 @@ void Add( ContainerComponent c )
87101

88102
return true;
89103
}
104+
105+
public bool RequireComponent<T>( BuildContext context )
106+
where T : ContainerComponent
107+
=> this.RequireComponent<T>( context, out _ );
108+
109+
public bool RequireComponent<T>( BuildContext context, [NotNullWhen( true )] out T? component )
110+
where T : ContainerComponent
111+
{
112+
component = this.Components.OfType<T>().SingleOrDefault();
113+
114+
if ( component == null )
115+
{
116+
context.Console.WriteError( $"The {typeof(T).Name} component is required." );
117+
118+
return false;
119+
}
120+
121+
return true;
122+
}
90123
}

0 commit comments

Comments
 (0)