Skip to content

Commit 85de57a

Browse files
committed
revamp clickdeploy for persistent deployment status
Signed-off-by: wwanarif <[email protected]>
1 parent a0ade96 commit 85de57a

File tree

13 files changed

+872
-447
lines changed

13 files changed

+872
-447
lines changed

studio-backend/app/routers/clickdeploy_router.py

Lines changed: 53 additions & 249 deletions
Large diffs are not rendered by default.

studio-backend/app/services/clickdeploy_service.py

Lines changed: 357 additions & 35 deletions
Large diffs are not rendered by default.

studio-frontend/packages/server/src/controllers/chatflows/index.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,57 @@ const getPublicKey = async (req: Request, res: Response, next: NextFunction) =>
285285
}
286286
}
287287

288+
const getDeploymentStatus = async (req: Request, res: Response, next: NextFunction) => {
289+
try {
290+
if (typeof req.params === 'undefined' || !req.params.id) {
291+
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsRouter.getDeploymentStatus - id not provided!`)
292+
}
293+
const chatflow = await chatflowsService.getChatflowById(req.params.id)
294+
if (!chatflow) {
295+
return res.status(404).json({ error: 'Chatflow not found' })
296+
}
297+
298+
let config = null
299+
let logs = []
300+
301+
try {
302+
config = chatflow.deploymentConfig ? JSON.parse(chatflow.deploymentConfig) : null
303+
} catch (e) {
304+
console.error('Error parsing deploymentConfig:', e)
305+
}
306+
307+
try {
308+
logs = chatflow.deploymentLogs ? JSON.parse(chatflow.deploymentLogs) : []
309+
} catch (e) {
310+
console.error('Error parsing deploymentLogs:', e)
311+
}
312+
313+
const response = {
314+
status: chatflow.deploymentStatus || 'Not Started',
315+
message: '',
316+
config: config,
317+
logs: logs
318+
}
319+
320+
return res.json(response)
321+
} catch (error) {
322+
next(error)
323+
}
324+
}
325+
326+
const updateDeploymentStatus = async (req: Request, res: Response, next: NextFunction) => {
327+
try {
328+
if (typeof req.params === 'undefined' || !req.params.id) {
329+
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsRouter.updateDeploymentStatus - id not provided!`)
330+
}
331+
const { status, message, logs, config } = req.body
332+
const result = await chatflowsService.updateDeploymentStatus(req.params.id, status, message, logs, config)
333+
return res.json(result)
334+
} catch (error) {
335+
next(error)
336+
}
337+
}
338+
288339
const oneClickDeployment = async (req: Request, res: Response, next: NextFunction) => {
289340
console.log('Deploying one click')
290341
try {
@@ -316,5 +367,7 @@ export default {
316367
stopChatflowSandbox,
317368
buildDeploymentPackage,
318369
getPublicKey,
370+
getDeploymentStatus,
371+
updateDeploymentStatus,
319372
oneClickDeployment
320373
}

studio-frontend/packages/server/src/database/entities/ChatFlow.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ export class ChatFlow implements IChatFlow {
5858
@Column({nullable: true, type: 'text'})
5959
sandboxDebugLogsUrl?: string
6060

61+
@Column({nullable: true, type: 'text'})
62+
deploymentStatus?: string
63+
64+
@Column({nullable: true, type: 'text'})
65+
deploymentConfig?: string
66+
67+
@Column({nullable: true, type: 'text'})
68+
deploymentLogs?: string
69+
6170
@Column({ type: 'timestamp' })
6271
@CreateDateColumn()
6372
createdDate: Date
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { MigrationInterface, QueryRunner } from 'typeorm'
2+
3+
export class AddDeploymentStatusToChatFlow1754700956637 implements MigrationInterface {
4+
public async up(queryRunner: QueryRunner): Promise<void> {
5+
const deploymentStatusExists = await queryRunner.hasColumn('chat_flow', 'deploymentStatus')
6+
if (!deploymentStatusExists) {
7+
await queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`deploymentStatus\` varchar(255) DEFAULT NULL;`)
8+
}
9+
10+
const deploymentConfigExists = await queryRunner.hasColumn('chat_flow', 'deploymentConfig')
11+
if (!deploymentConfigExists) {
12+
await queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`deploymentConfig\` TEXT DEFAULT NULL;`)
13+
}
14+
15+
const deploymentLogsExists = await queryRunner.hasColumn('chat_flow', 'deploymentLogs')
16+
if (!deploymentLogsExists) {
17+
await queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`deploymentLogs\` TEXT DEFAULT NULL;`)
18+
}
19+
}
20+
21+
public async down(queryRunner: QueryRunner): Promise<void> {
22+
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`deploymentStatus\`;`)
23+
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`deploymentConfig\`;`)
24+
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`deploymentLogs\`;`)
25+
}
26+
}

studio-frontend/packages/server/src/database/migrations/mysql/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { AddArtifactsToChatMessage1726156258465 } from './1726156258465-AddArtif
2929
import { AddStudioFieldsToChatFlow1733282099772 } from './1733282099772-AddStudioFieldsToChatFlow'
3030
import { AddSandboxTracerUrlToChatFlow1743740099772 } from './1743740099772-AddSandboxTracerUrlToChatFlow'
3131
import { AddSandboxDebugLogsUrlToChatFlow1749612373191 } from './1749612373191-AddSandboxDebugLogsUrlToChatFlow'
32+
import { AddDeploymentStatusToChatFlow1754700956637 } from './1754700956637-AddDeploymentStatusToChatFlow'
3233

3334

3435
export const mysqlMigrations = [
@@ -62,5 +63,6 @@ export const mysqlMigrations = [
6263
AddArtifactsToChatMessage1726156258465,
6364
AddStudioFieldsToChatFlow1733282099772,
6465
AddSandboxTracerUrlToChatFlow1743740099772,
65-
AddSandboxDebugLogsUrlToChatFlow1749612373191
66+
AddSandboxDebugLogsUrlToChatFlow1749612373191,
67+
AddDeploymentStatusToChatFlow1754700956637
6668
]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { MigrationInterface, QueryRunner } from 'typeorm'
2+
3+
export class AddDeploymentStatusToChatFlow1754700956637 implements MigrationInterface {
4+
public async up(queryRunner: QueryRunner): Promise<void> {
5+
const deploymentStatusExists = await queryRunner.hasColumn('chat_flow', 'deploymentStatus')
6+
if (!deploymentStatusExists) {
7+
await queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`deploymentStatus\` varchar(255) DEFAULT NULL;`)
8+
}
9+
10+
const deploymentConfigExists = await queryRunner.hasColumn('chat_flow', 'deploymentConfig')
11+
if (!deploymentConfigExists) {
12+
await queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`deploymentConfig\` TEXT DEFAULT NULL;`)
13+
}
14+
15+
const deploymentLogsExists = await queryRunner.hasColumn('chat_flow', 'deploymentLogs')
16+
if (!deploymentLogsExists) {
17+
await queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`deploymentLogs\` TEXT DEFAULT NULL;`)
18+
}
19+
}
20+
21+
public async down(queryRunner: QueryRunner): Promise<void> {
22+
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`deploymentStatus\`;`)
23+
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`deploymentConfig\`;`)
24+
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`deploymentLogs\`;`)
25+
}
26+
}

studio-frontend/packages/server/src/database/migrations/sqlite/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { AddCustomTemplate1725629836652 } from './1725629836652-AddCustomTemplat
2828
import { AddStudioFieldsToChatFlow1733282099772 } from './1733282099772-AddStudioFieldsToChatFlow'
2929
import { AddSandboxTracerUrlToChatFlow1743740099772 } from './1743740099772-AddSandboxTracerUrlToChatFlow'
3030
import { AddSandboxDebugLogsUrlToChatFlow1749612373191 } from './1749612373191-AddSandboxDebugLogsUrlToChatFlow'
31+
import { AddDeploymentStatusToChatFlow1754700956637 } from './1754700956637-AddDeploymentStatusToChatFlow'
3132

3233
export const sqliteMigrations = [
3334
Init1693835579790,
@@ -59,5 +60,6 @@ export const sqliteMigrations = [
5960
AddCustomTemplate1725629836652,
6061
AddStudioFieldsToChatFlow1733282099772,
6162
AddSandboxTracerUrlToChatFlow1743740099772,
62-
AddSandboxDebugLogsUrlToChatFlow1749612373191
63+
AddSandboxDebugLogsUrlToChatFlow1749612373191,
64+
AddDeploymentStatusToChatFlow1754700956637
6365
]

studio-frontend/packages/server/src/routes/chatflows/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ router.post('/importchatflows', chatflowsController.importChatflows)
1010
// READ
1111
router.get('/pubkey', chatflowsController.getPublicKey)
1212
router.get('/', chatflowsController.getAllChatflowsbyUserId)
13+
router.get('/deployment-status/:id', chatflowsController.getDeploymentStatus)
1314
router.get(['/', '/:id'], chatflowsController.getChatflowById)
1415
router.get(['/apikey/', '/apikey/:apikey'], chatflowsController.getChatflowByApiKey)
1516

1617
// UPDATE
1718
router.put(['/', '/:id'], chatflowsController.updateChatflow)
19+
router.put('/deployment-status/:id', chatflowsController.updateDeploymentStatus)
1820

1921
// DELETE
2022
router.delete(['/', '/:id'], chatflowsController.deleteChatflow)

studio-frontend/packages/server/src/services/chatflows/index.ts

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -504,10 +504,14 @@ const oneClickDeploymentService = async (chatflowId: string, deploymentConfig: R
504504
try {
505505
const chatflow = await generatePipelineJson(chatflowId)
506506
const studioServerUrl = STUDIO_SERVER_URL
507-
const endpoint = 'studio-backend/upload-pipeline-files'
508-
console.log('chatflow', JSON.stringify(chatflow))
509-
console.log('studioServerUrl', studioServerUrl)
510-
console.log('deploymentConfig', deploymentConfig)
507+
const endpoint = 'studio-backend/click-deployment'
508+
// console.log('chatflow', JSON.stringify(chatflow))
509+
// console.log('studioServerUrl', studioServerUrl)
510+
// console.log('deploymentConfig', deploymentConfig)
511+
512+
// Update chatflow with deployment status and config from backend response
513+
const appServer = getRunningExpressApp()
514+
const chatflowEntity = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({ id: chatflowId })
511515
const response = await axios.post(`${studioServerUrl}/${endpoint}`, {
512516
remoteHost: deploymentConfig.hostname,
513517
remoteUser: deploymentConfig.username,
@@ -516,8 +520,24 @@ const oneClickDeploymentService = async (chatflowId: string, deploymentConfig: R
516520
headers: { 'Content-Type': 'application/json' },
517521
timeout: 60 * 1000
518522
})
523+
if (chatflowEntity) {
524+
chatflowEntity.deploymentStatus = response.data.status
525+
chatflowEntity.deploymentConfig = JSON.stringify(deploymentConfig)
526+
chatflowEntity.deploymentLogs = JSON.stringify([response.data.message])
527+
await appServer.AppDataSource.getRepository(ChatFlow).save(chatflowEntity)
528+
}
529+
519530
return response.data
520531
} catch (error: unknown) {
532+
// Update chatflow with error status
533+
const appServer = getRunningExpressApp()
534+
const chatflowEntity = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({ id: chatflowId })
535+
if (chatflowEntity) {
536+
chatflowEntity.deploymentStatus = 'Error'
537+
chatflowEntity.deploymentLogs = JSON.stringify([`Error: ${error instanceof Error ? error.message : String(error)}`])
538+
await appServer.AppDataSource.getRepository(ChatFlow).save(chatflowEntity)
539+
}
540+
521541
if (error instanceof Error) {
522542
console.error(`Error: ${error.stack}`)
523543
} else {
@@ -527,6 +547,45 @@ const oneClickDeploymentService = async (chatflowId: string, deploymentConfig: R
527547
}
528548
}
529549

550+
const updateDeploymentStatus = async (chatflowId: string, status: string, message?: string, logs?: string[], config?: Record<string, any>) => {
551+
try {
552+
const appServer = getRunningExpressApp()
553+
const chatflow = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({ id: chatflowId })
554+
if (chatflow) {
555+
chatflow.deploymentStatus = status
556+
557+
// Update logs array - either use provided logs or append message to existing logs
558+
let updatedLogs: string[] = []
559+
if (logs && logs.length > 0) {
560+
updatedLogs = logs
561+
} else {
562+
// Parse existing logs and append new message
563+
try {
564+
const existingLogs = chatflow.deploymentLogs ? JSON.parse(chatflow.deploymentLogs) : []
565+
updatedLogs = Array.isArray(existingLogs) ? existingLogs : []
566+
if (message) {
567+
updatedLogs.push(message)
568+
}
569+
} catch (e) {
570+
updatedLogs = message ? [message] : []
571+
}
572+
}
573+
chatflow.deploymentLogs = JSON.stringify(updatedLogs)
574+
575+
if (config) {
576+
chatflow.deploymentConfig = JSON.stringify(config)
577+
}
578+
await appServer.AppDataSource.getRepository(ChatFlow).save(chatflow)
579+
}
580+
return chatflow
581+
} catch (error) {
582+
throw new InternalFlowiseError(
583+
StatusCodes.INTERNAL_SERVER_ERROR,
584+
`Error: chatflowsService.updateDeploymentStatus - ${getErrorMessage(error)}`
585+
)
586+
}
587+
}
588+
530589
const _checkAndUpdateDocumentStoreUsage = async (chatflow: ChatFlow) => {
531590
const parsedFlowData: IReactFlowObject = JSON.parse(chatflow.flowData)
532591
const nodes = parsedFlowData.nodes
@@ -556,5 +615,6 @@ export default {
556615
stopChatflowSandboxService,
557616
buildDeploymentPackageService,
558617
getSinglePublicChatbotConfig,
559-
oneClickDeploymentService
618+
oneClickDeploymentService,
619+
updateDeploymentStatus
560620
}

0 commit comments

Comments
 (0)