UNPKG

5.16 kBPlain TextView Raw
1#!/bin/bash
2
3assert_equal() {
4 local expected="${1}"
5 local actual="${2}"
6 if [ "$expected" != "$actual" ]; then
7 echo "\nFAILED: expected ${expected}, found ${actual}"
8 exit 1
9 fi
10}
11
12assert_contains() {
13 local expected="${1}"
14 local actual="${2}"
15 local return_instead_of_exit="${3}"
16 if echo "$actual" | grep -qi "$expected"; then
17 :
18 else
19 echo "\nFAILED: expected ${expected} to match ${actual}"
20 if [ "$return_instead_of_exit" == true ]; then
21 return 1
22 else
23 exit 1
24 fi
25 fi
26}
27
28cleanup() {
29 local app="${1}"
30 local extra_pid="${2}"
31 echo ''
32 echo 'Cleaning up...'
33 heroku destroy ${app} --confirm ${app}
34 cd ../..
35 rm -rf tmp/${app}
36
37 if [ "$CI" != "true" ]; then
38 pgid=$(ps -o pgid= $$ | grep -o '[0-9]*$')
39 echo "Killing processes in group $pgid..."
40 kill -- -$pgid
41 elif [ -n "$extra_pid" ]; then
42 kill $extra_pid
43 fi
44}
45
46wait_for() {
47 local cmd="${1}"
48 sleep 2
49 attempts=0
50 until $(${cmd}); do
51 attempts=$((attempts+1))
52 if [ $attempts -gt 10 ]; then
53 echo "Too many attempts waiting for service!"
54 exit 1
55 fi
56 sleep 2
57 done
58}
59
60wait_for_dyno() {
61 local dyno=${1:-web}
62 echo -n "Waiting for dyno..."
63 state="starting"
64 while [ "up" != "$state" ]; do
65 if [ "starting" != "$state" ] && [ "provisioning" != "$state" ]; then
66 echo "WARNING: dyno state is \"${state}\""
67 fi
68 echo -n "."
69 sleep 4
70 state=$(heroku ps ${dyno} --json | jq .[0].state -r)
71 done
72 sleep 5
73 echo ""
74}
75
76with_retry() {
77 local cmd=${1}
78 local assert_func=${2}
79 local n=0
80 until [ $n -ge 3 ]; do
81 local output="$($cmd)"
82 set +e
83 $assert_func "$output"
84 local result="$?"
85 set -e
86 [ "$result" == "0" ] && return 0
87 n=$[$n+1]
88 sleep 1
89 echo "Retrying..."
90 done
91 exit 1
92}
93
94heroku plugins:link . --force
95
96set -e
97
98app="heroku-exec-test-${RANDOM}"
99echo "Preparing test app ${app}..."
100
101mkdir -p tmp
102cd tmp
103rm -rf ${app}
104mkdir ${app}
105cd ${app}
106
107file_to_copy="file-to-copy.txt"
108
109echo "Creating git repo..."
110git init
111web="ruby -rwebrick -e\"s=WEBrick::HTTPServer.new(:BindAddress => '0.0.0.0', :Port => \$PORT, :DocumentRoot => Dir.pwd); s.mount_proc('/'){|q,r| r.body='Hello'}; s.start\""
112echo "web: ${web}" > Procfile
113echo "worker: echo 'success' > ${file_to_copy}; ruby -rwebrick -e'WEBrick::HTTPServer.new(:Port => 3000, :DocumentRoot => Dir.pwd).start'" >> Procfile
114
115echo "Creating Heroku app..."
116heroku create ${app} $(if [ -n "$HEROKU_SPACE" ]; then echo "--space $HEROKU_SPACE"; else echo "--region ${HEROKU_REGION:-us}"; fi)
117
118trap "{ cleanup ${app}; }" EXIT
119
120heroku buildpacks:set https://github.com/ryandotsmith/null-buildpack
121git add Procfile
122git commit -m "first"
123
124if [ "${1}" == "staging" ] || [ "${HEROKU_EXEC_TEST_ENV}" == "staging" ]; then
125 echo "=== skipping init tests"
126 export HEROKU_EXEC_URL="https://heroku-exec-staging.herokuapp.com/"
127 heroku buildpacks:add https://github.com/heroku/exec-buildpack#staging
128fi
129
130if [ -n "$HEROKU_SPACE" ]; then
131 initOutput="$(heroku ps:exec "ls" 2>&1)"
132 assert_contains "Initializing feature" "$initOutput"
133 assert_contains "Adding the Heroku Exec buildpack" "$initOutput"
134 assert_contains "Run the following commands to redeploy your app" "$initOutput"
135 assert_contains "git push heroku master" "$initOutput"
136 echo "=== test 0: success"
137else
138 # TODO would be better to test that the command prompts to confirm restart
139 heroku features:enable runtime-heroku-exec
140fi
141
142assert_contains "Heroku Exec is not running!" "$(heroku ps:exec --status 2>&1)"
143echo "=== test 1: success"
144
145output="$(heroku ps:exec ls 2>&1)"
146assert_contains "Establishing credentials" "$output"
147assert_contains "Could not connect to dyno!" "$output"
148echo "=== test 2: success"
149
150echo "Deploying..."
151git push heroku master
152
153wait_for_dyno "web"
154
155heroku ps:exec --ssh pwd
156assert_equal "0" "$?"
157
158
159_web_status_assert() {
160 assert_contains "web.1" "$output" true && \
161 assert_contains "running" "$output" true && \
162 assert_contains "up" "$output" true
163 return $?
164}
165with_retry "heroku ps:exec --status" "_web_status_assert"
166echo "=== test 3: success"
167
168heroku ps:scale web=0
169heroku ps:scale worker=1
170
171dyno="worker.1"
172wait_for_dyno "worker"
173echo "Dyno ${dyno} is ready!"
174
175_worker_status_assert() {
176 assert_contains "$dyno" "$1" true && \
177 assert_contains "running" "$1" true && \
178 assert_contains "up" "$1" true
179 return $?
180}
181with_retry "heroku ps:exec --status" "_worker_status_assert"
182
183heroku logs -d $dyno
184
185assert_contains "worker." "$dyno"
186
187_ps_copy_assert() {
188 assert_contains "Copying ${file_to_copy} to ${file_to_copy}" "$output" true && \
189 assert_contains "success" "$(cat ${file_to_copy})"
190 return $?
191}
192with_retry "heroku ps:copy --dyno $dyno $file_to_copy" "_ps_copy_assert"
193
194echo "=== test 4: success"
195
196eval "heroku ps:forward --app $app --dyno $dyno 3000 &"
197trap "{ cleanup ${app} $!; }" EXIT
198
199wait_for "curl -o /dev/null -s -I -f localhost:3000"
200assert_contains "${file_to_copy}" "$(curl -s -L localhost:3000)"
201echo "=== test 5: success"
202
203assert_contains "${file_to_copy}" "$(curl --socks5 localhost:1080 -s -L 0.0.0.0:3000)"
204echo "=== test 6: success"
205
206echo ""
207echo "SUCCESS: All tests passed!"
208exit 0