Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Snapshot additional mapping tokens #3468

Merged
merged 7 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Runner.Worker/JobExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public async Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipel
var snapshotOperationProvider = HostContext.GetService<ISnapshotOperationProvider>();
jobContext.RegisterPostJobStep(new JobExtensionRunner(
runAsync: (executionContext, _) => snapshotOperationProvider.CreateSnapshotRequestAsync(executionContext, snapshotRequest),
condition: $"{PipelineTemplateConstants.Success}()",
condition: snapshotRequest.Condition,
displayName: $"Create custom image",
data: null));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public sealed class PipelineTemplateConstants
public const String If = "if";
public const String Image = "image";
public const String ImageName = "image-name";
public const String CustomImageVersion = "version";
public const String Include = "include";
public const String Inputs = "inputs";
public const String Job = "job";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using GitHub.DistributedTask.Expressions2;
using GitHub.DistributedTask.Expressions2.Sdk;
Expand Down Expand Up @@ -349,6 +350,10 @@ internal static List<KeyValuePair<String, JobContainer>> ConvertToJobServiceCont
internal static Snapshot ConvertToJobSnapshotRequest(TemplateContext context, TemplateToken token)
{
string imageName = null;
string version = "1.*";
string versionString = string.Empty;
var condition = $"{PipelineTemplateConstants.Success}()";

if (token is StringToken snapshotStringLiteral)
{
imageName = snapshotStringLiteral.Value;
Expand All @@ -359,11 +364,19 @@ internal static Snapshot ConvertToJobSnapshotRequest(TemplateContext context, Te
foreach (var snapshotPropertyPair in snapshotMapping)
{
var propertyName = snapshotPropertyPair.Key.AssertString($"{PipelineTemplateConstants.Snapshot} key");
var propertyValue = snapshotPropertyPair.Value;
switch (propertyName.Value)
{
case PipelineTemplateConstants.ImageName:
imageName = snapshotPropertyPair.Value.AssertString($"{PipelineTemplateConstants.Snapshot} {propertyName}").Value;
break;
case PipelineTemplateConstants.If:
condition = ConvertToIfCondition(context, propertyValue, false);
break;
case PipelineTemplateConstants.CustomImageVersion:
versionString = propertyValue.AssertString($"job {PipelineTemplateConstants.Snapshot} {PipelineTemplateConstants.CustomImageVersion}").Value;
version = IsSnapshotImageVersionValid(versionString) ? versionString : null;
break;
default:
propertyName.AssertUnexpectedValue($"{PipelineTemplateConstants.Snapshot} key");
break;
Expand All @@ -376,7 +389,26 @@ internal static Snapshot ConvertToJobSnapshotRequest(TemplateContext context, Te
return null;
}

return new Snapshot(imageName);
return new Snapshot(imageName)
{
Condition = condition,
Version = version
};
}

private static bool IsSnapshotImageVersionValid(string versionString)
{
var versionSegments = versionString.Split(".");

if (versionSegments.Length != 2 ||
TingluoHuang marked this conversation as resolved.
Show resolved Hide resolved
!versionSegments[1].Equals("*") ||
!Int32.TryParse(versionSegments[0], NumberStyles.None, CultureInfo.InvariantCulture, result: out int parsedMajor) ||
parsedMajor < 0)
{
return false;
}

return true;
}

private static ActionStep ConvertToStep(
Expand Down
12 changes: 11 additions & 1 deletion src/Sdk/DTPipelines/Pipelines/Snapshot.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
using System;
using System.Runtime.Serialization;
using GitHub.DistributedTask.ObjectTemplating.Tokens;
using GitHub.DistributedTask.Pipelines.ObjectTemplating;

namespace GitHub.DistributedTask.Pipelines
{
[DataContract]
public class Snapshot
{
public Snapshot(string imageName)
public Snapshot(string imageName, string condition = null, string version = null)
{
ImageName = imageName;
Condition = condition ?? $"{PipelineTemplateConstants.Success}()";
Version = version ?? "1.*";
}

[DataMember(EmitDefaultValue = false)]
public String ImageName { get; set; }

[DataMember(EmitDefaultValue = false)]
public String Condition { get; set; }

[DataMember(EmitDefaultValue = false)]
public String Version { get; set; }
}
}
19 changes: 18 additions & 1 deletion src/Sdk/DTPipelines/workflow-v1.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,18 +162,35 @@
"snapshot-mapping"
]
},

rajrku marked this conversation as resolved.
Show resolved Hide resolved
"snapshot-mapping": {
"mapping": {
"properties": {
"image-name": {
"type": "non-empty-string",
"required": true
},
"if": "snapshot-if",
"version": {
"type": "non-empty-string",
"required": false
}
}
}
},

"snapshot-if": {
TingluoHuang marked this conversation as resolved.
Show resolved Hide resolved
"context": [
"github",
"inputs",
"vars",
"needs",
"strategy",
"matrix"
],
"string": {}
},

"runs-on": {
"context": [
"github",
Expand Down
46 changes: 40 additions & 6 deletions src/Test/L0/Worker/JobExtensionL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,27 @@ public Task EnsureSnapshotPostJobStepForMappingToken()
return EnsureSnapshotPostJobStepForToken(mappingToken, snapshot);
}

private async Task EnsureSnapshotPostJobStepForToken(TemplateToken snapshotToken, Pipelines.Snapshot expectedSnapshot)
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public Task EnsureSnapshotPostJobStepForMappingToken_WithIf_Is_False()
{
var snapshot = new Pipelines.Snapshot("TestImageNameFromMappingToken", condition: $"{PipelineTemplateConstants.Success}() && 1==0", version: "2.*");
var imageNameValueStringToken = new StringToken(null, null, null, snapshot.ImageName);
var condition = new StringToken(null, null, null, snapshot.Condition);
var version = new StringToken(null, null, null, snapshot.Version);

var mappingToken = new MappingToken(null, null, null)
{
{ new StringToken(null,null,null, PipelineTemplateConstants.ImageName), imageNameValueStringToken },
{ new StringToken(null,null,null, PipelineTemplateConstants.If), condition },
{ new StringToken(null,null,null, PipelineTemplateConstants.CustomImageVersion), version }
};

return EnsureSnapshotPostJobStepForToken(mappingToken, snapshot, skipSnapshotStep: true);
}

private async Task EnsureSnapshotPostJobStepForToken(TemplateToken snapshotToken, Pipelines.Snapshot expectedSnapshot, bool skipSnapshotStep = false)
{
using (TestHostContext hc = CreateTestContext())
{
Expand All @@ -524,14 +544,28 @@ private async Task EnsureSnapshotPostJobStepForToken(TemplateToken snapshotToken

Assert.Equal(1, postJobSteps.Count);
var snapshotStep = postJobSteps.First();
_jobEc.JobSteps.Enqueue(snapshotStep);

var _stepsRunner = new StepsRunner();
_stepsRunner.Initialize(hc);
await _stepsRunner.RunAsync(_jobEc);

Assert.Equal("Create custom image", snapshotStep.DisplayName);
Assert.Equal($"{PipelineTemplateConstants.Success}()", snapshotStep.Condition);
Assert.Equal(expectedSnapshot.Condition ?? $"{PipelineTemplateConstants.Success}()", snapshotStep.Condition);

// Run the mock snapshot step, so we can verify it was executed with the expected snapshot object.
await snapshotStep.RunAsync();

Assert.NotNull(_requestedSnapshot);
Assert.Equal(expectedSnapshot.ImageName, _requestedSnapshot.ImageName);
// await snapshotStep.RunAsync();
if (skipSnapshotStep)
{
Assert.Null(_requestedSnapshot);
}
else
{
Assert.NotNull(_requestedSnapshot);
Assert.Equal(expectedSnapshot.ImageName, _requestedSnapshot.ImageName);
Assert.Equal(expectedSnapshot.Condition ?? $"{PipelineTemplateConstants.Success}()", _requestedSnapshot.Condition);
Assert.Equal(expectedSnapshot.Version ?? "1.*", _requestedSnapshot.Version);
}
}
}
}
Expand Down
Loading