From f6e605694f2f75b78cafa8b79e0a4d78b8667934 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Jan 2016 15:15:45 +0100 Subject: [PATCH 01/10] Command analyzer --- deployment.coffee | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index 1c3f8a1..f656650 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -10,17 +10,43 @@ # module.exports = (robot) -> - robot.hear /deploy ([^\s]+)( from branch ([^\s]+))? to ([^\s]+)( after (.*))?$/i, (res) -> + fs = require 'fs' + + robot.hear /deploy +([^\s]+)( +from +branch +([^\s]+))? +to +([^\s]+)( +after (.*))?$/i, (res) -> project = res.match[1] environnement = res.match[4] branch = if res.match[3] then res.match[3] else null - commands = if res.match[6] then cleanCommands res.match[6].split(',') else [] + commands = if res.match[6] then cleanCommands res.match[6].split "," else [] + + directory = "/home/simon/www/repo/" + project + + try + fs.stat directory, (err, stats) -> + if err != null or !stats.isDirectory + return res.reply "Project not found [" + directory + "]" + + process.chdir(directory) + catch e + res.reply "Exception: " + e cleanCommands = (commands) -> results = [] - commands = commands.map(Function.prototype.call, String.prototype.trim) + commands = commands.map Function.prototype.call, String.prototype.trim + + interpreters = { + "sf" : "php symfony", + "sf2" : "php app/console", + "sf3" : "php bin/console", + "artisan": "php artisan", + } for command in commands - results.push(command) if command != '' + if command != "" + if command.match /(sf[2-3]?|artisan):.+/ + elements = command.split(":") + interpreter = elements[0] + elements = elements.splice 1 + args = elements.join(":") + results.push interpreters[interpreter] + " " + args results From 8484ecc66203e55af1696af3963fd12787229f5c Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Jan 2016 16:07:27 +0100 Subject: [PATCH 02/10] Project versionning detection --- deployment.coffee | 51 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index f656650..6f99b8f 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -2,7 +2,7 @@ # Deployment script # # Commands: -# hubot deploy [from branch ] to [after [, , ...]] +# hubot deploy [with ] [from branch ] to [after [, , ...]] # # URLS: # @@ -12,11 +12,12 @@ module.exports = (robot) -> fs = require 'fs' - robot.hear /deploy +([^\s]+)( +from +branch +([^\s]+))? +to +([^\s]+)( +after (.*))?$/i, (res) -> - project = res.match[1] - environnement = res.match[4] - branch = if res.match[3] then res.match[3] else null - commands = if res.match[6] then cleanCommands res.match[6].split "," else [] + robot.hear /deploy +([^\s]+)( +with +([^\s]+))?( +from +branch +([^\s]+))? +to +([^\s]+)( +after (.*))?$/i, (res) -> + project = res.match[1] + target = res.match[6] + program = if res.match[3] then res.match[3] else null + branch = if res.match[5] then res.match[5] else null + commands = if res.match[8] then cleanCommands res.match[8].split "," else [] directory = "/home/simon/www/repo/" + project @@ -26,9 +27,47 @@ module.exports = (robot) -> return res.reply "Project not found [" + directory + "]" process.chdir(directory) + + fs.stat '.svn', (err, stats) -> + if err == null + deploy new SvnProjectVersionning(branch), commands + + fs.stat '.git', (err, stats) -> + if err == null + deploy new GitProjectVersionning(branch), commands + catch e res.reply "Exception: " + e +class ProjectVersionning + constructor: (@branch) -> + getUpdateCommands: () -> + +class SvnProjectVersionning extends ProjectVersionning + getUpdateCommands: () -> + ['svn up'] + +class GitProjectVersionning extends ProjectVersionning + getUpdateCommands: () -> + commands = [] + + if @branch == null + commands.push 'git pull origin $(git rev-parse --abbrev-ref HEAD)' + else + br = @branch.split('/') + + if br.length == 1 + commands.push 'git checkout ' + br[0] + commands.push 'git pull origin ' + br[0] + else if br.length == 2 + commands.push 'git checkout ' + br[1] + commands.push 'git pull ' + br.join(' ') + + commands + +deploy = (projectVersionning, commands) -> + console.log projectVersionning.getUpdateCommands() + cleanCommands = (commands) -> results = [] commands = commands.map Function.prototype.call, String.prototype.trim From bd26e8cbfe8cf005bc2c0d66752482c4072e86d1 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Jan 2016 16:38:31 +0100 Subject: [PATCH 03/10] Deployment commands --- deployment.coffee | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index 6f99b8f..21f3509 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -26,16 +26,20 @@ module.exports = (robot) -> if err != null or !stats.isDirectory return res.reply "Project not found [" + directory + "]" - process.chdir(directory) - - fs.stat '.svn', (err, stats) -> - if err == null - deploy new SvnProjectVersionning(branch), commands + try + fs.statSync directory + '/.svn' + pv = new SvnProjectVersionning branch + catch e - fs.stat '.git', (err, stats) -> - if err == null - deploy new GitProjectVersionning(branch), commands + try + fs.statSync directory + '/.git' + pv = new GitProjectVersionning branch + catch e + if pv + deploy directory, pv, commands + else + res.reply "Not a SVN or GIT repository" catch e res.reply "Exception: " + e @@ -65,8 +69,12 @@ class GitProjectVersionning extends ProjectVersionning commands -deploy = (projectVersionning, commands) -> - console.log projectVersionning.getUpdateCommands() +deploy = (directory, projectVersionning, commands) -> + exec = require('sync-exec'); + commands = projectVersionning.getUpdateCommands().concat(commands) + + for command in commands + exec command, {cwd: directory} cleanCommands = (commands) -> results = [] From ca70506e9f90973656c00a76abaec2ac099fce51 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Jan 2016 16:41:30 +0100 Subject: [PATCH 04/10] composer interpreter --- deployment.coffee | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index 21f3509..6c66de5 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -81,10 +81,11 @@ cleanCommands = (commands) -> commands = commands.map Function.prototype.call, String.prototype.trim interpreters = { - "sf" : "php symfony", - "sf2" : "php app/console", - "sf3" : "php bin/console", - "artisan": "php artisan", + "sf" : "php symfony", + "sf2" : "php app/console", + "sf3" : "php bin/console", + "composer": "composer", + "artisan" : "php artisan", } for command in commands From ea4f3445fb16d39bdb878c0617becff0758e4f29 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Jan 2016 17:00:53 +0100 Subject: [PATCH 05/10] Deployment commands --- deployment.coffee | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index 6c66de5..7b8fec3 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -8,10 +8,9 @@ # # Notes: # +fs = require 'fs' module.exports = (robot) -> - fs = require 'fs' - robot.hear /deploy +([^\s]+)( +with +([^\s]+))?( +from +branch +([^\s]+))? +to +([^\s]+)( +after (.*))?$/i, (res) -> project = res.match[1] target = res.match[6] @@ -37,7 +36,7 @@ module.exports = (robot) -> catch e if pv - deploy directory, pv, commands + deploy directory, pv, commands, target, program else res.reply "Not a SVN or GIT repository" catch e @@ -69,13 +68,37 @@ class GitProjectVersionning extends ProjectVersionning commands -deploy = (directory, projectVersionning, commands) -> +deploy = (directory, projectVersionning, commands, target, program) -> exec = require('sync-exec'); commands = projectVersionning.getUpdateCommands().concat(commands) for command in commands exec command, {cwd: directory} + exec buildDeployCommand(directory, program, target), {cwd: directory} + +buildDeployCommand = (directory, program, target) -> + if program == 'mage' + command = 'mage deploy to:' + target + else + interpreter = null + + try + fs.statSync directory + '/bin/console' + interpreter = 'php bin/console' + catch e + + try + fs.statSync directory + '/app/console' + interpreter = 'php app/console' + catch e + + if interpreter != null + command = interpreter + ' project:deploy ' + target + ' --go' + + command + + cleanCommands = (commands) -> results = [] commands = commands.map Function.prototype.call, String.prototype.trim @@ -84,8 +107,7 @@ cleanCommands = (commands) -> "sf" : "php symfony", "sf2" : "php app/console", "sf3" : "php bin/console", - "composer": "composer", - "artisan" : "php artisan", + "composer": "composer" } for command in commands From 4b5f65b9dfa970d8e649879dfc56da025cd3bb02 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Jan 2016 17:42:54 +0100 Subject: [PATCH 06/10] Command runs --- deployment.coffee | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index 7b8fec3..ae80e74 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -68,18 +68,24 @@ class GitProjectVersionning extends ProjectVersionning commands -deploy = (directory, projectVersionning, commands, target, program) -> +logExec = (command, options) -> exec = require('sync-exec'); + + console.log command + exec command, options + + +deploy = (directory, projectVersionning, commands, target, program) -> commands = projectVersionning.getUpdateCommands().concat(commands) for command in commands - exec command, {cwd: directory} + logExec command , {cwd: directory} - exec buildDeployCommand(directory, program, target), {cwd: directory} + logExec buildDeployCommand(directory, program, target), {cwd: directory} buildDeployCommand = (directory, program, target) -> if program == 'mage' - command = 'mage deploy to:' + target + command = 'vendor/bin/mage deploy to:' + target else interpreter = null @@ -118,5 +124,6 @@ cleanCommands = (commands) -> elements = elements.splice 1 args = elements.join(":") results.push interpreters[interpreter] + " " + args - + else + results.push command results From 075380ec236523859235dbc98bc4768193ee8f01 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Fri, 22 Jan 2016 11:08:25 +0100 Subject: [PATCH 07/10] composer added --- deployment.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index ae80e74..f3a2321 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -57,7 +57,7 @@ class GitProjectVersionning extends ProjectVersionning if @branch == null commands.push 'git pull origin $(git rev-parse --abbrev-ref HEAD)' else - br = @branch.split('/') + br = @branch.split "/" if br.length == 1 commands.push 'git checkout ' + br[0] @@ -69,7 +69,7 @@ class GitProjectVersionning extends ProjectVersionning commands logExec = (command, options) -> - exec = require('sync-exec'); + exec = require "sync-exec" console.log command exec command, options @@ -118,8 +118,8 @@ cleanCommands = (commands) -> for command in commands if command != "" - if command.match /(sf[2-3]?|artisan):.+/ - elements = command.split(":") + if command.match /(sf[2-3]?|composer):.+/ + elements = command.split ":" interpreter = elements[0] elements = elements.splice 1 args = elements.join(":") From 4fb251d788734c7fcaf2f93fae719a867f51e035 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sat, 23 Jan 2016 10:49:44 +0100 Subject: [PATCH 08/10] projects directory --- deployment.coffee | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index f3a2321..41cae5c 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -10,15 +10,33 @@ # fs = require 'fs' +deploymentDirectory = null + module.exports = (robot) -> + robot.hear /deploy set ([^\s]+) +(.+)$/i, (res) -> + if res.match[1] == "directory" + deploymentDirectory = res.match[2] + robot.hear /deploy +([^\s]+)( +with +([^\s]+))?( +from +branch +([^\s]+))? +to +([^\s]+)( +after (.*))?$/i, (res) -> + + if ! process.env.hasOwnProperty('HUBO_DEPLOYMENT_PROJECTS_DIRECTORY') + if deploymentDirectory == null + res.reply "You must set the env var HUBO_DEPLOYMENT_PROJECTS_DIRECTORY with the directory of the projects." + res.reply "Temporaly, you can use the command: deploy set directory " + return + project = res.match[1] target = res.match[6] program = if res.match[3] then res.match[3] else null branch = if res.match[5] then res.match[5] else null commands = if res.match[8] then cleanCommands res.match[8].split "," else [] - directory = "/home/simon/www/repo/" + project + if deploymentDirectory != null + directory = deploymentDirectory + else + directory = process.env.HUBO_DEPLOYMENT_PROJECTS_DIRECTORY + + directory += "/" + project try fs.stat directory, (err, stats) -> @@ -103,7 +121,6 @@ buildDeployCommand = (directory, program, target) -> command = interpreter + ' project:deploy ' + target + ' --go' command - cleanCommands = (commands) -> results = [] From 350af4c943728be8d39f522309a8ced6f6426c6f Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sat, 23 Jan 2016 11:24:19 +0100 Subject: [PATCH 09/10] output --- deployment.coffee | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index 41cae5c..f7ad95f 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -54,7 +54,8 @@ module.exports = (robot) -> catch e if pv - deploy directory, pv, commands, target, program + d = deploy directory, pv, commands, target, program + res.reply d else res.reply "Not a SVN or GIT repository" catch e @@ -88,18 +89,52 @@ class GitProjectVersionning extends ProjectVersionning logExec = (command, options) -> exec = require "sync-exec" - - console.log command exec command, options deploy = (directory, projectVersionning, commands, target, program) -> commands = projectVersionning.getUpdateCommands().concat(commands) + canDeploy = true + results = [] - for command in commands - logExec command , {cwd: directory} + for command in commands + if !canDeploy + continue - logExec buildDeployCommand(directory, program, target), {cwd: directory} + stmt = logExec command , {cwd: directory} + + results.push { + command: command, + status: stmt.status, + stdout: stmt.stdout, + stderr: stmt.stderr, + } + + if stmt.status != 0 + canDeploy = false + + if canDeploy + command = buildDeployCommand(directory, program, target) + stmt = logExec command, {cwd: directory} + + results.push { + command: command, + status: stmt.status, + stdout: stmt.stdout, + stderr: stmt.stderr, + } + + output = "" + + for stmt in results + status = if stmt.status == 0 then 'OK' else 'KO' + output += "`#{stmt.command}` is *#{status}*\n" + + if stmt.status != 0 + output += "\n```#{stmt.stdout} #{stmt.stderr}```" + + output + buildDeployCommand = (directory, program, target) -> if program == 'mage' From 2fd887d40a54d37ea19cd3d0802b310374386d91 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sat, 23 Jan 2016 11:54:59 +0100 Subject: [PATCH 10/10] output --- deployment.coffee | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/deployment.coffee b/deployment.coffee index f7ad95f..27ec8fa 100644 --- a/deployment.coffee +++ b/deployment.coffee @@ -55,7 +55,7 @@ module.exports = (robot) -> if pv d = deploy directory, pv, commands, target, program - res.reply d + res.send d else res.reply "Not a SVN or GIT repository" catch e @@ -127,14 +127,26 @@ deploy = (directory, projectVersionning, commands, target, program) -> output = "" for stmt in results - status = if stmt.status == 0 then 'OK' else 'KO' - output += "`#{stmt.command}` is *#{status}*\n" - - if stmt.status != 0 - output += "\n```#{stmt.stdout} #{stmt.stderr}```" + output += generateOutput stmt output +generateOutput = (stmt) -> + prefix = "deploy-" + Date.now() + status = + if stmt.status == 0 + "OK" + else + "Failed" + """ +

#{stmt.command}
#{status}

+
+ Outputs: STDOUT STDERR + + +
+ + """ buildDeployCommand = (directory, program, target) -> if program == 'mage'