diff --git a/routes/applications.update.ts b/routes/applications.update.ts
index 1e159dd..d4e08b1 100644
--- a/routes/applications.update.ts
+++ b/routes/applications.update.ts
@@ -21,12 +21,23 @@ const UpdateForm = (application: Application, latestVersions: string[]) => {
`;
};
-const PendingUpdates = (pendingUpdates: UpdateDefinition[]) => {
+const FreeUpdateForm = (application: Application) => {
+ return html`
`;
+};
+
+const PendingUpdates = (pendingUpdates: UpdateDefinition[], logs: string) => {
if (pendingUpdates.length === 0) {
return "";
}
- return html`
+ return html`
Pending updates
${pendingUpdates
@@ -35,39 +46,52 @@ const PendingUpdates = (pendingUpdates: UpdateDefinition[]) => {
})
.join("")}
- `;
+
+ ${logs}
+
+ `;
};
const Page = (
application: Application,
latestVersions: string[],
- pendingUpdates: UpdateDefinition[]
+ pendingUpdates: UpdateDefinition[],
+ logs: string
) => {
return html`
Updating ${application.name}
- ${PendingUpdates(pendingUpdates)}
+ ${PendingUpdates(pendingUpdates, logs)}
-
- - Last deployment
- - ${application.lastDeployedAt.toLocaleString("fr-FR")}
+
+
`;
};
@@ -108,9 +132,13 @@ export default async (
);
const pendingUpdates = queries.pendingApplicationUpdates(appToUpdate.name);
+ let logs = "";
+ if (pendingUpdates.length > 0) {
+ logs = await caprover.getLogs(appToUpdate.name);
+ }
return new Response(
- Layout(Page(appToUpdate, latestVersions, pendingUpdates)),
+ Layout(Page(appToUpdate, latestVersions, pendingUpdates, logs)),
{
headers: { "Content-Type": "text/html" },
}
diff --git a/services/Caprover.test.ts b/services/Caprover.test.ts
index 32c68e3..f4e9bbd 100644
--- a/services/Caprover.test.ts
+++ b/services/Caprover.test.ts
@@ -134,5 +134,19 @@ describe("Caprover", () => {
expect(events).toBeArrayOfSize(0);
});
});
+
+ describe("getLogs", () => {
+ it("should return the logs of the application when it exists", async () => {
+ const logs = await caprover.getLogs("mysql");
+ expect(logs).toBe("mysql logs");
+ });
+
+ it("should throw an error when the application does not exist", async () => {
+ await expect(
+ caprover.getLogs("unknown")
+ // @ts-ignore toThrowError exists¯\_(ツ)_/¯
+ ).rejects.toThrowError(/Failed to fetch logs for application unknown/);
+ });
+ });
});
});
diff --git a/services/Caprover.ts b/services/Caprover.ts
index eef782f..e0ba49f 100644
--- a/services/Caprover.ts
+++ b/services/Caprover.ts
@@ -79,21 +79,23 @@ class Caprover {
async updateApplication(appName: string, version: string): Promise {
console.debug("Caprover: Updating application", appName, "to", version);
- const response = await this.fetch(`/user/apps/appData/${appName}`, {
- method: "POST",
- body: JSON.stringify({
- captainDefinitionContent: JSON.stringify({
- schemaVersion: 2,
- imageName: version,
+ try {
+ const response = await this.fetch(`/user/apps/appData/${appName}`, {
+ method: "POST",
+ body: JSON.stringify({
+ captainDefinitionContent: JSON.stringify({
+ schemaVersion: 2,
+ imageName: version,
+ }),
+ gitHash: "",
}),
- gitHash: "",
- }),
- });
-
- console.debug("update application response", response);
- if (response.status !== 100) {
+ });
+ if (response.status !== 100) {
+ throw new Error(response.description);
+ }
+ } catch (error) {
throw new Error(
- `Failed to update application ${appName} to ${version}: ${response.description}.`
+ `Failed to update application ${appName} to ${version}: ${error ?? ""}.`
);
}
@@ -105,6 +107,18 @@ class Caprover {
);
}
+ async getLogs(appName: string): Promise {
+ console.debug("Caprover: Fetching logs for", appName);
+ const response = await this.fetch(`/user/apps/appData/${appName}/logs`);
+ if (response.status !== 100) {
+ throw new Error(
+ `Failed to fetch logs for application ${appName}: ${response.description}`
+ );
+ }
+
+ return response.data.logs;
+ }
+
private async authenticate() {
if (this.authToken) {
return;
diff --git a/services/mocks/caproverServer.ts b/services/mocks/caproverServer.ts
index c59a414..d986487 100644
--- a/services/mocks/caproverServer.ts
+++ b/services/mocks/caproverServer.ts
@@ -1,9 +1,4 @@
-import {
- http,
- HttpResponse,
- HttpResponseResolver,
- PathParams
-} from "msw";
+import { http, HttpResponse, HttpResponseResolver, PathParams } from "msw";
import { setupServer } from "msw/node";
import appsFixtures from "./apps.fixtures.json";
@@ -97,6 +92,27 @@ const handlers = [
data: {},
});
}),
+ http.get(
+ `${BASE_URI}/user/apps/appData/:name/logs`,
+ withAuth(({ params }) => {
+ const app = appsFixtures.find((app) => app.appName === params.name);
+ if (!app) {
+ return HttpResponse.json({
+ status: 1000,
+ description: `App (${params.name}) could not be found. Make sure that you have created the app.`,
+ data: {},
+ });
+ }
+
+ return HttpResponse.json({
+ status: 100,
+ description: "App runtime logs are retrieved",
+ data: {
+ logs: `${params.name} logs`,
+ },
+ });
+ })
+ ),
];
const server = setupServer(...handlers);