Skip to content
This repository was archived by the owner on Jun 8, 2023. It is now read-only.

Commit 07769cf

Browse files
author
Tom Bell
committed
Merge pull request #902 from rh0/master
Drush integration script
2 parents 5d94df3 + 7afb290 commit 07769cf

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed

src/scripts/drush.coffee

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Description:
2+
# Playing with Drush integration. Simple implementation of informational drush commands, and a base
3+
# interface for further drush command integration.
4+
#
5+
# Dependencies:
6+
# None
7+
#
8+
# Configuration:
9+
# The hubot user will need permissions to run drush on the server that it is installed on.
10+
# If the site aliases are to remote servers (likely the case) then the hubot user will also need
11+
# ssh keys setup in order to access these sites.
12+
#
13+
# Notes:
14+
# It would have been easier and more elegant to simply allow the user to funnel drush commands directly
15+
# to the spawn method; however, being that is a colossal security risk, I opted to limit the commands that
16+
# can be executed as well as the options provided to those commands. By default this is limited to
17+
# relatively harmless "info" commands.
18+
#
19+
# Commands:
20+
# hubot drush sa - show the list of available sites ( --update-aliases will refresh this list )
21+
# hubot drush rq - show pending core requirements at a warning level or above
22+
# hubot drush <site alias> cc - Clears "all" cache for a given site alias.
23+
# hubot drush <site alias> pml - Lists the site modules ( "enabled" and "non-core" by default this can be changed with --disbaled or --core )
24+
# hubot drush <site alias> pmi <module/theme> - Show detailed info about a module or theme
25+
# hubot drush <site alias> uinf <user> - Display information about the user specified by uid, email, or username
26+
# hubot drush <site alias> ws - Show the 10 most recent watchdog messages
27+
# hubot drush <site alias> vget <variable name> - Show the value of a given variable
28+
#
29+
# Author:
30+
# rh0
31+
32+
spawn = require("child_process").spawn
33+
34+
drush_interface = ->
35+
site_aliases = []
36+
37+
# helper method to propagate the site aliases in memory
38+
update_aliases = (msg) ->
39+
output = ''
40+
raw_aliases = ''
41+
fetch_aliases = spawn("drush", ["sa"])
42+
fetch_aliases.stdout.on "data", (data) ->
43+
raw_aliases += data
44+
fetch_aliases.stderr.on "data", (data) ->
45+
output = "Update experienced an error: " + data
46+
fetch_aliases.on "exit", (code) ->
47+
if code is 0
48+
site_aliases = raw_aliases.split('\n')
49+
output = "Alias update complete."
50+
unless msg is `undefined`
51+
msg.send output
52+
53+
# run the update script
54+
update_aliases()
55+
56+
# generalized spawn method
57+
execute_drush = (msg, drush_args) ->
58+
output = ''
59+
msg.send "This may take a moment..."
60+
drush_spawn = spawn("drush", drush_args)
61+
drush_spawn.stdout.on "data", (data) ->
62+
output += data
63+
drush_spawn.stderr.on "data", (data) ->
64+
output += data
65+
drush_spawn.on "exit", (code) ->
66+
output += "Command complete."
67+
msg.send output
68+
69+
# the commands that we are allowing drush to execute
70+
# NOTE: If you decide to augment the commands here please carefully consider what you are opening to the people
71+
# interacting with hubot.
72+
allowed_commands =
73+
drush_sa: (msg, command) ->
74+
if command.args.indexOf('--update-aliases') is -1
75+
msg.send "If this list is empty or has unexpected results update aliases ('drush sa --update-aliases')."
76+
msg.send "Aliases we have in memory:\n" + site_aliases.join("\n")
77+
else
78+
msg.send "Updating aliases..."
79+
update_aliases(msg)
80+
81+
drush_cc: (msg, command) ->
82+
execute_drush(msg, [command.alias, "cc", "all"])
83+
84+
drush_rq: (msg, command) ->
85+
execute_drush(msg, [command.alias, "rq", "--severity=1"])
86+
87+
drush_pml: (msg, command) ->
88+
allowed_options = ["--status=enabled", "--status=disabled", "--no-core", "--core"]
89+
filtered_options = command.args.filter((elem) ->
90+
allowed_options.indexOf(elem) isnt -1
91+
)
92+
filtered_options.unshift(command.alias, "pml")
93+
execute_drush(msg, filtered_options)
94+
95+
drush_uinf: (msg, command) ->
96+
user_search = command.args.shift()
97+
execute_drush(msg, [command.alias, "uinf", user_search])
98+
99+
drush_pmi: (msg, command) ->
100+
extension_search = command.args.shift()
101+
execute_drush(msg, [command.alias, "pmi", extension_search])
102+
103+
drush_ws: (msg, command) ->
104+
allowed_options = ["--full"]
105+
filtered_options = command.args.filter((elem) ->
106+
allowed_options.indexOf(elem) isnt -1
107+
)
108+
filtered_options.unshift(command.alias, "ws")
109+
execute_drush(msg, filtered_options)
110+
111+
drush_vget: (msg, command) ->
112+
variable_search = command.args.shift()
113+
# forcing this to --exact to prevent channel flood from a huge search
114+
execute_drush(msg, [command.alias, "vget", variable_search, "--exact"])
115+
116+
# verify alias before firing the command, saves us time on waiting for an err from drush
117+
verify_alias = (check_alias) ->
118+
if site_aliases.indexOf(check_alias) is -1
119+
false
120+
else
121+
true
122+
123+
# parsing the user input after "drush "
124+
parse_command = (user_command) ->
125+
extra_args = user_command.split(' ')
126+
site_alias = extra_args.shift()
127+
command_suff = ''
128+
if site_alias.charAt(0) is "@"
129+
unless verify_alias(site_alias) is false
130+
command_suff = extra_args.shift()
131+
else
132+
`undefined`
133+
# Kind of gross but the site-alias command is the only one that does not need a site alias
134+
# so let's check before we fire up drush to fail.
135+
else unless site_alias is "sa"
136+
`undefined`
137+
else
138+
command_suff = site_alias
139+
site_alias = ''
140+
command = "drush_" + command_suff
141+
if typeof allowed_commands[command] is "function"
142+
return (
143+
cmnd: command
144+
alias: site_alias
145+
args: extra_args
146+
)
147+
else
148+
`undefined`
149+
150+
# BEGIN public facing methods
151+
152+
# The main method, fire this when we receive a "drush " command.
153+
execute: (msg) ->
154+
command = parse_command(msg.match[1])
155+
unless command is `undefined`
156+
allowed_commands[command.cmnd](msg, command)
157+
else
158+
msg.send "'drush " + msg.match[1] + "' is and invalid command. Please try again."
159+
160+
# Instantiate the drush interface
161+
drush = drush_interface()
162+
163+
# Hook in with hobot
164+
module.exports = (robot) ->
165+
robot.respond /drush (.*)$/i, (msg) ->
166+
drush.execute(msg)

0 commit comments

Comments
 (0)