Skip to content

Commit 33c2c7b

Browse files
committed
fix: resolve SC2059 shellcheck warnings in gateway demo
Replace printf format strings that embedded shell variables with proper format specifiers and variable arguments. All color variables are now passed as separate arguments using '%s' format specifiers, which satisfies shellcheck SC2059.
1 parent 8af59b0 commit 33c2c7b

File tree

1 file changed

+57
-57
lines changed

1 file changed

+57
-57
lines changed

demos/gateway/demo.sh

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ run_step() {
5656
local command="$2"
5757

5858
echo
59-
printf "${dim}# %s${reset}\n" "$description"
60-
printf "${bold}${green}\$${reset} "
59+
printf '%s# %s%s\n' "${dim}" "$description" "${reset}"
60+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
6161
typewrite "$command" 0.035
62-
printf "${dim}${reset}" # blinking-cursor illusion
62+
printf '%s ▌%s' "${dim}" "${reset}" # blinking-cursor illusion
6363

6464
# Wait for Enter
6565
read -r -s _
@@ -73,21 +73,21 @@ run_step() {
7373
pause_comment() {
7474
local msg="$1"
7575
echo
76-
printf "${dim}# %s${reset}" "$msg"
76+
printf '%s# %s%s' "${dim}" "$msg" "${reset}"
7777
read -r -s _
7878
echo
7979
}
8080

8181
# Section banner
8282
section() {
8383
echo
84-
printf "${bold}${blue}┌──────────────────────────────────────────────────────┐${reset}\n"
85-
printf "${bold}${blue}│ %-52s│${reset}\n" "$*"
86-
printf "${bold}${blue}└──────────────────────────────────────────────────────┘${reset}\n"
84+
printf '%s%s┌──────────────────────────────────────────────────────┐%s\n' "${bold}" "${blue}" "${reset}"
85+
printf '%s%s│ %-52s│%s\n' "${bold}" "${blue}" "$*" "${reset}"
86+
printf '%s%s└──────────────────────────────────────────────────────┘%s\n' "${bold}" "${blue}" "${reset}"
8787
}
8888

89-
ok() { printf "${green}✓ %s${reset}\n" "$*"; }
90-
info(){ printf "${cyan} %s${reset}\n" "$*"; }
89+
ok() { printf '%s✓ %s%s\n' "${green}" "$*" "${reset}"; }
90+
info(){ printf '%s %s%s\n' "${cyan}" "$*" "${reset}"; }
9191

9292
pretty_json() {
9393
python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin), indent=2))"
@@ -99,7 +99,7 @@ wait_for_gateway() {
9999
local retries=30
100100
while ! curl -sf "${GATEWAY_URL}/health" >/dev/null 2>&1; do
101101
retries=$((retries - 1))
102-
[[ $retries -eq 0 ]] && { printf "${red}Gateway did not start${reset}\n"; exit 1; }
102+
[[ $retries -eq 0 ]] && { printf '%sGateway did not start%s\n' "${red}" "${reset}"; exit 1; }
103103
sleep 0.2
104104
done
105105
}
@@ -136,7 +136,7 @@ trap 'stop_gateway' EXIT
136136
# ─────────────────────────────────────────────────────────────────────────────
137137

138138
clear
139-
printf "${bold}${blue}"
139+
printf '%s%s' "${bold}" "${blue}"
140140
cat <<'BANNER'
141141
██████╗ ██████╗ ██████╗ ██╗ ██╗ ███████╗ ██████╗
142142
██╔══██╗ ██╔═══██╗ ██╔════╝ ██║ ██╔╝ ██╔════╝ ██╔══██╗
@@ -159,10 +159,10 @@ cat <<'BANNER'
159159
╚██████╔╝ ██║ ██║ ██║ ███████╗ ╚███╔███╔╝ ██║ ██║ ██║
160160
╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝
161161
BANNER
162-
printf "${reset}\n"
163-
printf "${dim} Press ${reset}${bold}Enter${reset}${dim} to advance through each step.${reset}\n"
164-
printf "${dim} The gateway is started behind the scenes — commands shown are${reset}\n"
165-
printf "${dim} exactly what you would run in a real session.${reset}\n"
162+
printf '%s\n' "${reset}"
163+
printf '%s Press %s%sEnter%s%s to advance through each step.%s\n' "${dim}" "${reset}" "${bold}" "${reset}" "${dim}" "${reset}"
164+
printf '%s The gateway is started behind the scenes — commands shown are%s\n' "${dim}" "${reset}"
165+
printf '%s exactly what you would run in a real session.%s\n' "${dim}" "${reset}"
166166
echo
167167

168168
pause_comment "Let's begin — press Enter to start"
@@ -176,7 +176,7 @@ section "Step 1 — Write a gateway config"
176176
pause_comment "The gateway is driven by a simple YAML file. Here's a basic one."
177177

178178
echo
179-
printf "${dim}# demos/gateway/config-basic.yaml${reset}\n"
179+
printf '%s# demos/gateway/config-basic.yaml%s\n' "${dim}" "${reset}"
180180
cat "${SCRIPT_DIR}/config-basic.yaml"
181181

182182
pause_comment "Press Enter to start the gateway"
@@ -189,12 +189,12 @@ section "Step 2 — Start the gateway"
189189

190190
# Show the pretty command; actually run our binary in the background
191191
echo
192-
printf "${dim}# Starts an OpenAI-compatible proxy on :4000${reset}\n"
193-
printf "${bold}${green}\$${reset} "
192+
printf '%s# Starts an OpenAI-compatible proxy on :4000%s\n' "${dim}" "${reset}"
193+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
194194
typewrite "docker model gateway --config demos/gateway/config-basic.yaml" 0.035
195-
printf "${dim}${reset}"
195+
printf '%s ▌%s' "${dim}" "${reset}"
196196
read -r -s _
197-
printf "\r${bold}${green}\$${reset} ${white}docker model gateway --config demos/gateway/config-basic.yaml${reset}\n"
197+
printf '\r%s%s$%s %sdocker model gateway --config demos/gateway/config-basic.yaml%s\n' "${bold}" "${green}" "${reset}" "${white}" "${reset}"
198198

199199
# Actually launch
200200
launch_gateway "${SCRIPT_DIR}/config-basic.yaml"
@@ -230,12 +230,12 @@ section "Step 5 — Auth enforcement"
230230
pause_comment "The gateway rejects requests with the wrong key"
231231

232232
echo
233-
printf "${dim}# Wrong key → 401${reset}\n"
234-
printf "${bold}${green}\$${reset} "
233+
printf '%s# Wrong key → 401%s\n' "${dim}" "${reset}"
234+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
235235
typewrite "curl -s -o /dev/null -w '%{http_code}' http://localhost:${GATEWAY_PORT}/v1/chat/completions -H 'Authorization: Bearer WRONG'" 0.03
236-
printf "${dim}${reset}"
236+
printf '%s ▌%s' "${dim}" "${reset}"
237237
read -r -s _
238-
printf "\r${bold}${green}\$${reset} ${white}curl -s -o /dev/null -w '%%{http_code}' .../v1/chat/completions -H 'Authorization: Bearer WRONG'${reset}\n"
238+
printf '\r%s%s$%s %scurl -s -o /dev/null -w '\''%%{http_code}'\'' .../v1/chat/completions -H '\''Authorization: Bearer WRONG'\''%s\n' "${bold}" "${green}" "${reset}" "${white}" "${reset}"
239239

240240
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
241241
-X POST "${GATEWAY_URL}/v1/chat/completions" \
@@ -254,16 +254,16 @@ section "Step 6 — Chat completion"
254254
pause_comment "Standard OpenAI-compatible chat completions endpoint"
255255

256256
echo
257-
printf "${dim}# POST /v1/chat/completions — non-streaming${reset}\n"
258-
printf "${bold}${green}\$${reset} "
257+
printf '%s# POST /v1/chat/completions — non-streaming%s\n' "${dim}" "${reset}"
258+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
259259
typewrite "curl -s http://localhost:${GATEWAY_PORT}/v1/chat/completions \\" 0.03
260-
printf "\n"
260+
printf '\n'
261261
typewrite " -H 'Authorization: Bearer ${API_KEY}' \\" 0.03
262-
printf "\n"
262+
printf '\n'
263263
typewrite " -d '{\"model\":\"smollm2\",\"messages\":[{\"role\":\"user\",\"content\":\"What is Docker Model Runner?\"}],\"max_tokens\":80}'" 0.03
264-
printf "${dim}${reset}"
264+
printf '%s ▌%s' "${dim}" "${reset}"
265265
read -r -s _
266-
printf "\r${bold}${green}\$${reset} ${white}curl -s .../v1/chat/completions -H 'Authorization: Bearer ${API_KEY}' -d '{...}'${reset}\n\n"
266+
printf '\r%s%s$%s %scurl -s .../v1/chat/completions -H '\''Authorization: Bearer %s'\'' -d '\''{...}'\''%s\n\n' "${bold}" "${green}" "${reset}" "${white}" "${API_KEY}" "${reset}"
267267

268268
curl -sf -X POST "${GATEWAY_URL}/v1/chat/completions" \
269269
-H "Content-Type: application/json" \
@@ -286,16 +286,16 @@ section "Step 7 — Streaming (SSE)"
286286
pause_comment "Add stream:true — tokens arrive in real time"
287287

288288
echo
289-
printf "${dim}# Same endpoint, stream:true → server-sent events${reset}\n"
290-
printf "${bold}${green}\$${reset} "
289+
printf '%s# Same endpoint, stream:true → server-sent events%s\n' "${dim}" "${reset}"
290+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
291291
typewrite "curl -sN http://localhost:${GATEWAY_PORT}/v1/chat/completions \\" 0.03
292-
printf "\n"
292+
printf '\n'
293293
typewrite " -H 'Authorization: Bearer ${API_KEY}' \\" 0.03
294-
printf "\n"
294+
printf '\n'
295295
typewrite " -d '{\"model\":\"smollm2\",\"messages\":[{\"role\":\"user\",\"content\":\"Count 1 to 5\"}],\"stream\":true}'" 0.03
296-
printf "${dim}${reset}"
296+
printf '%s ▌%s' "${dim}" "${reset}"
297297
read -r -s _
298-
printf "\r${bold}${green}\$${reset} ${white}curl -sN .../v1/chat/completions -d '{...stream:true...}'${reset}\n\n"
298+
printf '\r%s%s$%s %scurl -sN .../v1/chat/completions -d '\''{...stream:true...}'\''%s\n\n' "${bold}" "${green}" "${reset}" "${white}" "${reset}"
299299

300300
curl -sfN -X POST "${GATEWAY_URL}/v1/chat/completions" \
301301
-H "Content-Type: application/json" \
@@ -327,15 +327,15 @@ section "Step 8 — Advanced config: load balancing & fallbacks"
327327
pause_comment "Restart the gateway with the advanced config"
328328

329329
echo
330-
printf "${dim}# config-advanced.yaml${reset}\n"
330+
printf '%s# config-advanced.yaml%s\n' "${dim}" "${reset}"
331331
cat "${SCRIPT_DIR}/config-advanced.yaml"
332332
echo
333333

334-
printf "${bold}${green}\$${reset} "
334+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
335335
typewrite "docker model gateway --config demos/gateway/config-advanced.yaml" 0.035
336-
printf "${dim}${reset}"
336+
printf '%s ▌%s' "${dim}" "${reset}"
337337
read -r -s _
338-
printf "\r${bold}${green}\$${reset} ${white}docker model gateway --config demos/gateway/config-advanced.yaml${reset}\n"
338+
printf '\r%s%s$%s %sdocker model gateway --config demos/gateway/config-advanced.yaml%s\n' "${bold}" "${green}" "${reset}" "${white}" "${reset}"
339339

340340
stop_gateway
341341
launch_gateway "${SCRIPT_DIR}/config-advanced.yaml"
@@ -351,12 +351,12 @@ section "Step 9 — Round-robin load balancing"
351351
pause_comment "'fast-model' has 2 backends — watch them alternate across 4 requests"
352352

353353
echo
354-
printf "${dim}# 4 requests to 'fast-model' → round-robins across smollm2 + qwen3${reset}\n"
355-
printf "${bold}${green}\$${reset} "
354+
printf '%s# 4 requests to '\''fast-model'\'' → round-robins across smollm2 + qwen3%s\n' "${dim}" "${reset}"
355+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
356356
typewrite "for i in 1 2 3 4; do curl -s .../v1/chat/completions -d '{\"model\":\"fast-model\",...}'; done" 0.03
357-
printf "${dim}${reset}"
357+
printf '%s ▌%s' "${dim}" "${reset}"
358358
read -r -s _
359-
printf "\r${bold}${green}\$${reset} ${white}for i in 1 2 3 4; do curl -s .../v1/chat/completions ...; done${reset}\n\n"
359+
printf '\r%s%s$%s %sfor i in 1 2 3 4; do curl -s .../v1/chat/completions ...; done%s\n\n' "${bold}" "${green}" "${reset}" "${white}" "${reset}"
360360

361361
for i in 1 2 3 4; do
362362
resp=$(curl -sf -X POST "${GATEWAY_URL}/v1/chat/completions" \
@@ -385,18 +385,18 @@ section "Step 10 — Embeddings (nomic-embed-text)"
385385
pause_comment "Dedicated embedding model behind its own alias"
386386

387387
echo
388-
printf "${dim}# POST /v1/embeddings — two sentences, then compute cosine similarity${reset}\n"
389-
printf "${bold}${green}\$${reset} "
388+
printf '%s# POST /v1/embeddings — two sentences, then compute cosine similarity%s\n' "${dim}" "${reset}"
389+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
390390
typewrite "curl -s -X POST http://localhost:${GATEWAY_PORT}/v1/embeddings \\" 0.03
391-
printf "\n"
391+
printf '\n'
392392
typewrite " -H 'Content-Type: application/json' \\" 0.03
393-
printf "\n"
393+
printf '\n'
394394
typewrite " -H 'Authorization: Bearer ${API_KEY}' \\" 0.03
395-
printf "\n"
395+
printf '\n'
396396
typewrite " -d '{\"model\":\"embeddings\",\"input\":[\"The quick brown fox\",\"A fast auburn canine\"]}'" 0.03
397-
printf "${dim}${reset}"
397+
printf '%s ▌%s' "${dim}" "${reset}"
398398
read -r -s _
399-
printf "\r${bold}${green}\$${reset} ${white}curl -s -X POST .../v1/embeddings -d '{...}'${reset}\n\n"
399+
printf '\r%s%s$%s %scurl -s -X POST .../v1/embeddings -d '\''{...}'\''%s\n\n' "${bold}" "${green}" "${reset}" "${white}" "${reset}"
400400

401401
curl -sf -X POST "${GATEWAY_URL}/v1/embeddings" \
402402
-H "Content-Type: application/json" \
@@ -426,7 +426,7 @@ section "Step 11 — OpenAI Python SDK compatibility"
426426
pause_comment "Any app already using the openai library works with zero code changes"
427427

428428
echo
429-
printf "${dim}# python demo — just swap base_url to point at the gateway${reset}\n"
429+
printf '%s# python demo — just swap base_url to point at the gateway%s\n' "${dim}" "${reset}"
430430
cat <<'PYSHOW'
431431
from openai import OpenAI
432432
@@ -443,11 +443,11 @@ cat <<'PYSHOW'
443443
print(resp.choices[0].message.content)
444444
PYSHOW
445445

446-
printf "${bold}${green}\$${reset} "
446+
printf '%s%s$%s ' "${bold}" "${green}" "${reset}"
447447
typewrite "python3 demo.py" 0.05
448-
printf "${dim}${reset}"
448+
printf '%s ▌%s' "${dim}" "${reset}"
449449
read -r -s _
450-
printf "\r${bold}${green}\$${reset} ${white}python3 demo.py${reset}\n\n"
450+
printf '\r%s%s$%s %spython3 demo.py%s\n\n' "${bold}" "${green}" "${reset}" "${white}" "${reset}"
451451

452452
if python3 -c "import openai" 2>/dev/null; then
453453
python3 - <<'PYEOF'
@@ -471,7 +471,7 @@ PYEOF
471471
echo
472472
ok "OpenAI SDK works against the gateway — no code changes required"
473473
else
474-
printf "${yellow} (skipped — openai package not installed: pip install openai)${reset}\n"
474+
printf '%s (skipped — openai package not installed: pip install openai)%s\n' "${yellow}" "${reset}"
475475
ok "OpenAI SDK step skipped — install openai to run it"
476476
fi
477477

@@ -482,7 +482,7 @@ fi
482482
section "Demo complete"
483483

484484
echo
485-
printf "${bold} What we showed:${reset}\n"
485+
printf '%s What we showed:%s\n' "${bold}" "${reset}"
486486
info "YAML-driven config — models, auth, retries, fallbacks"
487487
info "/health /v1/models /v1/chat/completions /v1/embeddings"
488488
info "Bearer-token auth (accept ✓ reject 401 ✓)"

0 commit comments

Comments
 (0)