-
Notifications
You must be signed in to change notification settings - Fork 11
294 lines (262 loc) · 10.8 KB
/
Copy pathd2e-demosetup-tunnel.yml
File metadata and controls
294 lines (262 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
name: d2e/demosetup-tunnel
permissions:
contents: read
packages: read
on:
repository_dispatch:
types: [demosetup-tunnel]
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
env:
REG_URL: ghcr.io/ohdsi
PREPULL_FLOW_IMAGES: "flow-base flow-i2b2 flow-data-management flow-search-embedding"
jobs:
demosetup_tunnel:
runs-on: ubuntu-24.04
timeout-minutes: 330
outputs:
tunnel_url: ${{ steps.tunnel.outputs.tunnel_url }}
env:
VERSION: ${{ github.event.client_payload.version || 'develop' }}
DOCKER_TAG_NAME: ${{ github.event.client_payload.version || 'develop' }}
PLUGINS_IMAGE_TAG: ${{ github.event.client_payload.version || 'develop' }}
DURATION_MINUTES: ${{ github.event.client_payload.duration_minutes || '120' }}
steps:
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Increase swapfile to 15G
run: |
sudo swapoff -a
sudo fallocate -l 15G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo swapon --show
- uses: actions/checkout@v4
with:
ref: ${{ github.event.client_payload.ref || github.ref }}
submodules: recursive
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Install cloudflared
run: |
curl -fsSL -o /tmp/cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i /tmp/cloudflared.deb
cloudflared --version
- name: Start Cloudflare quick tunnel
id: tunnel
run: |
nohup cloudflared tunnel --url https://localhost:443 --no-tls-verify --logfile /tmp/cloudflared.log > /dev/null 2>&1 &
echo "TUNNEL_PID=$!" >> $GITHUB_ENV
TUNNEL_URL=""
for i in $(seq 1 30); do
TUNNEL_URL=$(grep -oE 'https://[a-z0-9-]+\.trycloudflare\.com' /tmp/cloudflared.log | head -1 || true)
[ -n "$TUNNEL_URL" ] && break
sleep 2
done
if [ -z "$TUNNEL_URL" ]; then
echo "::error::Could not obtain tunnel URL"
cat /tmp/cloudflared.log
exit 1
fi
TUNNEL_HOST=${TUNNEL_URL#https://}
echo "TUNNEL_URL=$TUNNEL_URL" >> $GITHUB_ENV
echo "TUNNEL_HOST=$TUNNEL_HOST" >> $GITHUB_ENV
echo "127.0.0.1 $TUNNEL_HOST" | sudo tee -a /etc/hosts
echo "Tunnel URL: $TUNNEL_URL" | tee -a $GITHUB_STEP_SUMMARY
echo "tunnel_url=$TUNNEL_URL" >> $GITHUB_OUTPUT
printf '%s\n' "$TUNNEL_URL" > /tmp/tunnel-url.txt
# Published immediately so the URL can be fetched while the run is still going:
# job outputs and `gh run view --log` are only readable once the job has finished,
# by which point the tunnel is already torn down.
- name: Publish tunnel URL artifact
uses: actions/upload-artifact@v4
with:
name: tunnel-url
path: /tmp/tunnel-url.txt
retention-days: 1
- name: npm install
run: npm install
- name: Install Atlas plugin resources
working-directory: ./plugins/atlas
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm install
- name: Initialise d2e
id: init
run: |
init_choice=y ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config CADDY__D2E__PUBLIC_FQDN=$TUNNEL_HOST node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} init
echo "CADDY__ADDITIONAL_HOSTS=https://localhost" >> .env
- name: Pre-pull flow images
run: |
for img in $PREPULL_FLOW_IMAGES; do
docker pull "${REG_URL}/d2e/${img}:${DOCKER_TAG_NAME}"
done
- name: Pull docker compose images
if: success() || failure()
run: |
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions pull
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
- name: Start services
if: success() || failure()
uses: nick-fields/retry@v3
id: start
with:
timeout_seconds: 1800
retry_wait_seconds: 100
max_attempts: 2
retry_on: any
command: |
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions start
DC_EXIT_CODE=$?
docker ps --format {{.Names}},{{.Status}} 2> /dev/null | sort | tee -a $GITHUB_STEP_SUMMARY
[ $DC_EXIT_CODE = 0 ] || { echo EXIT DC_EXIT_CODE=$DC_EXIT_CODE && exit $DC_EXIT_CODE; }
- name: Logs
if: success() || failure()
run: |
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions logs
- name: Wait for d2e-trex healthy
if: success() || failure()
run: |
status=missing
for i in $(seq 1 60); do
status=$(docker inspect -f '{{.State.Health.Status}}' d2e-trex 2>/dev/null || echo "missing")
echo "[$i] d2e-trex health: $status"
[ "$status" = "healthy" ] && break
sleep 5
done
docker ps --format '{{.Names}},{{.Status}}' | sort
if [ "$status" != "healthy" ]; then
echo "::error::d2e-trex did not become healthy (last status: $status)"
exit 1
fi
- name: Pre-pull demo db image
if: success() || failure()
uses: nick-fields/retry@v3
with:
timeout_seconds: 600
retry_wait_seconds: 30
max_attempts: 5
retry_on: any
command: docker pull postgres:16-alpine
- name: Setupdemo
if: success() || failure()
uses: nick-fields/retry@v3
id: setupdemo
with:
timeout_seconds: 1800
retry_wait_seconds: 100
max_attempts: 3
retry_on: any
command: |
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions setupdemo
DC_EXIT_CODE=$?
docker ps --format {{.Names}},{{.Status}} 2> /dev/null | sort | tee -a $GITHUB_STEP_SUMMARY
[ $DC_EXIT_CODE = 0 ] || { echo EXIT DC_EXIT_CODE=$DC_EXIT_CODE && exit $DC_EXIT_CODE; }
- name: Checkflow
if: success() || failure()
uses: nick-fields/retry@v3
id: checkflow
with:
timeout_seconds: 1800
retry_wait_seconds: 100
max_attempts: 1
retry_on: any
command: |
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions checkflow
DC_EXIT_CODE=$?
[ $DC_EXIT_CODE = 0 ] || { echo EXIT DC_EXIT_CODE=$DC_EXIT_CODE && exit $DC_EXIT_CODE; }
- name: Restart d2e services
if: success() || failure()
run: |
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions stop
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions start
- name: Wait for webapi-init to complete
if: success() || failure()
run: |
echo "Waiting for webapi-init to complete (ensures logto admin user is created)..."
for i in $(seq 1 60); do
status=$(docker ps -a --filter "name=webapi-init" --format '{{.Status}}')
if echo "$status" | grep -q "(healthy)"; then
echo "webapi-init completed successfully"
break
fi
if echo "$status" | grep -qE "Exited \([1-9]"; then
echo "webapi-init failed!"
docker logs d2e-webapi-init || true
exit 1
fi
echo "Waiting for webapi-init... ($i/60)"
sleep 5
done
- name: Verify app is reachable
if: success() || failure()
run: |
echo "Local:"
curl -k -s -o /dev/null -w "%{http_code}\n" https://localhost:443/d2e/portal || echo "App not reachable locally"
echo "Tunnel:"
curl -s -o /dev/null -w "%{http_code}\n" --resolve "$TUNNEL_HOST:443:127.0.0.1" -k "$TUNNEL_URL/d2e/portal" || echo "App not reachable via tunnel host"
- name: Publish access details
if: success() || failure()
run: |
{
echo "## Demo environment is up"
echo ""
echo "- Portal: $TUNNEL_URL/d2e/portal"
echo "- Login: \`admin\` / \`Updatepassword12345\`"
echo "- Open for $DURATION_MINUTES minutes (until the 'Keep tunnel open' step ends)"
echo ""
echo "Cancel the workflow run to tear the environment down early."
} >> $GITHUB_STEP_SUMMARY
- name: Mark environment ready
if: success() || failure()
run: printf '%s\n' "$TUNNEL_URL" > /tmp/tunnel-ready.txt
- name: Publish readiness artifact
if: success() || failure()
uses: actions/upload-artifact@v4
with:
name: tunnel-ready
path: /tmp/tunnel-ready.txt
retention-days: 1
- name: Keep tunnel open
if: success() || failure()
run: |
END=$((SECONDS + DURATION_MINUTES * 60))
echo "Keeping tunnel open for $DURATION_MINUTES minutes: $TUNNEL_URL/d2e/portal"
while [ $SECONDS -lt $END ]; do
sleep 60
if ! kill -0 "$TUNNEL_PID" 2>/dev/null; then
echo "::warning::cloudflared exited early"
tail -20 /tmp/cloudflared.log || true
break
fi
REMAINING=$(( (END - SECONDS) / 60 ))
if [ $(( REMAINING % 10 )) -eq 0 ] || [ $REMAINING -le 1 ]; then
echo "[$(date -u '+%H:%M:%S')] tunnel open, ~${REMAINING}m remaining"
fi
done
echo "Tunnel window elapsed"
- name: Stop tunnel
if: always()
run: kill "$TUNNEL_PID" 2>/dev/null || true
- name: Stop d2e services
if: always()
run: |
ENV_TYPE=remote CADDY__CONFIG=./deploy/caddy-config node ./scripts/dist/cli.js -e -v ${{ env.VERSION }} -d ./plugins/functions stop
- name: Prune system
if: always()
run: docker system prune -af