mirror of
				https://github.com/easingthemes/ssh-deploy.git
				synced 2025-10-30 23:30:09 +08:00 
			
		
		
		
	[engine] use NodeJS instead of Docker
This commit is contained in:
		
							parent
							
								
									3c2d851430
								
							
						
					
					
						commit
						81256f2671
					
				
							
								
								
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| ### Node template | ||||
| # Logs | ||||
| logs | ||||
| *.log | ||||
| npm-debug.log* | ||||
| 
 | ||||
| # Diagnostic reports (https://nodejs.org/api/report.html) | ||||
| report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | ||||
| 
 | ||||
| # Dependency directories | ||||
| node_modules/ | ||||
| 
 | ||||
| # Optional npm cache directory | ||||
| .npm | ||||
| 
 | ||||
| # dotenv environment variables file | ||||
| .env | ||||
| .env.test | ||||
| 
 | ||||
							
								
								
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -1,16 +0,0 @@ | ||||
| FROM debian:9.5-slim | ||||
| 
 | ||||
| # Label | ||||
| LABEL "com.github.actions.name"="ssh deploy" | ||||
| LABEL "com.github.actions.description"="For deploying code over ssh" | ||||
| LABEL "com.github.actions.icon"="truck" | ||||
| LABEL "com.github.actions.color"="green" | ||||
| 
 | ||||
| LABEL "repository"="http://github.com/easingthemes/ssh-deploy" | ||||
| LABEL "homepage"="https://github.com/easingthemes/ssh-deploy" | ||||
| LABEL "maintainer"="Dragan Filipovic <info@frontenddot.com>" | ||||
| 
 | ||||
| # Copy entrypoint | ||||
| ADD entrypoint.sh /entrypoint.sh | ||||
| RUN chmod +x /entrypoint.sh | ||||
| ENTRYPOINT ["/entrypoint.sh"] | ||||
							
								
								
									
										27
									
								
								action.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								action.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| name: 'ssh deploy' | ||||
| description: 'For deploying code over ssh' | ||||
| inputs: | ||||
|   SSH_PRIVATE_KEY:  # Private Key | ||||
|     description: 'Private Key' | ||||
|     required: true | ||||
|   REMOTE_HOST: | ||||
|     description: 'Remote host' | ||||
|     required: true | ||||
|   REMOTE_USER: | ||||
|     description: 'Remote user' | ||||
|     required: true | ||||
|   SOURCE: | ||||
|     description: 'Source directory' | ||||
|     default: '' | ||||
|   TARGET: | ||||
|     description: 'Target directory' | ||||
|     default: '/home/REMOTE_USER/' | ||||
| outputs: | ||||
|   status: | ||||
|     description: 'Status' | ||||
| runs: | ||||
|   using: 'node10' | ||||
|   main: 'dist/index.js' | ||||
| branding: | ||||
|   color: 'green' | ||||
|   icon: 'truck' | ||||
							
								
								
									
										646
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										646
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @ -0,0 +1,646 @@ | ||||
| #!/usr/bin/env node
 | ||||
| module.exports = | ||||
| /******/ (function(modules, runtime) { // webpackBootstrap
 | ||||
| /******/ 	"use strict"; | ||||
| /******/ 	// The module cache
 | ||||
| /******/ 	var installedModules = {}; | ||||
| /******/ | ||||
| /******/ 	// The require function
 | ||||
| /******/ 	function __webpack_require__(moduleId) { | ||||
| /******/ | ||||
| /******/ 		// Check if module is in cache
 | ||||
| /******/ 		if(installedModules[moduleId]) { | ||||
| /******/ 			return installedModules[moduleId].exports; | ||||
| /******/ 		} | ||||
| /******/ 		// Create a new module (and put it into the cache)
 | ||||
| /******/ 		var module = installedModules[moduleId] = { | ||||
| /******/ 			i: moduleId, | ||||
| /******/ 			l: false, | ||||
| /******/ 			exports: {} | ||||
| /******/ 		}; | ||||
| /******/ | ||||
| /******/ 		// Execute the module function
 | ||||
| /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | ||||
| /******/ | ||||
| /******/ 		// Flag the module as loaded
 | ||||
| /******/ 		module.l = true; | ||||
| /******/ | ||||
| /******/ 		// Return the exports of the module
 | ||||
| /******/ 		return module.exports; | ||||
| /******/ 	} | ||||
| /******/ | ||||
| /******/ | ||||
| /******/ 	__webpack_require__.ab = __dirname + "/"; | ||||
| /******/ | ||||
| /******/ 	// the startup function
 | ||||
| /******/ 	function startup() { | ||||
| /******/ 		// Load entry module and return exports
 | ||||
| /******/ 		return __webpack_require__(676); | ||||
| /******/ 	}; | ||||
| /******/ | ||||
| /******/ 	// run startup
 | ||||
| /******/ 	return startup(); | ||||
| /******/ }) | ||||
| /************************************************************************/ | ||||
| /******/ ({ | ||||
| 
 | ||||
| /***/ 129: | ||||
| /***/ (function(module) { | ||||
| 
 | ||||
| module.exports = require("child_process"); | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 243: | ||||
| /***/ (function(module, __unusedexports, __webpack_require__) { | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| 
 | ||||
| var exec = __webpack_require__(129).exec; | ||||
| var execSync = __webpack_require__(129).execSync; | ||||
| var fs = __webpack_require__(747); | ||||
| var path = __webpack_require__(622); | ||||
| var access = fs.access; | ||||
| var accessSync = fs.accessSync; | ||||
| var constants = fs.constants || fs; | ||||
| 
 | ||||
| var isUsingWindows = process.platform == 'win32' | ||||
| 
 | ||||
| var fileNotExists = function(commandName, callback){ | ||||
|     access(commandName, constants.F_OK, | ||||
|     function(err){ | ||||
|         callback(!err); | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
| var fileNotExistsSync = function(commandName){ | ||||
|     try{ | ||||
|         accessSync(commandName, constants.F_OK); | ||||
|         return false; | ||||
|     }catch(e){ | ||||
|         return true; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| var localExecutable = function(commandName, callback){ | ||||
|     access(commandName, constants.F_OK | constants.X_OK, | ||||
|         function(err){ | ||||
|         callback(null, !err); | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
| var localExecutableSync = function(commandName){ | ||||
|     try{ | ||||
|         accessSync(commandName, constants.F_OK | constants.X_OK); | ||||
|         return true; | ||||
|     }catch(e){ | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| var commandExistsUnix = function(commandName, cleanedCommandName, callback) { | ||||
| 
 | ||||
|     fileNotExists(commandName, function(isFile){ | ||||
| 
 | ||||
|         if(!isFile){ | ||||
|             var child = exec('command -v ' + cleanedCommandName + | ||||
|                   ' 2>/dev/null' + | ||||
|                   ' && { echo >&1 ' + cleanedCommandName + '; exit 0; }', | ||||
|                   function (error, stdout, stderr) { | ||||
|                       callback(null, !!stdout); | ||||
|                   }); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         localExecutable(commandName, callback); | ||||
|     }); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| var commandExistsWindows = function(commandName, cleanedCommandName, callback) { | ||||
|   if (/[\x00-\x1f<>:"\|\?\*]/.test(commandName)) { | ||||
|     callback(null, false); | ||||
|     return; | ||||
|   } | ||||
|   var child = exec('where ' + cleanedCommandName, | ||||
|     function (error) { | ||||
|       if (error !== null){ | ||||
|         callback(null, false); | ||||
|       } else { | ||||
|         callback(null, true); | ||||
|       } | ||||
|     } | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
| var commandExistsUnixSync = function(commandName, cleanedCommandName) { | ||||
|   if(fileNotExistsSync(commandName)){ | ||||
|       try { | ||||
|         var stdout = execSync('command -v ' + cleanedCommandName + | ||||
|               ' 2>/dev/null' + | ||||
|               ' && { echo >&1 ' + cleanedCommandName + '; exit 0; }' | ||||
|               ); | ||||
|         return !!stdout; | ||||
|       } catch (error) { | ||||
|         return false; | ||||
|       } | ||||
|   } | ||||
|   return localExecutableSync(commandName); | ||||
| } | ||||
| 
 | ||||
| var commandExistsWindowsSync = function(commandName, cleanedCommandName, callback) { | ||||
|   if (/[\x00-\x1f<>:"\|\?\*]/.test(commandName)) { | ||||
|     return false; | ||||
|   } | ||||
|   try { | ||||
|       var stdout = execSync('where ' + cleanedCommandName, {stdio: []}); | ||||
|       return !!stdout; | ||||
|   } catch (error) { | ||||
|       return false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| var cleanInput = function(s) { | ||||
|   if (/[^A-Za-z0-9_\/:=-]/.test(s)) { | ||||
|     s = "'"+s.replace(/'/g,"'\\''")+"'"; | ||||
|     s = s.replace(/^(?:'')+/g, '') // unduplicate single-quote at the beginning
 | ||||
|       .replace(/\\'''/g, "\\'" ); // remove non-escaped single-quote if there are enclosed between 2 escaped
 | ||||
|   } | ||||
|   return s; | ||||
| } | ||||
| 
 | ||||
| if (isUsingWindows) { | ||||
|   cleanInput = function(s) { | ||||
|     var isPathName = /[\\]/.test(s); | ||||
|     if (isPathName) { | ||||
|       var dirname = '"' + path.dirname(s) + '"'; | ||||
|       var basename = '"' + path.basename(s) + '"'; | ||||
|       return dirname + ':' + basename; | ||||
|     } | ||||
|     return '"' + s + '"'; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| module.exports = function commandExists(commandName, callback) { | ||||
|   var cleanedCommandName = cleanInput(commandName); | ||||
|   if (!callback && typeof Promise !== 'undefined') { | ||||
|     return new Promise(function(resolve, reject){ | ||||
|       commandExists(commandName, function(error, output) { | ||||
|         if (output) { | ||||
|           resolve(commandName); | ||||
|         } else { | ||||
|           reject(error); | ||||
|         } | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
|   if (isUsingWindows) { | ||||
|     commandExistsWindows(commandName, cleanedCommandName, callback); | ||||
|   } else { | ||||
|     commandExistsUnix(commandName, cleanedCommandName, callback); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| module.exports.sync = function(commandName) { | ||||
|   var cleanedCommandName = cleanInput(commandName); | ||||
|   if (isUsingWindows) { | ||||
|     return commandExistsWindowsSync(commandName, cleanedCommandName); | ||||
|   } else { | ||||
|     return commandExistsUnixSync(commandName, cleanedCommandName); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 250: | ||||
| /***/ (function(module, __unusedexports, __webpack_require__) { | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| 
 | ||||
| var spawn = __webpack_require__(129).spawn | ||||
| var util = __webpack_require__(669) | ||||
| 
 | ||||
| var escapeSpaces = function(path) { | ||||
|   if (typeof path === 'string') { | ||||
|     return path.replace(/\b\s/g, '\\ ') | ||||
|   } else { | ||||
|     return path | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| var escapeSpacesInOptions = function(options) { | ||||
|   // Escape paths in the src, dest, include, exclude, and excludeFirst arguments
 | ||||
|   ;['src', 'dest', 'include', 'exclude', 'excludeFirst'].forEach(function( | ||||
|     optionKey | ||||
|   ) { | ||||
|     var option = options[optionKey] | ||||
|     if (typeof option === 'string') { | ||||
|       options[optionKey] = escapeSpaces(option) | ||||
|     } else if (Array.isArray(option) === true) { | ||||
|       options[optionKey] = option.map(escapeSpaces) | ||||
|     } | ||||
|   }) | ||||
| 
 | ||||
|   return options | ||||
| } | ||||
| 
 | ||||
| module.exports = function(options, callback) { | ||||
|   options = options || {} | ||||
|   options = util._extend({}, options) | ||||
|   options = escapeSpacesInOptions(options) | ||||
| 
 | ||||
|   var platform = options.platform || process.platform // Enable process.platform to be mocked in options for testing
 | ||||
|   var isWin = platform === 'win32' | ||||
| 
 | ||||
|   if (typeof options.src === 'undefined') { | ||||
|     throw new Error("'src' directory is missing from options") | ||||
|   } | ||||
| 
 | ||||
|   if (typeof options.dest === 'undefined') { | ||||
|     throw new Error("'dest' directory is missing from options") | ||||
|   } | ||||
| 
 | ||||
|   var dest = options.dest | ||||
| 
 | ||||
|   if (typeof options.host !== 'undefined') { | ||||
|     dest = options.host + ':' + options.dest | ||||
|   } | ||||
| 
 | ||||
|   if (!Array.isArray(options.src)) { | ||||
|     options.src = [options.src] | ||||
|   } | ||||
| 
 | ||||
|   var args = [].concat(options.src) | ||||
| 
 | ||||
|   args.push(dest) | ||||
| 
 | ||||
|   // [rsync failed on windows, copying persmissions](https://github.com/jedrichards/rsyncwrapper/issues/28)
 | ||||
|   // [set chmod flag by default on Windows](https://github.com/jedrichards/rsyncwrapper/pull/29)
 | ||||
|   var chmodArg = (options.args || []).find(function(arg) { | ||||
|     return arg.match(/--chmod=/) | ||||
|   }) | ||||
|   if (isWin && !chmodArg) { | ||||
|     args.push('--chmod=ugo=rwX') | ||||
|   } | ||||
| 
 | ||||
|   if (typeof options.host !== 'undefined' || options.ssh) { | ||||
|     args.push('--rsh') | ||||
|     var rshCmd = 'ssh' | ||||
|     if (typeof options.port !== 'undefined') { | ||||
|       rshCmd += ' -p ' + options.port | ||||
|     } | ||||
|     if (typeof options.privateKey !== 'undefined') { | ||||
|       rshCmd += ' -i ' + options.privateKey | ||||
|     } | ||||
|     if (typeof options.sshCmdArgs !== 'undefined') { | ||||
|       rshCmd += ' ' + options.sshCmdArgs.join(' ') | ||||
|     } | ||||
|     args.push(rshCmd) | ||||
|   } | ||||
| 
 | ||||
|   if (options.recursive === true) { | ||||
|     args.push('--recursive') | ||||
|   } | ||||
| 
 | ||||
|   if (options.times === true) { | ||||
|     args.push('--times') | ||||
|   } | ||||
| 
 | ||||
|   if (options.syncDest === true || options.deleteAll === true) { | ||||
|     args.push('--delete') | ||||
|     args.push('--delete-excluded') | ||||
|   } | ||||
| 
 | ||||
|   if (options.syncDestIgnoreExcl === true || options.delete === true) { | ||||
|     args.push('--delete') | ||||
|   } | ||||
| 
 | ||||
|   if (options.dryRun === true) { | ||||
|     args.push('--dry-run') | ||||
|     args.push('--verbose') | ||||
|   } | ||||
| 
 | ||||
|   if ( | ||||
|     typeof options.excludeFirst !== 'undefined' && | ||||
|     util.isArray(options.excludeFirst) | ||||
|   ) { | ||||
|     options.excludeFirst.forEach(function(value, index) { | ||||
|       args.push('--exclude=' + value) | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   if (typeof options.include !== 'undefined' && util.isArray(options.include)) { | ||||
|     options.include.forEach(function(value, index) { | ||||
|       args.push('--include=' + value) | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   if (typeof options.exclude !== 'undefined' && util.isArray(options.exclude)) { | ||||
|     options.exclude.forEach(function(value, index) { | ||||
|       args.push('--exclude=' + value) | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   switch (options.compareMode) { | ||||
|     case 'sizeOnly': | ||||
|       args.push('--size-only') | ||||
|       break | ||||
|     case 'checksum': | ||||
|       args.push('--checksum') | ||||
|       break | ||||
|   } | ||||
| 
 | ||||
|   if (typeof options.args !== 'undefined' && util.isArray(options.args)) { | ||||
|     args = [...new Set([...args, ...options.args])] | ||||
|   } | ||||
| 
 | ||||
|   args = [...new Set(args)] | ||||
| 
 | ||||
|   var noop = function() {} | ||||
|   var onStdout = options.onStdout || noop | ||||
|   var onStderr = options.onStderr || noop | ||||
| 
 | ||||
|   var cmd = 'rsync ' | ||||
|   args.forEach(function(arg) { | ||||
|     if (arg.substr(0, 4) === 'ssh ') { | ||||
|       arg = '"' + arg + '"' | ||||
|     } | ||||
|     cmd += arg + ' ' | ||||
|   }) | ||||
|   cmd = cmd.trim() | ||||
| 
 | ||||
|   if (options.noExec) { | ||||
|     callback(null, null, null, cmd) | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   try { | ||||
|     var stdout = '' | ||||
|     var stderr = '' | ||||
|     // Launch cmd in a shell just like Node's child_process.exec() does:
 | ||||
|     // see https://github.com/joyent/node/blob/937e2e351b2450cf1e9c4d8b3e1a4e2a2def58bb/lib/child_process.js#L589
 | ||||
|     var child | ||||
|     if (isWin) { | ||||
|       child = spawn('cmd.exe', ['/s', '/c', '"' + cmd + '"'], { | ||||
|         windowsVerbatimArguments: true, | ||||
|         stdio: [process.stdin, 'pipe', 'pipe'], | ||||
|       }) | ||||
|     } else { | ||||
|       child = spawn('/bin/sh', ['-c', cmd]) | ||||
|     } | ||||
| 
 | ||||
|     child.stdout.on('data', function(data) { | ||||
|       onStdout(data) | ||||
|       stdout += data | ||||
|     }) | ||||
| 
 | ||||
|     child.stderr.on('data', function(data) { | ||||
|       onStderr(data) | ||||
|       stderr += data | ||||
|     }) | ||||
| 
 | ||||
|     child.on('exit', function(code) { | ||||
|       var err = null | ||||
|       if (code !== 0) { | ||||
|         err = new Error('rsync exited with code ' + code) | ||||
|         err.code = code | ||||
|       } | ||||
|       callback(err, stdout, stderr, cmd) | ||||
|     }) | ||||
|   } catch (err) { | ||||
|     callback(err, null, null, cmd) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 428: | ||||
| /***/ (function(module, __unusedexports, __webpack_require__) { | ||||
| 
 | ||||
| var exec = __webpack_require__(129).exec; | ||||
| 
 | ||||
| var commandline={ | ||||
|     get:getString, | ||||
|     run:runCommand | ||||
| }; | ||||
| 
 | ||||
| function runCommand(command){ | ||||
|     //return refrence to the child process
 | ||||
|     return exec( | ||||
|         command | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| function getString(command,callback){ | ||||
|     //return refrence to the child process
 | ||||
|     return exec( | ||||
|         command, | ||||
|         ( | ||||
|             function(){ | ||||
|                 return function(err,data,stderr){ | ||||
|                     if(!callback) | ||||
|                         return; | ||||
| 
 | ||||
|                     callback(err, data, stderr); | ||||
|                 } | ||||
|             } | ||||
|         )(callback) | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| module.exports=commandline; | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 622: | ||||
| /***/ (function(module) { | ||||
| 
 | ||||
| module.exports = require("path"); | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 669: | ||||
| /***/ (function(module) { | ||||
| 
 | ||||
| module.exports = require("util"); | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 676: | ||||
| /***/ (function(__unusedmodule, __unusedexports, __webpack_require__) { | ||||
| 
 | ||||
| const fs = __webpack_require__(747); | ||||
| const path = __webpack_require__(622); | ||||
| const commandExists = __webpack_require__(677); | ||||
| const nodeCmd = __webpack_require__(428); | ||||
| const nodeRsync = __webpack_require__(250); | ||||
| 
 | ||||
| const { REMOTE_HOST, REMOTE_USER, SSH_PRIVATE_KEY, DEPLOY_KEY_NAME, SOURCE, TARGET, ARGS, GITHUB_WORKSPACE, HOME } = process.env; | ||||
| console.log('GITHUB_WORKSPACE', GITHUB_WORKSPACE); | ||||
| 
 | ||||
| const sshDeploy = (() => { | ||||
|     const rsync = ({ privateKey, src, dest, args }) => { | ||||
|         console.log(`Starting Rsync Action: ${src} to ${dest}`); | ||||
| 
 | ||||
|         try { | ||||
|             // RSYNC COMMAND
 | ||||
|             nodeRsync({ src, dest, args, privateKey, ssh: true, sshCmdArgs: ['-o StrictHostKeyChecking=no'], recursive: true }, (error, stdout, stderr, cmd) => { | ||||
|                 if (error) { | ||||
|                     console.error('⚠️ Rsync error', error.message); | ||||
|                     process.abort(); | ||||
|                 } else { | ||||
|                     console.log("✅ Rsync finished.", stdout); | ||||
|                 } | ||||
|             }); | ||||
|         } catch (err) { | ||||
|             console.error(`⚠️ An error happened:(.`, err.message, err.stack); | ||||
|             process.abort(); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const init = ({ | ||||
|                       src, | ||||
|                       dest, | ||||
|                       args, | ||||
|                       host = 'localhost', | ||||
|                       username, | ||||
|                       privateKeyContent | ||||
|                   }) => { | ||||
|         validateRsync(() => { | ||||
|             const privateKey = addSshKey(privateKeyContent, DEPLOY_KEY_NAME ||'deploy_key'); | ||||
| 
 | ||||
|             const remoteDest = username + '@' + host + ':' + dest; | ||||
| 
 | ||||
|             rsync({ privateKey, src, dest: remoteDest, args }); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     const validateDir = (dir) => { | ||||
|         if (!fs.existsSync(dir)){ | ||||
|             console.log(`Creating ${dir} dir in `, GITHUB_WORKSPACE); | ||||
|             fs.mkdirSync(dir); | ||||
|         } else { | ||||
|             console.log(`${dir} dir exist`); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const validateFile = (filePath) => { | ||||
|         if (!fs.existsSync(filePath)){ | ||||
|             console.log(`Creating ${filePath} file in `, GITHUB_WORKSPACE); | ||||
|             try { | ||||
|                 fs.writeFileSync(filePath, '', { | ||||
|                     encoding: 'utf8', | ||||
|                     mode: 0o600 | ||||
|                 }); | ||||
|             } catch (e) { | ||||
|                 console.error('⚠️ writeFileSync error', filePath, e.message); | ||||
|                 process.abort(); | ||||
|             } | ||||
|         } else { | ||||
|             console.log(`${filePath} file exist`); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const addSshKey = (key, name) => { | ||||
|         const sshDir = path.join(HOME || __dirname, '.ssh'); | ||||
|         const filePath = path.join(sshDir, name); | ||||
| 
 | ||||
|         validateDir(sshDir); | ||||
|         validateFile(sshDir + '/known_hosts'); | ||||
| 
 | ||||
|         try { | ||||
|             fs.writeFileSync(filePath, key, { | ||||
|                 encoding: 'utf8', | ||||
|                 mode: 0o600 | ||||
|             }); | ||||
|         } catch (e) { | ||||
|             console.error('⚠️ writeFileSync error', filePath, e.message); | ||||
|             process.abort(); | ||||
|         } | ||||
| 
 | ||||
|         console.log('✅ Ssh key added to `.ssh` dir ', filePath); | ||||
| 
 | ||||
|         return filePath; | ||||
|     }; | ||||
| 
 | ||||
|     const validateRsync = (callback = () => {}) => { | ||||
|         const rsyncCli = commandExists.sync('rsync'); | ||||
| 
 | ||||
|         if (!rsyncCli) { | ||||
|             nodeCmd.get( | ||||
|                 'sudo apt-get --no-install-recommends install rsync', | ||||
|                 function(err, data, stderr){ | ||||
|                     if (err) { | ||||
|                         console.log('⚠️ Rsync installation failed ', err.message); | ||||
|                         process.abort(); | ||||
|                     } else { | ||||
|                         console.log('✅ Rsync installed. \n', data, stderr); | ||||
|                         callback(); | ||||
|                     } | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             callback(); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     return { | ||||
|         init | ||||
|     } | ||||
| })(); | ||||
| 
 | ||||
| const validateInputs = (inputs) => { | ||||
|     const validInputs = inputs.filter(input => { | ||||
|         if (!input) { | ||||
|             console.error(`⚠️ ${input} is mandatory`); | ||||
|         } | ||||
| 
 | ||||
|         return input; | ||||
|     }); | ||||
| 
 | ||||
|     if (validInputs.length !== inputs.length) { | ||||
|         process.abort(); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| const run = () => { | ||||
|     validateInputs([SSH_PRIVATE_KEY, REMOTE_HOST, REMOTE_USER]); | ||||
| 
 | ||||
|     sshDeploy.init({ | ||||
|         src: GITHUB_WORKSPACE + '/' + SOURCE || '', | ||||
|         dest: TARGET || '/home/' + REMOTE_USER + '/', | ||||
|         args: [ARGS] || false, | ||||
|         host: REMOTE_HOST, | ||||
|         username: REMOTE_USER, | ||||
|         privateKeyContent: SSH_PRIVATE_KEY, | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
| run(); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 677: | ||||
| /***/ (function(module, __unusedexports, __webpack_require__) { | ||||
| 
 | ||||
| module.exports = __webpack_require__(243); | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ 747: | ||||
| /***/ (function(module) { | ||||
| 
 | ||||
| module.exports = require("fs"); | ||||
| 
 | ||||
| /***/ }) | ||||
| 
 | ||||
| /******/ }); | ||||
| @ -1,13 +0,0 @@ | ||||
| #!/bin/sh | ||||
| 
 | ||||
| set -eu | ||||
| 
 | ||||
| # Set deploy key | ||||
| SSH_PATH="$HOME/.ssh" | ||||
| mkdir "$SSH_PATH" | ||||
| echo "$DEPLOY_KEY" > "$SSH_PATH/deploy_key" | ||||
| chmod 600 "$SSH_PATH/deploy_key" | ||||
| 
 | ||||
| 
 | ||||
| # Do deployment | ||||
| sh -c "rsync $ARGS -e 'ssh -i $SSH_PATH/deploy_key -o StrictHostKeyChecking=no' $GITHUB_WORKSPACE/$SOURCE $TARGET" | ||||
							
								
								
									
										29
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| { | ||||
|   "name": "ssh-deploy", | ||||
|   "version": "2.0.0", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|     "@zeit/ncc": { | ||||
|       "version": "0.20.5", | ||||
|       "resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz", | ||||
|       "integrity": "sha512-XU6uzwvv95DqxciQx+aOLhbyBx/13ky+RK1y88Age9Du3BlA4mMPCy13BGjayOrrumOzlq1XV3SD/BWiZENXlw==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "command-exists": { | ||||
|       "version": "1.2.8", | ||||
|       "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", | ||||
|       "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" | ||||
|     }, | ||||
|     "node-cmd": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/node-cmd/-/node-cmd-3.0.0.tgz", | ||||
|       "integrity": "sha1-OP/3CkqqT2WdID61eGJzcBjiT28=" | ||||
|     }, | ||||
|     "rsyncwrapper": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/rsyncwrapper/-/rsyncwrapper-3.0.1.tgz", | ||||
|       "integrity": "sha512-fkGmeEJRbKveT/6bBqTVzzHS1wtbGQwL6qnwT/+1AtMAsEV5dX1fSAiOJVZrDOnVsOr2lFl8ga1MZLoHekV3yg==" | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										32
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| { | ||||
|   "name": "ssh-deploy", | ||||
|   "version": "2.0.0", | ||||
|   "description": "This GitHub Action deploys specific directory from `GITHUB_WORKSPACE` to a folder on a server via rsync over ssh.", | ||||
|   "main": "src/index.js", | ||||
|   "dependencies": { | ||||
|     "command-exists": "1.2.8", | ||||
|     "node-cmd": "3.0.0", | ||||
|     "rsyncwrapper": "3.0.1" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@zeit/ncc": "^0.20.5" | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "build": "ncc build ./src/index.js -o dist" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|     "url": "git+https://github.com/easingthemes/ssh-deploy.git" | ||||
|   }, | ||||
|   "keywords": [ | ||||
|     "deploy", | ||||
|     "ssh", | ||||
|     "rsync" | ||||
|   ], | ||||
|   "author": "Dragan Filipovic", | ||||
|   "license": "ISC", | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/easingthemes/ssh-deploy/issues" | ||||
|   }, | ||||
|   "homepage": "https://github.com/easingthemes/ssh-deploy#readme" | ||||
| } | ||||
							
								
								
									
										151
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,151 @@ | ||||
| #!/usr/bin/env node
 | ||||
| const fs = require('fs'); | ||||
| const path = require('path'); | ||||
| const commandExists = require('command-exists'); | ||||
| const nodeCmd = require('node-cmd'); | ||||
| const nodeRsync = require('rsyncwrapper'); | ||||
| 
 | ||||
| const { REMOTE_HOST, REMOTE_USER, SSH_PRIVATE_KEY, DEPLOY_KEY_NAME, SOURCE, TARGET, ARGS, GITHUB_WORKSPACE, HOME } = process.env; | ||||
| console.log('GITHUB_WORKSPACE', GITHUB_WORKSPACE); | ||||
| 
 | ||||
| const sshDeploy = (() => { | ||||
|     const rsync = ({ privateKey, src, dest, args }) => { | ||||
|         console.log(`Starting Rsync Action: ${src} to ${dest}`); | ||||
| 
 | ||||
|         try { | ||||
|             // RSYNC COMMAND
 | ||||
|             nodeRsync({ src, dest, args, privateKey, ssh: true, sshCmdArgs: ['-o StrictHostKeyChecking=no'], recursive: true }, (error, stdout, stderr, cmd) => { | ||||
|                 if (error) { | ||||
|                     console.error('⚠️ Rsync error', error.message); | ||||
|                     process.abort(); | ||||
|                 } else { | ||||
|                     console.log("✅ Rsync finished.", stdout); | ||||
|                 } | ||||
|             }); | ||||
|         } catch (err) { | ||||
|             console.error(`⚠️ An error happened:(.`, err.message, err.stack); | ||||
|             process.abort(); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const init = ({ | ||||
|                       src, | ||||
|                       dest, | ||||
|                       args, | ||||
|                       host = 'localhost', | ||||
|                       username, | ||||
|                       privateKeyContent | ||||
|                   }) => { | ||||
|         validateRsync(() => { | ||||
|             const privateKey = addSshKey(privateKeyContent, DEPLOY_KEY_NAME ||'deploy_key'); | ||||
| 
 | ||||
|             const remoteDest = username + '@' + host + ':' + dest; | ||||
| 
 | ||||
|             rsync({ privateKey, src, dest: remoteDest, args }); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     const validateDir = (dir) => { | ||||
|         if (!fs.existsSync(dir)){ | ||||
|             console.log(`Creating ${dir} dir in `, GITHUB_WORKSPACE); | ||||
|             fs.mkdirSync(dir); | ||||
|         } else { | ||||
|             console.log(`${dir} dir exist`); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const validateFile = (filePath) => { | ||||
|         if (!fs.existsSync(filePath)){ | ||||
|             console.log(`Creating ${filePath} file in `, GITHUB_WORKSPACE); | ||||
|             try { | ||||
|                 fs.writeFileSync(filePath, '', { | ||||
|                     encoding: 'utf8', | ||||
|                     mode: 0o600 | ||||
|                 }); | ||||
|             } catch (e) { | ||||
|                 console.error('⚠️ writeFileSync error', filePath, e.message); | ||||
|                 process.abort(); | ||||
|             } | ||||
|         } else { | ||||
|             console.log(`${filePath} file exist`); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const addSshKey = (key, name) => { | ||||
|         const sshDir = path.join(HOME || __dirname, '.ssh'); | ||||
|         const filePath = path.join(sshDir, name); | ||||
| 
 | ||||
|         validateDir(sshDir); | ||||
|         validateFile(sshDir + '/known_hosts'); | ||||
| 
 | ||||
|         try { | ||||
|             fs.writeFileSync(filePath, key, { | ||||
|                 encoding: 'utf8', | ||||
|                 mode: 0o600 | ||||
|             }); | ||||
|         } catch (e) { | ||||
|             console.error('⚠️ writeFileSync error', filePath, e.message); | ||||
|             process.abort(); | ||||
|         } | ||||
| 
 | ||||
|         console.log('✅ Ssh key added to `.ssh` dir ', filePath); | ||||
| 
 | ||||
|         return filePath; | ||||
|     }; | ||||
| 
 | ||||
|     const validateRsync = (callback = () => {}) => { | ||||
|         const rsyncCli = commandExists.sync('rsync'); | ||||
| 
 | ||||
|         if (!rsyncCli) { | ||||
|             nodeCmd.get( | ||||
|                 'sudo apt-get --no-install-recommends install rsync', | ||||
|                 function(err, data, stderr){ | ||||
|                     if (err) { | ||||
|                         console.log('⚠️ Rsync installation failed ', err.message); | ||||
|                         process.abort(); | ||||
|                     } else { | ||||
|                         console.log('✅ Rsync installed. \n', data, stderr); | ||||
|                         callback(); | ||||
|                     } | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             callback(); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     return { | ||||
|         init | ||||
|     } | ||||
| })(); | ||||
| 
 | ||||
| const validateInputs = (inputs) => { | ||||
|     const validInputs = inputs.filter(input => { | ||||
|         if (!input) { | ||||
|             console.error(`⚠️ ${input} is mandatory`); | ||||
|         } | ||||
| 
 | ||||
|         return input; | ||||
|     }); | ||||
| 
 | ||||
|     if (validInputs.length !== inputs.length) { | ||||
|         process.abort(); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| const run = () => { | ||||
|     validateInputs([SSH_PRIVATE_KEY, REMOTE_HOST, REMOTE_USER]); | ||||
| 
 | ||||
|     sshDeploy.init({ | ||||
|         src: GITHUB_WORKSPACE + '/' + SOURCE || '', | ||||
|         dest: TARGET || '/home/' + REMOTE_USER + '/', | ||||
|         args: [ARGS] || ['-rltgoDzvO'], | ||||
|         host: REMOTE_HOST, | ||||
|         username: REMOTE_USER, | ||||
|         privateKeyContent: SSH_PRIVATE_KEY, | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
| run(); | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Dragan Filipovic
						Dragan Filipovic