fix(db): register legacy task migrations
CI - Build & Test / Backend (.NET) (push) Successful in 50s
CI - Build & Test / Backend integration (PostgreSQL/Toxiproxy) (push) Failing after 58s
CI - Build & Test / Frontend (Vue/TS) (push) Has been cancelled
CI - Build & Test / Security Check (push) Has been cancelled
CI - Build & Test / Deploy Nexus (push) Has been cancelled
CI - Build & Test / Backend (.NET) (push) Successful in 50s
CI - Build & Test / Backend integration (PostgreSQL/Toxiproxy) (push) Failing after 58s
CI - Build & Test / Frontend (Vue/TS) (push) Has been cancelled
CI - Build & Test / Security Check (push) Has been cancelled
CI - Build & Test / Deploy Nexus (push) Has been cancelled
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Nexus.Api.Data;
|
||||||
using Nexus.Api.Migrations;
|
using Nexus.Api.Migrations;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@@ -5,6 +9,21 @@ namespace Nexus.Api.Tests;
|
|||||||
|
|
||||||
public sealed class MigrationSnapshotTests
|
public sealed class MigrationSnapshotTests
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Historical_task_migrations_are_discoverable()
|
||||||
|
{
|
||||||
|
var options = new DbContextOptionsBuilder<NexusDbContext>()
|
||||||
|
.UseNpgsql(
|
||||||
|
"Host=127.0.0.1;Database=nexus_migration_contract;Username=nexus;Password=unused")
|
||||||
|
.Options;
|
||||||
|
using var db = new NexusDbContext(options);
|
||||||
|
var migrations = db.GetService<IMigrationsAssembly>().Migrations.Keys;
|
||||||
|
|
||||||
|
Assert.Contains("20260618233000_AddTaskParentChild", migrations);
|
||||||
|
Assert.Contains("20260618233001_AddTaskDueDate", migrations);
|
||||||
|
Assert.Contains("20260618233002_AddActivityTaskReference", migrations);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Snapshot_builds_agent_provisioning_relationships()
|
public void Snapshot_builds_agent_provisioning_relationships()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -140,7 +140,14 @@ public sealed class ToxiproxyAgentProvisioningIntegrationTests
|
|||||||
|
|
||||||
var reconciled = await service.GetByIdAsync(created.Proposal.Id);
|
var reconciled = await service.GetByIdAsync(created.Proposal.Id);
|
||||||
Assert.NotNull(reconciled);
|
Assert.NotNull(reconciled);
|
||||||
Assert.Equal(AgentProposalStates.Ready, reconciled!.Status);
|
Assert.True(
|
||||||
|
string.Equals(
|
||||||
|
AgentProposalStates.Ready,
|
||||||
|
reconciled!.Status,
|
||||||
|
StringComparison.Ordinal),
|
||||||
|
$"Expected ready after read-only reconciliation, got "
|
||||||
|
+ $"'{reconciled.Status}' ({reconciled.Error?.Code}: "
|
||||||
|
+ $"{reconciled.Error?.Message}).");
|
||||||
Assert.Equal("release-analyst", reconciled.OpenClawAgentId);
|
Assert.Equal("release-analyst", reconciled.OpenClawAgentId);
|
||||||
Assert.Equal(1, gateway.CreateCalls);
|
Assert.Equal(1, gateway.CreateCalls);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,59 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Nexus.Api.Data;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Nexus.Api.Migrations
|
namespace Nexus.Api.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
[DbContext(typeof(NexusDbContext))]
|
||||||
|
[Migration("20260618233000_AddTaskParentChild")]
|
||||||
public partial class AddTaskParentChild : Migration
|
public partial class AddTaskParentChild : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.AddColumn<Guid>(
|
// This historical migration originally lacked EF discovery
|
||||||
name: "ParentTaskId",
|
// metadata. Keep the catch-up operations idempotent so existing
|
||||||
table: "Tasks",
|
// installations and fresh PostgreSQL databases converge safely.
|
||||||
type: "uuid",
|
migrationBuilder.Sql(
|
||||||
nullable: true);
|
"""
|
||||||
|
ALTER TABLE "Tasks"
|
||||||
|
ADD COLUMN IF NOT EXISTS "ParentTaskId" uuid;
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
CREATE INDEX IF NOT EXISTS "IX_Tasks_ParentTaskId"
|
||||||
name: "IX_Tasks_ParentTaskId",
|
ON "Tasks" ("ParentTaskId");
|
||||||
table: "Tasks",
|
|
||||||
column: "ParentTaskId");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
DO $$
|
||||||
name: "FK_Tasks_Tasks_ParentTaskId",
|
BEGIN
|
||||||
table: "Tasks",
|
IF NOT EXISTS (
|
||||||
column: "ParentTaskId",
|
SELECT 1
|
||||||
principalTable: "Tasks",
|
FROM pg_constraint
|
||||||
principalColumn: "Id",
|
WHERE conname = 'FK_Tasks_Tasks_ParentTaskId'
|
||||||
onDelete: ReferentialAction.SetNull);
|
AND conrelid = '"Tasks"'::regclass
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE "Tasks"
|
||||||
|
ADD CONSTRAINT "FK_Tasks_Tasks_ParentTaskId"
|
||||||
|
FOREIGN KEY ("ParentTaskId")
|
||||||
|
REFERENCES "Tasks" ("Id")
|
||||||
|
ON DELETE SET NULL;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.DropForeignKey(
|
migrationBuilder.Sql(
|
||||||
name: "FK_Tasks_Tasks_ParentTaskId",
|
"""
|
||||||
table: "Tasks");
|
ALTER TABLE "Tasks"
|
||||||
|
DROP CONSTRAINT IF EXISTS "FK_Tasks_Tasks_ParentTaskId";
|
||||||
migrationBuilder.DropIndex(
|
DROP INDEX IF EXISTS "IX_Tasks_ParentTaskId";
|
||||||
name: "IX_Tasks_ParentTaskId",
|
ALTER TABLE "Tasks"
|
||||||
table: "Tasks");
|
DROP COLUMN IF EXISTS "ParentTaskId";
|
||||||
|
""");
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "ParentTaskId",
|
|
||||||
table: "Tasks");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,34 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Nexus.Api.Data;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Nexus.Api.Migrations
|
namespace Nexus.Api.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
[DbContext(typeof(NexusDbContext))]
|
||||||
|
[Migration("20260618233001_AddTaskDueDate")]
|
||||||
public partial class AddTaskDueDate : Migration
|
public partial class AddTaskDueDate : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
migrationBuilder.Sql(
|
||||||
name: "DueDate",
|
"""
|
||||||
table: "Tasks",
|
ALTER TABLE "Tasks"
|
||||||
type: "timestamp with time zone",
|
ADD COLUMN IF NOT EXISTS "DueDate" timestamp with time zone;
|
||||||
nullable: true);
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.DropColumn(
|
migrationBuilder.Sql(
|
||||||
name: "DueDate",
|
"""
|
||||||
table: "Tasks");
|
ALTER TABLE "Tasks"
|
||||||
|
DROP COLUMN IF EXISTS "DueDate";
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,38 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Nexus.Api.Data;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Nexus.Api.Migrations
|
namespace Nexus.Api.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
[DbContext(typeof(NexusDbContext))]
|
||||||
|
[Migration("20260618233002_AddActivityTaskReference")]
|
||||||
public partial class AddActivityTaskReference : Migration
|
public partial class AddActivityTaskReference : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.AddColumn<Guid>(
|
migrationBuilder.Sql(
|
||||||
name: "TaskId",
|
"""
|
||||||
table: "Activity",
|
ALTER TABLE "Activity"
|
||||||
type: "uuid",
|
ADD COLUMN IF NOT EXISTS "TaskId" uuid;
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
CREATE INDEX IF NOT EXISTS "IX_Activity_TaskId"
|
||||||
name: "IX_Activity_TaskId",
|
ON "Activity" ("TaskId");
|
||||||
table: "Activity",
|
""");
|
||||||
column: "TaskId");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.DropIndex(
|
migrationBuilder.Sql(
|
||||||
name: "IX_Activity_TaskId",
|
"""
|
||||||
table: "Activity");
|
DROP INDEX IF EXISTS "IX_Activity_TaskId";
|
||||||
|
ALTER TABLE "Activity"
|
||||||
migrationBuilder.DropColumn(
|
DROP COLUMN IF EXISTS "TaskId";
|
||||||
name: "TaskId",
|
""");
|
||||||
table: "Activity");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user