Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 329 lines (270 sloc) 6.075 kb
741a894 @visnup our barely patched version of tj's deploy script
visnup authored
1 #!/usr/bin/env bash
2
3 VERSION="0.3.2"
4 CONFIG=./deploy.conf
5 LOG=/tmp/deploy.log
6 TEST=1
7 REF=
8 ENV=production
9
10 #
11 # Output usage information.
12 #
13
14 usage() {
15 cat <<-EOF
16
17 Usage: deploy [options] <env> [command]
18
19 Options:
20
21 -C, --chdir <path> change the working directory to <path>
22 -c, --config <path> set config path. defaults to ./deploy.conf
23 -T, --no-tests ignore test hook
24 -V, --version output program version
25 -h, --help output help information
26
27 Commands:
28
29 setup run remote setup commands
30 update update deploy to the latest release
31 revert [n] revert to [n]th last deployment or 1
32 config [key] output config file or [key]
33 curr[ent] output current release commit
34 prev[ious] output previous release commit
35 exec|run <cmd> execute the given <cmd>
36 list list previous deploy commits
37 [ref] deploy to [ref], the 'ref' setting, or latest tag
38
39 EOF
40 }
41
42 #
43 # Abort with <msg>
44 #
45
46 abort() {
47 echo
48 echo " $@" 1>&2
49 echo
50 exit 1
51 }
52
53 #
54 # Log <msg>.
55 #
56
57 log() {
58 echo "$@"
59 }
60
61 #
62 # Set configuration file <path>.
63 #
64
65 set_config_path() {
66 test -f $1 || abort invalid --config path
67 CONFIG=$1
68 }
69
70 #
71 # Check if config <section> exists.
72 #
73
74 config_section() {
75 grep "^\[$1" $CONFIG &> /dev/null
76 }
77
78 #
79 # Get config value by <key>.
80 #
81
82 config_get() {
83 local key=$1
84 test -n "$key" \
85 && grep "^\[$ENV" -A 20 $CONFIG \
86 | grep "^$key" \
87 | head -n 1 \
88 | cut -d ' ' -f 2-999
89 }
90
91 #
92 # Output version.
93 #
94
95 version() {
96 echo $VERSION
97 }
98
99 #
100 # Run the given remote <cmd>.
101 #
102
103 run() {
104 local url="`config_get user`@`config_get host`"
105 local key=`config_get key`
106 if test -n "$key"; then
107 local shell="ssh -i $key $url"
108 else
109 local shell="ssh $url"
110 fi
111 echo $shell "\"$@\"" >> $LOG
112 $shell $@
113 }
114
115 #
116 # Output config or [key].
117 #
118
119 config() {
120 if test $# -eq 0; then
121 cat $CONFIG
122 else
123 config_get $1
124 fi
125 }
126
127 #
128 # Execute hook <name> relative to the path configured.
129 #
130
131 hook() {
132 test -n "$1" || abort hook name required
133 local hook=$1
134 local path=`config_get path`
135 local cmd=`config_get $hook`
136 if test -n "$cmd"; then
137 log "executing $hook \`$cmd\`"
138 run "cd $path/current; \
139 SHARED=\"$path/shared\" \
140 $cmd 2>&1 | tee -a $LOG; \
141 exit \${PIPESTATUS[0]}"
142 test $? -eq 0
143 else
144 log hook $hook
145 fi
146 }
147
148 #
149 # Run setup.
150 #
151
152 setup() {
153 local path=`config_get path`
154 local repo=`config_get repo`
155 run "mkdir -p $path/{shared/{logs,pids},source}"
156 test $? -eq 0 || abort setup paths failed
157 log running setup
158 log cloning $repo
159 run "git clone $repo $path/source"
160 test $? -eq 0 || abort failed to clone
161 log setup complete
162 }
163
164 #
165 # Deploy [ref].
166 #
167
168 deploy() {
169 local ref=$1
170 local path=`config_get path`
171 log deploying
172
173 hook pre-deploy || abort pre-deploy hook failed
174
175 # fetch source
176 log fetching updates
177 run "cd $path/source && git fetch --all"
178 test $? -eq 0 || abort fetch failed
179
180 # latest tag
181 if test -z "$ref"; then
182 log fetching latest tag
183 ref=`run "cd $path/source && git for-each-ref refs/tags \
184 --sort=-authordate \
185 --format='%(refname)' \
186 --count=1 | cut -d '/' -f 3"`
187 test $? -eq 0 || abort failed to determine latest tag
188 fi
189
190 # reset HEAD
191 log resetting HEAD to $ref
192 run "cd $path/source && git reset --hard $ref"
193 test $? -eq 0 || abort git reset failed
194
195 # link current
196 run "ln -sfn $path/source $path/current"
197 test $? -eq 0 || abort symlink failed
198
199 # deploy log
200 run "cd $path/source && \
201 echo \`git rev-parse --short HEAD\` \
202 >> $path/.deploys"
203 test $? -eq 0 || abort deploy log append failed
204
205 hook post-deploy || abort post-deploy hook failed
206
207 if test $TEST -eq 1; then
208 hook test
209 if test $? -ne 0; then
210 log tests failed, reverting deploy
211 quickly_revert_to 1 && log "revert complete" && exit
212 fi
213 else
214 log ignoring tests
215 fi
216
217 # done
218 log successfully deployed $ref
219 }
220
221 #
222 # Get current commit.
223 #
224
225 current_commit() {
226 local path=`config_get path`
227 run "cd $path/source && \
228 git rev-parse --short HEAD"
229 }
230
231 #
232 # Get <n>th deploy commit.
233 #
234
235 nth_deploy_commit() {
236 local n=$1
237 local path=`config_get path`
238 run "cat $path/.deploys | tail -n $n | head -n 1 | cut -d ' ' -f 1"
239 }
240
241 #
242 # List deploys.
243 #
244
245 list_deploys() {
246 local path=`config_get path`
247 run "cat $path/.deploys"
248 }
249
250 #
251 # Revert to the <n>th last deployment, ignoring tests.
252 #
253
254 quickly_revert_to() {
255 local n=$1
256 log "quickly reverting $n deploy(s)"
257 local commit=`nth_deploy_commit $((n + 1))`
258 TEST=0 deploy "$commit"
259 }
260
261 #
262 # Revert to the <n>th last deployment.
263 #
264
265 revert_to() {
266 local n=$1
267 log "reverting $n deploy(s)"
268 local commit=`nth_deploy_commit $((n + 1))`
269 deploy "$commit"
270 }
271
272 #
273 # Require environment arg.
274 #
275
276 require_env() {
277 config_section $ENV || abort "[$ENV] config section not defined"
278 test -z "$ENV" && abort "<env> required"
279 }
280
281 #
282 # Update deploy.
283 #
284
285 update() {
286 log "updating deploy(1)"
287 rm -fr /tmp/deploy
288 git clone git://github.com/visionmedia/deploy.git \
289 --depth 0 \
290 /tmp/deploy \
291 &> /tmp/deploy.log \
292 && cd /tmp/deploy \
293 && make install \
294 && log "updated $VERSION -> `./bin/deploy --version`"
295 }
296
297 # parse argv
298
299 while test $# -ne 0; do
300 arg=$1; shift
301 case $arg in
302 -h|--help) usage; exit ;;
303 -V|--version) version; exit ;;
304 -c|--config) set_config_path $1; shift ;;
305 -C|--chdir) log cd $1; cd $1; shift ;;
306 -T|--no-tests) TEST=0 ;;
307 run|exec) require_env; run "cd `config_get path` && $@"; exit ;;
308 curr|current) require_env; current_commit; exit ;;
309 prev|previous) require_env; nth_deploy_commit 2; exit ;;
310 revert) require_env; revert_to ${1-1}; exit ;;
311 setup) require_env; setup $@; exit ;;
312 list) require_env; list_deploys; exit ;;
313 update) update; exit ;;
314 config) config $@; exit ;;
315 *)
316 if test -z "$ENV"; then
317 ENV=$arg;
318 else
319 REF="$REF $arg";
320 fi
321 ;;
322 esac
323 done
324
325 require_env
326
327 # deploy
328 deploy "${REF:-`config_get ref`}"
Something went wrong with that request. Please try again.