Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5569c0d4fd | |||
| adc27ae5d3 | |||
| cacd6f03f5 | |||
| e85e00bff2 |
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.5.002.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpeckleAutomateDotnetExample", "SpeckleAutomateDotnetExample\SpeckleAutomateDotnetExample.csproj", "{E1DE5809-1111-4817-9B7D-7ADCA087FA1C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestAutomateFunction", "TestAutomateFunction\TestAutomateFunction.csproj", "{B74B115F-D553-4FD5-8E4C-7B13134217DA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -15,6 +17,10 @@ Global
|
||||
{E1DE5809-1111-4817-9B7D-7ADCA087FA1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1DE5809-1111-4817-9B7D-7ADCA087FA1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E1DE5809-1111-4817-9B7D-7ADCA087FA1C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B74B115F-D553-4FD5-8E4C-7B13134217DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B74B115F-D553-4FD5-8E4C-7B13134217DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B74B115F-D553-4FD5-8E4C-7B13134217DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B74B115F-D553-4FD5-8E4C-7B13134217DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -4,7 +4,7 @@ using Speckle.Core.Api;
|
||||
using Speckle.Core.Models;
|
||||
using SpeckleAutomateDotnetExample;
|
||||
|
||||
static class AutomateFunction
|
||||
public static class AutomateFunction
|
||||
{
|
||||
public static string ADDED = "ADDED";
|
||||
public static string MODIFIED = "MODIFIED";
|
||||
@@ -19,11 +19,9 @@ static class AutomateFunction
|
||||
Console.WriteLine("Starting execution");
|
||||
_ = typeof(ObjectsKit).Assembly; // INFO: Force objects kit to initialize
|
||||
|
||||
double tolerance = functionInputs.Tolerance;
|
||||
|
||||
// get the testing and release branches
|
||||
string testBranchName = automationContext.AutomationRunData.BranchName;
|
||||
string releaseBranchName = testBranchName.Replace("/testing", "/release");
|
||||
string releaseBranchName = functionInputs.DiffBranch;
|
||||
Console.WriteLine($"Comparing {testBranchName} against {releaseBranchName}");
|
||||
Branch? releaseBranch = await automationContext.SpeckleClient
|
||||
.BranchGet(automationContext.AutomationRunData.ProjectId, releaseBranchName, 1)
|
||||
@@ -37,7 +35,7 @@ static class AutomateFunction
|
||||
Commit releaseCommit = releaseBranch.commits.items.First();
|
||||
if (releaseCommit is null)
|
||||
{
|
||||
throw new Exception("Release branch has no commits");
|
||||
throw new Exception("Diff branch has no commits");
|
||||
}
|
||||
|
||||
// get the test and release commit base
|
||||
@@ -67,7 +65,7 @@ static class AutomateFunction
|
||||
out int releaseObjectCount
|
||||
);
|
||||
Console.WriteLine(
|
||||
$"Found {releaseObjectCount} objects in RELEASE with {releaseCommitAppIdDict.Count} unique applicationIds and {releaseCommitSpeckleIdDict} unique speckle ids (for objects with no application id)."
|
||||
$"Found {releaseObjectCount} objects in RELEASE with {releaseCommitAppIdDict.Count} unique applicationIds and {releaseCommitSpeckleIdDict.Count} unique speckle ids (for objects with no application id)."
|
||||
);
|
||||
Utils.CreateDictionaryFromBaseById(
|
||||
testingCommitObject,
|
||||
@@ -76,7 +74,7 @@ static class AutomateFunction
|
||||
out int testingObjectCount
|
||||
);
|
||||
Console.WriteLine(
|
||||
$"Found {testingObjectCount} objects in TESTING with {testingCommitAppIdDict.Count} unique applicationIds and {testingCommitSpeckleIdDict} unique speckle ids (for objects with no application id)."
|
||||
$"Found {testingObjectCount} objects in TESTING with {testingCommitAppIdDict.Count} unique applicationIds and {testingCommitSpeckleIdDict.Count} unique speckle ids (for objects with no application id)."
|
||||
);
|
||||
|
||||
// COMPARE COMMIT OBJECTS WITH APPLICATION IDS
|
||||
@@ -249,6 +247,15 @@ static class AutomateFunction
|
||||
);
|
||||
}
|
||||
|
||||
if (addedAppIdObjects.Count > 0)
|
||||
{
|
||||
automationContext.AttachErrorToObjects(
|
||||
"ADDED",
|
||||
addedAppIdObjects.Select(o => o.Item1),
|
||||
"added objects with an application Id"
|
||||
);
|
||||
}
|
||||
|
||||
foreach (var deleted in deletedAppIdObjects)
|
||||
{
|
||||
Console.WriteLine(
|
||||
@@ -259,7 +266,16 @@ static class AutomateFunction
|
||||
foreach (var modified in modifiedAppIdObjects)
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"{MODIFIED} {modified.Item3} object: id( {modified.Item1} ), appId: {modified.Item2}. Changed props: {modified.Item4}"
|
||||
$"{MODIFIED} {modified.Item3} object: id( {modified.Item1} ), appId: {modified.Item2}, category: {modified.Item3}"
|
||||
);
|
||||
}
|
||||
|
||||
if (modifiedAppIdObjects.Count > 0)
|
||||
{
|
||||
automationContext.AttachErrorToObjects(
|
||||
"MODIFIED",
|
||||
modifiedAppIdObjects.Select(o => o.Item1),
|
||||
"modified objects with an application Id"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -267,6 +283,15 @@ static class AutomateFunction
|
||||
{
|
||||
Console.WriteLine($"CHANGED {changed.Item2} object: id( {changed.Item1} )");
|
||||
}
|
||||
|
||||
if (changedSpeckleIdObjects.Count > 0)
|
||||
{
|
||||
automationContext.AttachErrorToObjects(
|
||||
"CHANGED",
|
||||
changedSpeckleIdObjects.Select(o => o.Item1),
|
||||
"changed objects with no application Id"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@ using System.ComponentModel.DataAnnotations;
|
||||
/// </summary>
|
||||
/// This class is used to generate a JSON Schema to ensure that the user provided values
|
||||
/// are valid and match the required schema.
|
||||
struct FunctionInputs
|
||||
public struct FunctionInputs
|
||||
{
|
||||
//[Required]
|
||||
public double Tolerance;
|
||||
|
||||
//public string Exclusions;
|
||||
/// <summary>
|
||||
/// The name of the branch to compare against. This should be the full branch path.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string DiffBranch;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace SpeckleAutomateDotnetExample
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!string.IsNullOrWhiteSpace(commitObject.id))
|
||||
{
|
||||
if (speckleIdDict.ContainsKey(commitObject.id))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
# nullable enable
|
||||
namespace TestAutomateFunction;
|
||||
|
||||
using Speckle.Automate.Sdk.Schema;
|
||||
using Speckle.Automate.Sdk;
|
||||
using Speckle.Core.Api;
|
||||
using Speckle.Core.Credentials;
|
||||
using Speckle.Core.Models;
|
||||
using Speckle.Core.Transports;
|
||||
using Utils = TestAutomateUtils;
|
||||
|
||||
[TestFixture]
|
||||
public sealed class AutomationContextTest : IDisposable
|
||||
{
|
||||
// Regression testing function project id
|
||||
public string projectId = "6ada180f0c";
|
||||
|
||||
// e2e release branch and model id
|
||||
public string releaseBranchName = "e2e/release";
|
||||
public string releaseModelId = "e4c8cc3802";
|
||||
|
||||
// e2e testing branch and model id
|
||||
public string testingBranchName = "e2e/testing";
|
||||
public string testingModelId = "c374f0aade";
|
||||
|
||||
private async Task<AutomationRunData> AutomationRunData(
|
||||
Base testObject,
|
||||
Base releaseObject
|
||||
)
|
||||
{
|
||||
// send the release commit to the release branch
|
||||
string releaseObjId = await Operations.Send(
|
||||
releaseObject,
|
||||
new List<ITransport> { new ServerTransport(client.Account, projectId) }
|
||||
);
|
||||
|
||||
string releaseVersionId = await client.CommitCreate(
|
||||
new()
|
||||
{
|
||||
streamId = projectId,
|
||||
objectId = releaseObjId,
|
||||
branchName = releaseBranchName
|
||||
}
|
||||
);
|
||||
|
||||
// send the test object to the test branch
|
||||
string testObjId = await Operations.Send(
|
||||
testObject,
|
||||
new List<ITransport> { new ServerTransport(client.Account, projectId) }
|
||||
);
|
||||
|
||||
string testingVersionId = await client.CommitCreate(
|
||||
new()
|
||||
{
|
||||
streamId = projectId,
|
||||
objectId = testObjId,
|
||||
branchName = testingBranchName
|
||||
}
|
||||
);
|
||||
|
||||
// create a new automation on the testing branch
|
||||
var automationName = TestAutomateUtils.RandomString(10);
|
||||
var automationId = TestAutomateUtils.RandomString(10);
|
||||
var automationRevisionId = TestAutomateUtils.RandomString(10);
|
||||
|
||||
await TestAutomateUtils.RegisterNewAutomation(
|
||||
projectId,
|
||||
testingModelId,
|
||||
client,
|
||||
automationId,
|
||||
automationName,
|
||||
automationRevisionId
|
||||
);
|
||||
|
||||
var automationRunId = TestAutomateUtils.RandomString(10);
|
||||
var functionId = TestAutomateUtils.RandomString(10);
|
||||
var functionName = "Automation name " + TestAutomateUtils.RandomString(10);
|
||||
var functionRelease = TestAutomateUtils.RandomString(10);
|
||||
|
||||
return new AutomationRunData
|
||||
{
|
||||
ProjectId = projectId,
|
||||
ModelId = testingModelId,
|
||||
BranchName = testingBranchName,
|
||||
VersionId = testingVersionId,
|
||||
SpeckleServerUrl = client.ServerUrl,
|
||||
AutomationId = automationId,
|
||||
AutomationRevisionId = automationRevisionId,
|
||||
AutomationRunId = automationRunId,
|
||||
FunctionId = functionId,
|
||||
FunctionName = functionName,
|
||||
FunctionRelease = functionRelease,
|
||||
};
|
||||
}
|
||||
|
||||
private Client client;
|
||||
private Account account;
|
||||
|
||||
private string GetSpeckleToken()
|
||||
{
|
||||
var envVarName = "SPECKLE_TOKEN";
|
||||
Environment.SetEnvironmentVariable(envVarName, "");
|
||||
var token = Environment.GetEnvironmentVariable(envVarName);
|
||||
if (token is null)
|
||||
{
|
||||
throw new Exception(
|
||||
$"Cannot run tests without a {envVarName} environment variable"
|
||||
);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
private string GetSpeckleServerUrl() =>
|
||||
Environment.GetEnvironmentVariable("SPECKLE_SERVER_URL")
|
||||
?? "https://latest.speckle.systems";
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
account = new Account
|
||||
{
|
||||
token = GetSpeckleToken(),
|
||||
serverInfo = new ServerInfo { url = GetSpeckleServerUrl() }
|
||||
};
|
||||
client = new Client(account);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFunctionRun()
|
||||
{
|
||||
var automationRunData = await AutomationRunData(
|
||||
TestAutomateUtils.TestObject(),
|
||||
TestAutomateUtils.ReleaseObject()
|
||||
);
|
||||
var automationContext = await AutomationRunner.RunFunction(
|
||||
AutomateFunction.Run,
|
||||
automationRunData,
|
||||
account.token,
|
||||
new FunctionInputs { DiffBranch = releaseBranchName }
|
||||
);
|
||||
|
||||
Assert.That(automationContext.RunStatus, Is.EqualTo("FAILED"));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"profiles": {
|
||||
"TestAutomateFunction": {
|
||||
"commandName": "Project",
|
||||
"environmentVariables": {
|
||||
"SPECKLE_TOKEN": "718d0650eea8038642850414e43bd81314d740359a",
|
||||
"SPECKLE_SERVER_URL": "https://latest.speckle.dev/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<UserSecretsId>0b5cf4dd-cfa3-4982-9722-ca6c6672b8dd</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2" />
|
||||
<PackageReference Include="Speckle.Automate.Sdk" Version="2.18.0-fileInput" />
|
||||
<PackageReference Include="Speckle.Objects" Version="2.18.0-fileInput" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SpeckleAutomateDotnetExample\SpeckleAutomateDotnetExample.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using GraphQL;
|
||||
using Speckle.Core.Api;
|
||||
using Speckle.Core.Models;
|
||||
|
||||
namespace TestAutomateFunction;
|
||||
|
||||
public static class TestAutomateUtils
|
||||
{
|
||||
[SuppressMessage("Security", "CA5394:Do not use insecure randomness")]
|
||||
public static string RandomString(int length)
|
||||
{
|
||||
Random rand = new();
|
||||
const string pool = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var chars = Enumerable
|
||||
.Range(0, length)
|
||||
.Select(_ => pool[rand.Next(0, pool.Length)]);
|
||||
return new string(chars.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The test object to compare against the release object
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>Contains 3 children objects to capture the Added, Deleted, Modified, and Unchanged categories</remarks>
|
||||
public static Base TestObject()
|
||||
{
|
||||
Base unchanged = new() { ["unchangedProp"] = true };
|
||||
Base added = new() { ["addedProp"] = "added" };
|
||||
Base modified = new() { ["modifiedProp"] = 1 };
|
||||
Base testObject = new();
|
||||
testObject["unchanged"] = unchanged;
|
||||
testObject["added"] = added;
|
||||
testObject["modified"] = modified;
|
||||
return testObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The release object to compare the test object against
|
||||
/// </summary>
|
||||
/// <returns>Contains 3 children objects to capture the Added, Deleted, Modified, and Unchanged categories</returns>
|
||||
public static Base ReleaseObject()
|
||||
{
|
||||
Base unchanged = new() { ["unchangedProp"] = true };
|
||||
Base deleted = new() { ["deletedProp"] = "deleted" };
|
||||
Base modified = new() { ["modifiedProp"] = 0.5 };
|
||||
Base releaseObject = new();
|
||||
releaseObject["unchanged"] = unchanged;
|
||||
releaseObject["deleted"] = deleted;
|
||||
releaseObject["modified"] = modified;
|
||||
return releaseObject;
|
||||
}
|
||||
|
||||
public static async Task RegisterNewAutomation(
|
||||
string projectId,
|
||||
string modelId,
|
||||
Client speckleClient,
|
||||
string automationId,
|
||||
string automationName,
|
||||
string automationRevisionId
|
||||
)
|
||||
{
|
||||
GraphQLRequest query =
|
||||
new(
|
||||
query: """
|
||||
mutation CreateAutomation(
|
||||
$projectId: String!
|
||||
$modelId: String!
|
||||
$automationName: String!
|
||||
$automationId: String!
|
||||
$automationRevisionId: String!
|
||||
) {
|
||||
automationMutations {
|
||||
create(
|
||||
input: {
|
||||
projectId: $projectId
|
||||
modelId: $modelId
|
||||
automationName: $automationName
|
||||
automationId: $automationId
|
||||
automationRevisionId: $automationRevisionId
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
""",
|
||||
variables: new
|
||||
{
|
||||
projectId,
|
||||
modelId,
|
||||
automationName,
|
||||
automationId,
|
||||
automationRevisionId,
|
||||
}
|
||||
);
|
||||
|
||||
await speckleClient.ExecuteGraphQLRequest<object>(query);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using NUnit.Framework;
|
||||
Reference in New Issue
Block a user