hosting_deployWordpressPlugin
Upload a WordPress plugin directory to a hosting server and trigger its deployment.
Instructions
Deploy a WordPress plugin from a directory to a hosting server. This tool uploads all plugin files and triggers plugin deployment.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Domain name associated with the hosting account (e.g., example.com) | |
| slug | Yes | WordPress plugin slug (e.g., omnisend) | |
| pluginPath | Yes | Absolute or relative path to the plugin directory containing all plugin files |
Implementation Reference
- src/core/runtime.js:791-907 (handler)Main handler function for hosting_deployWordpressPlugin. Validates params, resolves username, scans plugin directory, uploads all plugin files to wp-content/plugins/<slug>-<random>/ dir, then triggers plugin deployment via API.
async handleWordpressPluginDeploy(params) { const { domain, slug, pluginPath } = params; this.hosting_deployWordpressPlugin_validateRequiredParams(params); this.hosting_deployWordpressPlugin_validatePluginDirectory(pluginPath); this.log('info', `Resolving username from domain: ${domain}`); const username = await this.resolveUsername(domain); const randomSuffix = this.hosting_deployWordpressPlugin_generateRandomString(8); const uploadDirName = `${slug}-${randomSuffix}`; this.log('info', `Scanning plugin directory: ${pluginPath}`); const pluginFiles = this.hosting_deployWordpressPlugin_scanDirectory(pluginPath); if (pluginFiles.length === 0) { throw new Error(`No files found in plugin directory: ${pluginPath}`); } this.log('info', `Found ${pluginFiles.length} files to upload`); let uploadCredentials; try { uploadCredentials = await this.fetchUploadCredentials(username, domain); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); throw new Error(`Failed to fetch upload credentials: ${errorMessage}`); } const { url: uploadUrl, auth_key: authToken, rest_auth_key: authRestToken } = uploadCredentials; if (!uploadUrl || !authToken || !authRestToken) { throw new Error('Invalid upload credentials received from API'); } this.log('info', `Starting plugin file upload to ${uploadUrl}`); const results = []; let successCount = 0; let failureCount = 0; for (const fileInfo of pluginFiles) { try { const normalizedRelativePath = this.normalizePath(fileInfo.relativePath); const uploadPath = `wp-content/plugins/${uploadDirName}/${normalizedRelativePath}`; this.log('info', `Uploading: ${fileInfo.absolutePath} -> ${uploadPath}`); const stats = fs.statSync(fileInfo.absolutePath); const uploadResult = await this.uploadFile( fileInfo.absolutePath, uploadPath, uploadUrl, authRestToken, authToken ); results.push({ file: fileInfo.absolutePath, remotePath: uploadPath, status: 'success', uploadUrl: uploadResult.url, size: stats.size }); successCount++; this.log('info', `Successfully uploaded: ${uploadPath}`); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); const normalizedRelativePath = this.normalizePath(fileInfo.relativePath); const uploadPath = `wp-content/plugins/${uploadDirName}/${normalizedRelativePath}`; results.push({ file: fileInfo.absolutePath, remotePath: uploadPath, status: 'error', error: errorMessage }); failureCount++; this.log('error', `Failed to upload ${fileInfo.absolutePath}: ${errorMessage}`); } } const overallStatus = failureCount === 0 ? 'success' : (successCount === 0 ? 'failure' : 'partial'); if (failureCount === 0) { try { this.log('info', 'All files uploaded successfully, triggering plugin deployment...'); await this.hosting_deployWordpressPlugin_deployPlugin(username, domain, slug, uploadDirName); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); this.log('error', `Plugin deployment failed: ${errorMessage}`); return { status: 'partial', summary: { total: pluginFiles.length, successful: successCount, failed: failureCount }, results, deploymentError: errorMessage }; } } return { status: overallStatus, summary: { total: pluginFiles.length, successful: successCount, failed: failureCount }, results, uploadDirName }; } - src/core/runtime.js:675-682 (helper)Generates a random 8-character alphanumeric string used as a suffix for the upload directory name.
hosting_deployWordpressPlugin_generateRandomString(length) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } - src/core/runtime.js:684-698 (helper)Validates the required params for the deploy plugin tool: domain, slug, and pluginPath must be present and strings.
hosting_deployWordpressPlugin_validateRequiredParams(params) { const { domain, slug, pluginPath } = params; if (!domain || typeof domain !== 'string') { throw new Error('domain is required and must be a string'); } if (!slug || typeof slug !== 'string') { throw new Error('slug is required and must be a string'); } if (!pluginPath || typeof pluginPath !== 'string') { throw new Error('pluginPath is required and must be a string'); } } - src/core/runtime.js:700-709 (helper)Validates that the pluginPath exists and is a directory.
hosting_deployWordpressPlugin_validatePluginDirectory(pluginPath) { if (!fs.existsSync(pluginPath)) { throw new Error(`Plugin directory not found: ${pluginPath}`); } const pluginStats = fs.statSync(pluginPath); if (!pluginStats.isDirectory()) { throw new Error(`Plugin path is not a directory: ${pluginPath}`); } } - src/core/runtime.js:711-735 (helper)Recursively scans a directory and returns all files with absolute and relative paths.
hosting_deployWordpressPlugin_scanDirectory(dirPath, basePath = dirPath) { const files = []; const scanDir = (currentPath) => { const items = fs.readdirSync(currentPath); for (const item of items) { const itemPath = path.join(currentPath, item); const stats = fs.statSync(itemPath); if (stats.isDirectory()) { scanDir(itemPath); } else if (stats.isFile()) { const relativePath = path.relative(basePath, itemPath); files.push({ absolutePath: itemPath, relativePath: relativePath }); } } }; scanDir(dirPath); return files; }