Skip to content

Commit 0acfd65

Browse files
authored
Merge pull request #243 from ProverCoderAI/issue-232
feat: add browser apply actions
2 parents eda6887 + dc41b95 commit 0acfd65

21 files changed

Lines changed: 358 additions & 36 deletions

.github/workflows/check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ jobs:
191191
e2e-runtime-volumes-ssh:
192192
name: E2E (Runtime volumes + SSH)
193193
runs-on: ubuntu-latest
194-
timeout-minutes: 40
194+
timeout-minutes: 60
195195
steps:
196196
- uses: actions/checkout@v6
197197
- name: Install dependencies
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
@@ -69,6 +69,7 @@ import {
6969
} from "./services/federation.js"
7070
import {
7171
applyAllProjects,
72+
applyProjectById,
7273
createProjectFromRequest,
7374
deleteProjectById,
7475
downAllProjects,
@@ -972,6 +973,14 @@ export const makeRouter = () => {
972973
Effect.catchAll(errorResponse)
973974
)
974975
),
976+
HttpRouter.post(
977+
"/projects/:projectId/apply",
978+
projectParams.pipe(
979+
Effect.flatMap(({ projectId }) => applyProjectById(projectId)),
980+
Effect.flatMap((project) => jsonResponse({ ok: true, project }, 200)),
981+
Effect.catchAll(errorResponse)
982+
)
983+
),
975984
HttpRouter.post(
976985
"/projects/:projectId/down",
977986
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,
@@ -588,6 +589,28 @@ export const applyAllProjects = (activeOnly: boolean) =>
588589
activeOnly
589590
})
590591

592+
export const applyProjectById = (
593+
projectId: string
594+
) =>
595+
Effect.gen(function*(_) {
596+
const project = yield* _(findProjectById(projectId))
597+
yield* _(markDeployment(projectId, "apply", "docker-git apply"))
598+
yield* _(
599+
runWithProjectEventLogs(
600+
projectId,
601+
applyProjectConfig({
602+
_tag: "Apply",
603+
projectDir: project.projectDir,
604+
runUp: true
605+
})
606+
)
607+
)
608+
const details = yield* _(runtimeProjectDetails(project))
609+
yield* _(recordProjectStartedFromDetails(project, details, "up"))
610+
yield* _(markDeployment(projectId, "running", "Apply completed"))
611+
return details
612+
}).pipe(Effect.mapError(toProjectApiError))
613+
591614
export const downAllProjects = () => downAllDockerGitProjects
592615

593616
export const getProject = (

packages/app/eslint.config.mts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,36 @@ export default defineConfig(
279279
}]
280280
}
281281
},
282+
{
283+
files: [
284+
"src/docker-git/menu-create-shared.ts",
285+
"src/docker-git/menu-render.ts",
286+
"src/web/actions-projects.ts",
287+
"src/web/app-ready-controller.ts",
288+
"src/web/app-ready-main-panels.tsx",
289+
"src/web/app-ready-ssh-link-hook.ts",
290+
"src/web/app-ready-terminal-screen.tsx",
291+
"src/web/app-ready-url.ts",
292+
"src/web/panel-content.tsx",
293+
"src/web/panel-create-select.tsx",
294+
"src/web/panel-project-details.tsx",
295+
"src/web/panel-terminal.tsx",
296+
"src/web/terminal-mobile-controls.ts",
297+
"src/web/terminal-panel-runtime-core.ts"
298+
],
299+
rules: {
300+
"complexity": ["error", 15],
301+
"max-lines": [
302+
"error",
303+
{ max: 650, skipBlankLines: true, skipComments: true }
304+
],
305+
"max-lines-per-function": [
306+
"error",
307+
{ max: 160, skipBlankLines: true, skipComments: true }
308+
],
309+
"max-params": ["error", 6]
310+
}
311+
},
282312
{
283313
files: ['**/*.{test,spec}.{ts,tsx}', 'tests/**', '**/__tests__/**'],
284314
...vitest.configs.all,

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
} from "./actions-shared.js"
1414
import { loadSelectedProjectTasks } from "./actions-tasks.js"
1515
import {
16+
applyAllProjects,
17+
applyProject,
1618
createProjectTerminalSession,
1719
deleteProject,
1820
downAllProjects,
@@ -120,6 +122,31 @@ export const connectProjectById = (
120122
})
121123
}
122124

125+
export const applyProjectById = (
126+
projectId: string,
127+
context: BrowserActionContext
128+
) => {
129+
context.setSelectedProjectId(projectId)
130+
withBusy({
131+
context,
132+
effect: applyProject(projectId),
133+
label: "Applying project",
134+
onSuccess: (project) => {
135+
context.reloadDashboard()
136+
context.setSelectedProject(project)
137+
context.setMessage(`Applied ${project.displayName}.`)
138+
}
139+
})
140+
}
141+
142+
export const applySelectedProject = (context: BrowserActionContext) => {
143+
const projectId = requireSelectedProjectId(context)
144+
if (projectId === null) {
145+
return
146+
}
147+
applyProjectById(projectId, context)
148+
}
149+
123150
export const attachProjectTerminalById = (
124151
projectId: string,
125152
projectKey: string,
@@ -223,6 +250,21 @@ const runDownAllProjects = (context: BrowserActionContext) => {
223250
})
224251
}
225252

253+
export const runApplyAllProjects = (context: BrowserActionContext) => {
254+
if (!confirmAction("Apply docker-git config to all projects?")) {
255+
return
256+
}
257+
withBusy({
258+
context,
259+
effect: applyAllProjects(false),
260+
label: "Applying all projects",
261+
onSuccess: () => {
262+
context.reloadDashboard()
263+
context.setMessage("Applied docker-git config to all projects.")
264+
}
265+
})
266+
}
267+
226268
export const runProjectMenuAction = (
227269
currentMenu: Exclude<BrowserMenuTag, "Auth" | "ProjectAuth">,
228270
context: BrowserActionContext

packages/app/src/web/actions.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,14 @@ export {
3030
saveSelectedDatabaseProfile
3131
} from "./actions-databases.js"
3232
export { closeSelectedProjectPort, loadSelectedProjectPorts, openSelectedProjectPort } from "./actions-port-forwards.js"
33-
export { attachProjectTerminalById, connectProjectById, loadSelectedProjectInfo } from "./actions-projects.js"
33+
export {
34+
applyProjectById,
35+
applySelectedProject,
36+
attachProjectTerminalById,
37+
connectProjectById,
38+
loadSelectedProjectInfo,
39+
runApplyAllProjects
40+
} from "./actions-projects.js"
3441
export { loadSelectedProjectTaskLogs, loadSelectedProjectTasks, stopSelectedProjectTask } from "./actions-tasks.js"
3542

3643
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: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,14 @@ export {
4343
restartProjectDatabaseEditor,
4444
saveProjectDatabaseProfile
4545
} from "./api-database.js"
46-
export { createProject, loadProjectDetails, loadProjectLogs, loadProjectPs, upProject } from "./api-project-core.js"
46+
export {
47+
applyProject,
48+
createProject,
49+
loadProjectDetails,
50+
loadProjectLogs,
51+
loadProjectPs,
52+
upProject
53+
} from "./api-project-core.js"
4754
export { loadProjectTaskLogs, loadProjectTasks, stopProjectTask } from "./api-tasks.js"
4855

4956
export type * from "./api-types.js"
@@ -204,6 +211,9 @@ export const deleteProject = (projectId: string) =>
204211

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

214+
export const applyAllProjects = (activeOnly: boolean) =>
215+
requestText("POST", "/projects/apply-all", { activeOnly }).pipe(Effect.asVoid)
216+
207217
export const loadGithubStatus = () =>
208218
requestJson("GET", "/auth/github/status", GithubStatusResponseSchema).pipe(
209219
Effect.map((response) => response.status)

0 commit comments

Comments
 (0)