Skip to main content
Glama
deploy-helper.jsโ€ข4.65 kB
import path from 'path'; import crypto from 'crypto'; /** * Deploy helper functions for secure file deployment */ /** * Generate a unique temporary filename */ export function getTempFilename(originalName) { const timestamp = Date.now(); const random = crypto.randomBytes(4).toString('hex'); const ext = path.extname(originalName); const base = path.basename(originalName, ext); return `/tmp/${base}_${timestamp}_${random}${ext}`; } /** * Build deployment strategy based on target path and permissions */ export function buildDeploymentStrategy(remotePath, options = {}) { const { sudoPassword = null, owner = null, permissions = null, backup = true, restart = null } = options; const strategy = { steps: [], requiresSudo: false }; // Step 1: Backup existing file if requested if (backup) { strategy.steps.push({ type: 'backup', command: `if [ -f "${remotePath}" ]; then cp "${remotePath}" "${remotePath}.bak.$(date +%Y%m%d_%H%M%S)"; fi` }); } // Step 2: Determine if we need sudo const needsSudo = remotePath.startsWith('/etc/') || remotePath.startsWith('/var/') || remotePath.startsWith('/usr/') || owner || permissions; if (needsSudo) { strategy.requiresSudo = true; } // Step 3: Copy from temp to final location const copyCmd = needsSudo && sudoPassword ? `echo "${sudoPassword}" | sudo -S cp {{tempFile}} "${remotePath}"` : needsSudo ? `sudo cp {{tempFile}} "${remotePath}"` : `cp {{tempFile}} "${remotePath}"`; strategy.steps.push({ type: 'copy', command: copyCmd }); // Step 4: Set ownership if specified if (owner) { const chownCmd = sudoPassword ? `echo "${sudoPassword}" | sudo -S chown ${owner} "${remotePath}"` : `sudo chown ${owner} "${remotePath}"`; strategy.steps.push({ type: 'chown', command: chownCmd }); } // Step 5: Set permissions if specified if (permissions) { const chmodCmd = sudoPassword ? `echo "${sudoPassword}" | sudo -S chmod ${permissions} "${remotePath}"` : `sudo chmod ${permissions} "${remotePath}"`; strategy.steps.push({ type: 'chmod', command: chmodCmd }); } // Step 6: Restart service if specified if (restart) { strategy.steps.push({ type: 'restart', command: restart }); } // Step 7: Cleanup temp file strategy.steps.push({ type: 'cleanup', command: 'rm -f {{tempFile}}' }); return strategy; } /** * Parse deployment configuration from file path patterns * Examples: * /home/user/app/file.js -> normal deploy * /etc/nginx/sites-available/site -> needs sudo * /var/www/html/index.html -> needs sudo */ export function detectDeploymentNeeds(remotePath) { const needs = { sudo: false, suggestedOwner: null, suggestedPerms: null }; // System directories that typically need sudo if (remotePath.startsWith('/etc/')) { needs.sudo = true; needs.suggestedOwner = 'root:root'; needs.suggestedPerms = '644'; } else if (remotePath.startsWith('/var/www/')) { needs.sudo = true; needs.suggestedOwner = 'www-data:www-data'; needs.suggestedPerms = '644'; } else if (remotePath.includes('/nginx/')) { needs.sudo = true; needs.suggestedOwner = 'root:root'; needs.suggestedPerms = '644'; } else if (remotePath.includes('/apache/') || remotePath.includes('/httpd/')) { needs.sudo = true; needs.suggestedOwner = 'www-data:www-data'; needs.suggestedPerms = '644'; } else if (remotePath.includes('/frappe-bench/')) { // For ERPNext/Frappe deployments needs.sudo = false; needs.suggestedOwner = null; // Will be handled by the app needs.suggestedPerms = '644'; } return needs; } /** * Create batch deployment script for multiple files */ export function createBatchDeployScript(deployments) { const script = ['#!/bin/bash', 'set -e', '']; script.push('# Batch deployment script'); script.push(`# Generated at ${new Date().toISOString()}`); script.push(''); deployments.forEach((deploy, index) => { script.push(`# File ${index + 1}: ${deploy.localPath} -> ${deploy.remotePath}`); deploy.strategy.steps.forEach(step => { if (step.type !== 'cleanup') { script.push(step.command.replace('{{tempFile}}', deploy.tempFile)); } }); script.push(''); }); // Cleanup all temp files at the end script.push('# Cleanup temporary files'); deployments.forEach(deploy => { script.push(`rm -f ${deploy.tempFile}`); }); return script.join('\n'); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bvisible/mcp-ssh-manager'

If you have feedback or need assistance with the MCP directory API, please join our Discord server