feat(caprover): allow human to mark an app as successfully updated
This commit is contained in:
15
domain/events/ApplicationUpdateFinished.ts
Normal file
15
domain/events/ApplicationUpdateFinished.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import DomainEvent from "../DomainEvent";
|
||||
|
||||
type ApplicationUpdateFinishedPayload = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export class ApplicationUpdateFinished
|
||||
implements DomainEvent<ApplicationUpdateFinishedPayload>
|
||||
{
|
||||
readonly type = "ApplicationUpdateFinished" as const;
|
||||
constructor(
|
||||
public readonly payload: ApplicationUpdateFinishedPayload,
|
||||
public readonly createdAt: Date
|
||||
) {}
|
||||
}
|
||||
99
domain/projections/ApplicationUpdates.test.ts
Normal file
99
domain/projections/ApplicationUpdates.test.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { beforeEach, describe, expect, it } from "bun:test";
|
||||
import { TestApp } from "../testing/TestApp";
|
||||
import { ApplicationUpdateStarted } from "../events/ApplicationUpdateStarted";
|
||||
import { ApplicationUpdateFinished } from "../events/ApplicationUpdateFinished";
|
||||
|
||||
describe("ApplicationUpdates", () => {
|
||||
describe("getPendingUpdates", () => {
|
||||
it("should return an empty array when there are no pending updates", () => {
|
||||
const app = new TestApp();
|
||||
expect(app.projections.ApplicationUpdates.getPendingUpdates()).toEqual(
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
it("should return all pending updates when several started", () => {
|
||||
const app = new TestApp([
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "mail", newVersion: "1.0.0" },
|
||||
new Date()
|
||||
),
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "blog", newVersion: "10.0.1" },
|
||||
new Date()
|
||||
),
|
||||
]);
|
||||
|
||||
const updates = app.projections.ApplicationUpdates.getPendingUpdates();
|
||||
expect(updates).toEqual([
|
||||
{ id: "mail", newVersion: "1.0.0" },
|
||||
{ id: "blog", newVersion: "10.0.1" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should return all pending updates for an application while it isn't successfull", () => {
|
||||
const app = new TestApp([
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "mail", newVersion: "1.0.0" },
|
||||
new Date()
|
||||
),
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "blog", newVersion: "10.0.1" },
|
||||
new Date()
|
||||
),
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "mail", newVersion: "1.0.1" },
|
||||
new Date()
|
||||
),
|
||||
]);
|
||||
|
||||
const updates = app.projections.ApplicationUpdates.getPendingUpdates();
|
||||
expect(updates).toEqual([
|
||||
{ id: "mail", newVersion: "1.0.0" },
|
||||
{ id: "blog", newVersion: "10.0.1" },
|
||||
{ id: "mail", newVersion: "1.0.1" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should not return updates for applications after they were marked as successful", () => {
|
||||
const app = new TestApp([
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "mail", newVersion: "1.0.0" },
|
||||
new Date()
|
||||
),
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "blog", newVersion: "10.0.1" },
|
||||
new Date()
|
||||
),
|
||||
new ApplicationUpdateFinished({ id: "mail" }, new Date()),
|
||||
]);
|
||||
|
||||
const updates = app.projections.ApplicationUpdates.getPendingUpdates();
|
||||
expect(updates).toEqual([{ id: "blog", newVersion: "10.0.1" }]);
|
||||
});
|
||||
|
||||
it("should consider the latest update for an application", () => {
|
||||
const app = new TestApp([
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "mail", newVersion: "1.0.0" },
|
||||
new Date()
|
||||
),
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "blog", newVersion: "4.2.0" },
|
||||
new Date()
|
||||
),
|
||||
new ApplicationUpdateFinished({ id: "mail" }, new Date()),
|
||||
new ApplicationUpdateStarted(
|
||||
{ id: "mail", newVersion: "1.0.1" },
|
||||
new Date()
|
||||
),
|
||||
]);
|
||||
|
||||
const updates = app.projections.ApplicationUpdates.getPendingUpdates();
|
||||
expect(updates).toEqual([
|
||||
{ id: "blog", newVersion: "4.2.0" },
|
||||
{ id: "mail", newVersion: "1.0.1" },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,7 @@
|
||||
import DomainEvent from "../DomainEvent";
|
||||
import DomainProjection from "../DomainProjection";
|
||||
import { ApplicationUpdateFinished } from "../events/ApplicationUpdateFinished";
|
||||
import { ApplicationUpdateStarted } from "../events/ApplicationUpdateStarted";
|
||||
|
||||
export type UpdateDefinition = {
|
||||
id: string;
|
||||
@@ -7,10 +9,14 @@ export type UpdateDefinition = {
|
||||
};
|
||||
|
||||
export default class ApplicationUpdates implements DomainProjection {
|
||||
private readonly pendingUpdates: UpdateDefinition[] = [];
|
||||
private pendingUpdates: UpdateDefinition[] = [];
|
||||
handle(event: DomainEvent<any>): void {
|
||||
if (event.type === "ApplicationUpdateStarted") {
|
||||
this.pendingUpdates.push(event.payload);
|
||||
} else if (event.type === "ApplicationUpdateFinished") {
|
||||
this.pendingUpdates = this.pendingUpdates.filter((pendingUpdate) => {
|
||||
return pendingUpdate.id !== event.payload.id;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user