Compare commits
2 Commits
2241568bac
...
5014ca5c58
| Author | SHA1 | Date | |
|---|---|---|---|
| 5014ca5c58 | |||
| efd86bca0a |
@@ -6,7 +6,7 @@ on:
|
||||
- main
|
||||
|
||||
env:
|
||||
VERSION: 3.9.7
|
||||
VERSION: 3.9.8
|
||||
|
||||
jobs:
|
||||
# ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>3.9.7</Version>
|
||||
<Version>3.9.8</Version>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
+3
-3
@@ -49,7 +49,7 @@ services:
|
||||
crond -f
|
||||
|
||||
bot:
|
||||
image: git.codeanddice.ru/toutsu/gmrelay-bot:3.9.7
|
||||
image: git.codeanddice.ru/toutsu/gmrelay-bot:3.9.8
|
||||
restart: always
|
||||
depends_on:
|
||||
db:
|
||||
@@ -67,7 +67,7 @@ services:
|
||||
retries: 3
|
||||
|
||||
discord:
|
||||
image: git.codeanddice.ru/toutsu/gmrelay-discord-bot:3.9.7
|
||||
image: git.codeanddice.ru/toutsu/gmrelay-discord-bot:3.9.8
|
||||
restart: always
|
||||
depends_on:
|
||||
db:
|
||||
@@ -86,7 +86,7 @@ services:
|
||||
retries: 3
|
||||
|
||||
web:
|
||||
image: git.codeanddice.ru/toutsu/gmrelay-web:3.9.7
|
||||
image: git.codeanddice.ru/toutsu/gmrelay-web:3.9.8
|
||||
restart: always
|
||||
depends_on:
|
||||
db:
|
||||
|
||||
@@ -82,7 +82,13 @@ public sealed class CreateSessionHandler(
|
||||
AND p.external_user_id = @ExternalGmId
|
||||
ON CONFLICT (group_id, player_id) DO NOTHING
|
||||
""",
|
||||
new { GroupId = groupId, ExternalGmId = externalUserId, OwnerRole = GroupManagerRoleExtensions.OwnerValue },
|
||||
new
|
||||
{
|
||||
GroupId = groupId,
|
||||
Platform = platform,
|
||||
ExternalGmId = externalUserId,
|
||||
OwnerRole = GroupManagerRoleExtensions.OwnerValue
|
||||
},
|
||||
transaction);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="nav-version">v3.9.7</div>
|
||||
<div class="nav-version">v3.9.8</div>
|
||||
</div>
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
using GmRelay.Shared.Domain;
|
||||
using GmRelay.Shared.Features.Sessions.CreateSession;
|
||||
using GmRelay.Shared.Platform;
|
||||
using Npgsql;
|
||||
using Testcontainers.PostgreSql;
|
||||
|
||||
namespace GmRelay.Bot.Tests.Features.Sessions.CreateSession;
|
||||
|
||||
[CollectionDefinition(Name)]
|
||||
public sealed class CreateSessionHandlerPostgresCollection : ICollectionFixture<CreateSessionHandlerPostgresFixture>
|
||||
{
|
||||
public const string Name = "Create session handler PostgreSQL";
|
||||
}
|
||||
|
||||
public sealed class CreateSessionHandlerPostgresFixture : IAsyncLifetime
|
||||
{
|
||||
private static readonly TimeSpan ContainerTimeout = TimeSpan.FromMinutes(2);
|
||||
private readonly PostgreSqlContainer container = new PostgreSqlBuilder("postgres:17-alpine").Build();
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
return container.StartAsync().WaitAsync(ContainerTimeout);
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
return container.DisposeAsync().AsTask().WaitAsync(ContainerTimeout);
|
||||
}
|
||||
|
||||
public async Task<string> CreateMigratedDatabaseAsync()
|
||||
{
|
||||
var databaseName = $"create_session_{Guid.NewGuid():N}";
|
||||
|
||||
await using (var adminConnection = new NpgsqlConnection(container.GetConnectionString()))
|
||||
{
|
||||
await adminConnection.OpenAsync().WaitAsync(ContainerTimeout);
|
||||
await using var createDatabase = new NpgsqlCommand($"CREATE DATABASE \"{databaseName}\"", adminConnection);
|
||||
await createDatabase.ExecuteNonQueryAsync().WaitAsync(ContainerTimeout);
|
||||
}
|
||||
|
||||
var connectionString = new NpgsqlConnectionStringBuilder(container.GetConnectionString())
|
||||
{
|
||||
Database = databaseName,
|
||||
Timeout = 10,
|
||||
CommandTimeout = 30
|
||||
}.ConnectionString;
|
||||
|
||||
await using var connection = new NpgsqlConnection(connectionString);
|
||||
await connection.OpenAsync().WaitAsync(ContainerTimeout);
|
||||
|
||||
foreach (var migration in GetMigrationPaths())
|
||||
{
|
||||
await using var command = new NpgsqlCommand(await File.ReadAllTextAsync(migration), connection)
|
||||
{
|
||||
CommandTimeout = 30
|
||||
};
|
||||
await command.ExecuteNonQueryAsync().WaitAsync(ContainerTimeout);
|
||||
}
|
||||
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<string> GetMigrationPaths()
|
||||
{
|
||||
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (directory is not null)
|
||||
{
|
||||
var migrationsDirectory = Path.Combine(directory.FullName, "src", "GmRelay.Bot", "Migrations");
|
||||
if (Directory.Exists(migrationsDirectory))
|
||||
{
|
||||
return Directory.GetFiles(migrationsDirectory, "V*.sql")
|
||||
.OrderBy(path => Path.GetFileName(path), StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
directory = directory.Parent;
|
||||
}
|
||||
|
||||
throw new DirectoryNotFoundException("Could not locate the bot migrations directory.");
|
||||
}
|
||||
}
|
||||
|
||||
[Collection(CreateSessionHandlerPostgresCollection.Name)]
|
||||
public sealed class CreateSessionHandlerIntegrationTests(CreateSessionHandlerPostgresFixture fixture)
|
||||
{
|
||||
[Fact]
|
||||
public async Task HandleAsync_NewPlatformGroup_AddsOwnerAndPersistsSession()
|
||||
{
|
||||
var connectionString = await fixture.CreateMigratedDatabaseAsync();
|
||||
await using var dataSource = NpgsqlDataSource.Create(connectionString);
|
||||
var sut = new CreateSessionHandler(dataSource);
|
||||
|
||||
var result = await sut.HandleAsync(
|
||||
new CreateSessionCommand(
|
||||
new PlatformUser(PlatformKind.Telegram, "111111111", "Test GM", "test_gm"),
|
||||
new PlatformGroup(PlatformKind.Telegram, "222222222", "Test Group"),
|
||||
"Test Adventure",
|
||||
string.Empty,
|
||||
[DateTimeOffset.UtcNow.AddDays(1)],
|
||||
null,
|
||||
null,
|
||||
GameSystem.Dnd5e,
|
||||
"Integration regression test",
|
||||
"Online",
|
||||
240,
|
||||
true),
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.True(result.Success, result.ErrorMessage);
|
||||
Assert.NotNull(result.BatchId);
|
||||
Assert.NotNull(result.GroupId);
|
||||
|
||||
await using var connection = await dataSource.OpenConnectionAsync();
|
||||
await using var command = new NpgsqlCommand(
|
||||
"""
|
||||
SELECT count(*)
|
||||
FROM group_managers gm
|
||||
JOIN players p ON p.id = gm.player_id
|
||||
WHERE gm.group_id = @group_id
|
||||
AND gm.role = 'Owner'
|
||||
AND p.platform = 'Telegram'
|
||||
AND p.external_user_id = '111111111'
|
||||
""",
|
||||
connection);
|
||||
command.Parameters.AddWithValue("group_id", result.GroupId.Value);
|
||||
|
||||
var ownerCount = (long)(await command.ExecuteScalarAsync() ?? 0L);
|
||||
Assert.Equal(1, ownerCount);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user