[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