#!/bin/sh # discourse-cli validation script. # Runs everything inside containers so no host tooling (curl, etc.) is needed. # # Usage: ./validate.sh (reads .env from the discourse-cli directory) # # Exit codes: 0 = all checks passed, 1 = one or more checks failed set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" # Ensure .env exists if [ ! -f .env ]; then echo "FAIL: .env not found. Copy .env.example to .env and fill in real values." exit 1 fi IMAGE="${DISCOURSE_CLI_IMAGE:-kneldevstack-aimiddleware-discourse-cli}" PASS=0 FAIL=0 TOTAL=0 ok() { TOTAL=$((TOTAL+1)); echo "PASS: $1"; PASS=$((PASS+1)); } fail() { TOTAL=$((TOTAL+1)); echo "FAIL: $1"; FAIL=$((FAIL+1)); } echo "============================================" echo " discourse-cli validation" echo " image: ${IMAGE}" echo "============================================" echo "" # ---------------------------------------------------------------- # # 0. Credential sanity (raw HTTP via containerized curl) # ---------------------------------------------------------------- # echo "--- [0] Credential check (raw HTTP via containerized curl) ---" # Load env vars from .env for the raw test DISCOURSE_URL=$(grep -E '^DISCOURSE_URL=' .env | cut -d= -f2-) DISCOURSE_API_KEY=$(grep -E '^DISCOURSE_API_KEY=' .env | cut -d= -f2-) DISCOURSE_API_USERNAME=$(grep -E '^DISCOURSE_API_USERNAME=' .env | cut -d= -f2-) HTTP_CODE=$(docker run --rm curlimages/curl:latest \ -s -o /dev/null -w '%{http_code}' \ -H "Api-Key: ${DISCOURSE_API_KEY}" \ -H "Api-Username: ${DISCOURSE_API_USERNAME}" \ -H "Accept: application/json" \ "${DISCOURSE_URL}/session/current.json" 2>/dev/null || echo "000") if [ "$HTTP_CODE" = "200" ]; then ok "raw HTTP credentials accepted (HTTP ${HTTP_CODE})" else fail "raw HTTP credentials rejected (HTTP ${HTTP_CODE})" echo " -> Discourse at ${DISCOURSE_URL} returned ${HTTP_CODE} for /session/current.json" echo " -> Check: API key active? IP allowlist? Username matches key scope?" echo "" echo " Stopping: cannot validate CLI commands without valid credentials." echo "" echo "============================================" echo " RESULTS: ${PASS}/${TOTAL} passed, ${FAIL} failed" echo "============================================" exit 1 fi echo "" # ---------------------------------------------------------------- # # 1. whoami (live connection test) # ---------------------------------------------------------------- # echo "--- [1] whoami ---" OUT=$(docker run --rm --env-file .env "${IMAGE}" whoami 2>&1) || true if echo "$OUT" | grep -qE '^username:'; then ok "whoami returned user info" echo " $OUT" | head -5 else fail "whoami did not return expected output" echo " $OUT" | head -5 fi echo "" # ---------------------------------------------------------------- # # 2. categories (live read) # ---------------------------------------------------------------- # echo "--- [2] categories ---" OUT=$(docker run --rm --env-file .env "${IMAGE}" categories 2>&1) || true if echo "$OUT" | grep -qE '^[0-9]+ category'; then ok "categories returned data" echo " $OUT" | head -6 # Grab first category id for later tests CAT_ID=$(echo "$OUT" | grep -E '^[0-9]' | head -1 | awk '{print $1}') else fail "categories did not return expected output" echo " $OUT" | head -6 CAT_ID="" fi echo "" # ---------------------------------------------------------------- # # 3. topics / ls (live read) # ---------------------------------------------------------------- # echo "--- [3] topics (latest) ---" OUT=$(docker run --rm --env-file .env "${IMAGE}" ls 2>&1) || true if echo "$OUT" | grep -qE 'topic\(s\)'; then ok "topics list returned data" echo " $OUT" | head -6 TOPIC_ID=$(echo "$OUT" | grep -E '^[0-9]' | head -1 | awk '{print $1}') else fail "topics list did not return expected output" echo " $OUT" | head -6 TOPIC_ID="" fi echo "" # ---------------------------------------------------------------- # # 4. show topic (live read) # ---------------------------------------------------------------- # if [ -n "${TOPIC_ID:-}" ]; then echo "--- [4] show topic ${TOPIC_ID} ---" OUT=$(docker run --rm --env-file .env "${IMAGE}" show "${TOPIC_ID}" 2>&1) || true if echo "$OUT" | grep -qE '^#'; then ok "show topic ${TOPIC_ID} returned content" echo " $OUT" | head -8 else fail "show topic ${TOPIC_ID} did not return expected output" echo " $OUT" | head -8 fi else echo "--- [4] show topic (SKIPPED - no topic id found in step 3) ---" fi echo "" # ---------------------------------------------------------------- # # 5. search (live read) # ---------------------------------------------------------------- # echo "--- [5] search ---" OUT=$(docker run --rm --env-file .env "${IMAGE}" search "test" 2>&1) || true if echo "$OUT" | grep -qE 'result\(s\)'; then ok "search returned results" echo " $OUT" | head -5 else fail "search did not return expected output" echo " $OUT" | head -5 fi echo "" # ---------------------------------------------------------------- # # 6. create + reply + update + delete (live write cycle) # ---------------------------------------------------------------- # echo "--- [6] create + reply + update + delete (write cycle) ---" CREATE_OUT=$(docker run --rm --env-file .env "${IMAGE}" create \ ${CAT_ID:+-c "$CAT_ID"} \ -t "discourse-cli validation test $(date +%s)" \ -b "This is an automated validation test post. It will be cleaned up shortly after creation." \ 2>&1) || true NEW_TOPIC_ID=$(echo "$CREATE_OUT" | grep -oE 'topic #[0-9]+' | grep -oE '[0-9]+') if [ -n "${NEW_TOPIC_ID:-}" ]; then ok "create topic succeeded (topic #${NEW_TOPIC_ID})" echo " $CREATE_OUT" # reply REPLY_OUT=$(docker run --rm --env-file .env "${IMAGE}" reply "${NEW_TOPIC_ID}" \ -b "Validation reply test." 2>&1) || true POST_ID=$(echo "$REPLY_OUT" | grep -oE 'id=[0-9]+' | grep -oE '[0-9]+') if echo "$REPLY_OUT" | grep -qE 'Posted reply'; then ok "reply succeeded" echo " $REPLY_OUT" else fail "reply failed" echo " $REPLY_OUT" fi # update if [ -n "${POST_ID:-}" ]; then UPD_OUT=$(docker run --rm --env-file .env "${IMAGE}" update "${POST_ID}" \ -b "Updated validation reply test." 2>&1) || true if echo "$UPD_OUT" | grep -qE 'Updated post'; then ok "update post ${POST_ID} succeeded" else fail "update post ${POST_ID} failed" echo " $UPD_OUT" fi # delete DEL_OUT=$(docker run --rm --env-file .env "${IMAGE}" delete "${POST_ID}" 2>&1) || true if echo "$DEL_OUT" | grep -qE 'Deleted post'; then ok "delete post ${POST_ID} succeeded" else fail "delete post ${POST_ID} failed" echo " $DEL_OUT" fi fi else fail "create topic failed" echo " $CREATE_OUT" fi echo "" # ---------------------------------------------------------------- # # Summary # ---------------------------------------------------------------- # echo "============================================" echo " RESULTS: ${PASS}/${TOTAL} passed, ${FAIL} failed" echo "============================================" if [ "$FAIL" -gt 0 ]; then exit 1 fi exit 0