Last active
September 8, 2022 08:19
-
-
Save raymondmars/0aed27a95291892a670b to your computer and use it in GitHub Desktop.
Node project deploy script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
module.exports = function(grunt) { | |
// Please see the Grunt documentation for more information regarding task | |
// creation: http://gruntjs.com/creating-tasks | |
grunt.registerMultiTask('deploy', 'Your task description goes here.', function() { | |
var self = this; | |
var done = self.async(); | |
var Connection = require('ssh2'); | |
var moment = require('moment'); | |
var timeStamp = moment().format('YYYYMMDDHHmmssSSS'); | |
var options = self.options(); | |
var connections = []; | |
var execSingleServer = function(server, connection){ | |
var exec = function(cmd, showLog, next){ | |
//console.log(server.username + "@" + server.host + ":~$ " + cmd); | |
connection.exec(cmd, function(err, stream) { | |
if (err) {throw err;} | |
stream.on('data', function(data, extended) { | |
showLog && console.log(data + ''); | |
}); | |
stream.on('end', function() { | |
next && next(); | |
}); | |
}); | |
}; | |
var execCmds = function(cmds, index, showLog, next){ | |
if(!cmds || cmds.length <= index) { | |
next && next(); | |
} | |
else{ | |
exec(cmds[index++], showLog, function(){ | |
execCmds(cmds,index,true,next); | |
}) | |
} | |
} | |
console.log('executing cmds before deploy'); | |
execCmds(options.cmds_before_deploy, 0, true, function(){ | |
console.log('cmds before deploy executed'); | |
//prepare folder | |
var prepareFolder = 'mkdir -p '+ options.deploy_path + '/node_modules && mkdir -p '+ options.deploy_path + '/releases ';// && mkdir -p '+ options.deploy_path + '/current ' | |
var create_new_release_Folder = 'cd ' + options.deploy_path + '/releases && mkdir ' + timeStamp; | |
var removeCurrent = 'rm -rf ' + options.deploy_path + '/current'; | |
var setCurrent = 'ln -s ' + options.deploy_path + '/releases/' + timeStamp + ' ' + options.deploy_path + '/current'; | |
//set node modules soft link | |
var setModules = 'ln -s ' + options.deploy_path + '/node_modules ' + options.deploy_path + '/current/node_modules'; | |
//install dependency modules /use taobao cnpm | |
var install_dependency = ' cd ' + options.deploy_path + '/current && cnpm install --production ' | |
console.log('start deploy'); | |
exec(prepareFolder + ' && ' + create_new_release_Folder + ' && ' + removeCurrent + ' && ' + setCurrent + ' && ' + setModules, false,function(){ | |
var sys = require('sys') | |
var execLocal = require('child_process').exec; | |
var child; | |
//use rsync | |
child = execLocal("cp -r ./lib ./dist/ && cp ./package.json ./dist/ && cp ./app.coffee ./dist/ && rsync -r -e 'ssh -p " + server.port + "' --exclude='.*' ./dist/ " + server.username + "@" + server.host + ":" + options.deploy_path + "/releases/" + timeStamp, function (error, stdout, stderr) { | |
console.log('end deploy'); | |
console.log('install dependency...'); | |
exec(install_dependency,false,function() { | |
console.log('executing cmds after deploy'); | |
execCmds(options.cmds_after_deploy, 0, true, function(e,r,s){ | |
console.log('cmds after deploy executed'); | |
connection.end(); | |
}); | |
}); | |
}); | |
}) | |
}) | |
} | |
var length = options.servers.length; | |
var completed = 0; | |
var checkCompleted = function(){ | |
completed++; | |
if(completed>=length){ | |
done(); | |
} | |
} | |
options.servers.forEach(function(server){ | |
var c = new Connection(); | |
c.on('connect', function() { | |
console.log('Connecting to server: ' + server.host); | |
}); | |
c.on('ready', function() { | |
console.log('Connected to server: ' + server.host); | |
execSingleServer(server,c); | |
}); | |
c.on('error', function(err) { | |
console.log("Error on server: " + server.host) | |
console.error(err); | |
if (err) {throw err;} | |
}); | |
c.on('close', function(had_error) { | |
console.log("Closed connection for server: " + server.host); | |
checkCompleted(); | |
}); | |
c.connect(server); | |
}) | |
}); | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
module.exports = function (grunt) { | |
// show elapsed time at the end | |
require('time-grunt')(grunt); | |
// load all grunt tasks | |
require('load-grunt-tasks')(grunt); | |
var path_ex = require('path-extra'); | |
grunt.initConfig({ | |
// Watch Config | |
watch: { | |
files: ['views/**/*'], | |
options: { | |
livereload: true | |
}, | |
scripts: { | |
files: [ | |
'assets/scripts/**/*.js', | |
], | |
}, | |
css: { | |
files: [ | |
'assets/styles/**/*.css', | |
], | |
}, | |
sass: { | |
files: ['assets/styles/**/*.sass'], | |
tasks: ['sass:dev'] | |
}, | |
images: { | |
files: [ | |
'assets/images/**/*.{png,jpg,jpeg,webp}' | |
], | |
}, | |
express: { | |
files: [ 'app.coffee', '!**/node_modules/**', '!Gruntfile.js' ], | |
tasks: [ 'express:dev' ], | |
options: { | |
nospawn: true // Without this option specified express won't be reloaded | |
} | |
}, | |
}, | |
// Clean Config | |
clean: { | |
dist: { | |
files: [{ | |
dot: true, | |
src: [ | |
'.tmp', | |
'dist/*', | |
'!dist/.git*' | |
] | |
}] | |
}, | |
server: ['.tmp'], | |
}, | |
// Hint Config | |
jshint: { | |
options: { | |
jshintrc: '.jshintrc' | |
}, | |
all: [ | |
'Gruntfile.js', | |
'assets/scripts/**/*.js', | |
'!assets/scripts/vendor/*', | |
'test/spec/**/*.js' | |
] | |
}, | |
// Sass Config | |
sass: { | |
options: { | |
cacheLocation: '.tmp/.sass-cache' | |
}, | |
dev: { | |
options: { | |
style: 'expanded', | |
lineComments: true | |
}, | |
files: [{ | |
expand: true, | |
cwd: 'assets/styles/sass', | |
dest: 'assets/styles', | |
src: ['screen.sass'], | |
ext: '.css' | |
}] | |
} | |
}, | |
// Express Config | |
express: { | |
options: { | |
// Override defaults here | |
/*cmd: 'coffee'*/ | |
cmd: process.argv[0], | |
opts: ['node_modules/coffee-script/bin/coffee'] | |
}, | |
dev: { | |
options: { | |
script: 'app.coffee' | |
} | |
} | |
}, | |
// Open Config | |
open: { | |
site: { | |
path: 'http://localhost:9001', | |
app: 'Google Chrome' | |
}, | |
editor: { | |
path: './', | |
}, | |
}, | |
// Rev Config | |
rev: { | |
dist: { | |
files: { | |
src: [ | |
'dist/assets/scripts/**/*.js', | |
'dist/assets/styles/**/*.css', | |
'dist/assets/images/**/*.{png,jpg,jpeg,gif,webp}', | |
'dist/assets/styles/fonts/**/*.*' | |
] | |
} | |
} | |
}, | |
// Usemin Config | |
useminPrepare: { | |
options: { | |
dest: 'dist/assets' | |
}, | |
html: ['assets/{,*/}*.html', 'views/**/*.handlebars'] | |
}, | |
usemin: { | |
options: { | |
dirs: ['dist/assets'], | |
basedir: 'dist/assets', | |
}, | |
html: ['dist/assets/{,*/}*.html', 'dist/views/**/*.handlebars'], | |
css: ['dist/assets/styles/{,*/}*.css'] | |
}, | |
// Imagemin Config | |
imagemin: { | |
dist: { | |
files: [{ | |
expand: true, | |
cwd: 'assets/images', | |
src: '**/*.{png,jpg,jpeg}', | |
dest: 'dist/assets/images' | |
}] | |
} | |
}, | |
// SVGmin Config | |
svgmin: { | |
dist: { | |
files: [{ | |
expand: true, | |
cwd: 'assets/images', | |
src: '{,*/}*.svg', | |
dest: 'dist/assets/images' | |
}] | |
} | |
}, | |
// HTML Config | |
htmlmin: { | |
dist: { | |
options: { | |
/*removeCommentsFromCDATA: true, | |
// https://github.com/yeoman/grunt-usemin/issues/44 | |
//collapseWhitespace: true, | |
collapseBooleanAttributes: true, | |
removeAttributeQuotes: true, | |
removeRedundantAttributes: true, | |
useShortDoctype: true, | |
removeEmptyAttributes: true, | |
removeOptionalTags: true*/ | |
}, | |
files: [{ | |
expand: true, | |
cwd: 'assets', | |
src: '*.html', | |
dest: 'dist/assets' | |
}] | |
} | |
}, | |
// Copy Config | |
// Put files not handled in other tasks here | |
copy: { | |
dist: { | |
files: [{ | |
expand: true, | |
dot: true, | |
cwd: 'assets', | |
dest: 'dist/assets', | |
src: [ | |
'*.{ico,png,txt}', | |
'.htaccess', | |
'images/**/*.{webp,gif}', | |
'styles/fonts/{,*/}*.*', | |
'fonts/**/*.*', | |
] | |
}, { | |
expand: true, | |
dot: true, | |
cwd: 'views', | |
dest: 'dist/views/', | |
src: '**/*.handlebars', | |
}] | |
}, | |
styles: { | |
expand: true, | |
dot: true, | |
cwd: 'assets/styles', | |
dest: '.tmp/styles/', | |
src: '{,*/}*.css' | |
}, | |
client_notneedprocess_file: { | |
expand: true, | |
dot: true, | |
cwd: 'assets', | |
dest: 'dist/assets', | |
src: ['images/shake/s1.png','images/shake/s2.png'] | |
}, | |
}, | |
// Concurrent Config | |
concurrent: { | |
dist: [ | |
'copy:styles', | |
'svgmin', | |
'htmlmin' | |
] | |
}, | |
deploy: { | |
production: { | |
options: { | |
servers: [{ | |
host: "Your server ip address", | |
port: portnumber, | |
username: "Your username", | |
privateKey: require('fs').readFileSync(path_ex.join(path_ex.homedir(),'.ssh/id_rsa'), 'utf8') | |
}], | |
cmds_before_deploy: [], | |
cmds_after_deploy: ["cd /data/www/nodeapp/current/ && NODE_ENV=production pm2 kill && NODE_ENV=production pm2 start app.coffee"], | |
/*cmds_after_deploy: [],*/ | |
deploy_path: "/data/www/nodeapp" | |
} | |
} | |
} | |
}); | |
grunt.loadTasks('tasks'); | |
// Register Tasks | |
// Workon | |
grunt.registerTask('workon', 'Start working on this project.', [ | |
//'jshint', | |
'sass:dev', | |
'express:dev', | |
/*'open:site',*/ | |
//'open:editor', | |
'watch' | |
]); | |
// Restart | |
grunt.registerTask('restart', 'Restart the server.', [ | |
'express:dev', | |
'watch' | |
]); | |
// Build | |
grunt.registerTask('build', 'Build production ready assets and views.', [ | |
'clean:dist', | |
'concurrent:dist', | |
'useminPrepare', | |
'imagemin', | |
'concat', | |
'cssmin', | |
'uglify', | |
'copy:dist', | |
'rev', | |
'usemin', | |
'copy:client_notneedprocess_file' | |
]); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment