From a455b14c27a14c9810643c3a20fb4e8c18ee97d2 Mon Sep 17 00:00:00 2001
From: Paython Veazie
Date: Sat, 8 Nov 2025 10:13:35 -0800
Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20Deploy=20flow:=20wired=20pipeline?=
=?UTF-8?q?=5Fcommit=20to=20send=20repoFullName=20+=20YAML=20from=20dashbo?=
=?UTF-8?q?ard=20to=20backend?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 2 +
client/src/lib/api.ts | 93 +++++++++++++++++++++-------
client/src/pages/ConfigurePage.tsx | 2 +-
client/src/pages/DashboardPage.tsx | 38 ++++++++++--
client/src/pages/DeployPage.tsx | 18 +++++-
client/src/store/useDeployStore.ts | 28 +++++++--
client/src/store/usePipelineStore.ts | 11 +++-
7 files changed, 156 insertions(+), 36 deletions(-)
diff --git a/.gitignore b/.gitignore
index 74afc5d..0653358 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,8 @@ web_modules/
.env
.env.*
!.env.example
+curl.txt
+
# parcel-bundler cache (https://parceljs.org/)
.cache
diff --git a/client/src/lib/api.ts b/client/src/lib/api.ts
index b8f29f7..6a43724 100644
--- a/client/src/lib/api.ts
+++ b/client/src/lib/api.ts
@@ -1,3 +1,5 @@
+import { usePipelineStore } from "../store/usePipelineStore";
+
export const BASE =
import.meta.env.VITE_API_BASE ?? "http://localhost:3000/api";
@@ -139,35 +141,82 @@ export const api = {
return { results };
},
- // --- Mock deploy APIs for Dashboard ---
- async startDeploy({ repo, env }: { repo: string; env: string }) {
- const jobId = `job_${Math.random().toString(36).slice(2)}`;
- // Stash minimal job info in memory for the stream to reference
- JOBS.set(jobId, { repo, env, startedAt: Date.now() });
- return { jobId } as const;
- },
+ // --- Deploy APIs for Dashboard ---
+async startDeploy({
+ repoFullName: fromCallerRepo,
+ branch,
+ env,
+ yaml: fromCallerYaml,
+ provider,
+ path,
+}: {
+ repoFullName?: string;
+ branch?: string;
+ env?: string;
+ yaml?: string;
+ provider?: string;
+ path?: string;
+}) {
+ const pipelineStore = usePipelineStore.getState();
+ const repoFullName = fromCallerRepo || pipelineStore?.repoFullName || pipelineStore?.result?.repo;
+ const selectedBranch = branch || pipelineStore?.selectedBranch || "main";
+ const yaml = pipelineStore?.result?.generated_yaml;
+ const environment = env || pipelineStore?.environment || "dev";
+
+ const providerFinal = provider || pipelineStore?.provider || "aws";
+ const pathFinal = path || `.github/workflows/${environment}-deploy.yml`;
+
+ console.group("[Deploy Debug]");
+ console.log("repoFullName:", repoFullName);
+ console.log("selectedBranch:", selectedBranch);
+ console.log("environment:", environment);
+ console.log("provider:", providerFinal);
+ console.log("path:", pathFinal);
+ console.log("YAML length:", yaml ? yaml.length : 0);
+ console.groupEnd();
+
+ const payload = {
+ repoFullName,
+ branch: selectedBranch,
+ env: environment,
+ yaml,
+ provider: providerFinal,
+ path: pathFinal,
+ };
+
+ console.log("[Deploy] Final payload:", payload);
+
+ const res = await fetch(`${SERVER_BASE}/mcp/v1/pipeline_commit`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ credentials: "include",
+ body: JSON.stringify(payload),
+ });
+
+ const data = await res.json().catch(() => ({}));
+
+ console.group("[Deploy Response]");
+ console.log("Status:", res.status);
+ console.log("Data:", data);
+ console.groupEnd();
+
+ if (!res.ok) throw new Error(`Pipeline commit failed: ${res.statusText}`);
+ return data;
+},
- streamJob(
- jobId: string,
- onEvent: (e: { ts: string; level: "info" | "warn" | "error"; msg: string }) => void
- ) {
- const meta = JOBS.get(jobId) || { repo: "?", env: "dev" };
+ streamJob(_jobId: string, onEvent: (e: { ts: string; level: "info"; msg: string }) => void) {
const steps = [
- `Authenticating to AWS (${meta.env})`,
- `Assuming role`,
- `Validating permissions`,
- `Building artifacts`,
- `Deploying ${meta.repo}`,
- `Verifying rollout`,
- `Done`
+ "Connecting to GitHub...",
+ "Committing workflow file...",
+ "Verifying commit...",
+ "Done ✅"
];
let i = 0;
const timer = setInterval(() => {
if (i >= steps.length) return;
- const level = i === steps.length - 1 ? "info" : "info";
- onEvent({ ts: new Date().toISOString(), level, msg: steps[i++] });
+ onEvent({ ts: new Date().toISOString(), level: "info", msg: steps[i++] });
if (i >= steps.length) clearInterval(timer);
- }, 800);
+ }, 600);
return () => clearInterval(timer);
},
};
diff --git a/client/src/pages/ConfigurePage.tsx b/client/src/pages/ConfigurePage.tsx
index 4003081..dee3edc 100644
--- a/client/src/pages/ConfigurePage.tsx
+++ b/client/src/pages/ConfigurePage.tsx
@@ -122,7 +122,7 @@ export default function ConfigurePage() {
YAML Preview
-
+
{pipeline.result?.yaml ?? pipeline.result?.generated_yaml ?? "Click Generate Pipeline to preview YAML…"}
diff --git a/client/src/pages/DashboardPage.tsx b/client/src/pages/DashboardPage.tsx
index a8145ff..ad2c229 100644
--- a/client/src/pages/DashboardPage.tsx
+++ b/client/src/pages/DashboardPage.tsx
@@ -7,8 +7,13 @@ import { useDeployStore } from "../store/useDeployStore";
export default function DashboardPage() {
const { repo } = useRepoStore();
const { result } = usePipelineStore();
+ console.log("Debug: result.generated_yaml =", result?.generated_yaml);
const cfg = useConfigStore();
+ console.log("Debug: repo =", repo);
+ console.log("Debug: cfg.env =", cfg.env);
+ console.log("Debug: result =", result);
+
// Select stable slices from the deploy store to avoid effect loops
const running = useDeployStore((s) => s.running);
const events = useDeployStore((s) => s.events);
@@ -34,7 +39,7 @@ export default function DashboardPage() {
{result?.pipeline_name} · Generated {result ? new Date(result.created_at).toLocaleString() : "—"}
-
+
{result?.generated_yaml ?? "No pipeline generated yet."}
@@ -42,15 +47,40 @@ export default function DashboardPage() {
startDeploy({ repo: repo!, env: cfg.env })}
+ onClick={() => {
+ const repoFullName = result?.repo || repo;
+ const yaml = result?.generated_yaml;
+ const branch = result?.branch || "main";
+ const environment = cfg.env || "dev";
+ const provider = "aws";
+ const path = `.github/workflows/${environment}-deploy.yml`;
+
+ console.log("Deploy button clicked with payload:", {
+ repoFullName,
+ branch,
+ env: environment,
+ yaml: yaml ? yaml.slice(0, 100) + "..." : "No YAML",
+ provider,
+ path,
+ });
+
+ startDeploy({
+ repoFullName,
+ branch,
+ env: environment,
+ yaml,
+ provider,
+ path,
+ });
+ }}
>
- {running ? "Deploying…" : "Deploy to AWS"}
+ {running ? "Committing…" : "Commit to GitHub"}
{running && Stop }
-
Logs
+
Commit Logs
{events.length === 0 ? "No logs yet." :
events.map((e, i) => (
diff --git a/client/src/pages/DeployPage.tsx b/client/src/pages/DeployPage.tsx
index b8d404e..8eb1b1f 100644
--- a/client/src/pages/DeployPage.tsx
+++ b/client/src/pages/DeployPage.tsx
@@ -10,15 +10,29 @@ export default function DeployPage() {
// loadRoles();
}, []);
+ function startCommit() {
+ // Placeholder function to start commit process
+ console.log("Commit to GitHub started");
+ }
+
return (
+
Commit Workflow to GitHub
{!repo || !branch ? (
Pick a repo/branch on Connect first.
) : (
-
Deploying {repo} @ {branch}
+ <>
+
Committing workflow to GitHub for {repo} @ {branch}
+
+ Commit to GitHub
+
+ >
)}
- {/* role picker + open PR button go here, wired to your deploy store */}
+ {/* role picker + commit to GitHub button go here, wired to your deploy store */}
);
}
diff --git a/client/src/store/useDeployStore.ts b/client/src/store/useDeployStore.ts
index e53560c..a5d5449 100644
--- a/client/src/store/useDeployStore.ts
+++ b/client/src/store/useDeployStore.ts
@@ -19,13 +19,29 @@ type DeployActions = {
export const useDeployStore = create
()((set) => ({
running: false,
events: [],
- async startDeploy({ repo, env }) {
+ async startDeploy(payload: {
+ repoFullName: string;
+ branch?: string;
+ env: string;
+ yaml?: string;
+ provider?: string;
+ path?: string;
+ }) {
+ const { repoFullName, branch = "main", env, yaml, provider = "aws", path = `.github/workflows/${env}-deploy.yml` } = payload || {};
set({ running: true, events: [] });
- const { jobId } = await api.startDeploy({ repo, env });
- const stop = api.streamJob(jobId, (e) =>
- set((s) => ({ events: [...s.events, e] }))
- );
- set({ jobId, stopStream: stop });
+ try {
+ console.group("[useDeployStore.startDeploy] Prepared payload");
+ console.log({ repoFullName, branch, env, provider, path, yamlLength: yaml ? yaml.length : 0 });
+ console.groupEnd();
+ const { jobId } = await api.startDeploy({ repoFullName, branch, env, yaml, provider, path });
+ const stop = api.streamJob(jobId, (e) =>
+ set((s) => ({ events: [...s.events, e] }))
+ );
+ set({ jobId, stopStream: stop });
+ } catch (err) {
+ console.error("[useDeployStore.startDeploy] Error:", err);
+ set({ running: false });
+ }
},
stop() {
set((s) => {
diff --git a/client/src/store/usePipelineStore.ts b/client/src/store/usePipelineStore.ts
index 19ae342..1bd1b87 100644
--- a/client/src/store/usePipelineStore.ts
+++ b/client/src/store/usePipelineStore.ts
@@ -18,6 +18,7 @@ type PipelineState = {
// outputs from MCP
result?: McpPipeline;
+ repoFullName?: string;
// local UI state
roles: { name: string; arn: string }[];
@@ -117,8 +118,16 @@ export const usePipelineStore = create()((set,
res?.generated_yaml ||
"";
+ const repoFullName =
+ res?.data?.data?.repo ||
+ res?.data?.repo ||
+ "";
+
+ console.log("[usePipelineStore] Captured repoFullName:", repoFullName);
+
set({
- result: { ...res, yaml: generated_yaml },
+ result: { ...res, yaml: generated_yaml, generated_yaml },
+ repoFullName,
status: "success",
editing: false,
editedYaml: undefined,