Skip to content

Commit 037563a

Browse files
committed
Docker support.
1 parent 3625d42 commit 037563a

File tree

10 files changed

+92
-45
lines changed

10 files changed

+92
-45
lines changed

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,10 @@ public ParametrizedDependency[] ParametrizedDependencies
207207

208208
public IBumpStrategy BumpStrategy { get; init; } = new DefaultBumpStrategy();
209209

210-
internal bool UseDockerInTeamcity => this.ResolvedBuildAgentRequirements.IsDockerHost;
210+
internal bool UseDocker => this.ResolvedBuildAgentRequirements.IsDockerHost;
211+
212+
internal DockerSpec? DockerSpec
213+
=> this.ResolvedBuildAgentRequirements.IsDockerHost ? new DockerSpec( $"{this.ProductNameWithoutDot}-{this.ProductFamily.Version}".ToLowerInvariant() ) : null;
211214

212215
public bool IsPublishingNonReleaseBranchesAllowed { get; init; }
213216

@@ -2431,7 +2434,11 @@ internal bool GenerateTeamcityConfiguration( BuildContext context, CommonCommand
24312434

24322435
var teamCityBuildSteps = new List<TeamCityBuildStep>();
24332436

2434-
if ( !this.UseDockerInTeamcity )
2437+
if ( this.UseDocker )
2438+
{
2439+
teamCityBuildSteps.Add( new TeamCityEngineeringPrepareImageBuildStep( "PrepareImage", "Prepare the Docker image", this.DockerSpec! ) );
2440+
}
2441+
else
24352442
{
24362443
teamCityBuildSteps.Add( new TeamCityEngineeringCommandBuildStep( "PreKill", "Kill background processes before cleanup", "tools kill" ) );
24372444
}
@@ -2457,9 +2464,9 @@ internal bool GenerateTeamcityConfiguration( BuildContext context, CommonCommand
24572464
areCustomArgumentsAllowed: true ) );
24582465
}
24592466

2460-
teamCityBuildSteps.Add( new TeamCityEngineeringBuildBuildStep( configuration, true, this.UseDockerInTeamcity ) );
2467+
teamCityBuildSteps.Add( new TeamCityEngineeringBuildBuildStep( configuration, true, this.DockerSpec ) );
24612468

2462-
if ( !this.UseDockerInTeamcity )
2469+
if ( !this.UseDocker )
24632470
{
24642471
teamCityBuildSteps.Add(
24652472
new TeamCityEngineeringCommandBuildStep( "PostKill", "Kill background processes before next build", "tools kill" ) );

src/PostSharp.Engineering.BuildTools/ContinuousIntegration/Model/BuildAgentRequirements.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ public BuildAgentRequirements( params BuildAgentRequirement[] items )
1818

1919
public static BuildAgentRequirements Empty { get; } = new();
2020

21-
public static BuildAgentRequirements Default { get; } = BuildAgentRequirements.SelfHosted( "caravela04cloud" );
21+
public static BuildAgentRequirements Default { get; } = SelfHosted( "caravela04cloud" );
2222

23-
public static BuildAgentRequirements WindowsDockerHost { get; } = BuildAgentRequirements.SelfHosted( "buildagent-docker-win-1", true );
23+
public static BuildAgentRequirements WindowsDockerHost { get; } = SelfHosted( "docker-win-x64-md", true );
2424

25-
public static BuildAgentRequirements SelfHosted( string name, bool isDockerHost = false ) => new( new BuildAgentRequirement( "env.BuildAgentType", name ) ) { IsDockerHost = isDockerHost };
25+
public static BuildAgentRequirements SelfHosted( string name, bool isDockerHost = false ) => new( new BuildAgentRequirement( "env.BuildAgentType", name ) ) { IsDockerHost = isDockerHost };
2626

2727
public static BuildAgentRequirements JetBrainsHosted( string name ) => new( new BuildAgentRequirement( "teamcity.agent.name", name ) );
2828

src/PostSharp.Engineering.BuildTools/ContinuousIntegration/Model/BuildSteps/TeamCityEngineeringBuildBuildStep.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ namespace PostSharp.Engineering.BuildTools.ContinuousIntegration.Model.BuildStep
66

77
public class TeamCityEngineeringBuildBuildStep : TeamCityEngineeringCommandBuildStep
88
{
9-
public TeamCityEngineeringBuildBuildStep( BuildConfiguration configuration, bool testOnBuild, bool useDocker ) : base(
9+
public TeamCityEngineeringBuildBuildStep( BuildConfiguration configuration, bool testOnBuild, DockerSpec? dockerSpec = null ) : base(
1010
"Build",
1111
"Build",
1212
testOnBuild ? "test" : "build",
1313
$"--configuration {configuration} --buildNumber %build.number% --buildType %system.teamcity.buildType.id%",
1414
true,
15-
useDocker ) { }
16-
}
15+
dockerSpec ) { }
16+
}

src/PostSharp.Engineering.BuildTools/ContinuousIntegration/Model/BuildSteps/TeamCityEngineeringCommandBuildStep.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ public TeamCityEngineeringCommandBuildStep(
1414
string command,
1515
string? arguments = null,
1616
bool areCustomArgumentsAllowed = false,
17-
bool useDocker = false ) : base(
17+
DockerSpec? dockerSpec = null ) : base(
1818
id,
1919
name,
20-
useDocker ? "DockerBuild.ps1" : "Build.ps1",
21-
$"{command}{(arguments == null ? "" : $" {arguments}")}{(!areCustomArgumentsAllowed ? "" : $" %{GetCustomArgumentsParameterName( id )}%")}" )
20+
dockerSpec != null ? $"DockerBuild.ps1" : "Build.ps1",
21+
GetScriptArguments( id, command, arguments, areCustomArgumentsAllowed, dockerSpec ) )
2222
{
2323
if ( areCustomArgumentsAllowed )
2424
{
@@ -32,4 +32,16 @@ public TeamCityEngineeringCommandBuildStep(
3232
];
3333
}
3434
}
35+
36+
private static string GetScriptArguments( string id, string command, string? arguments, bool areCustomArgumentsAllowed, DockerSpec? dockerSpec)
37+
{
38+
var args = $"{command}{(arguments == null ? "" : $" {arguments}")}{(!areCustomArgumentsAllowed ? "" : $" %{GetCustomArgumentsParameterName( id )}%")}";
39+
40+
if ( dockerSpec != null )
41+
{
42+
args = $"-ImageName {dockerSpec.ImageName} -NoBuildImage " + args;
43+
}
44+
45+
return args;
46+
}
3547
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace PostSharp.Engineering.BuildTools.ContinuousIntegration.Model.BuildSteps;
2+
3+
public class TeamCityEngineeringPrepareImageBuildStep : TeamCityPowerShellBuildStep
4+
{
5+
private static string GetCustomArgumentsParameterName( string objectName ) => $"{objectName}Arguments";
6+
7+
public TeamCityEngineeringPrepareImageBuildStep(
8+
string id,
9+
string name,
10+
DockerSpec dockerSpec ) : base(
11+
id,
12+
name,
13+
$"DockerBuild.ps1",
14+
$"-BuildImage -ImageName {dockerSpec.ImageName}" )
15+
{
16+
}
17+
}

src/PostSharp.Engineering.BuildTools/ContinuousIntegration/Model/BuildSteps/TeamCityEngineeringPublishBuildStep.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ namespace PostSharp.Engineering.BuildTools.ContinuousIntegration.Model.BuildStep
66

77
public class TeamCityEngineeringPublishBuildStep : TeamCityEngineeringCommandBuildStep
88
{
9-
public TeamCityEngineeringPublishBuildStep( BuildConfiguration configuration, bool useDocker = false ) : base(
9+
public TeamCityEngineeringPublishBuildStep( BuildConfiguration configuration, DockerSpec? dockerSpec = null ) : base(
1010
"Publish",
1111
"Publish",
1212
"publish",
1313
$"--configuration {configuration}",
14-
true, useDocker ) { }
14+
true, dockerSpec ) { }
1515
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.
2+
3+
namespace PostSharp.Engineering.BuildTools.ContinuousIntegration.Model;
4+
5+
public record DockerSpec( string ImageName );

src/PostSharp.Engineering.BuildTools/ContinuousIntegration/TeamCityHelper.cs

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -677,12 +677,13 @@ internal static bool TryGenerateConsolidatedTeamcityConfiguration( BuildContext
677677
return false;
678678
}
679679

680-
var consolidatedProjectId = context.Product.DependencyDefinition.CiConfiguration.ProjectId;
680+
var product = context.Product;
681+
var consolidatedProjectId = product.DependencyDefinition.CiConfiguration.ProjectId;
681682
var consolidatedProjectIdPrefix = $"{consolidatedProjectId}_";
682-
var defaultBranch = context.Product.DependencyDefinition.Branch;
683-
var deploymentBranch = context.Product.DependencyDefinition.ReleaseBranch;
684-
var defaultBranchParameter = context.Product.DependencyDefinition.VcsRepository.DefaultBranchParameter;
685-
var vcsRootId = GetVcsRootId( context.Product.DependencyDefinition );
683+
var defaultBranch = product.DependencyDefinition.Branch;
684+
var deploymentBranch = product.DependencyDefinition.ReleaseBranch;
685+
var defaultBranchParameter = product.DependencyDefinition.VcsRepository.DefaultBranchParameter;
686+
var vcsRootId = GetVcsRootId( product.DependencyDefinition );
686687

687688
if ( deploymentBranch == null )
688689
{
@@ -702,7 +703,7 @@ internal static bool TryGenerateConsolidatedTeamcityConfiguration( BuildContext
702703
return false;
703704
}
704705

705-
var consolidatedProjectName = context.Product.ProductName;
706+
var consolidatedProjectName = product.ProductName;
706707

707708
var buildConfigurations = new List<(string ProjectId, string ProjectName, string BuildConfigurationId, HashSet<string> SnapshotDependencies)>();
708709

@@ -776,14 +777,14 @@ bool TryPopulateBuildConfigurations(
776777
{
777778
var dependencyProjectId = buildConfiguration.ProjectId;
778779

779-
if ( !context.Product.DependencyDefinition.ProductFamily.TryGetDependencyDefinitionByCiId( dependencyProjectId, out var dependencyDefinition ) )
780+
if ( !product.DependencyDefinition.ProductFamily.TryGetDependencyDefinitionByCiId( dependencyProjectId, out var dependencyDefinition ) )
780781
{
781782
context.Console.WriteError( $"Dependency definition for project '{dependencyProjectId}' not found." );
782783

783784
return false;
784785
}
785786

786-
if ( dependencyDefinition.ProductFamily == context.Product.ProductFamily
787+
if ( dependencyDefinition.ProductFamily == product.ProductFamily
787788
&& !projectsWithNoNuGetArtifacts.Any( p => dependencyDefinition.Name.Contains( p, StringComparison.Ordinal ) ) )
788789
{
789790
var dependencyMsBuildConfiguration = dependencyDefinition.MSBuildConfiguration[configuration];
@@ -839,13 +840,13 @@ bool TryPopulateBuildConfigurations(
839840
.Select( c => c! ) );
840841
}
841842

842-
var buildInfo = new BuildInfo( null, configuration, context.Product, null );
843+
var buildInfo = new BuildInfo( null, configuration, product, null );
843844

844845
var privateArtifactsDirectory =
845-
context.Product.PrivateArtifactsDirectory.ToString( buildInfo ).Replace( "\\", "/", StringComparison.Ordinal );
846+
product.PrivateArtifactsDirectory.ToString( buildInfo ).Replace( "\\", "/", StringComparison.Ordinal );
846847

847848
var publicArtifactsDirectory =
848-
context.Product.PublicArtifactsDirectory.ToString( buildInfo ).Replace( "\\", "/", StringComparison.Ordinal );
849+
product.PublicArtifactsDirectory.ToString( buildInfo ).Replace( "\\", "/", StringComparison.Ordinal );
849850

850851
buildArtifactRules =
851852
$@"+:{privateArtifactsDirectory}/**/*=>{privateArtifactsDirectory}\n+:{publicArtifactsDirectory}/**/*=>{publicArtifactsDirectory}";
@@ -867,8 +868,15 @@ bool TryPopulateBuildConfigurations(
867868
SnapshotDependencies = dependencies.ToArray(), BuildTriggers = consolidatedBuildTriggers
868869
};
869870

871+
DockerSpec? dockerSpec = null;
872+
873+
if ( product.UseDocker )
874+
{
875+
dockerSpec = new DockerSpec( $"{product.ProductNameWithoutDot}-{product.ProductFamily.Version}" );
876+
}
877+
870878
var nuGetBuildSteps =
871-
new TeamCityBuildStep[] { new TeamCityEngineeringBuildBuildStep( configuration, false, context.Product.UseDockerInTeamcity ) };
879+
new TeamCityBuildStep[] { new TeamCityEngineeringBuildBuildStep( configuration, false, dockerSpec ) };
872880

873881
// The default branch is the same as for public build of any other project - see the build configuration of a regular project.
874882
nuGetBuildConfiguration = new(
@@ -877,12 +885,12 @@ bool TryPopulateBuildConfigurations(
877885
defaultBranch,
878886
defaultBranchParameter,
879887
vcsRootId,
880-
context.Product.ResolvedBuildAgentRequirements )
888+
product.ResolvedBuildAgentRequirements )
881889
{
882890
BuildSteps = nuGetBuildSteps,
883891
SnapshotDependencies = nuGetDependencies.ToArray(),
884892
ArtifactRules = buildArtifactRules,
885-
BuildTimeOutThreshold = context.Product.BuildTimeOutThreshold
893+
BuildTimeOutThreshold = product.BuildTimeOutThreshold
886894
};
887895

888896
return true;
@@ -996,7 +1004,7 @@ bool TryPopulateBuildConfigurations(
9961004
var success = true;
9971005

9981006
TeamCitySourceDependency CreateSourceDependency( string vcsProjectRootId, string projectName )
999-
=> new( vcsProjectRootId, true, $"+:. => {context.Product.SourceDependenciesDirectory}/{projectName}" );
1007+
=> new( vcsProjectRootId, true, $"+:. => {product.SourceDependenciesDirectory}/{projectName}" );
10001008

10011009
TeamCitySourceDependency CreateSourceDependencyFromDefinition( DependencyDefinition dependencyDefinition )
10021010
=> CreateSourceDependency( GetVcsRootId( dependencyDefinition ), dependencyDefinition.Name );
@@ -1006,7 +1014,7 @@ TeamCitySourceDependency CreateSourceDependencyFromDefinition( DependencyDefinit
10061014
var bumpedProjectId = buildConfiguration.ProjectId;
10071015
var bumpedProjectName = buildConfiguration.ProjectName;
10081016

1009-
if ( !context.Product.DependencyDefinition.ProductFamily.TryGetDependencyDefinitionByCiId( bumpedProjectId, out var dependencyDefinition ) )
1017+
if ( !product.DependencyDefinition.ProductFamily.TryGetDependencyDefinitionByCiId( bumpedProjectId, out var dependencyDefinition ) )
10101018
{
10111019
context.Console.WriteError( $"Dependency definition for project '{bumpedProjectId}' not found." );
10121020

@@ -1066,7 +1074,7 @@ TeamCitySourceDependency CreateSourceDependencyFromDefinition( DependencyDefinit
10661074
defaultBranch,
10671075
defaultBranchParameter,
10681076
vcsRootId,
1069-
context.Product.ResolvedBuildAgentRequirements )
1077+
product.ResolvedBuildAgentRequirements )
10701078
{
10711079
BuildSteps = consolidatedVersionBumpSteps.ToArray(),
10721080
BuildTriggers = consolidatedVersionBumpBuildTriggers,
@@ -1088,7 +1096,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
10881096
List<TeamCityBuildStep> steps = new();
10891097
List<TeamCityBuildConfigurationParameterBase> parameters = new();
10901098

1091-
if ( context.Product.MainVersionDependency == null )
1099+
if ( product.MainVersionDependency == null )
10921100
{
10931101
context.Console.WriteError( "Main version dependency is not set for the consolidated project." );
10941102

@@ -1102,7 +1110,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
11021110
continue;
11031111
}
11041112

1105-
if ( !context.Product.ProductFamily.TryGetDependencyDefinitionByCiId( project.Id, out var projectDependencyDefinition ) )
1113+
if ( !product.ProductFamily.TryGetDependencyDefinitionByCiId( project.Id, out var projectDependencyDefinition ) )
11061114
{
11071115
// This is a container for other projects.
11081116
continue;
@@ -1151,7 +1159,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
11511159
{
11521160
var dependencyProjectId = string.Join( '_', dependencyConfigurationId.Split( '_' ).SkipLast( 1 ) );
11531161

1154-
if ( !context.Product.ProductFamily.TryGetDependencyDefinitionByCiId( dependencyProjectId, out var dependencyDefinition ) )
1162+
if ( !product.ProductFamily.TryGetDependencyDefinitionByCiId( dependencyProjectId, out var dependencyDefinition ) )
11551163
{
11561164
context.Console.WriteError(
11571165
$"Dependency definition for project '{dependencyProjectId}' (configuration '{dependencyConfigurationId}') not found." );
@@ -1178,7 +1186,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
11781186
}
11791187
}
11801188

1181-
sourceDependencies.Add( CreateSourceDependencyFromDefinition( context.Product.DependencyDefinition ) );
1189+
sourceDependencies.Add( CreateSourceDependencyFromDefinition( product.DependencyDefinition ) );
11821190

11831191
steps.Add(
11841192
new TeamCityEngineeringCommandBuildStep(
@@ -1190,7 +1198,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
11901198
WorkingDirectory = $"source-dependencies/{consolidatedProjectName}"
11911199
} );
11921200

1193-
var branch = getBranch( context.Product.DependencyDefinition );
1201+
var branch = getBranch( product.DependencyDefinition );
11941202

11951203
if ( branch == null )
11961204
{
@@ -1206,7 +1214,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
12061214
branch,
12071215
defaultBranchParameter,
12081216
vcsRootId,
1209-
context.Product.ResolvedBuildAgentRequirements )
1217+
product.ResolvedBuildAgentRequirements )
12101218
{
12111219
BuildSteps = steps.ToArray(),
12121220
SourceDependencies = sourceDependencies.ToArray(),
@@ -1258,11 +1266,11 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
12581266
deploymentBranch,
12591267
defaultBranchParameter,
12601268
vcsRootId,
1261-
context.Product.ResolvedBuildAgentRequirements )
1269+
product.ResolvedBuildAgentRequirements )
12621270
{
12631271
BuildSteps = nuGetPublicDeploymentSteps,
12641272
SnapshotDependencies = nuGetPublicDeploymentDependencies.ToArray(),
1265-
BuildTimeOutThreshold = context.Product.DeploymentTimeOutThreshold,
1273+
BuildTimeOutThreshold = product.DeploymentTimeOutThreshold,
12661274
IsDeployment = true
12671275
} );
12681276

@@ -1292,7 +1300,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
12921300
defaultBranch,
12931301
defaultBranchParameter,
12941302
vcsRootId,
1295-
context.Product.ResolvedBuildAgentRequirements )
1303+
product.ResolvedBuildAgentRequirements )
12961304
{
12971305
SnapshotDependencies = consolidatedPublicDeploymentSnapshotDependencies.ToArray(), IsDeployment = true
12981306
} );
@@ -1311,7 +1319,7 @@ bool TryAddPreOrPostDeploymentBuildConfiguration(
13111319

13121320
var tcProject = new TeamCityProject( tcConfigurations.ToArray(), [nuGetProject] );
13131321

1314-
GeneratePom( context, consolidatedProjectId.Id, context.Product.DependencyDefinition.CiConfiguration.BaseUrl );
1322+
GeneratePom( context, consolidatedProjectId.Id, product.DependencyDefinition.CiConfiguration.BaseUrl );
13151323
GenerateTeamCityConfiguration( context, tcProject );
13161324

13171325
return true;

src/PostSharp.Engineering.BuildTools/Dependencies/Definitions/MetalamaDependencies.V2026_0.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using PostSharp.Engineering.BuildTools.ContinuousIntegration;
55
using PostSharp.Engineering.BuildTools.ContinuousIntegration.Model;
66
using PostSharp.Engineering.BuildTools.Dependencies.Model;
7-
using PostSharp.Engineering.BuildTools.Docker;
87
using System;
98
using System.IO;
109
using System.Runtime.InteropServices.Marshalling;
@@ -56,7 +55,6 @@ public MetalamaDependencyDefinition(
5655

5756
public static ProductFamily Family { get; } = new( _projectName, "2026.0", DevelopmentDependencies.Family, PostSharpDependencies.V2026_0.Family )
5857
{
59-
DockerBaseImage = DockerImages.WindowsServerCore,
6058
UpstreamProductFamily = V2025_2.Family
6159
// DownstreamProductFamily = V2026_1.Family
6260
};

src/PostSharp.Engineering.BuildTools/Dependencies/Model/ProductFamily.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class ProductFamily
3131

3232
public ProductFamily? DownstreamProductFamily { get; init; }
3333

34-
public BuildAgentRequirements DefaultBuildAgentRequirements { get; init; } = BuildAgentRequirements.SelfHosted( "caravela04cloud" );
34+
public BuildAgentRequirements DefaultBuildAgentRequirements { get; init; } = BuildAgentRequirements.Default;
3535

3636
public bool HasConsolidatedBuild => this.TryGetDependencyDefinition( ConsolidatedProjectName, out _ );
3737

0 commit comments

Comments
 (0)