Skip to content

Commit 872affa

Browse files
gfraiteurclaude
andcommitted
Add ReuseLastSuccessfulBuild support for snapshot dependencies
When set, generates artifacts with buildRule = lastSuccessful() instead of a snapshot dependency, allowing the build to use the last successful build regardless of source revision. Flows to transitive dependencies. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 90f2808 commit 872affa

3 files changed

Lines changed: 73 additions & 51 deletions

File tree

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ internal override TeamCityBuildConfiguration TeamCityBuildConfiguration(
5454
.ToList();
5555

5656
// Create snapshot dependencies for all transitive dependencies
57-
var reuseBuilds = this.ReuseLastSuccessfulBuild ? ReuseBuilds.Successful : ReuseBuilds.Default;
57+
var reuseBuilds = this.ReuseLastSuccessfulBuild ? ReuseBuilds.LastSuccessful : ReuseBuilds.Default;
5858

5959
snapshotDependencies =
6060
[new TeamCitySnapshotDependency( buildConfiguration.ObjectName, false, $"+:{buildArtifactsDirectory}/**/*=>{buildArtifactsDirectory}", ReuseBuilds: reuseBuilds )];
@@ -63,7 +63,8 @@ internal override TeamCityBuildConfiguration TeamCityBuildConfiguration(
6363
dependencies.Select( d => new TeamCitySnapshotDependency(
6464
d.Definition.CiConfiguration.BuildTypes[d.Configuration],
6565
true,
66-
$"+:{d.Definition.GetPrivateArtifactsDirectory( d.Configuration ).Replace( Path.DirectorySeparatorChar, '/' )}/**/*=>dependencies/{d.Definition.Name}" ) ) );
66+
$"+:{d.Definition.GetPrivateArtifactsDirectory( d.Configuration ).Replace( Path.DirectorySeparatorChar, '/' )}/**/*=>dependencies/{d.Definition.Name}",
67+
ReuseBuilds: reuseBuilds ) ) );
6768

6869
// If we have a build snapshot dependency, copy nuget.restored.config to nuget.config
6970
var copyNuGetConfigCommand = $@"Copy-Item -Path ""{buildArtifactsDirectory}/nuget.restored.config"" -Destination ""nuget.config"" -Force;";

src/PostSharp.Engineering.BuildTools/ContinuousIntegration/TeamCity/TeamCityBuildConfiguration.cs

Lines changed: 69 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,12 @@ public TeamCityBuildConfiguration(
6464
public void GenerateTeamcityCode( TextWriter writer )
6565
{
6666
writer.WriteLine(
67-
$@"object {this.ObjectName} : BuildType({{
67+
$$"""
68+
object {{this.ObjectName}} : BuildType({
6869
69-
name = ""{this.Name}""
70-
" );
70+
name = "{{this.Name}}"
71+
72+
""" );
7173

7274
if ( this.IsDeployment )
7375
{
@@ -125,18 +127,20 @@ void AddBuildStep( BuildStep newStep )
125127
if ( buildParameters.Count > 0 )
126128
{
127129
writer.WriteLine(
128-
$@" params {{
129-
{string.Join( Environment.NewLine, buildParameters.Select( p => p.GenerateTeamCityCode() ) )}
130-
}}
131-
" );
130+
$$"""
131+
params {
132+
{{string.Join( Environment.NewLine, buildParameters.Select( p => p.GenerateTeamCityCode() ) )}}
133+
}
134+
135+
""" );
132136
}
133137

134138
writer.WriteLine( " vcs {" );
135139

136140
if ( this.IsDefaultVcsRootUsed )
137141
{
138142
// We set the VCS root explicitly for consolidated as well builds to enable the DefaultBranch paramater.
139-
writer.WriteLine( @$" root(AbsoluteId(""{this.VcsId}""))" );
143+
writer.WriteLine( $""" root(AbsoluteId("{this.VcsId}"))""" );
140144

141145
if ( allBuildSteps.Count == 0 )
142146
{
@@ -151,7 +155,7 @@ void AddBuildStep( BuildStep newStep )
151155
{
152156
foreach ( var sourceDependency in this.SourceDependencies! )
153157
{
154-
var objectName = sourceDependency.IsAbsoluteId ? @$"AbsoluteId(""{sourceDependency.VcsId}"")" : sourceDependency.VcsId;
158+
var objectName = sourceDependency.IsAbsoluteId ? $"""AbsoluteId("{sourceDependency.VcsId}")""" : sourceDependency.VcsId;
155159

156160
writer.WriteLine(
157161
$""""
@@ -173,8 +177,10 @@ void AddBuildStep( BuildStep newStep )
173177
}
174178

175179
writer.WriteLine(
176-
$@"
177-
steps {{" );
180+
$$"""
181+
182+
steps {
183+
""" );
178184

179185
foreach ( var buildStep in allBuildSteps )
180186
{
@@ -212,17 +218,21 @@ void AddBuildStep( BuildStep newStep )
212218
if ( requiresAnyFeatures )
213219
{
214220
writer.WriteLine(
215-
$@"
216-
features {{" );
221+
$$"""
222+
223+
features {
224+
""" );
217225

218226
if ( requiresSwabra )
219227
{
220228
writer.WriteLine(
221-
$@" swabra {{
222-
filesCleanup = Swabra.FilesCleanup.BEFORE_BUILD
223-
lockingProcesses = Swabra.LockingProcessPolicy.KILL
224-
verbose = true
225-
}}" );
229+
$$"""
230+
swabra {
231+
filesCleanup = Swabra.FilesCleanup.BEFORE_BUILD
232+
lockingProcesses = Swabra.LockingProcessPolicy.KILL
233+
verbose = true
234+
}
235+
""" );
226236
}
227237

228238
if ( this.RequiresCommitStatusPublisher )
@@ -262,10 +272,12 @@ void AddBuildStep( BuildStep newStep )
262272
if ( requiresSshAgent )
263273
{
264274
writer.WriteLine(
265-
$@" sshAgent {{
266-
// By convention, the SSH key name is always PostSharp.Engineering for all repositories using SSH to connect.
267-
teamcitySshKey = ""PostSharp.Engineering""
268-
}}" );
275+
$$"""
276+
sshAgent {
277+
// By convention, the SSH key name is always PostSharp.Engineering for all repositories using SSH to connect.
278+
teamcitySshKey = "PostSharp.Engineering"
279+
}
280+
""" );
269281
}
270282

271283
writer.WriteLine( $@" }}" );
@@ -275,8 +287,10 @@ void AddBuildStep( BuildStep newStep )
275287
if ( this.BuildTriggers is { Length: > 0 } )
276288
{
277289
writer.WriteLine(
278-
@"
279-
triggers {" );
290+
"""
291+
292+
triggers {
293+
""" );
280294

281295
foreach ( var trigger in this.BuildTriggers )
282296
{
@@ -292,12 +306,14 @@ void AddBuildStep( BuildStep newStep )
292306
if ( hasSnapshotDependencies )
293307
{
294308
writer.WriteLine(
295-
$@"
296-
dependencies {{" );
309+
$$"""
310+
311+
dependencies {
312+
""" );
297313

298314
foreach ( var dependency in this.SnapshotDependencies! )
299315
{
300-
var objectName = dependency.IsAbsoluteId ? @$"AbsoluteId(""{dependency.ObjectId}"")" : dependency.ObjectId;
316+
var objectName = dependency.IsAbsoluteId ? $"""AbsoluteId("{dependency.ObjectId}")""" : dependency.ObjectId;
301317

302318
var failureAction = dependency.FailureAction switch
303319
{
@@ -308,38 +324,44 @@ void AddBuildStep( BuildStep newStep )
308324
_ => throw new ArgumentOutOfRangeException()
309325
};
310326

311-
var reuseBuildsLine = dependency.ReuseBuilds switch
327+
// ReuseBuilds.Any: no snapshot dependency, artifacts use lastSuccessful()
328+
// ReuseBuilds.Successful: snapshot with synchronizeRevisions = false
329+
// Default: normal snapshot dependency
330+
if ( dependency.ReuseBuilds != ReuseBuilds.LastSuccessful )
312331
{
313-
ReuseBuilds.Successful => $"\n reuseBuilds = ReuseBuilds.SUCCESSFUL",
314-
ReuseBuilds.Any => $"\n reuseBuilds = ReuseBuilds.ANY",
315-
_ => ""
316-
};
317-
318-
writer.WriteLine(
319-
$@" dependency({objectName}) {{
320-
snapshot {{
321-
onDependencyFailure = FailureAction.{failureAction}{reuseBuildsLine}
322-
}}" );
332+
writer.WriteLine(
333+
$$"""
334+
snapshot({{objectName}}) {
335+
onDependencyFailure = FailureAction.{{failureAction}}
336+
}
337+
""" );
338+
}
323339

324340
if ( dependency.ArtifactRules != null )
325341
{
342+
var buildRule = dependency.ReuseBuilds == ReuseBuilds.LastSuccessful
343+
? "\n buildRule = lastSuccessful()"
344+
: "";
345+
326346
writer.WriteLine(
327-
$@"
328-
artifacts {{
329-
cleanDestination = true
330-
artifactRules = ""{dependency.ArtifactRules}""
331-
}}" );
332-
}
347+
$$"""
333348
334-
writer.WriteLine( $@" }}" );
349+
artifacts({{objectName}}) { {{buildRule}}
350+
cleanDestination = true
351+
artifactRules = "{{dependency.ArtifactRules}}"
352+
}
353+
""" );
354+
}
335355
}
336356

337357
writer.WriteLine( $@" }}" );
338358
}
339359

340360
writer.WriteLine(
341-
$@"
342-
}})" );
361+
$$"""
362+
363+
})
364+
""" );
343365
}
344366
}
345367
}

src/PostSharp.Engineering.BuildTools/ContinuousIntegration/TeamCity/TeamCitySnapshotDependency.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,5 @@ internal enum FailureAction
2020
internal enum ReuseBuilds
2121
{
2222
Default,
23-
Successful,
24-
Any
23+
LastSuccessful
2524
}

0 commit comments

Comments
 (0)