- Fix problem load assemblies in test cli

- Add Test pipeline to ci-cd
This commit is contained in:
meysamhadeli 2023-01-09 00:23:36 +03:30
parent 6a410a7b05
commit 97ab953975
8 changed files with 102 additions and 37 deletions

View File

@ -21,4 +21,6 @@ jobs:
run: dotnet restore
- name: Build
run: dotnet build -c Release --no-restore
- name: Test
run: dotnet test -c Release --no-restore

View File

@ -18,8 +18,8 @@ public static class Extensions
bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER"), out var inContainer) &&
inContainer;
public static IServiceCollection AddCustomMassTransit(this IServiceCollection services, Assembly assembly,
IWebHostEnvironment env)
public static IServiceCollection AddCustomMassTransit(this IServiceCollection services,
IWebHostEnvironment env, Assembly assembly)
{
services.AddOptions<RabbitMqOptions>()
.BindConfiguration(nameof(RabbitMqOptions))
@ -29,22 +29,22 @@ public static class Extensions
{
services.AddMassTransitTestHarness(configure =>
{
SetupMasstransitConfigurations(services, assembly, configure);
SetupMasstransitConfigurations(services, configure, assembly);
});
}
else
{
services.AddMassTransit(configure =>
{
SetupMasstransitConfigurations(services, assembly, configure);
SetupMasstransitConfigurations(services, configure, assembly);
});
}
return services;
}
private static void SetupMasstransitConfigurations(IServiceCollection services, Assembly assembly,
IBusRegistrationConfigurator configure)
private static void SetupMasstransitConfigurations(IServiceCollection services,
IBusRegistrationConfigurator configure, Assembly assembly)
{
configure.AddConsumers(assembly);
@ -60,38 +60,44 @@ public static class Extensions
h.Password(rabbitMqOptions?.Password);
});
var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
var integrationEventRootAssemblies = Assembly.GetAssembly(typeof(IIntegrationEvent));
var types = integrationEventRootAssemblies?.GetTypes()
.Where(x => x.IsAssignableTo(typeof(IIntegrationEvent))
&& !x.IsInterface
&& !x.IsAbstract
&& !x.IsGenericType);
&& !x.IsGenericType)?.ToList();
foreach (var type in types)
if (types != null && types.Any())
{
var consumers = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
.Where(x => x.IsAssignableTo(typeof(IConsumer<>).MakeGenericType(type))).ToList();
foreach (var type in types)
{
var consumers = assembly?.GetTypes()
.Where(x => x.IsAssignableTo(typeof(IConsumer<>).MakeGenericType(type))).ToList();
if (consumers.Any())
configurator.ReceiveEndpoint(
string.IsNullOrEmpty(rabbitMqOptions.ExchangeName)
? type.Name.Underscore()
: $"{rabbitMqOptions.ExchangeName}_{type.Name.Underscore()}", e =>
{
e.UseConsumeFilter(typeof(ConsumeFilter<>), context); //generic filter
foreach (var consumer in consumers)
if (consumers != null && consumers.Any())
configurator.ReceiveEndpoint(
string.IsNullOrEmpty(rabbitMqOptions.ExchangeName)
? type.Name.Underscore()
: $"{rabbitMqOptions.ExchangeName}_{type.Name.Underscore()}", e =>
{
configurator.ConfigureEndpoints(context, x => x.Exclude(consumer));
var methodInfo = typeof(DependencyInjectionReceiveEndpointExtensions)
.GetMethods()
.Where(x => x.GetParameters()
.Any(p => p.ParameterType == typeof(IServiceProvider)))
.FirstOrDefault(x => x.Name == "Consumer" && x.IsGenericMethod);
e.UseConsumeFilter(typeof(ConsumeFilter<>), context); //generic filter
var generic = methodInfo?.MakeGenericMethod(consumer);
generic?.Invoke(e, new object[] {e, context, null});
}
});
foreach (var consumer in consumers)
{
configurator.ConfigureEndpoints(context, x => x.Exclude(consumer));
var methodInfo = typeof(DependencyInjectionReceiveEndpointExtensions)
.GetMethods()
.Where(x => x.GetParameters()
.Any(p => p.ParameterType == typeof(IServiceProvider)))
.FirstOrDefault(x => x.Name == "Consumer" && x.IsGenericMethod);
var generic = methodInfo?.MakeGenericMethod(consumer);
generic?.Invoke(e, new object[] { e, context, null });
}
});
}
}
});
}

View File

@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
namespace BuildingBlocks.Utils;
@ -36,4 +37,49 @@ public static class TypeProvider
return result;
}
public static IReadOnlyList<Assembly> GetReferencedAssemblies(Assembly? rootAssembly)
{
var visited = new HashSet<string>();
var queue = new Queue<Assembly?>();
var listResult = new List<Assembly>();
var root = rootAssembly ?? Assembly.GetEntryAssembly();
queue.Enqueue(root);
do
{
var asm = queue.Dequeue();
if (asm == null)
break;
listResult.Add(asm);
foreach (var reference in asm.GetReferencedAssemblies())
{
if (!visited.Contains(reference.FullName))
{
// Load will add assembly into the application domain of the caller. loading assemblies explicitly to AppDomain, because assemblies are loaded lazily
// https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.load
queue.Enqueue(Assembly.Load(reference));
visited.Add(reference.FullName);
}
}
} while (queue.Count > 0);
return listResult.Distinct().ToList().AsReadOnly();
}
public static IReadOnlyList<Assembly> GetApplicationPartAssemblies(Assembly rootAssembly)
{
var rootNamespace = rootAssembly.GetName().Name!.Split('.').First();
var list = rootAssembly!.GetCustomAttributes<ApplicationPartAttribute>()
.Where(x => x.AssemblyName.StartsWith(rootNamespace, StringComparison.InvariantCulture))
.Select(name => Assembly.Load(name.AssemblyName))
.Distinct();
return list.ToList().AsReadOnly();
}
}

View File

@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Builder;
using System.Reflection;
using BuildingBlocks.Utils;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Scrutor;
@ -10,10 +12,19 @@ public static class MinimalApiExtensions
public static IServiceCollection AddMinimalEndpoints(
this WebApplicationBuilder applicationBuilder,
ServiceLifetime lifetime = ServiceLifetime.Scoped)
ServiceLifetime lifetime = ServiceLifetime.Scoped,
params Assembly[] assemblies)
{
var scanAssemblies = assemblies.Any()
? assemblies
: TypeProvider.GetReferencedAssemblies(Assembly.GetCallingAssembly())
.Concat(TypeProvider.GetApplicationPartAssemblies(Assembly.GetCallingAssembly()))
.Distinct()
.ToArray();
applicationBuilder.Services.Scan(scan => scan
.FromAssemblies(AppDomain.CurrentDomain.GetAssemblies())
.FromAssemblies(scanAssemblies)
.AddClasses(classes => classes.AssignableTo(typeof(IMinimalEndpoint)))
.UsingRegistrationStrategy(RegistrationStrategy.Append)
.As<IMinimalEndpoint>()

View File

@ -72,7 +72,7 @@ public static class InfrastructureExtensions
builder.Services.AddCustomProblemDetails();
builder.Services.AddCustomMapster(typeof(BookingRoot).Assembly);
builder.Services.AddCustomHealthCheck();
builder.Services.AddCustomMassTransit(typeof(BookingRoot).Assembly, env);
builder.Services.AddCustomMassTransit(env, typeof(BookingRoot).Assembly);
builder.Services.AddCustomOpenTelemetry();
builder.Services.AddTransient<AuthHeaderHandler>();

View File

@ -78,7 +78,7 @@ public static class InfrastructureExtensions
builder.Services.AddValidatorsFromAssembly(typeof(FlightRoot).Assembly);
builder.Services.AddCustomMapster(typeof(FlightRoot).Assembly);
builder.Services.AddHttpContextAccessor();
builder.Services.AddCustomMassTransit(typeof(FlightRoot).Assembly, env);
builder.Services.AddCustomMassTransit(env, typeof(FlightRoot).Assembly);
builder.Services.AddCustomOpenTelemetry();
builder.Services.AddCustomHealthCheck();

View File

@ -68,7 +68,7 @@ public static class InfrastructureExtensions
builder.Services.AddCustomMapster(typeof(IdentityRoot).Assembly);
builder.Services.AddCustomHealthCheck();
builder.Services.AddCustomMassTransit(typeof(IdentityRoot).Assembly, env);
builder.Services.AddCustomMassTransit(env, typeof(IdentityRoot).Assembly);
builder.Services.AddCustomOpenTelemetry();
SnowFlakIdGenerator.Configure(4);

View File

@ -73,7 +73,7 @@ public static class InfrastructureExtensions
builder.Services.AddCustomMapster(typeof(PassengerRoot).Assembly);
builder.Services.AddHttpContextAccessor();
builder.Services.AddCustomHealthCheck();
builder.Services.AddCustomMassTransit(typeof(PassengerRoot).Assembly, env);
builder.Services.AddCustomMassTransit(env, typeof(PassengerRoot).Assembly);
builder.Services.AddCustomOpenTelemetry();
builder.Services.AddGrpc(options =>
{