feat: add deployment endpoint
This commit is contained in:
parent
0835d966f1
commit
7e05fae7b3
@ -213,7 +213,7 @@ async def upload_file(prompt_id, filename, subfolder=None):
|
|||||||
filename = os.path.basename(filename)
|
filename = os.path.basename(filename)
|
||||||
file = os.path.join(output_dir, filename)
|
file = os.path.join(output_dir, filename)
|
||||||
|
|
||||||
print("uploading file", file)
|
# print("uploading file", file)
|
||||||
|
|
||||||
file_upload_endpoint = prompt_metadata[prompt_id]['file_upload_endpoint']
|
file_upload_endpoint = prompt_metadata[prompt_id]['file_upload_endpoint']
|
||||||
|
|
||||||
|
BIN
web/bun.lockb
BIN
web/bun.lockb
Binary file not shown.
40
web/drizzle/0005_worthless_dakota_north.sql
Normal file
40
web/drizzle/0005_worthless_dakota_north.sql
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE "deployment_environment" AS ENUM('staging', 'production');
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE IF NOT EXISTS "comfy_deploy"."deployments" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
"workflow_version_id" uuid NOT NULL,
|
||||||
|
"workflow_id" uuid NOT NULL,
|
||||||
|
"machine_id" uuid,
|
||||||
|
"environment" "deployment_environment" NOT NULL,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "comfy_deploy"."deployments" ADD CONSTRAINT "deployments_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "comfy_deploy"."users"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "comfy_deploy"."deployments" ADD CONSTRAINT "deployments_workflow_version_id_workflow_versions_id_fk" FOREIGN KEY ("workflow_version_id") REFERENCES "comfy_deploy"."workflow_versions"("id") ON DELETE no action ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "comfy_deploy"."deployments" ADD CONSTRAINT "deployments_workflow_id_workflows_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "comfy_deploy"."workflows"("id") ON DELETE no action ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "comfy_deploy"."deployments" ADD CONSTRAINT "deployments_machine_id_machines_id_fk" FOREIGN KEY ("machine_id") REFERENCES "comfy_deploy"."machines"("id") ON DELETE no action ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
1
web/drizzle/0006_chief_mariko_yashida.sql
Normal file
1
web/drizzle/0006_chief_mariko_yashida.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "comfy_deploy"."deployments" ALTER COLUMN "machine_id" SET NOT NULL;
|
531
web/drizzle/meta/0005_snapshot.json
Normal file
531
web/drizzle/meta/0005_snapshot.json
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
{
|
||||||
|
"id": "af90a047-fec9-4d35-be52-82f8e0ee1cf4",
|
||||||
|
"prevId": "07a389e2-3713-4047-93e7-bf1da2333b16",
|
||||||
|
"version": "5",
|
||||||
|
"dialect": "pg",
|
||||||
|
"tables": {
|
||||||
|
"deployments": {
|
||||||
|
"name": "deployments",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"workflow_version_id": {
|
||||||
|
"name": "workflow_version_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"workflow_id": {
|
||||||
|
"name": "workflow_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"machine_id": {
|
||||||
|
"name": "machine_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"environment": {
|
||||||
|
"name": "environment",
|
||||||
|
"type": "deployment_environment",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"deployments_user_id_users_id_fk": {
|
||||||
|
"name": "deployments_user_id_users_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"deployments_workflow_version_id_workflow_versions_id_fk": {
|
||||||
|
"name": "deployments_workflow_version_id_workflow_versions_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "workflow_versions",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_version_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"deployments_workflow_id_workflows_id_fk": {
|
||||||
|
"name": "deployments_workflow_id_workflows_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "workflows",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"deployments_machine_id_machines_id_fk": {
|
||||||
|
"name": "deployments_machine_id_machines_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "machines",
|
||||||
|
"columnsFrom": [
|
||||||
|
"machine_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"machines": {
|
||||||
|
"name": "machines",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"endpoint": {
|
||||||
|
"name": "endpoint",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"machines_user_id_users_id_fk": {
|
||||||
|
"name": "machines_user_id_users_id_fk",
|
||||||
|
"tableFrom": "machines",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"name": "users",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"name": "username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflow_run_outputs": {
|
||||||
|
"name": "workflow_run_outputs",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"run_id": {
|
||||||
|
"name": "run_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"name": "data",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflow_run_outputs_run_id_workflow_runs_id_fk": {
|
||||||
|
"name": "workflow_run_outputs_run_id_workflow_runs_id_fk",
|
||||||
|
"tableFrom": "workflow_run_outputs",
|
||||||
|
"tableTo": "workflow_runs",
|
||||||
|
"columnsFrom": [
|
||||||
|
"run_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflow_runs": {
|
||||||
|
"name": "workflow_runs",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"workflow_version_id": {
|
||||||
|
"name": "workflow_version_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"workflow_id": {
|
||||||
|
"name": "workflow_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"machine_id": {
|
||||||
|
"name": "machine_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "workflow_run_status",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "'not-started'"
|
||||||
|
},
|
||||||
|
"ended_at": {
|
||||||
|
"name": "ended_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflow_runs_workflow_version_id_workflow_versions_id_fk": {
|
||||||
|
"name": "workflow_runs_workflow_version_id_workflow_versions_id_fk",
|
||||||
|
"tableFrom": "workflow_runs",
|
||||||
|
"tableTo": "workflow_versions",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_version_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "set null",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"workflow_runs_workflow_id_workflows_id_fk": {
|
||||||
|
"name": "workflow_runs_workflow_id_workflows_id_fk",
|
||||||
|
"tableFrom": "workflow_runs",
|
||||||
|
"tableTo": "workflows",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"workflow_runs_machine_id_machines_id_fk": {
|
||||||
|
"name": "workflow_runs_machine_id_machines_id_fk",
|
||||||
|
"tableFrom": "workflow_runs",
|
||||||
|
"tableTo": "machines",
|
||||||
|
"columnsFrom": [
|
||||||
|
"machine_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "set null",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflows": {
|
||||||
|
"name": "workflows",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflows_user_id_users_id_fk": {
|
||||||
|
"name": "workflows_user_id_users_id_fk",
|
||||||
|
"tableFrom": "workflows",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflow_versions": {
|
||||||
|
"name": "workflow_versions",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"workflow_id": {
|
||||||
|
"name": "workflow_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"workflow": {
|
||||||
|
"name": "workflow",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"workflow_api": {
|
||||||
|
"name": "workflow_api",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "version",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflow_versions_workflow_id_workflows_id_fk": {
|
||||||
|
"name": "workflow_versions_workflow_id_workflows_id_fk",
|
||||||
|
"tableFrom": "workflow_versions",
|
||||||
|
"tableTo": "workflows",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enums": {
|
||||||
|
"deployment_environment": {
|
||||||
|
"name": "deployment_environment",
|
||||||
|
"values": {
|
||||||
|
"staging": "staging",
|
||||||
|
"production": "production"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workflow_run_status": {
|
||||||
|
"name": "workflow_run_status",
|
||||||
|
"values": {
|
||||||
|
"not-started": "not-started",
|
||||||
|
"running": "running",
|
||||||
|
"success": "success",
|
||||||
|
"failed": "failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schemas": {
|
||||||
|
"comfy_deploy": "comfy_deploy"
|
||||||
|
},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
}
|
||||||
|
}
|
531
web/drizzle/meta/0006_snapshot.json
Normal file
531
web/drizzle/meta/0006_snapshot.json
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
{
|
||||||
|
"id": "c68b3727-5154-41eb-b44e-d5f26b72be44",
|
||||||
|
"prevId": "af90a047-fec9-4d35-be52-82f8e0ee1cf4",
|
||||||
|
"version": "5",
|
||||||
|
"dialect": "pg",
|
||||||
|
"tables": {
|
||||||
|
"deployments": {
|
||||||
|
"name": "deployments",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"workflow_version_id": {
|
||||||
|
"name": "workflow_version_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"workflow_id": {
|
||||||
|
"name": "workflow_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"machine_id": {
|
||||||
|
"name": "machine_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"environment": {
|
||||||
|
"name": "environment",
|
||||||
|
"type": "deployment_environment",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"deployments_user_id_users_id_fk": {
|
||||||
|
"name": "deployments_user_id_users_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"deployments_workflow_version_id_workflow_versions_id_fk": {
|
||||||
|
"name": "deployments_workflow_version_id_workflow_versions_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "workflow_versions",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_version_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"deployments_workflow_id_workflows_id_fk": {
|
||||||
|
"name": "deployments_workflow_id_workflows_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "workflows",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"deployments_machine_id_machines_id_fk": {
|
||||||
|
"name": "deployments_machine_id_machines_id_fk",
|
||||||
|
"tableFrom": "deployments",
|
||||||
|
"tableTo": "machines",
|
||||||
|
"columnsFrom": [
|
||||||
|
"machine_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"machines": {
|
||||||
|
"name": "machines",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"endpoint": {
|
||||||
|
"name": "endpoint",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"machines_user_id_users_id_fk": {
|
||||||
|
"name": "machines_user_id_users_id_fk",
|
||||||
|
"tableFrom": "machines",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"name": "users",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"name": "username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflow_run_outputs": {
|
||||||
|
"name": "workflow_run_outputs",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"run_id": {
|
||||||
|
"name": "run_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"name": "data",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflow_run_outputs_run_id_workflow_runs_id_fk": {
|
||||||
|
"name": "workflow_run_outputs_run_id_workflow_runs_id_fk",
|
||||||
|
"tableFrom": "workflow_run_outputs",
|
||||||
|
"tableTo": "workflow_runs",
|
||||||
|
"columnsFrom": [
|
||||||
|
"run_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflow_runs": {
|
||||||
|
"name": "workflow_runs",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"workflow_version_id": {
|
||||||
|
"name": "workflow_version_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"workflow_id": {
|
||||||
|
"name": "workflow_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"machine_id": {
|
||||||
|
"name": "machine_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "workflow_run_status",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "'not-started'"
|
||||||
|
},
|
||||||
|
"ended_at": {
|
||||||
|
"name": "ended_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflow_runs_workflow_version_id_workflow_versions_id_fk": {
|
||||||
|
"name": "workflow_runs_workflow_version_id_workflow_versions_id_fk",
|
||||||
|
"tableFrom": "workflow_runs",
|
||||||
|
"tableTo": "workflow_versions",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_version_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "set null",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"workflow_runs_workflow_id_workflows_id_fk": {
|
||||||
|
"name": "workflow_runs_workflow_id_workflows_id_fk",
|
||||||
|
"tableFrom": "workflow_runs",
|
||||||
|
"tableTo": "workflows",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"workflow_runs_machine_id_machines_id_fk": {
|
||||||
|
"name": "workflow_runs_machine_id_machines_id_fk",
|
||||||
|
"tableFrom": "workflow_runs",
|
||||||
|
"tableTo": "machines",
|
||||||
|
"columnsFrom": [
|
||||||
|
"machine_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "set null",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflows": {
|
||||||
|
"name": "workflows",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflows_user_id_users_id_fk": {
|
||||||
|
"name": "workflows_user_id_users_id_fk",
|
||||||
|
"tableFrom": "workflows",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"workflow_versions": {
|
||||||
|
"name": "workflow_versions",
|
||||||
|
"schema": "comfy_deploy",
|
||||||
|
"columns": {
|
||||||
|
"workflow_id": {
|
||||||
|
"name": "workflow_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"workflow": {
|
||||||
|
"name": "workflow",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"workflow_api": {
|
||||||
|
"name": "workflow_api",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "version",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"workflow_versions_workflow_id_workflows_id_fk": {
|
||||||
|
"name": "workflow_versions_workflow_id_workflows_id_fk",
|
||||||
|
"tableFrom": "workflow_versions",
|
||||||
|
"tableTo": "workflows",
|
||||||
|
"columnsFrom": [
|
||||||
|
"workflow_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enums": {
|
||||||
|
"deployment_environment": {
|
||||||
|
"name": "deployment_environment",
|
||||||
|
"values": {
|
||||||
|
"staging": "staging",
|
||||||
|
"production": "production"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workflow_run_status": {
|
||||||
|
"name": "workflow_run_status",
|
||||||
|
"values": {
|
||||||
|
"not-started": "not-started",
|
||||||
|
"running": "running",
|
||||||
|
"success": "success",
|
||||||
|
"failed": "failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schemas": {
|
||||||
|
"comfy_deploy": "comfy_deploy"
|
||||||
|
},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
}
|
||||||
|
}
|
@ -36,6 +36,20 @@
|
|||||||
"when": 1702357291227,
|
"when": 1702357291227,
|
||||||
"tag": "0004_zippy_freak",
|
"tag": "0004_zippy_freak",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 5,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1702545286004,
|
||||||
|
"tag": "0005_worthless_dakota_north",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 6,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1702556119574,
|
||||||
|
"tag": "0006_chief_mariko_yashida",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -39,6 +39,7 @@
|
|||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-hook-form": "^7.48.2",
|
"react-hook-form": "^7.48.2",
|
||||||
"react-use-websocket": "^4.5.0",
|
"react-use-websocket": "^4.5.0",
|
||||||
|
"shiki": "^0.14.6",
|
||||||
"sonner": "^1.2.4",
|
"sonner": "^1.2.4",
|
||||||
"tailwind-merge": "^2.1.0",
|
"tailwind-merge": "^2.1.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { RunsTable } from "../../components/RunsTable";
|
import { DeploymentsTable, RunsTable } from "../../components/RunsTable";
|
||||||
import { findFirstTableWithVersion } from "../../server/findFirstTableWithVersion";
|
import { findFirstTableWithVersion } from "../../server/findFirstTableWithVersion";
|
||||||
import { MachinesWSMain } from "@/components/MachinesWS";
|
import { MachinesWSMain } from "@/components/MachinesWS";
|
||||||
import {
|
import {
|
||||||
|
CreateDeploymentButton,
|
||||||
MachineSelect,
|
MachineSelect,
|
||||||
RunWorkflowButton,
|
RunWorkflowButton,
|
||||||
VersionSelect,
|
VersionSelect,
|
||||||
@ -28,6 +29,7 @@ export default async function Page({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-4 w-full flex flex-col lg:flex-row gap-4 max-h-[calc(100dvh-100px)]">
|
<div className="mt-4 w-full flex flex-col lg:flex-row gap-4 max-h-[calc(100dvh-100px)]">
|
||||||
|
<div className="flex gap-4 flex-col">
|
||||||
<Card className="w-full lg:w-fit lg:min-w-[500px] h-fit">
|
<Card className="w-full lg:w-fit lg:min-w-[500px] h-fit">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>{workflow?.name}</CardTitle>
|
<CardTitle>{workflow?.name}</CardTitle>
|
||||||
@ -41,11 +43,22 @@ export default async function Page({
|
|||||||
<VersionSelect workflow={workflow} />
|
<VersionSelect workflow={workflow} />
|
||||||
<MachineSelect machines={machines} />
|
<MachineSelect machines={machines} />
|
||||||
<RunWorkflowButton workflow={workflow} machines={machines} />
|
<RunWorkflowButton workflow={workflow} machines={machines} />
|
||||||
|
<CreateDeploymentButton workflow={workflow} machines={machines} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MachinesWSMain machines={machines} />
|
<MachinesWSMain machines={machines} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
<Card className="w-full ">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Deployments</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<CardContent>
|
||||||
|
<DeploymentsTable workflow_id={workflow_id} />
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Card className="w-full ">
|
<Card className="w-full ">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
import { parseDataSafe } from "../../../lib/parseDataSafe";
|
|
||||||
import { createRun } from "../../../server/createRun";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
const Request = z.object({
|
|
||||||
workflow_version_id: z.string(),
|
|
||||||
// workflow_version: z.number().optional(),
|
|
||||||
machine_id: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
|
||||||
const [data, error] = await parseDataSafe(Request, request);
|
|
||||||
if (!data || error) return error;
|
|
||||||
|
|
||||||
const origin = new URL(request.url).origin;
|
|
||||||
|
|
||||||
const { workflow_version_id, machine_id } = data;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const workflow_run_id = await createRun(
|
|
||||||
origin,
|
|
||||||
workflow_version_id,
|
|
||||||
machine_id
|
|
||||||
);
|
|
||||||
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
workflow_run_id: workflow_run_id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: 200,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (error: any) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{
|
|
||||||
error: error.message,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: 500,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
84
web/src/app/api/run/route.ts
Normal file
84
web/src/app/api/run/route.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { parseDataSafe } from "../../../lib/parseDataSafe";
|
||||||
|
import { createRun } from "../../../server/createRun";
|
||||||
|
import { db } from "@/db/db";
|
||||||
|
import { deploymentsTable } from "@/db/schema";
|
||||||
|
import { getRunsData } from "@/server/getRunsOutput";
|
||||||
|
import { replaceCDNUrl } from "@/server/resource";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const Request = z.object({
|
||||||
|
deployment_id: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const Request2 = z.object({
|
||||||
|
run_id: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
const [data, error] = await parseDataSafe(Request2, request);
|
||||||
|
if (!data || error) return error;
|
||||||
|
|
||||||
|
const run = await getRunsData(data.run_id);
|
||||||
|
|
||||||
|
if (run?.status === "success" && run?.outputs?.length > 0) {
|
||||||
|
for (let i = 0; i < run.outputs.length; i++) {
|
||||||
|
const output = run.outputs[i];
|
||||||
|
|
||||||
|
if (output.data?.images === undefined) continue;
|
||||||
|
|
||||||
|
for (let j = 0; j < output.data?.images.length; j++) {
|
||||||
|
const element = output.data?.images[j];
|
||||||
|
element.url = replaceCDNUrl(
|
||||||
|
`${process.env.SPACES_ENDPOINT}/comfyui-deploy/outputs/runs/${run.id}/${element.filename}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(run, {
|
||||||
|
status: 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: Request) {
|
||||||
|
const [data, error] = await parseDataSafe(Request, request);
|
||||||
|
if (!data || error) return error;
|
||||||
|
|
||||||
|
const origin = new URL(request.url).origin;
|
||||||
|
|
||||||
|
const { deployment_id } = data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const deploymentData = await db.query.deploymentsTable.findFirst({
|
||||||
|
where: eq(deploymentsTable.id, deployment_id),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!deploymentData) throw new Error("Deployment not found");
|
||||||
|
|
||||||
|
const run_id = await createRun(
|
||||||
|
origin,
|
||||||
|
deploymentData.workflow_version_id,
|
||||||
|
deploymentData.machine_id
|
||||||
|
);
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
run_id: run_id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: error.message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -66,6 +66,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shiki>code>span {
|
||||||
|
/* text-wrap: wrap; */
|
||||||
|
/* word-wrap: break-word; */
|
||||||
|
/* @apply break-all ; */
|
||||||
|
text-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shiki {
|
||||||
|
/* @apply rounded-lg p-2 overflow-x-scroll */
|
||||||
|
@apply rounded-lg p-2 overflow-hidden
|
||||||
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
|
30
web/src/components/CodeBlock.tsx
Normal file
30
web/src/components/CodeBlock.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { CopyButton } from "@/components/CopyButton";
|
||||||
|
import type { Lang } from "shiki";
|
||||||
|
import shiki from "shiki";
|
||||||
|
|
||||||
|
export async function CodeBlock(props: { code: string; lang: Lang }) {
|
||||||
|
const highlighter = await shiki.getHighlighter({
|
||||||
|
theme: "one-dark-pro",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative w-full max-w-full text-sm">
|
||||||
|
{/* max-w-[calc(32rem-1.5rem-1.5rem)] */}
|
||||||
|
{/* <div className=""> */}
|
||||||
|
<p
|
||||||
|
// tabIndex={1}
|
||||||
|
className="[&>pre]:p-4 rounded-sm "
|
||||||
|
style={{
|
||||||
|
overflowWrap: "break-word",
|
||||||
|
}}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: highlighter.codeToHtml(props.code.trim(), {
|
||||||
|
lang: props.lang,
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* </div> */}
|
||||||
|
<CopyButton className="absolute right-2 top-2" text={props.code} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
24
web/src/components/CopyButton.tsx
Normal file
24
web/src/components/CopyButton.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { Copy } from "lucide-react";
|
||||||
|
|
||||||
|
export function CopyButton({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
text: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(props.text);
|
||||||
|
}}
|
||||||
|
className={cn(" p-2 min-h-0 aspect-square", className)}
|
||||||
|
>
|
||||||
|
<Copy size={14} />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
113
web/src/components/DeploymentDisplay.tsx
Normal file
113
web/src/components/DeploymentDisplay.tsx
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import { CodeBlock } from "@/components/CodeBlock";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { TableCell, TableRow } from "@/components/ui/table";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { getRelativeTime } from "@/lib/getRelativeTime";
|
||||||
|
import type { findAllDeployments } from "@/server/findAllRuns";
|
||||||
|
|
||||||
|
const curlTemplate = `
|
||||||
|
curl --request POST \
|
||||||
|
--url <URL> \
|
||||||
|
--header 'Content-Type: application/json' \
|
||||||
|
--data '{
|
||||||
|
"deployment_id": "<ID>"
|
||||||
|
}'
|
||||||
|
`;
|
||||||
|
|
||||||
|
const jsTemplate = `
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: '{"deployment_id":"<ID>"}'
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch('<URL>', options)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(response => console.log(response))
|
||||||
|
.catch(err => console.error(err));
|
||||||
|
`;
|
||||||
|
|
||||||
|
const jsTemplate_checkStatus = `
|
||||||
|
const options = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
};
|
||||||
|
|
||||||
|
const run_id = '<RUN_ID>';
|
||||||
|
|
||||||
|
fetch('<URL>?run_id=' + run_id, options)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(response => console.log(response))
|
||||||
|
.catch(err => console.error(err));
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function DeploymentDisplay({
|
||||||
|
deployment,
|
||||||
|
}: {
|
||||||
|
deployment: Awaited<ReturnType<typeof findAllDeployments>>[0];
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger asChild className="appearance-none hover:cursor-pointer">
|
||||||
|
<TableRow>
|
||||||
|
<TableCell className="capitalize">{deployment.environment}</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{deployment.version?.version}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{deployment.machine?.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-right">
|
||||||
|
{getRelativeTime(deployment.updated_at)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="max-w-xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="capitalize">
|
||||||
|
{deployment.environment} Deployment
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription>Code for your deployment client</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<Tabs defaultValue="js" className="w-full">
|
||||||
|
<TabsList className="grid w-fit grid-cols-2">
|
||||||
|
<TabsTrigger value="js">js</TabsTrigger>
|
||||||
|
<TabsTrigger value="curl">curl</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
<TabsContent className="flex flex-col gap-2" value="js">
|
||||||
|
<CodeBlock lang="js" code={formatCode(jsTemplate, deployment)} />
|
||||||
|
<CodeBlock
|
||||||
|
lang="js"
|
||||||
|
code={formatCode(jsTemplate_checkStatus, deployment)}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
<TabsContent value="curl">
|
||||||
|
<CodeBlock
|
||||||
|
lang="bash"
|
||||||
|
code={formatCode(curlTemplate, deployment)}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCode(
|
||||||
|
codeTemplate: string,
|
||||||
|
deployment: Awaited<ReturnType<typeof findAllDeployments>>[0]
|
||||||
|
) {
|
||||||
|
return codeTemplate
|
||||||
|
.replace(
|
||||||
|
"<URL>",
|
||||||
|
`${process.env.VERCEL_URL ?? "http://localhost:3000"}/api/run`
|
||||||
|
)
|
||||||
|
.replace("<ID>", deployment.id);
|
||||||
|
}
|
@ -161,7 +161,7 @@ export const columns: ColumnDef<Machine>[] = [
|
|||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="text-destructive"
|
className="text-destructive"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
callServerWithToast(await deleteMachine(workflow.id));
|
callServerPromise(deleteMachine(workflow.id));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Delete Machine
|
Delete Machine
|
||||||
@ -176,15 +176,16 @@ export const columns: ColumnDef<Machine>[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
async function callServerWithToast(result: {
|
export async function callServerPromise<T>(result: Promise<T>) {
|
||||||
message: string;
|
return result
|
||||||
error?: boolean;
|
.then((x) => {
|
||||||
}) {
|
if ((x as { message: string })?.message !== undefined) {
|
||||||
if (result.error) {
|
toast.success((x as { message: string }).message);
|
||||||
toast.error(result.message);
|
|
||||||
} else {
|
|
||||||
toast.success(result.message);
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
toast.error(error.message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MachineList({ data }: { data: Machine[] }) {
|
export function MachineList({ data }: { data: Machine[] }) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { RunOutputs } from "./RunOutputs";
|
||||||
import { useStore } from "@/components/MachinesWS";
|
import { useStore } from "@/components/MachinesWS";
|
||||||
import { StatusBadge } from "@/components/StatusBadge";
|
import { StatusBadge } from "@/components/StatusBadge";
|
||||||
import {
|
import {
|
||||||
@ -10,18 +11,9 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import {
|
import { TableCell, TableRow } from "@/components/ui/table";
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table";
|
|
||||||
import { getRelativeTime } from "@/lib/getRelativeTime";
|
import { getRelativeTime } from "@/lib/getRelativeTime";
|
||||||
import { type findAllRuns } from "@/server/findAllRuns";
|
import { type findAllRuns } from "@/server/findAllRuns";
|
||||||
import { getRunsOutput } from "@/server/getRunsOutput";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
export function RunDisplay({
|
export function RunDisplay({
|
||||||
run,
|
run,
|
||||||
@ -73,42 +65,6 @@ export function RunDisplay({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RunOutputs({ run_id }: { run_id: string }) {
|
|
||||||
const [outputs, setOutputs] = useState<
|
|
||||||
Awaited<ReturnType<typeof getRunsOutput>>
|
|
||||||
>([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getRunsOutput(run_id).then((x) => setOutputs(x));
|
|
||||||
}, [run_id]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Table>
|
|
||||||
{/* <TableCaption>A list of your recent runs.</TableCaption> */}
|
|
||||||
<TableHeader className="bg-background top-0 sticky">
|
|
||||||
<TableRow>
|
|
||||||
<TableHead className="w-[100px]">File</TableHead>
|
|
||||||
<TableHead className="">Output</TableHead>
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{outputs?.map((run) => {
|
|
||||||
const fileName = run.data.images[0].filename;
|
|
||||||
// const filePath
|
|
||||||
return (
|
|
||||||
<TableRow key={run.id}>
|
|
||||||
<TableCell>{fileName}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<OutputRender run_id={run_id} filename={fileName} />
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function OutputRender(props: { run_id: string; filename: string }) {
|
export function OutputRender(props: { run_id: string; filename: string }) {
|
||||||
if (props.filename.endsWith(".png")) {
|
if (props.filename.endsWith(".png")) {
|
||||||
return (
|
return (
|
||||||
|
53
web/src/components/RunOutputs.tsx
Normal file
53
web/src/components/RunOutputs.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { OutputRender } from "./RunDisplay";
|
||||||
|
import { callServerPromise } from "@/components/MachineList";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { getRunsOutput } from "@/server/getRunsOutput";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export function RunOutputs({ run_id }: { run_id: string }) {
|
||||||
|
const [outputs, setOutputs] =
|
||||||
|
useState<Awaited<ReturnType<typeof getRunsOutput>>>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!run_id) return;
|
||||||
|
// fetch(`/api/run?run_id=${run_id}`)
|
||||||
|
// .then((x) => x.json())
|
||||||
|
// .then((x) => setOutputs(x));
|
||||||
|
callServerPromise(getRunsOutput(run_id).then((x) => setOutputs(x)));
|
||||||
|
}, [run_id, outputs]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
{/* <TableCaption>A list of your recent runs.</TableCaption> */}
|
||||||
|
<TableHeader className="bg-background top-0 sticky">
|
||||||
|
<TableRow>
|
||||||
|
<TableHead className="w-[100px]">File</TableHead>
|
||||||
|
<TableHead className="">Output</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{outputs?.map((run) => {
|
||||||
|
const fileName = run.data.images[0].filename;
|
||||||
|
// const filePath
|
||||||
|
return (
|
||||||
|
<TableRow key={run.id}>
|
||||||
|
<TableCell>{fileName}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<OutputRender run_id={run_id} filename={fileName} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { findAllRuns } from "../server/findAllRuns";
|
import { findAllDeployments, findAllRuns } from "../server/findAllRuns";
|
||||||
|
import { DeploymentDisplay } from "./DeploymentDisplay";
|
||||||
import { RunDisplay } from "./RunDisplay";
|
import { RunDisplay } from "./RunDisplay";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@ -33,3 +34,27 @@ export async function RunsTable(props: { workflow_id: string }) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function DeploymentsTable(props: { workflow_id: string }) {
|
||||||
|
const allRuns = await findAllDeployments(props.workflow_id);
|
||||||
|
return (
|
||||||
|
<div className="overflow-auto h-[400px] w-full">
|
||||||
|
<Table className="">
|
||||||
|
<TableCaption>A list of your deployments</TableCaption>
|
||||||
|
<TableHeader className="bg-background top-0 sticky">
|
||||||
|
<TableRow>
|
||||||
|
<TableHead className=" w-[100px]">Environment</TableHead>
|
||||||
|
<TableHead className=" w-[100px]">Version</TableHead>
|
||||||
|
<TableHead className="">Machine</TableHead>
|
||||||
|
<TableHead className=" text-right">Updated At</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{allRuns.map((run) => (
|
||||||
|
<DeploymentDisplay deployment={run} key={run.id} />
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { LoadingIcon } from "@/components/LoadingIcon";
|
import { LoadingIcon } from "@/components/LoadingIcon";
|
||||||
|
import { callServerPromise } from "@/components/MachineList";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@ -12,9 +19,10 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { createRun } from "@/server/createRun";
|
import { createRun } from "@/server/createRun";
|
||||||
|
import { createDeployments } from "@/server/curdDeploments";
|
||||||
import type { getMachines } from "@/server/curdMachine";
|
import type { getMachines } from "@/server/curdMachine";
|
||||||
import type { findFirstTableWithVersion } from "@/server/findFirstTableWithVersion";
|
import type { findFirstTableWithVersion } from "@/server/findFirstTableWithVersion";
|
||||||
import { Play } from "lucide-react";
|
import { MoreVertical, Play } from "lucide-react";
|
||||||
import { parseAsInteger, useQueryState } from "next-usequerystate";
|
import { parseAsInteger, useQueryState } from "next-usequerystate";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
@ -122,3 +130,70 @@ export function RunWorkflowButton({
|
|||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function CreateDeploymentButton({
|
||||||
|
workflow,
|
||||||
|
machines,
|
||||||
|
}: {
|
||||||
|
workflow: Awaited<ReturnType<typeof findFirstTableWithVersion>>;
|
||||||
|
machines: Awaited<ReturnType<typeof getMachines>>;
|
||||||
|
}) {
|
||||||
|
const [version] = useQueryState("version", {
|
||||||
|
defaultValue: workflow?.versions[0].version ?? 1,
|
||||||
|
...parseAsInteger,
|
||||||
|
});
|
||||||
|
const [machine] = useQueryState("machine", {
|
||||||
|
defaultValue: machines[0].id ?? "",
|
||||||
|
});
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const workflow_version_id = workflow?.versions.find(
|
||||||
|
(x) => x.version === version
|
||||||
|
)?.id;
|
||||||
|
return (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button className="gap-2" disabled={isLoading} variant="outline">
|
||||||
|
Deploy <MoreVertical size={14} /> {isLoading && <LoadingIcon />}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent className="w-56">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={async () => {
|
||||||
|
if (!workflow_version_id) return;
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
await callServerPromise(
|
||||||
|
createDeployments(
|
||||||
|
workflow.id,
|
||||||
|
workflow_version_id,
|
||||||
|
machine,
|
||||||
|
"production"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setIsLoading(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Production
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={async () => {
|
||||||
|
if (!workflow_version_id) return;
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
await callServerPromise(
|
||||||
|
createDeployments(
|
||||||
|
workflow.id,
|
||||||
|
workflow_version_id,
|
||||||
|
machine,
|
||||||
|
"staging"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setIsLoading(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Staging
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as React from "react"
|
import { cn } from "@/lib/utils";
|
||||||
|
import * as React from "react";
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const Card = React.forwardRef<
|
const Card = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
@ -14,8 +13,8 @@ const Card = React.forwardRef<
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
Card.displayName = "Card"
|
Card.displayName = "Card";
|
||||||
|
|
||||||
const CardHeader = React.forwardRef<
|
const CardHeader = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
@ -26,8 +25,8 @@ const CardHeader = React.forwardRef<
|
|||||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
CardHeader.displayName = "CardHeader"
|
CardHeader.displayName = "CardHeader";
|
||||||
|
|
||||||
const CardTitle = React.forwardRef<
|
const CardTitle = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
@ -41,8 +40,8 @@ const CardTitle = React.forwardRef<
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
CardTitle.displayName = "CardTitle"
|
CardTitle.displayName = "CardTitle";
|
||||||
|
|
||||||
const CardDescription = React.forwardRef<
|
const CardDescription = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
@ -53,16 +52,16 @@ const CardDescription = React.forwardRef<
|
|||||||
className={cn("text-sm text-muted-foreground", className)}
|
className={cn("text-sm text-muted-foreground", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
CardDescription.displayName = "CardDescription"
|
CardDescription.displayName = "CardDescription";
|
||||||
|
|
||||||
const CardContent = React.forwardRef<
|
const CardContent = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
React.HTMLAttributes<HTMLDivElement>
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||||
))
|
));
|
||||||
CardContent.displayName = "CardContent"
|
CardContent.displayName = "CardContent";
|
||||||
|
|
||||||
const CardFooter = React.forwardRef<
|
const CardFooter = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
@ -73,7 +72,14 @@ const CardFooter = React.forwardRef<
|
|||||||
className={cn("flex items-center p-6 pt-0", className)}
|
className={cn("flex items-center p-6 pt-0", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
CardFooter.displayName = "CardFooter"
|
CardFooter.displayName = "CardFooter";
|
||||||
|
|
||||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
export {
|
||||||
|
Card,
|
||||||
|
CardHeader,
|
||||||
|
CardFooter,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
CardContent,
|
||||||
|
};
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import { cn } from "@/lib/utils";
|
||||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||||
import { X } from "lucide-react"
|
import { X } from "lucide-react";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
const Dialog = DialogPrimitive.Root;
|
||||||
|
|
||||||
const Dialog = DialogPrimitive.Root
|
const DialogTrigger = DialogPrimitive.Trigger;
|
||||||
|
|
||||||
const DialogTrigger = DialogPrimitive.Trigger
|
const DialogPortal = DialogPrimitive.Portal;
|
||||||
|
|
||||||
const DialogPortal = DialogPrimitive.Portal
|
const DialogClose = DialogPrimitive.Close;
|
||||||
|
|
||||||
const DialogClose = DialogPrimitive.Close
|
|
||||||
|
|
||||||
const DialogOverlay = React.forwardRef<
|
const DialogOverlay = React.forwardRef<
|
||||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||||
@ -26,8 +25,8 @@ const DialogOverlay = React.forwardRef<
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
||||||
|
|
||||||
const DialogContent = React.forwardRef<
|
const DialogContent = React.forwardRef<
|
||||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||||
@ -37,8 +36,9 @@ const DialogContent = React.forwardRef<
|
|||||||
<DialogOverlay />
|
<DialogOverlay />
|
||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
// grid tuning off grid for styling issue
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
"fixed left-[50%] top-[50%] z-50 w-full max-w-lg translate-x-[-50%] grid grid-cols-1 translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -50,8 +50,8 @@ const DialogContent = React.forwardRef<
|
|||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
</DialogPrimitive.Content>
|
</DialogPrimitive.Content>
|
||||||
</DialogPortal>
|
</DialogPortal>
|
||||||
))
|
));
|
||||||
DialogContent.displayName = DialogPrimitive.Content.displayName
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||||
|
|
||||||
const DialogHeader = ({
|
const DialogHeader = ({
|
||||||
className,
|
className,
|
||||||
@ -64,8 +64,8 @@ const DialogHeader = ({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
DialogHeader.displayName = "DialogHeader"
|
DialogHeader.displayName = "DialogHeader";
|
||||||
|
|
||||||
const DialogFooter = ({
|
const DialogFooter = ({
|
||||||
className,
|
className,
|
||||||
@ -78,8 +78,8 @@ const DialogFooter = ({
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
DialogFooter.displayName = "DialogFooter"
|
DialogFooter.displayName = "DialogFooter";
|
||||||
|
|
||||||
const DialogTitle = React.forwardRef<
|
const DialogTitle = React.forwardRef<
|
||||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||||
@ -93,8 +93,8 @@ const DialogTitle = React.forwardRef<
|
|||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||||
|
|
||||||
const DialogDescription = React.forwardRef<
|
const DialogDescription = React.forwardRef<
|
||||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||||
@ -105,8 +105,8 @@ const DialogDescription = React.forwardRef<
|
|||||||
className={cn("text-sm text-muted-foreground", className)}
|
className={cn("text-sm text-muted-foreground", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Dialog,
|
Dialog,
|
||||||
@ -119,4 +119,4 @@ export {
|
|||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
}
|
};
|
||||||
|
@ -67,6 +67,11 @@ export const workflowRunStatus = pgEnum("workflow_run_status", [
|
|||||||
"failed",
|
"failed",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export const deploymentEnvironment = pgEnum("deployment_environment", [
|
||||||
|
"staging",
|
||||||
|
"production",
|
||||||
|
]);
|
||||||
|
|
||||||
// We still want to keep the workflow run record.
|
// We still want to keep the workflow run record.
|
||||||
export const workflowRunsTable = dbSchema.table("workflow_runs", {
|
export const workflowRunsTable = dbSchema.table("workflow_runs", {
|
||||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||||
@ -91,7 +96,9 @@ export const workflowRunsTable = dbSchema.table("workflow_runs", {
|
|||||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const workflowRunRelations = relations(workflowRunsTable, ({ one }) => ({
|
export const workflowRunRelations = relations(
|
||||||
|
workflowRunsTable,
|
||||||
|
({ one, many }) => ({
|
||||||
machine: one(machinesTable, {
|
machine: one(machinesTable, {
|
||||||
fields: [workflowRunsTable.machine_id],
|
fields: [workflowRunsTable.machine_id],
|
||||||
references: [machinesTable.id],
|
references: [machinesTable.id],
|
||||||
@ -100,7 +107,9 @@ export const workflowRunRelations = relations(workflowRunsTable, ({ one }) => ({
|
|||||||
fields: [workflowRunsTable.workflow_version_id],
|
fields: [workflowRunsTable.workflow_version_id],
|
||||||
references: [workflowVersionTable.id],
|
references: [workflowVersionTable.id],
|
||||||
}),
|
}),
|
||||||
}));
|
outputs: many(workflowRunOutputs),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// We still want to keep the workflow run record.
|
// We still want to keep the workflow run record.
|
||||||
export const workflowRunOutputs = dbSchema.table("workflow_run_outputs", {
|
export const workflowRunOutputs = dbSchema.table("workflow_run_outputs", {
|
||||||
@ -116,6 +125,16 @@ export const workflowRunOutputs = dbSchema.table("workflow_run_outputs", {
|
|||||||
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const workflowOutputRelations = relations(
|
||||||
|
workflowRunOutputs,
|
||||||
|
({ one }) => ({
|
||||||
|
run: one(workflowRunsTable, {
|
||||||
|
fields: [workflowRunOutputs.run_id],
|
||||||
|
references: [workflowRunsTable.id],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// when user delete, also delete all the workflow versions
|
// when user delete, also delete all the workflow versions
|
||||||
export const machinesTable = dbSchema.table("machines", {
|
export const machinesTable = dbSchema.table("machines", {
|
||||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||||
@ -130,5 +149,37 @@ export const machinesTable = dbSchema.table("machines", {
|
|||||||
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const deploymentsTable = dbSchema.table("deployments", {
|
||||||
|
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||||
|
user_id: text("user_id")
|
||||||
|
.references(() => usersTable.id, {
|
||||||
|
onDelete: "cascade",
|
||||||
|
})
|
||||||
|
.notNull(),
|
||||||
|
workflow_version_id: uuid("workflow_version_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => workflowVersionTable.id),
|
||||||
|
workflow_id: uuid("workflow_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => workflowTable.id),
|
||||||
|
machine_id: uuid("machine_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => machinesTable.id),
|
||||||
|
environment: deploymentEnvironment("environment").notNull(),
|
||||||
|
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||||
|
updated_at: timestamp("updated_at").defaultNow().notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const deploymentsRelations = relations(deploymentsTable, ({ one }) => ({
|
||||||
|
machine: one(machinesTable, {
|
||||||
|
fields: [deploymentsTable.machine_id],
|
||||||
|
references: [machinesTable.id],
|
||||||
|
}),
|
||||||
|
version: one(workflowVersionTable, {
|
||||||
|
fields: [deploymentsTable.workflow_version_id],
|
||||||
|
references: [workflowVersionTable.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
export type UserType = InferSelectModel<typeof usersTable>;
|
export type UserType = InferSelectModel<typeof usersTable>;
|
||||||
export type WorkflowType = InferSelectModel<typeof workflowTable>;
|
export type WorkflowType = InferSelectModel<typeof workflowTable>;
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
import { db } from "./db/db";
|
import { authMiddleware, redirectToSignIn } from "@clerk/nextjs";
|
||||||
import { usersTable } from "./db/schema";
|
|
||||||
import { authMiddleware, redirectToSignIn, clerkClient } from "@clerk/nextjs";
|
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import { NextResponse } from "next/server";
|
|
||||||
|
|
||||||
// This example protects all routes including api/trpc routes
|
// This example protects all routes including api/trpc routes
|
||||||
// Please edit this to allow other routes to be public as needed.
|
// Please edit this to allow other routes to be public as needed.
|
||||||
// See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your Middleware
|
// See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your Middleware
|
||||||
export default authMiddleware({
|
export default authMiddleware({
|
||||||
|
// debug: true,
|
||||||
publicRoutes: ["/api/(.*)"],
|
publicRoutes: ["/api/(.*)"],
|
||||||
// publicRoutes: ["/", "/(.*)"],
|
// publicRoutes: ["/", "/(.*)"],
|
||||||
async afterAuth(auth, req, evt) {
|
async afterAuth(auth, req, evt) {
|
||||||
@ -33,6 +30,6 @@ export default authMiddleware({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/" , "/(api|trpc)(.*)"],
|
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
|
||||||
// matcher: ['/','/create', '/api/(twitter|generation|init|voice-cloning)'],
|
// matcher: ['/','/create', '/api/(twitter|generation|init|voice-cloning)'],
|
||||||
};
|
};
|
||||||
|
46
web/src/server/curdDeploments.ts
Normal file
46
web/src/server/curdDeploments.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { db } from "@/db/db";
|
||||||
|
import { deploymentsTable } from "@/db/schema";
|
||||||
|
import { auth } from "@clerk/nextjs";
|
||||||
|
import { and, eq } from "drizzle-orm";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
import "server-only";
|
||||||
|
|
||||||
|
export async function createDeployments(
|
||||||
|
workflow_id: string,
|
||||||
|
version_id: string,
|
||||||
|
machine_id: string,
|
||||||
|
environment: "production" | "staging"
|
||||||
|
) {
|
||||||
|
const { userId } = auth();
|
||||||
|
if (!userId) throw new Error("No user id");
|
||||||
|
|
||||||
|
// Same environment and same workflow
|
||||||
|
const existingDeployment = await db.query.deploymentsTable.findFirst({
|
||||||
|
where: and(
|
||||||
|
eq(deploymentsTable.workflow_id, workflow_id),
|
||||||
|
eq(deploymentsTable.environment, environment)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingDeployment) {
|
||||||
|
await db
|
||||||
|
.update(deploymentsTable)
|
||||||
|
.set({
|
||||||
|
workflow_id,
|
||||||
|
workflow_version_id: version_id,
|
||||||
|
machine_id,
|
||||||
|
})
|
||||||
|
.where(eq(deploymentsTable.id, existingDeployment.id));
|
||||||
|
} else {
|
||||||
|
await db.insert(deploymentsTable).values({
|
||||||
|
user_id: userId,
|
||||||
|
workflow_id,
|
||||||
|
workflow_version_id: version_id,
|
||||||
|
machine_id,
|
||||||
|
environment,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
revalidatePath(`/${workflow_id}`);
|
||||||
|
}
|
@ -43,14 +43,7 @@ export async function addMachine(name: string, endpoint: string) {
|
|||||||
export async function deleteMachine(
|
export async function deleteMachine(
|
||||||
machine_id: string
|
machine_id: string
|
||||||
): Promise<{ message: string; error?: boolean }> {
|
): Promise<{ message: string; error?: boolean }> {
|
||||||
try {
|
|
||||||
await db.delete(machinesTable).where(eq(machinesTable.id, machine_id));
|
await db.delete(machinesTable).where(eq(machinesTable.id, machine_id));
|
||||||
revalidatePath("/machines");
|
revalidatePath("/machines");
|
||||||
return { message: "Machine Deleted" };
|
return { message: "Machine Deleted" };
|
||||||
} catch (error: unknown) {
|
|
||||||
return {
|
|
||||||
message: `Error: ${error.detail}`,
|
|
||||||
error: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { db } from "@/db/db";
|
import { db } from "@/db/db";
|
||||||
import { workflowRunsTable } from "@/db/schema";
|
import { deploymentsTable, workflowRunsTable } from "@/db/schema";
|
||||||
import { desc, eq } from "drizzle-orm";
|
import { desc, eq } from "drizzle-orm";
|
||||||
|
|
||||||
export async function findAllRuns(workflow_id: string) {
|
export async function findAllRuns(workflow_id: string) {
|
||||||
@ -21,3 +21,22 @@ export async function findAllRuns(workflow_id: string) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function findAllDeployments(workflow_id: string) {
|
||||||
|
return await db.query.deploymentsTable.findMany({
|
||||||
|
where: eq(deploymentsTable.workflow_id, workflow_id),
|
||||||
|
orderBy: desc(deploymentsTable.environment),
|
||||||
|
with: {
|
||||||
|
machine: {
|
||||||
|
columns: {
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
version: {
|
||||||
|
columns: {
|
||||||
|
version: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -1,12 +1,27 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { db } from "@/db/db";
|
import { db } from "@/db/db";
|
||||||
import { workflowRunOutputs } from "@/db/schema";
|
import { workflowRunOutputs, workflowRunsTable } from "@/db/schema";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
export async function getRunsOutput(run_id: string) {
|
export async function getRunsOutput(run_id: string) {
|
||||||
|
// throw new Error("Not implemented");
|
||||||
return await db
|
return await db
|
||||||
.select()
|
.select()
|
||||||
.from(workflowRunOutputs)
|
.from(workflowRunOutputs)
|
||||||
.where(eq(workflowRunOutputs.run_id, run_id));
|
.where(eq(workflowRunOutputs.run_id, run_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getRunsData(run_id: string) {
|
||||||
|
// throw new Error("Not implemented");
|
||||||
|
return await db.query.workflowRunsTable.findFirst({
|
||||||
|
where: eq(workflowRunsTable.id, run_id),
|
||||||
|
with: {
|
||||||
|
outputs: {
|
||||||
|
columns: {
|
||||||
|
data: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@ const s3Client = new S3({
|
|||||||
forcePathStyle: true,
|
forcePathStyle: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
function replaceCDNUrl(url: string) {
|
export function replaceCDNUrl(url: string) {
|
||||||
url = url.replace(
|
url = url.replace(
|
||||||
process.env.SPACES_ENDPOINT!,
|
process.env.SPACES_ENDPOINT!,
|
||||||
process.env.SPACES_ENDPOINT_CDN!
|
process.env.SPACES_ENDPOINT_CDN!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user