< Summary

Information
Class: Program
Assembly: Elsa.Server.Web
File(s): /home/runner/work/elsa-core/elsa-core/src/apps/Elsa.Server.Web/Program.cs
Line coverage
100%
Covered lines: 114
Uncovered lines: 0
Coverable lines: 114
Total lines: 200
Line coverage: 100%
Branch coverage
95%
Covered branches: 23
Total branches: 24
Branch coverage: 95.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
<Main>$()95.83%2424100%
get_ConfigureForTest()100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/apps/Elsa.Server.Web/Program.cs

#LineLine coverage
 1using System.Text.Encodings.Web;
 2using Elsa.Caching.Options;
 3using Elsa.Common.RecurringTasks;
 4using Elsa.Expressions.Helpers;
 5using Elsa.Extensions;
 6using Elsa.Features.Services;
 7using Elsa.Persistence.EFCore.Extensions;
 8using Elsa.Persistence.EFCore.Modules.Management;
 9using Elsa.Persistence.EFCore.Modules.Runtime;
 10using Elsa.Server.Web.Filters;
 11using Elsa.Tenants.AspNetCore;
 12using Elsa.Tenants.Extensions;
 13using Elsa.WorkflowProviders.BlobStorage.ElsaScript.Extensions;
 14using Elsa.Workflows;
 15using Elsa.Workflows.Api;
 16using Elsa.Workflows.CommitStates.Strategies;
 17using Elsa.Workflows.IncidentStrategies;
 18using Elsa.Workflows.LogPersistence;
 19using Elsa.Workflows.Options;
 20using Elsa.Workflows.Runtime.Distributed.Extensions;
 21using Elsa.Workflows.Runtime.Options;
 22using Elsa.Workflows.Runtime.Tasks;
 23using JetBrains.Annotations;
 24using Microsoft.Extensions.Options;
 25
 26// ReSharper disable RedundantAssignment
 27const bool useReadOnlyMode = false;
 28const bool useSignalR = false; // Disabled until Elsa Studio sends authenticated requests.
 29const bool useMultitenancy = false;
 30const bool disableVariableWrappers = false;
 31
 132ObjectConverter.StrictMode = true;
 33
 134var builder = WebApplication.CreateBuilder(args);
 135var services = builder.Services;
 136var configuration = builder.Configuration;
 137var identitySection = configuration.GetSection("Identity");
 138var identityTokenSection = identitySection.GetSection("Tokens");
 39
 40// Add Elsa services.
 141services
 142    .AddElsa(elsa =>
 143    {
 144        elsa
 145            .AddActivitiesFrom<Program>()
 146            .AddWorkflowsFrom<Program>()
 147            .UseIdentity(identity =>
 148            {
 149                identity.TokenOptions += options => identityTokenSection.Bind(options);
 150                identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options));
 151                identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options));
 152                identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options));
 153            })
 154            .UseDefaultAuthentication()
 155            .UseWorkflows(workflows =>
 156            {
 157                workflows.UseCommitStrategies(strategies =>
 158                {
 159                    strategies.AddStandardStrategies();
 160                    strategies.Add("Every 10 seconds", new PeriodicWorkflowStrategy(TimeSpan.FromSeconds(10)));
 261                });
 162            })
 163            .UseWorkflowManagement(management =>
 164            {
 265                management.UseEntityFrameworkCore(ef => ef.UseSqlite());
 166                management.SetDefaultLogPersistenceMode(LogPersistenceMode.Inherit);
 167                management.UseCache();
 168                management.UseReadOnlyMode(useReadOnlyMode);
 169            })
 170            .UseWorkflowRuntime(runtime =>
 171            {
 272                runtime.UseEntityFrameworkCore(ef => ef.UseSqlite());
 173                runtime.UseCache();
 174                runtime.UseDistributedRuntime();
 175            })
 176            .UseWorkflowsApi()
 177            .UseFluentStorageProvider()
 178            .UseElsaScriptBlobStorage()
 179            .UseScheduling()
 180            .UseCSharp(options =>
 181            {
 182                options.DisableWrappers = disableVariableWrappers;
 183                options.AppendScript("string Greet(string name) => $\"Hello {name}!\";");
 184                options.AppendScript("string SayHelloWorld() => Greet(\"World\");");
 185            })
 186            .UseJavaScript(options =>
 187            {
 188                options.AllowClrAccess = true;
 189                options.ConfigureEngine(engine =>
 190                {
 1791                    engine.Execute("function greet(name) { return `Hello ${name}!`; }");
 1792                    engine.Execute("function sayHelloWorld() { return greet('World'); }");
 1893                });
 194            })
 195            .UsePython(python =>
 196            {
 197                python.PythonOptions += options =>
 198                {
 199                    // Make sure to configure the path to the python DLL. E.g. /opt/homebrew/Cellar/python@3.11/3.11.6_1
 1100                    // alternatively, you can set the PYTHONNET_PYDLL environment variable.
 1101                    configuration.GetSection("Scripting:Python").Bind(options);
 1102
 1103                    options.AddScript(sb =>
 1104                    {
 1105                        sb.AppendLine("def greet():");
 1106                        sb.AppendLine("    return \"Hello, welcome to Python!\"");
 2107                    });
 2108                };
 1109            })
 2110            .UseLiquid(liquid => liquid.FluidOptions = options => options.Encoder = HtmlEncoder.Default)
 1111            .UseHttp(http =>
 1112            {
 2113                http.ConfigureHttpOptions = options => configuration.GetSection("Http").Bind(options);
 1114                http.UseCache();
 2115            });
 1116        ConfigureForTest?.Invoke(elsa);
 2117    });
 118
 119// Obfuscate HTTP request headers.
 1120services.AddActivityStateFilter<HttpRequestAuthenticationHeaderFilter>();
 121
 122// Optionally configure recurring tasks using alternative schedules.
 1123services.Configure<RecurringTaskOptions>(options =>
 1124{
 1125    options.Schedule.ConfigureTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(300));
 1126    options.Schedule.ConfigureTask<PurgeBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(300));
 1127    options.Schedule.ConfigureTask<RestartInterruptedWorkflowsTask>(TimeSpan.FromSeconds(15));
 2128});
 129
 3130services.Configure<RuntimeOptions>(options => { options.InactivityThreshold = TimeSpan.FromSeconds(15); });
 1131services.Configure<BookmarkQueuePurgeOptions>(options => options.Ttl = TimeSpan.FromSeconds(3600));
 2132services.Configure<CachingOptions>(options => options.CacheDuration = TimeSpan.FromDays(1));
 1133services.Configure<IncidentOptions>(options => options.DefaultIncidentStrategy = typeof(ContinueWithIncidentsStrategy));
 1134services.AddHealthChecks();
 1135services.AddControllers();
 3136services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().WithE
 137
 138// Build the web application.
 1139var app = builder.Build();
 140
 141
 142// Configure the pipeline.
 1143if (app.Environment.IsDevelopment())
 1144    app.UseDeveloperExceptionPage();
 145
 146// CORS.
 1147app.UseCors();
 148
 149// Health checks.
 1150app.MapHealthChecks("/");
 151
 152// Routing used for SignalR.
 1153app.UseRouting();
 154
 155// Security.
 1156app.UseAuthentication();
 1157app.UseAuthorization();
 158
 159// Multitenancy.
 160if (useMultitenancy)
 161    app.UseTenants();
 162
 163// Elsa API endpoints for designer.
 1164var routePrefix = app.Services.GetRequiredService<IOptions<ApiEndpointOptions>>().Value.RoutePrefix;
 1165app.UseWorkflowsApi(routePrefix);
 166
 167// Captures unhandled exceptions and returns a JSON response.
 1168app.UseJsonSerializationErrorHandler();
 169
 170// Elsa HTTP Endpoint activities.
 1171app.UseWorkflows();
 172
 1173app.MapControllers();
 174
 175// Swagger API documentation.
 1176if (app.Environment.IsDevelopment())
 177{
 1178    app.UseSwaggerUI();
 179}
 180
 181// SignalR.
 182if (useSignalR)
 183{
 184    app.UseWorkflowsSignalRHubs();
 185}
 186
 187// Run.
 1188await app.RunAsync();
 189
 190/// <summary>
 191/// The main entry point for the application made public for end to end testing.
 192/// </summary>
 193[UsedImplicitly]
 194public partial class Program
 195{
 196    /// <summary>
 197    /// Set by the test runner to configure the module for testing.
 198    /// </summary>
 3199    public static Action<IModule>? ConfigureForTest { get; set; }
 200}

Methods/Properties

<Main>$()
get_ConfigureForTest()