@reliverse/rse-sdk
Version:
@reliverse/rse-sdk allows you to create new plugins for @reliverse/rse CLI, interact with reliverse.org, and even extend your own CLI functionality (you may also try @reliverse/dler-sdk for this case).
161 lines (160 loc) • 5.3 kB
JavaScript
import { relinka, relinkaAsync } from "@reliverse/relinka";
import { deploymentsCreateDeployment } from "@vercel/sdk/funcs/deploymentsCreateDeployment";
import { deploymentsGetDeployment } from "@vercel/sdk/funcs/deploymentsGetDeployment";
import { deploymentsGetDeploymentEvents } from "@vercel/sdk/funcs/deploymentsGetDeploymentEvents";
import { simpleGit } from "simple-git";
import { withRateLimit } from "./vercel-api.js";
import { getPrimaryVercelTeam } from "./vercel-team.js";
export async function monitorDeployment(vercelInstance, deploymentId, teamId, slug, showDetailedLogs = false) {
try {
const logsRes = await deploymentsGetDeploymentEvents(vercelInstance, {
idOrUrl: deploymentId,
teamId,
slug
});
if (!logsRes.ok) throw logsRes.error;
const logs = logsRes.value;
if (Array.isArray(logs)) {
let errors = 0;
let warnings = 0;
for (const log of logs) {
const timestamp = new Date(log.created).toLocaleTimeString();
const message = `[${log.type}] ${log.text}`;
if (log.type === "error") {
errors++;
relinka("error", `${timestamp}: ${message}`);
} else if (log.type === "warning") {
warnings++;
relinka("warn", `${timestamp}: ${message}`);
} else if (showDetailedLogs) {
relinka("info", `${timestamp}: ${message}`);
}
}
if (errors > 0 || warnings > 0) {
relinka(
"info",
`Deployment summary: ${errors} errors, ${warnings} warnings`
);
}
}
} catch (error) {
relinka(
"error",
"Error monitoring deployment:",
error instanceof Error ? error.message : String(error)
);
}
}
export async function createInitialVercelDeployment(githubInstance, vercelInstance, projectId, memory, projectName, config, selectedOptions, githubUsername, githubToken) {
if (!githubToken) {
throw new Error(
"GitHub token not found in rse's memory. Please restart the CLI and try again. Notify the @reliverse/rse developers if the problem persists."
);
}
relinka("info", "Creating the initial deployment...");
relinka("verbose", "Using Vercel deployment config:", JSON.stringify(config));
const vercelTeam = await getPrimaryVercelTeam(vercelInstance, memory);
if (!vercelTeam) throw new Error("No Vercel team found.");
const teamId = vercelTeam.id;
const slug = vercelTeam.slug;
const git = simpleGit();
let commitSha;
try {
commitSha = await git.revparse(["HEAD"]);
} catch (error) {
throw new Error(
`Failed to get local commit SHA. Ensure the repository is not empty. ${error}`
);
}
let numericRepoId;
try {
const repoResp = await githubInstance.rest.repos.get({
owner: githubUsername,
repo: projectName
});
numericRepoId = repoResp.data.id;
} catch (error) {
throw new Error(`Failed to fetch GitHub repository numeric ID. ${error}`);
}
const deploymentRes = await withRateLimit(async () => {
return await deploymentsCreateDeployment(vercelInstance, {
teamId,
slug,
requestBody: {
name: projectName,
target: "production",
project: projectId,
gitSource: {
type: "github",
ref: "main",
repoId: numericRepoId,
sha: commitSha
}
}
});
});
if (!deploymentRes.ok) throw deploymentRes.error;
const deployment = deploymentRes.value;
if (!deployment?.id || !deployment.readyState || !deployment.url) {
throw new Error(
"Failed to create deployment: invalid response from Vercel"
);
}
const inProgressStates = ["BUILDING", "INITIALIZING", "QUEUED"];
const deploymentUrl = slug ? `https://vercel.com/${slug}/${projectName}/${deployment.id}` : "https://vercel.com";
relinka(
"info",
`Deployment started. To monitor progress, visit: ${deploymentUrl}`,
"Status messages will appear every 10 seconds."
);
let lastMessageTime = Date.now();
let status = deployment.readyState;
while (inProgressStates.includes(status)) {
await monitorDeployment(
vercelInstance,
deployment.id,
teamId,
slug,
selectedOptions.includes("monitoring")
);
await new Promise((resolve) => setTimeout(resolve, 5e3));
const depRes = await withRateLimit(async () => {
return await deploymentsGetDeployment(vercelInstance, {
idOrUrl: deployment.id,
teamId,
slug
});
});
if (!depRes.ok) throw depRes.error;
status = depRes.value.readyState;
const now = Date.now();
if (now - lastMessageTime >= 1e4) {
await relinkaAsync(
"info",
`Deployment status: ${status}`,
void 0,
void 0,
{ delay: 50, useSpinner: true, spinnerDelay: 50 }
);
lastMessageTime = now;
}
}
if (status !== "READY") {
await monitorDeployment(
vercelInstance,
deployment.id,
teamId,
slug,
selectedOptions.includes("monitoring")
);
throw new Error(`Deployment failed with status: ${status}`);
}
await monitorDeployment(
vercelInstance,
deployment.id,
teamId,
slug,
selectedOptions.includes("monitoring")
);
return { url: deployment.url, id: deployment.id };
}