customer-riverside/docker/php/entrypoint.sh
Philip Peterson 1e3ba132a4 Suppress duplicate key errors on semaphore table during rebuilds
- In _riverside_pt_rebuild(): proactively TRUNCATE the semaphore table
  at the very start of every rebuild. This eliminates the common
  'duplicate key value violates unique constraint "semaphore____pkey"'
  errors for 'state:Drupal\Core\Cache\CacheCollector' and 'cron' that
  appear in postgres logs.

- In entrypoint.sh: add TRUNCATE semaphore at strategic points
  (right after site:install, before module enables, before/after
  riverside:rebuild, before final drush cr). Wrapped with || true
  so they never break the startup script.

- Added a note in CLAUDE.md under the rebuild section explaining
  the errors and the quick manual fix.

These are harmless (Drupal's DbLockBackend usually recovers) but
very noisy in the container logs during the default full rebuild
path.
2026-06-04 00:06:27 -07:00

123 lines
5 KiB
Bash

#!/bin/sh
DB_HOST="${DB_HOST:-postgres}"
DB_USER="${DB_USER:-drupal}"
DB_NAME="${DB_NAME:-drupal}"
for var in SITE_NAME ADMIN_PASS; do
eval val=\$$var
if [ -z "$val" ]; then
echo "[entrypoint] FATAL: $var is required."
exit 1
fi
done
echo "[entrypoint] Waiting for PostgreSQL at ${DB_HOST}..."
until pg_isready -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -q; do
sleep 1
done
echo "[entrypoint] PostgreSQL is ready."
cd /var/www/html
DRUSH="vendor/bin/drush --root=/var/www/html/web"
echo "[entrypoint] Preparing database..."
if [ "${DRUPAL_FAST:-}" = "1" ]; then
echo "[entrypoint] DRUPAL_FAST=1 — skipping database wipe and full site reinstall."
else
echo "[entrypoint] Full rebuild mode (default). Dropping database..."
$DRUSH sql:drop -y || true
echo "[entrypoint] Installing Drupal (standard profile)..."
$DRUSH site:install standard \
--site-name="$SITE_NAME" \
--account-name=admin \
--account-pass="$ADMIN_PASS" \
-y || { echo "[entrypoint] FATAL: site:install failed."; exit 1; }
echo "[entrypoint] Drupal installed."
# Clear semaphores immediately after fresh install (prevents early
# duplicate key errors during first module enables + rebuild).
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
fi
# Always clear stale semaphores before module enables + rebuild.
# This is the most reliable way to avoid the duplicate key errors
# on "semaphore" (CacheCollector, cron, state locks, etc.).
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
echo "[entrypoint] Enabling required modules..."
$DRUSH en -y views views_ui field_ui text options link datetime && \
echo "[entrypoint] Core modules enabled." || echo "[entrypoint] WARNING: core modules failed."
$DRUSH en -y webform webform_ui && \
echo "[entrypoint] Webform enabled." || echo "[entrypoint] WARNING: webform failed."
$DRUSH en -y symfony_mailer && \
echo "[entrypoint] Mailer enabled." || echo "[entrypoint] WARNING: symfony_mailer failed."
$DRUSH en -y riverside_pt && \
echo "[entrypoint] riverside_pt enabled." || echo "[entrypoint] WARNING: riverside_pt failed."
# Clear semaphores to avoid duplicate key violations on the semaphore
# table (e.g. during CacheCollector, cron, state operations) that can
# occur during rapid config/entity changes in the rebuild.
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
echo "[entrypoint] Rebuilding site structure from code (riverside:rebuild)..."
$DRUSH riverside:rebuild || echo "[entrypoint] WARNING: riverside:rebuild encountered an issue."
# Re-assert a few key pieces (cheap and safe).
$DRUSH theme:enable starterkit_theme claro_compact -y && \
$DRUSH config:set system.theme default starterkit_theme -y && \
$DRUSH config:set system.theme admin claro_compact -y && \
echo "[entrypoint] Themes set." || echo "[entrypoint] WARNING: theme enable failed."
$DRUSH config:set system.site page.front /home -y && \
echo "[entrypoint] Front page set." || echo "[entrypoint] WARNING: front page set failed."
npm run build --prefix /var/www/html >/dev/null 2>&1 && echo "[entrypoint] Tailwind built." || echo "[entrypoint] WARNING: Tailwind build failed."
# One more semaphore clear before the final cache rebuild (common source
# of the duplicate key errors seen in logs).
$DRUSH sql:query "TRUNCATE TABLE semaphore;" 2>/dev/null || true
$DRUSH cache:rebuild >/dev/null 2>&1 && echo "[entrypoint] Cache rebuilt."
if [ "${DEBUG:-false}" = "true" ]; then
# Mock sendmail on localhost/dev: prints full email to stderr (visible in docker logs)
# instead of erroring with "sh: 1: /usr/sbin/sendmail: not found".
# This catches any php_mail / legacy mail() calls (e.g. some webforms, fallbacks).
# Real emails should still go via symfony_mailer + Postmark when configured.
cat > /usr/local/bin/fake-sendmail.sh << 'FAKE_SENDMAIL'
#!/bin/sh
echo "=== MOCK SENDMAIL (dev - email logged, not sent) ===" >&2
echo "Timestamp: $(date -Iseconds)" >&2
echo "Called as: $0 $*" >&2
echo "----- EMAIL CONTENT -----" >&2
cat >&2
echo "" >&2
echo "=== END MOCK SENDMAIL ===" >&2
exit 0
FAKE_SENDMAIL
chmod +x /usr/local/bin/fake-sendmail.sh
echo "[entrypoint] Installed fake sendmail for dev logging."
# Override sendmail_path for PHP (affects php_mail interface and any direct mail()).
echo 'sendmail_path = /usr/local/bin/fake-sendmail.sh' > /usr/local/etc/php/conf.d/sendmail.ini 2>/dev/null || true
else
# Ensure no dev mock leaks into prod: remove any sendmail_path override and the fake script.
rm -f /usr/local/etc/php/conf.d/sendmail.ini /usr/local/bin/fake-sendmail.sh 2>/dev/null || true
fi
if [ "${DEBUG:-false}" = "true" ]; then
NGINX_CSS_CACHE='expires off; add_header Cache-Control "no-store";'
else
NGINX_CSS_CACHE='expires max;'
fi
export NGINX_CSS_CACHE
envsubst '${NGINX_CSS_CACHE}' \
< /etc/nginx/conf.d/default.conf.template \
> /etc/nginx/conf.d/default.conf
echo "[entrypoint] nginx cache mode: ${DEBUG:-false} = debug."
echo "[entrypoint] Starting services..."
exec supervisord -c /etc/supervisor/conf.d/supervisord.conf