Skip to content

Commit 15289c3

Browse files
committed
feat: add browser apply actions
1 parent 49ff044 commit 15289c3

16 files changed

Lines changed: 213 additions & 15 deletions
89.8 KB
Loading
30 KB
Loading

packages/api/src/http.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import {
6464
} from "./services/federation.js"
6565
import {
6666
applyAllProjects,
67+
applyProjectById,
6768
createProjectFromRequest,
6869
deleteProjectById,
6970
downAllProjects,
@@ -905,6 +906,14 @@ export const makeRouter = () => {
905906
Effect.catchAll(errorResponse)
906907
)
907908
),
909+
HttpRouter.post(
910+
"/projects/:projectId/apply",
911+
projectParams.pipe(
912+
Effect.flatMap(({ projectId }) => applyProjectById(projectId)),
913+
Effect.flatMap((project) => jsonResponse({ ok: true, project }, 200)),
914+
Effect.catchAll(errorResponse)
915+
)
916+
),
908917
HttpRouter.post(
909918
"/projects/:projectId/down",
910919
projectParams.pipe(

packages/api/src/services/projects.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
type AppError,
3+
applyProjectConfig,
34
buildCreateCommand,
45
defaultTemplateConfig,
56
createProject,
@@ -570,6 +571,28 @@ export const applyAllProjects = (activeOnly: boolean) =>
570571
activeOnly
571572
})
572573

574+
export const applyProjectById = (
575+
projectId: string
576+
) =>
577+
Effect.gen(function*(_) {
578+
const project = yield* _(findProjectById(projectId))
579+
yield* _(markDeployment(projectId, "apply", "docker-git apply"))
580+
yield* _(
581+
runWithProjectEventLogs(
582+
projectId,
583+
applyProjectConfig({
584+
_tag: "Apply",
585+
projectDir: project.projectDir,
586+
runUp: true
587+
})
588+
)
589+
)
590+
const details = yield* _(runtimeProjectDetails(project))
591+
yield* _(recordProjectStartedFromDetails(project, details, "up"))
592+
yield* _(markDeployment(projectId, "running", "Apply completed"))
593+
return details
594+
}).pipe(Effect.mapError(toProjectApiError))
595+
573596
export const downAllProjects = () => downAllDockerGitProjects
574597

575598
export const getProject = (

packages/app/src/web/actions-projects.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
} from "./actions-shared.js"
1313
import { loadSelectedProjectTasks } from "./actions-tasks.js"
1414
import {
15+
applyAllProjects,
16+
applyProject,
1517
createProjectTerminalSession,
1618
deleteProject,
1719
downAllProjects,
@@ -104,6 +106,31 @@ export const connectProjectById = (
104106
})
105107
}
106108

109+
export const applyProjectById = (
110+
projectId: string,
111+
context: BrowserActionContext
112+
) => {
113+
context.setSelectedProjectId(projectId)
114+
withBusy({
115+
context,
116+
effect: applyProject(projectId),
117+
label: "Applying project",
118+
onSuccess: (project) => {
119+
context.reloadDashboard()
120+
context.setSelectedProject(project)
121+
context.setMessage(`Applied ${project.displayName}.`)
122+
}
123+
})
124+
}
125+
126+
export const applySelectedProject = (context: BrowserActionContext) => {
127+
const projectId = requireSelectedProjectId(context)
128+
if (projectId === null) {
129+
return
130+
}
131+
applyProjectById(projectId, context)
132+
}
133+
107134
const runProjectOutputAction = (
108135
context: BrowserActionContext,
109136
effect: (projectId: string) => ReturnType<typeof loadProjectPs>,
@@ -177,6 +204,21 @@ const runDownAllProjects = (context: BrowserActionContext) => {
177204
})
178205
}
179206

207+
export const runApplyAllProjects = (context: BrowserActionContext) => {
208+
if (!confirmAction("Apply docker-git config to all projects?")) {
209+
return
210+
}
211+
withBusy({
212+
context,
213+
effect: applyAllProjects(false),
214+
label: "Applying all projects",
215+
onSuccess: () => {
216+
context.reloadDashboard()
217+
context.setMessage("Applied docker-git config to all projects.")
218+
}
219+
})
220+
}
221+
180222
export const runProjectMenuAction = (
181223
currentMenu: Exclude<BrowserMenuTag, "Auth" | "ProjectAuth">,
182224
context: BrowserActionContext

packages/app/src/web/actions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export {
3030
saveSelectedDatabaseProfile
3131
} from "./actions-databases.js"
3232
export { closeSelectedProjectPort, loadSelectedProjectPorts, openSelectedProjectPort } from "./actions-port-forwards.js"
33-
export { connectProjectById, loadSelectedProjectInfo } from "./actions-projects.js"
33+
export { applyProjectById, applySelectedProject, connectProjectById, loadSelectedProjectInfo, runApplyAllProjects } from "./actions-projects.js"
3434
export { loadSelectedProjectTaskLogs, loadSelectedProjectTasks, stopSelectedProjectTask } from "./actions-tasks.js"
3535

3636
export const runBrowserMenuAction = (

packages/app/src/web/api-project-core.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ export const loadProjectLogs = (projectId: string) =>
1919
Effect.map((response) => response.output)
2020
)
2121

22+
export const applyProject = (projectId: string) =>
23+
requestJson(
24+
"POST",
25+
`/projects/${encodeURIComponent(projectId)}/apply`,
26+
ProjectResponseSchema
27+
).pipe(
28+
Effect.map((response) => response.project)
29+
)
30+
2231
export const createProject = (draft: CreateProjectDraft) =>
2332
requestJson(
2433
"POST",

packages/app/src/web/api.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export {
4040
restartProjectDatabaseEditor,
4141
saveProjectDatabaseProfile
4242
} from "./api-database.js"
43-
export { createProject, loadProjectDetails, loadProjectLogs, loadProjectPs, upProject } from "./api-project-core.js"
43+
export { applyProject, createProject, loadProjectDetails, loadProjectLogs, loadProjectPs, upProject } from "./api-project-core.js"
4444
export { loadProjectTaskLogs, loadProjectTasks, stopProjectTask } from "./api-tasks.js"
4545

4646
export type * from "./api-types.js"
@@ -170,6 +170,9 @@ export const deleteProject = (projectId: string) =>
170170

171171
export const downAllProjects = () => requestText("POST", "/projects/down-all").pipe(Effect.asVoid)
172172

173+
export const applyAllProjects = (activeOnly: boolean) =>
174+
requestText("POST", "/projects/apply-all", { activeOnly }).pipe(Effect.asVoid)
175+
173176
export const loadGithubStatus = () =>
174177
requestJson("GET", "/auth/github/status", GithubStatusResponseSchema).pipe(
175178
Effect.map((response) => response.status)

packages/app/src/web/app-ready-controller.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { updateActionPromptValue } from "./action-prompt.js"
22
import {
33
cancelBrowserActionPrompt,
4+
applyProjectById,
5+
applySelectedProject,
46
closeSelectedProjectPort,
57
connectProjectById,
68
loadSelectedProjectBrowser,
79
loadSelectedProjectPorts,
810
openProjectBrowserById,
911
openSelectedProjectBrowser,
1012
openSelectedProjectPort,
13+
runApplyAllProjects,
1114
submitBrowserActionPrompt
1215
} from "./actions.js"
1316
import type { DashboardData } from "./api.js"
@@ -248,6 +251,15 @@ const bindBrowserActions = (
248251
const bindTerminalActions = (
249252
actionContext: ReturnType<typeof createActionContext>
250253
) => ({
254+
onApplyProjectById: (projectId: string) => {
255+
applyProjectById(projectId, actionContext)
256+
},
257+
onApplySelectedProject: () => {
258+
applySelectedProject(actionContext)
259+
},
260+
onApplyAllProjects: () => {
261+
runApplyAllProjects(actionContext)
262+
},
251263
onOpenProjectTerminalById: (projectId: string) => {
252264
connectProjectById(projectId, actionContext)
253265
}

packages/app/src/web/app-ready-layout.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ export type ReadyLayoutProps = {
4545
readonly onActionPromptCancel: () => void
4646
readonly onActionPromptChange: (key: string, value: string) => void
4747
readonly onActionPromptSubmit: () => void
48+
readonly onApplyAllProjects: () => void
49+
readonly onApplyProjectById: (projectId: string) => void
50+
readonly onApplySelectedProject: () => void
4851
readonly onBackScreen: () => void
4952
readonly onCreateBufferChange: (buffer: string) => void
5053
readonly onCreateCancel: () => void

0 commit comments

Comments
 (0)