Add ToolVersion field to workflow definition

This commit is contained in:
Sipke Schoorstra 2023-07-06 15:48:28 +02:00
parent 7efe9e590e
commit 0eea344406
29 changed files with 104 additions and 28 deletions

View file

@ -23,6 +23,11 @@ public class WorkflowDefinition : VersionedEntity
/// </summary>
public string? Description { get; set; }
/// <summary>
/// The version of the tool that created this workflow.
/// </summary>
public Version? ToolVersion { get; set; }
/// <summary>
/// A set of options for the workflow.
/// </summary>

View file

@ -17,6 +17,7 @@ public class Initial : Migration
.WithColumn("Id").AsString().PrimaryKey()
.WithColumn("DefinitionId").AsString().NotNullable()
.WithColumn("Name").AsString().Nullable()
.WithColumn("ToolVersion").AsString().Nullable()
.WithColumn("Description").AsString().Nullable()
.WithColumn("ProviderName").AsString().Nullable()
.WithColumn("MaterializerName").AsString().NotNullable()

View file

@ -5,6 +5,7 @@ internal class WorkflowDefinitionRecord
public string Id { get; set; } = default!;
public string DefinitionId { get; set; } = default!;
public string? Name { get; set; }
public string? ToolVersion { get; set; }
public string? Description { get; set; }
public string? ProviderName { get; set; }
public string MaterializerName { get; set; } = default!;

View file

@ -22,9 +22,5 @@
<ItemGroup>
<ProjectReference Include="..\Elsa.EntityFrameworkCore\Elsa.EntityFrameworkCore.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\Management\" />
</ItemGroup>
</Project>

View file

@ -11,7 +11,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Elsa.EntityFrameworkCore.MySql.Migrations.Management
{
[DbContext(typeof(ManagementElsaDbContext))]
[Migration("20230603165710_Initial")]
[Migration("20230706133103_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -69,6 +69,9 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("longtext");
b.Property<string>("ToolVersion")
.HasColumnType("longtext");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("tinyint(1)");

View file

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
@ -29,6 +30,8 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Management
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ToolVersion = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ProviderName = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
MaterializerName = table.Column<string>(type: "longtext", nullable: false)

View file

@ -66,6 +66,9 @@ namespace Elsa.EntityFrameworkCore.MySql.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("longtext");
b.Property<string>("ToolVersion")
.HasColumnType("longtext");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("tinyint(1)");

View file

@ -1,5 +1,5 @@
dotnet ef migrations add Initial -c ActivityDefinitionsElsaDbContext -o Migrations/ActivityDefinitions
dotnet ef migrations add Initial -c LabelsElsaDbContext -o Migrations/Labels
dotnet ef migrations add Initial -c ManagementElsaDbContext -o Migrations/Management
dotnet ef migrations add Initial -c RuntimeElsaDbContext -o Migrations/Runtime
dotnet ef migrations add Initial -c IdentityElsaDbContext -o Migrations/Identity
dotnet ef migrations add Initial -c ActivityDefinitionsElsaDbContext -o Migrations/ActivityDefinitions -- "Server=localhost;Port=3306;Database=elsa;User=root;Password=password;"
dotnet ef migrations add Initial -c LabelsElsaDbContext -o Migrations/Labels -- "Server=localhost;Port=3306;Database=elsa;User=root;Password=password;"
dotnet ef migrations add Initial -c ManagementElsaDbContext -o Migrations/Management -- "Server=localhost;Port=3306;Database=elsa;User=root;Password=password;"
dotnet ef migrations add Initial -c RuntimeElsaDbContext -o Migrations/Runtime -- "Server=localhost;Port=3306;Database=elsa;User=root;Password=password;"
dotnet ef migrations add Initial -c IdentityElsaDbContext -o Migrations/Identity -- "Server=localhost;Port=3306;Database=elsa;User=root;Password=password;"

View file

@ -22,9 +22,5 @@
<ItemGroup>
<ProjectReference Include="..\Elsa.EntityFrameworkCore\Elsa.EntityFrameworkCore.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\Management\" />
</ItemGroup>
</Project>

View file

@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Management
{
[DbContext(typeof(ManagementElsaDbContext))]
[Migration("20230603165731_Initial")]
[Migration("20230706133144_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -72,6 +72,9 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("text");
b.Property<string>("ToolVersion")
.HasColumnType("text");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("boolean");

View file

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
@ -22,6 +23,7 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Management
DefinitionId = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: true),
Description = table.Column<string>(type: "text", nullable: true),
ToolVersion = table.Column<string>(type: "text", nullable: true),
ProviderName = table.Column<string>(type: "text", nullable: true),
MaterializerName = table.Column<string>(type: "text", nullable: false),
MaterializerContext = table.Column<string>(type: "text", nullable: true),

View file

@ -69,6 +69,9 @@ namespace Elsa.EntityFrameworkCore.PostgreSql.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("text");
b.Property<string>("ToolVersion")
.HasColumnType("text");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("boolean");

View file

@ -23,8 +23,4 @@
<ProjectReference Include="..\Elsa.EntityFrameworkCore\Elsa.EntityFrameworkCore.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\Management\" />
</ItemGroup>
</Project>

View file

@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management
{
[DbContext(typeof(ManagementElsaDbContext))]
[Migration("20230603165756_Initial")]
[Migration("20230706133258_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -72,6 +72,9 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("nvarchar(max)");
b.Property<string>("ToolVersion")
.HasColumnType("nvarchar(max)");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("bit");

View file

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
@ -22,6 +23,7 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management
DefinitionId = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(450)", nullable: true),
Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
ToolVersion = table.Column<string>(type: "nvarchar(max)", nullable: true),
ProviderName = table.Column<string>(type: "nvarchar(max)", nullable: true),
MaterializerName = table.Column<string>(type: "nvarchar(max)", nullable: false),
MaterializerContext = table.Column<string>(type: "nvarchar(max)", nullable: true),

View file

@ -69,6 +69,9 @@ namespace Elsa.EntityFrameworkCore.SqlServer.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("nvarchar(max)");
b.Property<string>("ToolVersion")
.HasColumnType("nvarchar(max)");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("bit");

View file

@ -25,7 +25,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\Management\" />
<Folder Include="Migrations\Runtime\" />
</ItemGroup>

View file

@ -11,7 +11,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management
{
[DbContext(typeof(ManagementElsaDbContext))]
[Migration("20230628212338_Initial")]
[Migration("20230706133213_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -67,6 +67,9 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("TEXT");
b.Property<string>("ToolVersion")
.HasColumnType("TEXT");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("INTEGER");

View file

@ -18,6 +18,7 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management
DefinitionId = table.Column<string>(type: "TEXT", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: true),
Description = table.Column<string>(type: "TEXT", nullable: true),
ToolVersion = table.Column<string>(type: "TEXT", nullable: true),
ProviderName = table.Column<string>(type: "TEXT", nullable: true),
MaterializerName = table.Column<string>(type: "TEXT", nullable: false),
MaterializerContext = table.Column<string>(type: "TEXT", nullable: true),

View file

@ -64,6 +64,9 @@ namespace Elsa.EntityFrameworkCore.Sqlite.Migrations.Management
b.Property<string>("StringData")
.HasColumnType("TEXT");
b.Property<string>("ToolVersion")
.HasColumnType("TEXT");
b.Property<bool?>("UsableAsActivity")
.HasColumnType("INTEGER");

View file

@ -1,3 +1,4 @@
using System.Linq.Expressions;
using Elsa.Workflows.Core.Models;
using Elsa.Workflows.Management.Entities;
using Microsoft.EntityFrameworkCore;
@ -8,6 +9,9 @@ namespace Elsa.EntityFrameworkCore.Modules.Management;
internal class Configurations : IEntityTypeConfiguration<WorkflowDefinition>, IEntityTypeConfiguration<WorkflowInstance>
{
private static Expression<Func<Version?, string?>> VersionToStringConverter => v => v != null ? v.ToString() : null;
private static Expression<Func<string?, Version?>> StringToVersionConverter => v => v != null ? Version.Parse(v) : null;
public void Configure(EntityTypeBuilder<WorkflowDefinition> builder)
{
builder.Ignore(x => x.Variables);
@ -18,6 +22,7 @@ internal class Configurations : IEntityTypeConfiguration<WorkflowDefinition>, IE
builder.Ignore(x => x.Options);
builder.Property<string>("Data");
builder.Property<bool?>("UsableAsActivity");
builder.Property(x => x.ToolVersion).HasConversion(VersionToStringConverter, StringToVersionConverter);
builder.HasIndex(x => new {x.DefinitionId, x.Version}).HasDatabaseName($"IX_{nameof(WorkflowDefinition)}_{nameof(WorkflowDefinition.DefinitionId)}_{nameof(WorkflowDefinition.Version)}").IsUnique();
builder.HasIndex(x => x.Version).HasDatabaseName($"IX_{nameof(WorkflowDefinition)}_{nameof(WorkflowDefinition.Version)}");

View file

@ -3,8 +3,20 @@ using MongoDB.Driver;
namespace Elsa.MongoDb.Extensions;
/// <summary>
/// Provides extension methods for building expressions.
/// </summary>
public static class DocumentExtensions
{
/// <summary>
/// Builds a filter expression for the specified property name.
/// </summary>
/// <param name="document">The document.</param>
/// <param name="selector">The property selector.</param>
/// <typeparam name="TDocument">The type of the document.</typeparam>
/// <typeparam name="TResult">The type of the property.</typeparam>
/// <exception cref="ArgumentNullException">The document is null.</exception>
/// <exception cref="ArgumentException">The selector is not a member expression.</exception>
public static Expression<Func<TDocument, bool>> BuildExpression<TDocument, TResult>(this TDocument document, Expression<Func<TDocument, TResult>> selector)
{
if (document == null) throw new ArgumentNullException(nameof(document));
@ -18,9 +30,20 @@ public static class DocumentExtensions
return document.BuildFilter(propertyName);
}
/// <summary>
/// Builds a filter expression for the Id property.
/// </summary>
/// <param name="document">The document.</param>
/// <typeparam name="TDocument">The type of the document.</typeparam>
public static Expression<Func<TDocument, bool>> BuildIdFilter<TDocument>(this TDocument document) =>
document.BuildFilter("Id");
/// <summary>
/// Builds a filter expression for the Id property name of the specified documents.
/// </summary>
/// <param name="documents">The documents.</param>
/// <typeparam name="TDocument">The type of the document.</typeparam>
/// <exception cref="InvalidOperationException">The type does not have an Id property.</exception>
public static FilterDefinition<TDocument> BuildIdFilterForList<TDocument>(this IEnumerable<TDocument> documents)
{
var propertyName = "Id";

View file

@ -6,6 +6,7 @@ using Elsa.Workflows.Core.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver;
using MongoDB.Driver.Core.Extensions.DiagnosticSources;
@ -46,6 +47,7 @@ public class MongoDbFeature : FeatureBase
BsonSerializer.RegisterSerializer(typeof(object), new PolymorphicSerializer());
BsonSerializer.RegisterSerializer(typeof(Type), new TypeSerializer());
BsonSerializer.RegisterSerializer(typeof(Variable), new VariableSerializer());
BsonSerializer.RegisterSerializer(typeof(Version), new VersionSerializer());
}
private static IMongoDatabase CreateDatabase(IServiceProvider sp, string connectionString)

View file

@ -63,6 +63,7 @@ public class Export : ElsaEndpoint<Request>
definition.Description,
definition.CreatedAt,
definition.Version,
definition.ToolVersion,
variables,
definition.Inputs,
definition.Outputs,

View file

@ -83,6 +83,7 @@ internal class Post : ElsaEndpoint<SaveWorkflowDefinitionRequest, WorkflowDefini
draft!.StringData = stringData;
draft.MaterializerName = JsonWorkflowMaterializer.MaterializerName;
draft.Name = model.Name?.Trim();
draft.ToolVersion = model.ToolVersion;
draft.Description = model.Description?.Trim();
draft.CustomProperties = model.CustomProperties ?? new Dictionary<string, object>();
draft.Variables = variables;

View file

@ -1,5 +1,12 @@
namespace Elsa.Workflows.Core.Models;
public record WorkflowMetadata(string? Name = default, string? Description = default, DateTimeOffset CreatedAt = default)
/// <summary>
/// Represents metadata about a workflow.
/// </summary>
/// <param name="Name">The name of the workflow.</param>
/// <param name="Description">The description of the workflow.</param>
/// <param name="CreatedAt">The date and time the workflow was created.</param>
/// <param name="ToolVersion">The version of the tool that created the workflow.</param>
public record WorkflowMetadata(string? Name = default, string? Description = default, DateTimeOffset CreatedAt = default, Version? ToolVersion = default)
{
}

View file

@ -19,10 +19,15 @@ public class WorkflowDefinition : VersionedEntity
public string? Name { get; set; }
/// <summary>
/// A short description of that the workflow is about.
/// A short description of what the workflow is about.
/// </summary>
public string? Description { get; set; }
/// <summary>
/// The version of the tool that created this workflow.
/// </summary>
public Version? ToolVersion { get; set; }
/// <summary>
/// A set of options for the workflow.
/// </summary>

View file

@ -60,12 +60,15 @@ public class WorkflowDefinitionMapper
var options = source.Options ?? new WorkflowOptions();
// TODO: Remove this in the future when users have migrated workflows to use the new UsableAsActivity options property.
#pragma warning disable CS0618
options.UsableAsActivity ??= source.UsableAsActivity ?? false;
#pragma warning restore CS0618
return new(
new WorkflowIdentity(source.DefinitionId, source.Version, source.Id),
new WorkflowPublication(source.IsLatest, source.IsPublished),
new WorkflowMetadata(source.Name, source.Description, source.CreatedAt),
new WorkflowMetadata(source.Name, source.Description, source.CreatedAt, source.ToolVersion),
options,
root,
variables,
@ -94,6 +97,7 @@ public class WorkflowDefinitionMapper
workflowDefinition.Description,
workflowDefinition.CreatedAt,
workflowDefinition.Version,
workflowDefinition.ToolVersion,
variables,
workflowDefinition.Inputs,
workflowDefinition.Outputs,

View file

@ -32,6 +32,7 @@ public record WorkflowDefinitionModel(
string? Description,
DateTimeOffset CreatedAt,
int Version,
Version? ToolVersion,
ICollection<VariableDefinition>? Variables,
ICollection<InputDefinition>? Inputs,
ICollection<OutputDefinition>? Outputs,
@ -64,6 +65,7 @@ public record WorkflowDefinitionModel(
default!,
default!,
default!,
default!,
default!)
{
}