dcbd9bab41
PR Checks / test-and-build (pull_request) Successful in 11m4s
GmRelay.Shared references Dapper.AOT with PrivateAssets=all, which prevents the runtime DLL from flowing to downstream projects. Telegram bot works because it explicitly references Dapper.AOT directly, but Discord bot did not — causing FileNotFoundException for Dapper.AOT at runtime, breaking the scheduler and slash commands. - Add Dapper.AOT 1.0.48 to GmRelay.DiscordBot.csproj - Add regression test: DiscordWorkerProject_ShouldExist asserts Dapper.AOT is present in the DiscordBot csproj - Bump version → 3.0.9 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
125 lines
5.1 KiB
C#
125 lines
5.1 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace GmRelay.Bot.Tests.Discord;
|
|
|
|
public sealed class DiscordProjectStructureTests
|
|
{
|
|
private static string GetRepoRoot()
|
|
{
|
|
var dir = AppContext.BaseDirectory;
|
|
while (!string.IsNullOrEmpty(dir) && !File.Exists(Path.Combine(dir, "Directory.Build.props")))
|
|
{
|
|
dir = Directory.GetParent(dir)?.FullName;
|
|
}
|
|
|
|
return dir ?? throw new InvalidOperationException("Could not find repo root");
|
|
}
|
|
|
|
[Fact]
|
|
public void Solution_ShouldIncludeDiscordWorkerProject()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
var solution = File.ReadAllText(Path.Combine(repoRoot, "GM-Relay.slnx"));
|
|
|
|
Assert.Contains("src/GmRelay.DiscordBot/GmRelay.DiscordBot.csproj", solution);
|
|
}
|
|
|
|
[Fact]
|
|
public void DiscordWorkerProject_ShouldExistWithoutTelegramDependency()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
var projectPath = Path.Combine(repoRoot, "src", "GmRelay.DiscordBot", "GmRelay.DiscordBot.csproj");
|
|
|
|
Assert.True(File.Exists(projectPath), "Discord worker project should exist.");
|
|
|
|
var project = File.ReadAllText(projectPath);
|
|
Assert.Contains("Microsoft.NET.Sdk.Worker", project);
|
|
Assert.Contains("NetCord.Hosting", project);
|
|
Assert.Contains("GmRelay.ServiceDefaults.csproj", project);
|
|
Assert.Contains("GmRelay.Shared.csproj", project);
|
|
Assert.DoesNotContain("Telegram.Bot", project);
|
|
Assert.DoesNotContain("GmRelay.Bot.csproj", project);
|
|
Assert.Contains("Dapper.AOT", project);
|
|
}
|
|
|
|
[Fact]
|
|
public void TelegramWorkerProject_ShouldNotReferenceNetCord()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
var project = File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.Bot", "GmRelay.Bot.csproj"));
|
|
|
|
Assert.DoesNotContain("NetCord", project, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void RuntimeWiring_ShouldIncludeDiscordServiceWithoutCouplingTelegram()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
var compose = File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"));
|
|
var appHostProject = File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.AppHost", "GmRelay.AppHost.csproj"));
|
|
var appHostProgram = File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.AppHost", "Program.cs"));
|
|
var prChecks = File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "pr-checks.yml"));
|
|
var deploy = File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "deploy.yml"));
|
|
|
|
Assert.Contains("gmrelay-discord-bot:3.0.9", compose);
|
|
Assert.Contains("Discord__Token=${DISCORD_BOT_TOKEN:?Set DISCORD_BOT_TOKEN in .env}", compose);
|
|
Assert.Contains("src/GmRelay.DiscordBot/Dockerfile", deploy);
|
|
Assert.Contains("DISCORD_BOT_TOKEN", deploy);
|
|
Assert.Contains("dotnet build src/GmRelay.DiscordBot/GmRelay.DiscordBot.csproj --no-restore", prChecks);
|
|
Assert.Contains("GmRelay.DiscordBot.csproj", appHostProject);
|
|
Assert.Contains("Projects.GmRelay_DiscordBot", appHostProgram);
|
|
}
|
|
|
|
[Fact]
|
|
public void Version_ShouldBeSynchronizedForDiscordFeatureRelease()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
|
|
Assert.Contains("<Version>3.0.9</Version>", File.ReadAllText(Path.Combine(repoRoot, "Directory.Build.props")));
|
|
Assert.Contains("VERSION: 3.0.9", File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "deploy.yml")));
|
|
Assert.Contains("gmrelay-bot:3.0.9", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml")));
|
|
Assert.Contains("gmrelay-web:3.0.9", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml")));
|
|
Assert.Contains("gmrelay-discord-bot:3.0.9", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml")));
|
|
Assert.Contains(
|
|
"v3.0.9",
|
|
File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.Web", "Components", "Layout", "NavMenu.razor")));
|
|
}
|
|
|
|
[Fact]
|
|
public void EnvExample_ShouldContainDiscordBotToken()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
var envExample = File.ReadAllText(Path.Combine(repoRoot, ".env.example"));
|
|
|
|
Assert.Contains("DISCORD_BOT_TOKEN", envExample);
|
|
}
|
|
|
|
[Fact]
|
|
public void Readme_ShouldNotAskForUnusedDiscordBotClientId()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
var readme = File.ReadAllText(Path.Combine(repoRoot, "README.md"));
|
|
|
|
Assert.DoesNotContain("DISCORD_BOT_CLIENT_ID", readme);
|
|
Assert.Contains("DISCORD_CLIENT_ID", readme);
|
|
}
|
|
|
|
[Fact]
|
|
public void Compose_ShouldIncludeDiscordHealthcheck()
|
|
{
|
|
var repoRoot = GetRepoRoot();
|
|
var compose = File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"));
|
|
|
|
var discordIndex = compose.IndexOf("discord:", StringComparison.Ordinal);
|
|
Assert.True(discordIndex >= 0, "compose.yaml should contain discord service");
|
|
|
|
var nextServiceIndex = compose.IndexOf(" web:", StringComparison.Ordinal);
|
|
var discordBlock = compose[discordIndex..nextServiceIndex];
|
|
|
|
Assert.Contains("healthcheck:", discordBlock);
|
|
Assert.Contains("test:", discordBlock);
|
|
Assert.Contains("localhost:8082/health", discordBlock);
|
|
}
|
|
}
|