smoke-install.sh 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/usr/bin/env bash
  2. # Build a container image with qmd installed via npm and bun, then run smoke tests.
  3. # Works with docker or podman (whichever is available).
  4. #
  5. # Usage:
  6. # test/smoke-install.sh # build + run all smoke tests
  7. # test/smoke-install.sh --build # build image only
  8. # test/smoke-install.sh --shell # drop into container shell
  9. # test/smoke-install.sh -- CMD... # run arbitrary command in container
  10. set -euo pipefail
  11. cd "$(dirname "$0")/.."
  12. # Pick container runtime
  13. if command -v podman &>/dev/null; then
  14. CTR=podman
  15. elif command -v docker &>/dev/null; then
  16. CTR=docker
  17. else
  18. echo "Error: neither podman nor docker found" >&2
  19. exit 1
  20. fi
  21. IMAGE=qmd-smoke
  22. build_image() {
  23. echo "==> Building TypeScript..."
  24. npm run build --silent
  25. echo "==> Packing tarball..."
  26. rm -f test/tobilu-qmd-*.tgz
  27. TARBALL=$(npm pack --pack-destination test/ 2>/dev/null | tail -1)
  28. echo " $TARBALL"
  29. # Copy project files into build context so vitest/bun tests can run inside
  30. rm -rf test/test-src
  31. mkdir -p test/test-src/src test/test-src/test
  32. cp src/*.ts test/test-src/src/
  33. cp -r dist test/test-src/
  34. cp test/*.test.ts test/test-src/test/
  35. cp package.json tsconfig.json tsconfig.build.json test/test-src/
  36. echo "==> Building container image ($CTR)..."
  37. $CTR build -f test/Containerfile -t "$IMAGE" test/
  38. # Clean up
  39. rm -f test/tobilu-qmd-*.tgz
  40. rm -rf test/test-src
  41. echo "==> Image ready: $IMAGE"
  42. }
  43. run() {
  44. $CTR run --rm "$IMAGE" bash -c "$*"
  45. }
  46. PASS=0
  47. FAIL=0
  48. ok() { printf " %-50s OK\n" "$1"; PASS=$((PASS + 1)); }
  49. fail() { printf " %-50s FAIL\n" "$1"; FAIL=$((FAIL + 1)); echo "$2" | sed 's/^/ /'; }
  50. smoke_test() {
  51. local label="$1"; shift
  52. local out
  53. if out=$(run "$@" 2>&1); then
  54. ok "$label"
  55. else
  56. fail "$label" "$out"
  57. fi
  58. }
  59. smoke_test_output() {
  60. local label="$1"; local expect="$2"; shift 2
  61. local out
  62. out=$(run "$@" 2>&1) || true
  63. if echo "$out" | grep -q "$expect"; then
  64. ok "$label"
  65. else
  66. fail "$label" "$out"
  67. fi
  68. }
  69. run_smoke_tests() {
  70. # ------------------------------------------------------------------
  71. # Node (npm-installed qmd)
  72. # ------------------------------------------------------------------
  73. local NODE_BIN='$(mise where node@latest)/bin'
  74. echo "=== Node (npm install) ==="
  75. smoke_test_output "qmd shows help" "Usage:" \
  76. "export PATH=$NODE_BIN:\$PATH; qmd"
  77. smoke_test "qmd collection list" \
  78. "export PATH=$NODE_BIN:\$PATH; qmd collection list"
  79. smoke_test "qmd status" \
  80. "export PATH=$NODE_BIN:\$PATH; qmd status"
  81. smoke_test "sqlite-vec loads" \
  82. "export PATH=$NODE_BIN:\$PATH;
  83. NPM_GLOBAL=\$(npm root -g);
  84. node -e \"
  85. const {openDatabase, loadSqliteVec} = await import('\$NPM_GLOBAL/@tobilu/qmd/dist/db.js');
  86. const db = openDatabase(':memory:');
  87. loadSqliteVec(db);
  88. const r = db.prepare('SELECT vec_version() as v').get();
  89. console.log('sqlite-vec', r.v);
  90. if (!r.v) process.exit(1);
  91. \""
  92. smoke_test "vitest (node)" \
  93. "export PATH=$NODE_BIN:\$PATH; cd /opt/qmd && npx vitest run --reporter=verbose test/store.test.ts 2>&1 | tail -5"
  94. # ------------------------------------------------------------------
  95. # Bun (bun-installed qmd)
  96. # ------------------------------------------------------------------
  97. local BUN_BIN='$(mise where bun@latest)/bin'
  98. echo ""
  99. echo "=== Bun (bun install) ==="
  100. smoke_test_output "qmd shows help" "Usage:" \
  101. "export PATH=$BUN_BIN:$NODE_BIN:\$PATH; \$HOME/.bun/bin/qmd"
  102. smoke_test "qmd collection list" \
  103. "export PATH=$BUN_BIN:$NODE_BIN:\$PATH; \$HOME/.bun/bin/qmd collection list"
  104. smoke_test "qmd status" \
  105. "export PATH=$BUN_BIN:$NODE_BIN:\$PATH; \$HOME/.bun/bin/qmd status"
  106. smoke_test "sqlite-vec loads (bun)" \
  107. "export PATH=$BUN_BIN:\$PATH; bun -e \"
  108. const {openDatabase, loadSqliteVec} = await import('\$HOME/.bun/install/global/node_modules/@tobilu/qmd/dist/db.js');
  109. const db = openDatabase(':memory:');
  110. loadSqliteVec(db);
  111. const r = db.prepare('SELECT vec_version() as v').get();
  112. console.log('sqlite-vec', r.v);
  113. if (!r.v) process.exit(1);
  114. \""
  115. smoke_test "bun test store" \
  116. "export PATH=$BUN_BIN:\$PATH; cd /opt/qmd && bun test --preload ./src/test-preload.ts --timeout 30000 test/store.test.ts 2>&1 | tail -10"
  117. # ------------------------------------------------------------------
  118. echo ""
  119. echo "=== Results: $PASS passed, $FAIL failed ==="
  120. [[ $FAIL -eq 0 ]]
  121. }
  122. # Parse arguments
  123. case "${1:-}" in
  124. --build)
  125. build_image
  126. ;;
  127. --shell)
  128. build_image
  129. echo "==> Dropping into container shell..."
  130. $CTR run --rm -it "$IMAGE" bash
  131. ;;
  132. --)
  133. shift
  134. run "$@"
  135. ;;
  136. *)
  137. build_image
  138. echo ""
  139. echo "==> Running smoke tests..."
  140. run_smoke_tests
  141. ;;
  142. esac