Fix issues with Gitea using workers
This commit is contained in:
@@ -86,18 +86,25 @@ jobs:
|
|||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
env:
|
env:
|
||||||
# Defaults match docker-compose.yml published ports; fixtures fall back to these anyway.
|
# act_runner runs in its own container; Compose publishes ports on the VM.
|
||||||
|
# host.docker.internal reaches those published ports (requires extra_hosts
|
||||||
|
# host-gateway on the runner). RabbitMQ guest remote access is enabled in
|
||||||
|
# infra/rabbitmq/rabbitmq.conf for this topology.
|
||||||
ConnectionStrings__DefaultConnection: "Host=host.docker.internal;Port=5436;Database=vigilcare_test;Username=postgres;Password=password"
|
ConnectionStrings__DefaultConnection: "Host=host.docker.internal;Port=5436;Database=vigilcare_test;Username=postgres;Password=password"
|
||||||
ConnectionStrings__GatewayDb: "Host=host.docker.internal;Port=5437;Database=vigilcare_ward_test;Username=postgres;Password=password"
|
ConnectionStrings__GatewayDb: "Host=host.docker.internal;Port=5437;Database=vigilcare_ward_test;Username=postgres;Password=password"
|
||||||
Redis__ConnectionString: "host.docker.internal:6382,defaultDatabase=1,allowAdmin=true"
|
Redis__ConnectionString: "host.docker.internal:6382,defaultDatabase=1,allowAdmin=true"
|
||||||
Gateway__Redis__ConnectionString: "host.docker.internal:6383,defaultDatabase=2,allowAdmin=true"
|
Gateway__Redis__ConnectionString: "host.docker.internal:6383,defaultDatabase=2,allowAdmin=true"
|
||||||
RabbitMq__Host: "host.docker.internal"
|
RabbitMq__Host: "host.docker.internal"
|
||||||
RabbitMq__Port: "5674"
|
RabbitMq__Port: "5674"
|
||||||
|
Gateway__RabbitMq__Host: "host.docker.internal"
|
||||||
Gateway__RabbitMq__Port: "5675"
|
Gateway__RabbitMq__Port: "5675"
|
||||||
Kafka__BootstrapServers: "host.docker.internal:9092"
|
Kafka__BootstrapServers: "host.docker.internal:9092"
|
||||||
Kafka__ReplicationFactor: "1"
|
Kafka__ReplicationFactor: "1"
|
||||||
|
Kafka__SecurityProtocol: "Plaintext"
|
||||||
Elasticsearch__Uri: "http://host.docker.internal:9200"
|
Elasticsearch__Uri: "http://host.docker.internal:9200"
|
||||||
Minio__Endpoint: "host.docker.internal:9005"
|
Minio__Endpoint: "host.docker.internal:9005"
|
||||||
|
Minio__UseSSL: "false"
|
||||||
|
ASPNETCORE_ENVIRONMENT: "Testing"
|
||||||
run: |
|
run: |
|
||||||
dotnet test VigilCareClinical.sln -c Release --no-build \
|
dotnet test VigilCareClinical.sln -c Release --no-build \
|
||||||
--logger "trx;LogFileName=test-results.trx" \
|
--logger "trx;LogFileName=test-results.trx" \
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc.Testing;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
public class GatewayApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
public class GatewayApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
||||||
@@ -13,9 +14,9 @@ public class GatewayApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
|||||||
Environment.GetEnvironmentVariable("ConnectionStrings__GatewayDb")
|
Environment.GetEnvironmentVariable("ConnectionStrings__GatewayDb")
|
||||||
?? "Host=localhost;Port=5437;Database=vigilcare_ward_test;Username=postgres;Password=password";
|
?? "Host=localhost;Port=5437;Database=vigilcare_ward_test;Username=postgres;Password=password";
|
||||||
|
|
||||||
|
// Never fall back to the API Redis__* env — that points at a different instance/DB index.
|
||||||
public static string RedisConnection { get; } =
|
public static string RedisConnection { get; } =
|
||||||
Environment.GetEnvironmentVariable("Gateway__Redis__ConnectionString")
|
Environment.GetEnvironmentVariable("Gateway__Redis__ConnectionString")
|
||||||
?? Environment.GetEnvironmentVariable("Redis__ConnectionString")
|
|
||||||
?? "localhost:6383,defaultDatabase=2,allowAdmin=true";
|
?? "localhost:6383,defaultDatabase=2,allowAdmin=true";
|
||||||
|
|
||||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||||
@@ -30,12 +31,14 @@ public class GatewayApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
|||||||
["RabbitMq:Host"] = Environment.GetEnvironmentVariable("Gateway__RabbitMq__Host")
|
["RabbitMq:Host"] = Environment.GetEnvironmentVariable("Gateway__RabbitMq__Host")
|
||||||
?? Environment.GetEnvironmentVariable("RabbitMq__Host")
|
?? Environment.GetEnvironmentVariable("RabbitMq__Host")
|
||||||
?? "localhost",
|
?? "localhost",
|
||||||
|
// Do not fall back to RabbitMq__Port (API uses 5674); gateway broker is 5675.
|
||||||
["RabbitMq:Port"] = Environment.GetEnvironmentVariable("Gateway__RabbitMq__Port")
|
["RabbitMq:Port"] = Environment.GetEnvironmentVariable("Gateway__RabbitMq__Port")
|
||||||
?? Environment.GetEnvironmentVariable("RabbitMq__Port")
|
|
||||||
?? "5675",
|
?? "5675",
|
||||||
["RabbitMq:Username"] = Environment.GetEnvironmentVariable("RabbitMq__Username") ?? "guest",
|
["RabbitMq:Username"] = Environment.GetEnvironmentVariable("RabbitMq__Username") ?? "guest",
|
||||||
["RabbitMq:Password"] = Environment.GetEnvironmentVariable("RabbitMq__Password") ?? "guest",
|
["RabbitMq:Password"] = Environment.GetEnvironmentVariable("RabbitMq__Password") ?? "guest",
|
||||||
["RabbitMq:PagingAckTimeoutMs"] = "5000",
|
["RabbitMq:PagingAckTimeoutMs"] = "5000",
|
||||||
|
// Neutralize appsettings.Production.json if the process env was Production.
|
||||||
|
["RabbitMq:UseSsl"] = "false",
|
||||||
["CentralApi:BaseUrl"] = "http://127.0.0.1:1",
|
["CentralApi:BaseUrl"] = "http://127.0.0.1:1",
|
||||||
["Gateway:GatewayId"] = "22222222-2222-2222-2222-222222222222",
|
["Gateway:GatewayId"] = "22222222-2222-2222-2222-222222222222",
|
||||||
["Gateway:SiteId"] = "11111111-1111-1111-1111-111111111111",
|
["Gateway:SiteId"] = "11111111-1111-1111-1111-111111111111",
|
||||||
@@ -54,6 +57,9 @@ public class GatewayApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
|||||||
|
|
||||||
builder.ConfigureServices(services =>
|
builder.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
services.Configure<HostOptions>(o =>
|
||||||
|
o.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore);
|
||||||
|
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.DefaultAuthenticateScheme = TestingAuthHandler.SchemeName;
|
options.DefaultAuthenticateScheme = TestingAuthHandler.SchemeName;
|
||||||
|
|||||||
@@ -24,6 +24,28 @@ public sealed class LocalEscalationWorkerService : BackgroundService
|
|||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||||
|
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await RunConsumerAsync(stoppingToken);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex,
|
||||||
|
"LocalEscalationWorkerService disconnected — retrying in 5s");
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RunConsumerAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
var o = _opts.Value;
|
var o = _opts.Value;
|
||||||
var factory = RabbitMqConnectionFactory.Create(o, dispatchConsumersAsync: true);
|
var factory = RabbitMqConnectionFactory.Create(o, dispatchConsumersAsync: true);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,28 @@ public sealed class LocalPagingWorkerService : BackgroundService
|
|||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||||
|
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await RunConsumerAsync(stoppingToken);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex,
|
||||||
|
"LocalPagingWorkerService disconnected — retrying in 5s");
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RunConsumerAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
var o = _opts.Value;
|
var o = _opts.Value;
|
||||||
var factory = RabbitMqConnectionFactory.Create(o, dispatchConsumersAsync: true);
|
var factory = RabbitMqConnectionFactory.Create(o, dispatchConsumersAsync: true);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc.Testing;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
public class ApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
public class ApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
||||||
@@ -40,16 +41,22 @@ public class ApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
|||||||
["RabbitMq:Password"] = Environment.GetEnvironmentVariable("RabbitMq__Password") ?? "guest",
|
["RabbitMq:Password"] = Environment.GetEnvironmentVariable("RabbitMq__Password") ?? "guest",
|
||||||
["RabbitMq:PagingAckTimeoutMs"] = "5000",
|
["RabbitMq:PagingAckTimeoutMs"] = "5000",
|
||||||
["RabbitMq:VirtualHost"] = "vigilcare_test",
|
["RabbitMq:VirtualHost"] = "vigilcare_test",
|
||||||
|
// Neutralize appsettings.Production.json if the process env was Production.
|
||||||
|
["RabbitMq:UseSsl"] = "false",
|
||||||
["Kafka:BootstrapServers"] =
|
["Kafka:BootstrapServers"] =
|
||||||
Environment.GetEnvironmentVariable("Kafka__BootstrapServers") ?? "localhost:9092",
|
Environment.GetEnvironmentVariable("Kafka__BootstrapServers") ?? "localhost:9092",
|
||||||
["Kafka:ReplicationFactor"] =
|
["Kafka:ReplicationFactor"] =
|
||||||
Environment.GetEnvironmentVariable("Kafka__ReplicationFactor") ?? "1",
|
Environment.GetEnvironmentVariable("Kafka__ReplicationFactor") ?? "1",
|
||||||
|
["Kafka:SecurityProtocol"] =
|
||||||
|
Environment.GetEnvironmentVariable("Kafka__SecurityProtocol") ?? "Plaintext",
|
||||||
["Kafka:NotificationPublisherGroupId"] = "notification-publisher-integration-test",
|
["Kafka:NotificationPublisherGroupId"] = "notification-publisher-integration-test",
|
||||||
["Kafka:NotificationPublisherAutoOffsetReset"] = "Latest",
|
["Kafka:NotificationPublisherAutoOffsetReset"] = "Latest",
|
||||||
["Elasticsearch:Uri"] =
|
["Elasticsearch:Uri"] =
|
||||||
Environment.GetEnvironmentVariable("Elasticsearch__Uri") ?? "http://localhost:9200",
|
Environment.GetEnvironmentVariable("Elasticsearch__Uri") ?? "http://localhost:9200",
|
||||||
["Minio:Endpoint"] =
|
["Minio:Endpoint"] =
|
||||||
Environment.GetEnvironmentVariable("Minio__Endpoint") ?? "localhost:9005",
|
Environment.GetEnvironmentVariable("Minio__Endpoint") ?? "localhost:9005",
|
||||||
|
["Minio:UseSSL"] =
|
||||||
|
Environment.GetEnvironmentVariable("Minio__UseSSL") ?? "false",
|
||||||
["Fhir:ApiKey"] = "dev-integration-key-change-in-production",
|
["Fhir:ApiKey"] = "dev-integration-key-change-in-production",
|
||||||
["ApiKey:Gateway"] = GatewayAuthHelper.DevGatewayKey,
|
["ApiKey:Gateway"] = GatewayAuthHelper.DevGatewayKey,
|
||||||
});
|
});
|
||||||
@@ -59,6 +66,9 @@ public class ApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
|
|||||||
|
|
||||||
builder.ConfigureServices(services =>
|
builder.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
services.Configure<HostOptions>(o =>
|
||||||
|
o.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore);
|
||||||
|
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.DefaultAuthenticateScheme = TestingAuthHandler.SchemeName;
|
options.DefaultAuthenticateScheme = TestingAuthHandler.SchemeName;
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
RABBITMQ_DEFAULT_USER: guest
|
RABBITMQ_DEFAULT_USER: guest
|
||||||
RABBITMQ_DEFAULT_PASS: guest
|
RABBITMQ_DEFAULT_PASS: guest
|
||||||
|
volumes:
|
||||||
|
# Allow guest from host.docker.internal / CI runner (dev only).
|
||||||
|
- ./infra/rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "rabbitmq-diagnostics", "ping"]
|
test: ["CMD", "rabbitmq-diagnostics", "ping"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
@@ -181,6 +184,8 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
RABBITMQ_DEFAULT_USER: guest
|
RABBITMQ_DEFAULT_USER: guest
|
||||||
RABBITMQ_DEFAULT_PASS: guest
|
RABBITMQ_DEFAULT_PASS: guest
|
||||||
|
volumes:
|
||||||
|
- ./infra/rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "rabbitmq-diagnostics", "ping"]
|
test: ["CMD", "rabbitmq-diagnostics", "ping"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
## Dev/CI only — allow the default guest user from non-loopback clients.
|
||||||
|
## Needed when tests run inside act_runner and reach brokers via host.docker.internal.
|
||||||
|
## Do not use this setting on production brokers.
|
||||||
|
loopback_users.guest = false
|
||||||
Reference in New Issue
Block a user