-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add auto-bootstrap seed functionality for empty database tables… #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -234,6 +234,31 @@ jobs: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eval "$MIGRATION_COMMAND" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Auto-bootstrap seed when DB is empty (prevents blank app after deploy/reset). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| get_table_count() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| table="$1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sudo docker compose -f docker-compose.prod.yml exec -T mysql \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mysql -N -s -uroot -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" -e "SELECT COUNT(*) FROM $table;" 2>/dev/null | tr -d '\r' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PRODUCTS_COUNT="$(get_table_count products || echo 0)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VARIANTS_COUNT="$(get_table_count product_variants || echo 0)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| STOCK_COUNT="$(get_table_count inventory_stock || echo 0)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+240
to
+246
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sudo docker compose -f docker-compose.prod.yml exec -T mysql \ | |
| mysql -N -s -uroot -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" -e "SELECT COUNT(*) FROM $table;" 2>/dev/null | tr -d '\r' | |
| } | |
| PRODUCTS_COUNT="$(get_table_count products || echo 0)" | |
| VARIANTS_COUNT="$(get_table_count product_variants || echo 0)" | |
| STOCK_COUNT="$(get_table_count inventory_stock || echo 0)" | |
| # Wait for MySQL to be ready and fail loudly on errors. | |
| local attempt=0 | |
| local max_attempts=5 | |
| local sleep_seconds=3 | |
| local count | |
| # Ensure pipeline failures propagate (mysql errors aren't hidden by `tr`). | |
| set -o pipefail | |
| while [ "$attempt" -lt "$max_attempts" ]; do | |
| if count="$( | |
| sudo docker compose -f docker-compose.prod.yml exec -T mysql \ | |
| mysql -N -s -uroot -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" \ | |
| -e "SELECT COUNT(*) FROM $table;" | tr -d '\r' | |
| )"; then | |
| if printf '%s\n' "$count" | grep -Eq '^[0-9]+$'; then | |
| echo "$count" | |
| return 0 | |
| else | |
| echo "Non-numeric row count '$count' returned for table '$table'" >&2 | |
| return 1 | |
| fi | |
| fi | |
| attempt=$((attempt + 1)) | |
| echo "Unable to query table '$table' (attempt $attempt/$max_attempts). Waiting for MySQL to become ready..." >&2 | |
| sleep "$sleep_seconds" | |
| done | |
| echo "Failed to query table '$table' after $max_attempts attempts; aborting." >&2 | |
| return 1 | |
| } | |
| if ! PRODUCTS_COUNT="$(get_table_count products)"; then | |
| echo "Error retrieving row count for 'products' table; aborting deployment." >&2 | |
| exit 1 | |
| fi | |
| if ! VARIANTS_COUNT="$(get_table_count product_variants)"; then | |
| echo "Error retrieving row count for 'product_variants' table; aborting deployment." >&2 | |
| exit 1 | |
| fi | |
| if ! STOCK_COUNT="$(get_table_count inventory_stock)"; then | |
| echo "Error retrieving row count for 'inventory_stock' table; aborting deployment." >&2 | |
| exit 1 | |
| fi |
Copilot
AI
Mar 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition products == 0 || variants == 0 will run reset-db-and-seed.sh, which drops and recreates the database. This is risky because a legitimately empty table (or a transient/partial seed) would wipe an otherwise valid production DB. Consider tightening the guard to only bootstrap when the database is clearly fresh (e.g., all critical tables are 0 and/or schema just created), and/or gate behind an explicit flag/secret (e.g., AUTO_BOOTSTRAP_SEED=true) so normal deploys can’t trigger a destructive reset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MySQL root password is passed as a CLI argument (
-p"$MYSQL_ROOT_PASSWORD"), which can be visible to other processes on the VM via process listings. Prefer usingMYSQL_PWD(passed viadocker compose exec -e MYSQL_PWD=...) or a defaults file inside the container so the password isn’t part of the command line.