Skip to content

Commit ff31d3c

Browse files
committed
test retry loops to create ephemeral instances
1 parent 40084a8 commit ff31d3c

File tree

3 files changed

+136
-37
lines changed

3 files changed

+136
-37
lines changed

.github/workflows/ephemeral.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
name: LocalStack Ephemeral Instance Test
22
on:
3-
workflow_dispatch:
3+
pull_request:
4+
paths-ignore:
5+
- ./*.md
6+
- LICENSE
47

58
jobs:
69
preview-test:

ephemeral/shutdown/action.yml

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
name: Shutdown Ephemeral Instance
2+
description: 'Shutdowns an Ephemeral Instance (PR Preview)'
23

34
inputs:
4-
localstack-api-key:
5-
description: 'LocalStack API key used to access the platform api'
6-
required: true
5+
localstack-auth-token:
6+
description: 'LocalStack Auth Token used to access the platform api'
7+
required: false
78
github-token:
89
description: 'Github token used to create PR comments'
910
required: true
@@ -34,16 +35,39 @@ runs:
3435
- name: Shutdown ephemeral instance
3536
shell: bash
3637
run: |
37-
response=$(curl -X DELETE \
38-
-s -o /dev/null -w "%{http_code}" \
39-
-H "ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}}" \
40-
-H "content-type: application/json" \
41-
https://api.localstack.cloud/v1/compute/instances/$previewName)
42-
if [[ "$response" -ne 200 ]]; then
43-
# In case the deletion fails, e.g. if the instance cannot be found, we raise a proper error on the platform
44-
echo "Unable to delete preview environment. API response: $response"
45-
exit 1
38+
AUTH_HEADER="ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-auth-token }}}}"
39+
CONTENT_TYPE_HEADER="content-type: application/json"
40+
API_URL_BASE="https://api.localstack.cloud/v1/compute/instances"
41+
42+
retry() {
43+
local retries=5
44+
local count=0
45+
local wait=5
46+
while [ $count -lt $retries ]; do
47+
"$@"
48+
local exit_code=$?
49+
if [ $exit_code -eq 0 ]; then
50+
return 0
51+
fi
52+
count=$((count + 1))
53+
echo "Command failed with exit code $exit_code. Retrying in $wait seconds... ($count/$retries)"
54+
sleep $wait
55+
done
56+
echo "Command failed after $retries retries."
57+
return 1
58+
}
59+
60+
shutdown_instance() {
61+
http_code=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
62+
-H "$AUTH_HEADER" \
63+
-H "$CONTENT_TYPE_HEADER" \
64+
"$API_URL_BASE/$previewName")
65+
if [[ "$http_code" -ne 200 && "$http_code" -ne 404 ]]; then
66+
echo "Unable to delete preview environment. API returned HTTP code: $http_code"
67+
return 1
68+
fi
4669
fi
70+
retry shutdown_instance
4771
4872
- name: Update status comment
4973
uses: actions-cool/maintain-one-comment@v3.1.1

ephemeral/startup/action.yml

Lines changed: 96 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
name: Create PR Preview
2+
description: 'Spins up an Ephemeral Instance for a PR Preview'
23

34
inputs:
45
github-token:
56
description: 'Github token used to create PR comments'
67
required: true
7-
localstack-api-key:
8-
description: 'LocalStack API key used to create the preview environment'
8+
localstack-auth-token:
9+
description: 'LocalStack Auth Token used to create the preview environment'
910
required: false
1011
preview-cmd:
1112
description: 'Command(s) used to create a preview of the PR (can use $AWS_ENDPOINT_URL)'
@@ -68,33 +69,78 @@ runs:
6869
shell: bash
6970
id: create-instance
7071
run: |
72+
AUTH_HEADER="ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-auth-token }}}}"
73+
CONTENT_TYPE_HEADER="content-type: application/json"
74+
API_URL_BASE="https://api.localstack.cloud/v1/compute/instances"
75+
76+
retry() {
77+
local retries=5
78+
local count=0
79+
local wait=5
80+
while [ $count -lt $retries ]; do
81+
"$@"
82+
local exit_code=$?
83+
if [ $exit_code -eq 0 ]; then
84+
return 0
85+
fi
86+
count=$((count + 1))
87+
echo "Command failed with exit code $exit_code. Retrying in $wait seconds... ($count/$retries)"
88+
sleep $wait
89+
done
90+
echo "Command failed after $retries retries."
91+
return 1
92+
}
93+
94+
fetch_instances() {
95+
list_response=$(curl --fail-with-body -s -X GET \
96+
-H "$AUTH_HEADER" \
97+
-H "$CONTENT_TYPE_HEADER" \
98+
"$API_URL_BASE")
99+
if echo "$list_response" | jq -e '.error == true' > /dev/null; then
100+
echo "API returned an error: $list_response"
101+
return 1
102+
fi
103+
}
104+
105+
retry fetch_instances
106+
71107
autoLoadPod="${AUTO_LOAD_POD:-${{ inputs.auto-load-pod }}}"
72108
extensionAutoInstall="${EXTENSION_AUTO_INSTALL:-${{ inputs.extension-auto-install }}}"
73109
lifetime="${{ inputs.lifetime }}"
74110
75-
list_response=$(curl -X GET \
76-
-H "ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}}" \
77-
-H "content-type: application/json" \
78-
https://api.localstack.cloud/v1/compute/instances)
79-
80111
instance_exists=$(echo "$list_response" | jq --arg NAME "$previewName" '.[] | select(.instance_name == $NAME)')
81112
113+
delete_instance() {
114+
# We expect a 200 on success or 404 if it's already gone. Other codes are errors.
115+
http_code=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
116+
-H "$AUTH_HEADER" \
117+
-H "$CONTENT_TYPE_HEADER" \
118+
"$API_URL_BASE/$previewName")
119+
if [ "$http_code" -ne 200 ] && [ "$http_code" -ne 404 ]; then
120+
echo "Error deleting instance, HTTP code: $http_code"
121+
return 1
122+
fi
123+
}
124+
82125
if [ -n "$instance_exists" ]; then
83-
del_response=$(curl -X DELETE \
84-
-H "ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}}" \
85-
-H "content-type: application/json" \
86-
https://api.localstack.cloud/v1/compute/instances/$previewName)
126+
retry delete_instance
87127
fi
88128
89-
response=$(curl -X POST -d "{\"instance_name\": \"${previewName}\", \"lifetime\": ${lifetime} ,\"env_vars\": {\"AUTO_LOAD_POD\": \"${autoLoadPod}\", \"EXTENSION_AUTO_INSTALL\": \"${extensionAutoInstall}\"}}"\
90-
-H "ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}}" \
91-
-H "content-type: application/json" \
92-
https://api.localstack.cloud/v1/compute/instances)
93-
endpointUrl=$(echo "$response" | jq -r .endpoint_url)
94-
if [ "$endpointUrl" = "null" ] || [ "$endpointUrl" = "" ]; then
95-
echo "Unable to create preview environment. API response: $response"
96-
exit 1
129+
create_instance_func() {
130+
response=$(curl --fail-with-body -s -X POST -d "{\"instance_name\": \"${previewName}\", \"lifetime\": ${lifetime} ,\"env_vars\": {\"AUTO_LOAD_POD\": \"${autoLoadPod}\", \"EXTENSION_AUTO_INSTALL\": \"${extensionAutoInstall}\"}}"\
131+
-H "$AUTH_HEADER" \
132+
-H "$CONTENT_TYPE_HEADER" \
133+
"$API_URL_BASE")
134+
135+
endpointUrl=$(echo "$response" | jq -r .endpoint_url)
136+
if [ "$endpointUrl" = "null" ] || [ "$endpointUrl" = "" ]; then
137+
echo "Unable to create preview environment. API response: $response"
138+
return 1
139+
fi
97140
fi
141+
142+
retry create_instance_func
143+
98144
echo "Created preview environment with endpoint URL: $endpointUrl"
99145
100146
echo $endpointUrl > ./ls-preview-url.txt
@@ -117,9 +163,35 @@ runs:
117163
if: ${{ !cancelled() && steps.create-instance.outcome == 'success' }}
118164
shell: bash
119165
run: |
120-
log_response=$(curl -X GET \
121-
-H "ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-api-key }}}}" \
122-
-H "content-type: application/json" \
123-
https://api.localstack.cloud/v1/compute/instances/$previewName/logs)
124-
166+
AUTH_HEADER="ls-api-key: ${LOCALSTACK_AUTH_TOKEN:-${LOCALSTACK_API_KEY:-${{ inputs.localstack-auth-token }}}}"
167+
CONTENT_TYPE_HEADER="content-type: application/json"
168+
API_URL_BASE="https://api.localstack.cloud/v1/compute/instances"
169+
170+
# TODO code duplication
171+
retry() {
172+
local retries=5
173+
local count=0
174+
local wait=5
175+
while [ $count -lt $retries ]; do
176+
"$@"
177+
local exit_code=$?
178+
if [ $exit_code -eq 0 ]; then
179+
return 0
180+
fi
181+
count=$((count + 1))
182+
echo "Command failed with exit code $exit_code. Retrying in $wait seconds... ($count/$retries)"
183+
sleep $wait
184+
done
185+
echo "Command failed after $retries retries."
186+
return 1
187+
}
188+
189+
fetch_logs() {
190+
log_response=$(curl --fail-with-body -s -X GET \
191+
-H "$AUTH_HEADER" \
192+
-H "$CONTENT_TYPE_HEADER" \
193+
"$API_URL_BASE/$previewName/logs")
194+
}
195+
196+
retry fetch_logs
125197
echo "$log_response" | jq -r '.[].content'

0 commit comments

Comments
 (0)