Deploy projects by pushing files to Dokku server via git.
This commit is contained in:
80
backend/server/src/SecureGitClient.ts
Normal file
80
backend/server/src/SecureGitClient.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import simpleGit, { SimpleGit } from "simple-git";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
|
||||
export type FileData = {
|
||||
id: string;
|
||||
data: string;
|
||||
};
|
||||
|
||||
export class SecureGitClient {
|
||||
private gitUrl: string;
|
||||
private sshKeyPath: string;
|
||||
|
||||
constructor(gitUrl: string, sshKeyPath: string) {
|
||||
this.gitUrl = gitUrl;
|
||||
this.sshKeyPath = sshKeyPath;
|
||||
}
|
||||
|
||||
async pushFiles(fileData: FileData[], repository: string): Promise<void> {
|
||||
let tempDir: string | undefined;
|
||||
|
||||
try {
|
||||
// Create a temporary directory
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'git-push-'));
|
||||
console.log(`Temporary directory created: ${tempDir}`);
|
||||
|
||||
// Write files to the temporary directory
|
||||
for (const { id, data } of fileData) {
|
||||
const filePath = path.join(tempDir, id);
|
||||
const dirPath = path.dirname(filePath);
|
||||
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
}
|
||||
|
||||
console.log("Writing ", filePath, data);
|
||||
fs.writeFileSync(filePath, data);
|
||||
}
|
||||
|
||||
// Initialize the simple-git instance with the temporary directory and custom SSH command
|
||||
const git: SimpleGit = simpleGit(tempDir, {
|
||||
config: [
|
||||
'core.sshCommand=ssh -i ' + this.sshKeyPath + ' -o IdentitiesOnly=yes'
|
||||
]
|
||||
});
|
||||
|
||||
// Initialize a new Git repository
|
||||
await git.init();
|
||||
|
||||
// Add remote repository
|
||||
await git.addRemote("origin", `${this.gitUrl}:${repository}`);
|
||||
|
||||
// Add files to the repository
|
||||
for (const {id, data} of fileData) {
|
||||
await git.add(id);
|
||||
}
|
||||
|
||||
// Commit the changes
|
||||
await git.commit("Add files.");
|
||||
|
||||
// Push the changes to the remote repository
|
||||
await git.push("origin", "master");
|
||||
|
||||
console.log("Files successfully pushed to the repository");
|
||||
|
||||
if (tempDir) {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
console.log(`Temporary directory removed: ${tempDir}`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (tempDir) {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
console.log(`Temporary directory removed: ${tempDir}`);
|
||||
}
|
||||
console.error("Error pushing files to the repository:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import cors from "cors";
|
||||
import express, { Express } from "express";
|
||||
import dotenv from "dotenv";
|
||||
import { createServer } from "http";
|
||||
import { Server } from "socket.io";
|
||||
import { DokkuClient, SSHConfig } from "./DokkuClient";
|
||||
import { DokkuClient } from "./DokkuClient";
|
||||
import { SecureGitClient, FileData } from "./SecureGitClient";
|
||||
import fs from "fs";
|
||||
|
||||
import { z } from "zod";
|
||||
@ -126,6 +126,11 @@ const client = new DokkuClient({
|
||||
|
||||
client.connect();
|
||||
|
||||
const git = new SecureGitClient(
|
||||
"dokku@gitwit.app",
|
||||
process.env.DOKKU_KEY
|
||||
)
|
||||
|
||||
io.on("connection", async (socket) => {
|
||||
try {
|
||||
if (inactivityTimeout) clearTimeout(inactivityTimeout);
|
||||
@ -292,6 +297,33 @@ io.on("connection", async (socket) => {
|
||||
}
|
||||
);
|
||||
|
||||
socket.on(
|
||||
"deploy",
|
||||
async (callback: (response: CallbackResponse) => void) => {
|
||||
try {
|
||||
// Push the project files to the Dokku server
|
||||
console.log("Deploying project ${data.sandboxId}...");
|
||||
// Remove the /project/[id]/ component of each file path:
|
||||
const fixedFilePaths = sandboxFiles.fileData.map((file) => {
|
||||
return {
|
||||
...file,
|
||||
id: file.id.split("/").slice(2).join("/"),
|
||||
};
|
||||
});
|
||||
// Push all files to Dokku.
|
||||
await git.pushFiles(fixedFilePaths, data.sandboxId);
|
||||
callback({
|
||||
success: true,
|
||||
});
|
||||
} catch (error) {
|
||||
callback({
|
||||
success: false,
|
||||
message: "Failed to deploy project: " + error,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
socket.on("createFile", async (name: string, callback) => {
|
||||
try {
|
||||
const size: number = await getProjectSize(data.sandboxId);
|
||||
|
Reference in New Issue
Block a user