mirror of
https://github.com/we-promise/sure.git
synced 2026-07-12 21:05:20 +00:00
* fix(preview): bind :3000 instantly and bound diagnostics posts The trusted preview deploy chain now succeeds end to end (after #2124, #2207, #2217), but the preview container itself dies on Cloudflare with "Container crashed while checking for ports" and no entrypoint diagnostics ever arrive (run 27186150190). Two compounding causes, both reproduced/measured locally against the pinned @cloudflare/containers 0.3.3 behavior: 1. The port window is unwinnable. The library waits a hardcoded ~20s for the container port, but the entrypoint only binds :3000 after redis, postgres, and rails db:prepare complete -- measured at 69s under a basic instance's 1/4 vCPU. Fix: bind :3000 within ~1s via a tiny Ruby placeholder responder (static 503 + meta-refresh, input ignored), verified with a TCP connect poll, and released just before the real server starts. The worker still gates previewReady on the real Rails /up probe and sample data, so readiness semantics are unchanged. 2. Diagnostics could stall boot and never deliver. emit_status used curl with no timeout against the worker, whose Durable Object can be unresponsive while it waits for this container's port (observed as 15s status timeouts in the failed run) -- so boot could deadlock against the port check, and failure detail (#2217) never reached the diagnostics artifact. Fix: --connect-timeout 2 --max-time 5 on all posts, progress events fire-and-forget in the background, and failure paths flush synchronously before exit. Validated locally at Cloudflare basic limits (1 GiB / 0.25 vCPU): first :3000 response in 1s, full boot to Rails /up=200 at ~76s with no OOM, and a forced postgres failure exits 1 in 4s with the failure event flushed. With the port window satisfied, the next real failure will finally surface postgres detail in _container_status and CI artifacts. * fix(preview): never read from placeholder clients Superagent flagged on PR #2286 that the single-threaded :3000 placeholder blocked on client.readpartial, so one connection that sends nothing -- such as a bare TCP port probe, which is exactly what the Cloudflare port check performs -- would wedge the accept loop and starve every later probe. The response is static, so drop the read entirely: each connection is written the 503 warming page and closed immediately, making the loop effectively non-blocking per client. Regression-tested by holding three idle TCP connections open while HTTP probes still answered 503 immediately; full boot under basic-instance limits (1 GiB / 0.25 vCPU) still reaches Rails /up=200 with the placeholder answering at 1s. * fix(preview): stop postgres crashing on Cloudflare's small /dev/shm This is the actual root cause of the preview container dying on Cloudflare with "Container crashed while checking for ports" (run 27341808838) and the maintainer's "dies immediately after postgres-start" (#2217). Reproduced locally: running the preview image with a tiny /dev/shm and a WRITABLE root (the realistic Cloudflare model) crashes postgres on startup with: FATAL: could not resize shared memory segment "/PostgreSQL..." to 1048576 bytes: No space left on device PostgreSQL 17 defaults to dynamic_shared_memory_type = posix, which allocates dynamic shared memory in /dev/shm. Cloudflare Containers provide only a tiny /dev/shm, so postgres FATALs before the entrypoint can bind a port, and the container exits -> the supervisor reports it crashed during the port check. Local Docker hid this because its default /dev/shm is 64MB. Memory was ruled out (boots fine at -m 512m); it is specifically /dev/shm. Fix: set dynamic_shared_memory_type = mmap so DSM is file-backed in the data directory instead of /dev/shm. The build comments out the default posix line, appends mmap, verifies the result, and fails hard if postgresql.conf is missing so this critical setting cannot silently regress. Also log fail_preview reasons to stderr so the real failure is captured by Cloudflare container observability even when the HTTP diagnostics channel is blocked by the worker's port wait. Verified at Cloudflare basic-equivalent limits (1 GiB / 0.25 vCPU, /dev/shm 64k): before, exit 1 right after "Starting PostgreSQL..."; after, "PostgreSQL is ready" -> Rails /up=200 (~97s), placeholder answering :3000 within 1s. Normal-resource boot still reaches /up=200 in ~9s. * fix(preview): use standard-1 instance and widen CI readiness poll Two changes the preview needs to actually deploy and be reported ready on Cloudflare, both validated by deploying to a real CF account. - instance_type basic -> standard-1. The container runs postgres + redis + puma AND generates the full demo dataset (Demo::Generator, ~12 years of transactions), which peaks just over basic's 1 GiB and OOM-kills the container (exit 137) before demo-data-ready. standard-1 (1/2 vCPU, 4 GiB) completes it. Measured on real Cloudflare: rails ready ~46s, demo data ~149s, peak well under 4 GiB, no OOM. - "Collect preview diagnostics" poll budget 40 -> 100 (~128s -> ~350s), with the matching guard in bin/preview_deploy_security_check.rb. A real CF standard-1 run reached previewReady at ~195s, so the old 40-poll budget would have failed a working preview before it finished warming up. The loop still breaks early on previewReady/previewFailed. * fix(preview): apply DSM override to the cluster the entrypoint starts The build selected postgresql.conf via `find ... | head -1`, which picks an arbitrary cluster, while the entrypoint starts the highest-version cluster (ls /etc/postgresql | sort -V | tail -1). Today only PG17 is installed so they coincide, but if a second major version were ever present the override could land on a cluster that never runs, silently reintroducing the /dev/shm crash. Derive PG_CONF from the same highest-version cluster the entrypoint starts so the dynamic_shared_memory_type=mmap override always applies to the active cluster. Verified: build edits /etc/postgresql/17/main/postgresql.conf, and at runtime under a tiny /dev/shm postgres starts with SHOW dynamic_shared_memory_type = mmap. * fix(preview): apply pg_hba trust rules to the cluster the entrypoint starts Same latent issue as the dynamic_shared_memory_type override: the build wrote the local `trust` rules to `find ... | head -1` (arbitrary cluster), while the entrypoint starts the highest-version cluster. With a single PG17 they coincide, but a second major version would send the trust rules to a cluster that never runs, breaking the entrypoint's trust-auth db setup. Derive PG_HBA from the same highest-version cluster (ls /etc/postgresql | sort -V | tail -1) and fail the build if it's missing. Verified under a tiny /dev/shm: postgres starts and CREATE ROLE/CREATE DATABASE succeed via trust.
386 lines
15 KiB
Docker
386 lines
15 KiB
Docker
# syntax = docker/dockerfile:1
|
|
|
|
# Preview Dockerfile for Cloudflare Containers
|
|
# Includes PostgreSQL and Redis for self-contained development testing
|
|
|
|
ARG RUBY_VERSION=3.4.7
|
|
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim AS base
|
|
|
|
WORKDIR /rails
|
|
|
|
# Install base packages including PostgreSQL and Redis servers
|
|
RUN apt-get update -qq \
|
|
&& apt-get install --no-install-recommends -y \
|
|
curl libvips postgresql postgresql-client redis-server libyaml-0-2 procps sudo openssl strace \
|
|
&& rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
|
|
# Set development environment
|
|
ARG BUILD_COMMIT_SHA
|
|
ENV RAILS_ENV="development" \
|
|
BUNDLE_PATH="/usr/local/bundle" \
|
|
BUILD_COMMIT_SHA=${BUILD_COMMIT_SHA}
|
|
|
|
# Build stage
|
|
FROM base AS build
|
|
|
|
RUN apt-get update -qq \
|
|
&& apt-get install --no-install-recommends -y build-essential libpq-dev git pkg-config libyaml-dev \
|
|
&& rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
|
|
COPY .ruby-version Gemfile Gemfile.lock ./
|
|
RUN bundle install \
|
|
&& rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git \
|
|
&& bundle exec bootsnap precompile --gemfile -j 0
|
|
|
|
COPY . .
|
|
|
|
RUN bundle exec bootsnap precompile -j 0 app/ lib/
|
|
|
|
# Precompile assets
|
|
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
|
|
|
|
# Final stage
|
|
FROM base
|
|
|
|
# Create rails user and configure PostgreSQL/Redis permissions
|
|
RUN groupadd --system --gid 1000 rails && \
|
|
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
|
|
echo "rails ALL=(ALL) NOPASSWD: /usr/bin/pg_ctlcluster, /usr/bin/redis-server" > /etc/sudoers.d/rails && \
|
|
chmod 0440 /etc/sudoers.d/rails
|
|
|
|
# Configure PostgreSQL to allow local connections. Target the highest-version
|
|
# cluster's pg_hba.conf -- the same one the entrypoint starts (ls
|
|
# /etc/postgresql | sort -V | tail -1) -- so the trust rules always land on the
|
|
# cluster that actually runs, even if multiple majors are present.
|
|
RUN PG_VERSION="$(ls /etc/postgresql 2>/dev/null | sort -V | tail -1)" && \
|
|
PG_HBA="/etc/postgresql/${PG_VERSION}/main/pg_hba.conf" && \
|
|
if [ -z "$PG_VERSION" ] || [ ! -f "$PG_HBA" ]; then \
|
|
echo "ERROR: pg_hba.conf not found for cluster '${PG_VERSION:-none}'; cannot configure local trust" >&2; \
|
|
exit 1; \
|
|
fi && \
|
|
echo "local all all trust" > "$PG_HBA" && \
|
|
echo "host all all 127.0.0.1/32 trust" >> "$PG_HBA" && \
|
|
echo "host all all ::1/128 trust" >> "$PG_HBA"
|
|
|
|
# Use file-backed dynamic shared memory instead of POSIX /dev/shm.
|
|
# Cloudflare Containers provide only a tiny /dev/shm, and PostgreSQL's default
|
|
# dynamic_shared_memory_type = posix FATALs on startup there with
|
|
# "could not resize shared memory segment ... No space left on device", which
|
|
# kills the container before it can serve a port. mmap keeps DSM in the data
|
|
# directory ($PGDATA/pg_dynshmem), removing the /dev/shm dependency. Local
|
|
# Docker hides this because its default /dev/shm is 64MB.
|
|
#
|
|
# Select the highest-version cluster's config -- the same one the entrypoint
|
|
# starts (ls /etc/postgresql | sort -V | tail -1) -- so the override always
|
|
# lands on the cluster that actually runs, even if multiple majors are present.
|
|
RUN PG_VERSION="$(ls /etc/postgresql 2>/dev/null | sort -V | tail -1)" && \
|
|
PG_CONF="/etc/postgresql/${PG_VERSION}/main/postgresql.conf" && \
|
|
if [ -z "$PG_VERSION" ] || [ ! -f "$PG_CONF" ]; then \
|
|
echo "ERROR: postgresql.conf not found for cluster '${PG_VERSION:-none}'; cannot disable /dev/shm DSM dependency" >&2; \
|
|
exit 1; \
|
|
fi && \
|
|
sed -i 's/^[[:space:]]*dynamic_shared_memory_type[[:space:]]*=/# &/' "$PG_CONF" && \
|
|
printf '\n# Preview: avoid /dev/shm dependency (small in Cloudflare Containers)\ndynamic_shared_memory_type = mmap\n' >> "$PG_CONF" && \
|
|
grep -qx 'dynamic_shared_memory_type = mmap' "$PG_CONF" && \
|
|
echo "Configured dynamic_shared_memory_type=mmap in $PG_CONF"
|
|
|
|
# Create database directory with correct permissions
|
|
RUN mkdir -p /var/run/postgresql && \
|
|
chown -R postgres:postgres /var/run/postgresql && \
|
|
chmod 2775 /var/run/postgresql
|
|
|
|
# Copy built artifacts
|
|
COPY --chown=rails:rails --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
|
COPY --chown=rails:rails --from=build /rails /rails
|
|
|
|
# Create preview entrypoint script inline
|
|
RUN cat > /rails/bin/preview-entrypoint << 'ENTRYPOINT_EOF'
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
cd /rails
|
|
|
|
# Diagnostics posts are best-effort and must NEVER stall boot: the worker's
|
|
# Durable Object can be unresponsive while it waits for this container's port,
|
|
# so an unbounded curl here deadlocks startup against the port check.
|
|
emit_status_sync() {
|
|
if [ -n "$PREVIEW_ORIGIN" ] && [ -n "$PREVIEW_DIAGNOSTICS_NONCE" ]; then
|
|
local stage="$1"
|
|
local detail="$2"
|
|
local payload
|
|
payload=$(STAGE="$stage" DETAIL="$detail" ruby -rjson -e 'print JSON.generate({stage: ENV.fetch("STAGE"), detail: ENV.fetch("DETAIL", "")})' 2>/dev/null) || return 0
|
|
curl -fsS --connect-timeout 2 --max-time 5 -X POST "$PREVIEW_ORIGIN/_container_event" \
|
|
-H 'content-type: application/json' \
|
|
-H "x-preview-diagnostics-nonce: $PREVIEW_DIAGNOSTICS_NONCE" \
|
|
--data "$payload" >/dev/null || true
|
|
fi
|
|
}
|
|
|
|
emit_status() {
|
|
emit_status_sync "$1" "$2" &
|
|
}
|
|
|
|
summarize_log_tail() {
|
|
local file="$1"
|
|
local label="$2"
|
|
|
|
if [ ! -f "$file" ]; then
|
|
printf '%s log unavailable' "$label"
|
|
return 0
|
|
fi
|
|
|
|
tail -n 80 "$file" 2>&1 |
|
|
sed 's/"/'"'"'/g' |
|
|
tr '\n' ' ' |
|
|
sed 's/ */ /g' |
|
|
cut -c 1-1600
|
|
}
|
|
|
|
fail_preview() {
|
|
local detail="$1"
|
|
trap - ERR
|
|
# Always log to stderr too: the HTTP diagnostics channel can be unreachable
|
|
# while the worker's Durable Object is still waiting for this container's
|
|
# port, but stderr is captured by Cloudflare container observability, so the
|
|
# real reason survives even when the event POST does not.
|
|
echo "PREVIEW FAILED: ${detail}" >&2
|
|
emit_status_sync failed "$detail"
|
|
exit 1
|
|
}
|
|
|
|
postgres_cluster_snapshot() {
|
|
local snapshot=""
|
|
local cluster_status
|
|
local postgres_log
|
|
|
|
if command -v pg_lsclusters >/dev/null 2>&1; then
|
|
cluster_status="$(pg_lsclusters 2>&1 | tr '\n' '|' | sed 's/"/'"'"'/g' | cut -c 1-500)"
|
|
snapshot="clusters=${cluster_status}"
|
|
fi
|
|
|
|
postgres_log="/var/log/postgresql/postgresql-${PG_VERSION}-main.log"
|
|
if [ -f "$postgres_log" ]; then
|
|
snapshot="${snapshot} log=$(summarize_log_tail "$postgres_log" postgres)"
|
|
fi
|
|
|
|
printf '%s' "$snapshot"
|
|
}
|
|
|
|
trap 'emit_status_sync failed "preview-entrypoint failed on line ${LINENO}"' ERR
|
|
emit_status boot "preview-entrypoint started"
|
|
|
|
# Bind :3000 immediately with a tiny placeholder responder. Cloudflare's
|
|
# container supervisor only waits ~20s for the port, while the full stack
|
|
# (redis, postgres, migrations) needs 60s+ on a basic instance. The
|
|
# placeholder answers 503 with a meta-refresh; the worker still gates
|
|
# previewReady on the real Rails /up probe and sample data, so readiness
|
|
# semantics are unchanged. It is replaced by the real server below.
|
|
ruby -rsocket -e '
|
|
server = TCPServer.new("0.0.0.0", 3000)
|
|
body = "<!doctype html><html><head><meta http-equiv=\"refresh\" content=\"3\"><title>Sure preview warming</title></head><body>Sure preview is booting (database setup in progress). This page refreshes automatically.</body></html>"
|
|
loop do
|
|
client = begin
|
|
server.accept
|
|
rescue StandardError
|
|
next
|
|
end
|
|
begin
|
|
# Never read from the client: the response is static, and a blocking read
|
|
# would let one silent connection (e.g. a bare TCP port probe) wedge this
|
|
# single-threaded loop and starve every later probe.
|
|
client.write("HTTP/1.1 503 Service Unavailable\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: #{body.bytesize}\r\nRetry-After: 3\r\nConnection: close\r\n\r\n#{body}")
|
|
rescue StandardError
|
|
ensure
|
|
begin
|
|
client.close
|
|
rescue StandardError
|
|
end
|
|
end
|
|
end
|
|
' >/tmp/port-placeholder.log 2>&1 &
|
|
PLACEHOLDER_PID=$!
|
|
|
|
# Confirm the placeholder actually bound :3000 before reporting it. A plain
|
|
# TCP connect is used because the placeholder intentionally answers 503.
|
|
PLACEHOLDER_BOUND=0
|
|
for i in {1..10}; do
|
|
if (exec 3<>/dev/tcp/127.0.0.1/3000) 2>/dev/null; then
|
|
PLACEHOLDER_BOUND=1
|
|
break
|
|
fi
|
|
if ! kill -0 "$PLACEHOLDER_PID" 2>/dev/null; then
|
|
break
|
|
fi
|
|
sleep 0.2
|
|
done
|
|
if [ "$PLACEHOLDER_BOUND" -eq 1 ]; then
|
|
emit_status port-placeholder "bound :3000 placeholder responder (pid ${PLACEHOLDER_PID})"
|
|
else
|
|
echo "Warning: :3000 placeholder did not come up; continuing boot" >&2
|
|
emit_status port-placeholder-missing "placeholder responder failed to bind :3000: $(summarize_log_tail /tmp/port-placeholder.log port-placeholder)"
|
|
fi
|
|
|
|
REDIS_READY=0
|
|
POSTGRES_READY=0
|
|
|
|
# Start Redis
|
|
echo "Starting Redis..."
|
|
emit_status redis-start "starting redis"
|
|
sudo redis-server --daemonize yes --bind 127.0.0.1
|
|
|
|
# Wait for Redis to be ready
|
|
echo "Waiting for Redis to be ready..."
|
|
for i in {1..10}; do
|
|
if redis-cli ping > /dev/null 2>&1; then
|
|
echo "Redis is ready"
|
|
emit_status redis-ready "redis is ready"
|
|
REDIS_READY=1
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if [ "$REDIS_READY" -ne 1 ]; then
|
|
fail_preview "redis did not become ready in time"
|
|
fi
|
|
|
|
# Start PostgreSQL
|
|
echo "Starting PostgreSQL..."
|
|
emit_status postgres-start "starting postgres"
|
|
PG_VERSION=$(ls /etc/postgresql/ | sort -V | tail -1)
|
|
if [ -z "$PG_VERSION" ]; then
|
|
fail_preview "could not determine installed PostgreSQL version"
|
|
fi
|
|
if sudo pg_ctlcluster --skip-systemctl-redirect "$PG_VERSION" main status > /dev/null 2>&1; then
|
|
emit_status postgres-already-running "postgres cluster already running"
|
|
else
|
|
POSTGRES_START_LOG=/tmp/postgres-start.log
|
|
if ! sudo pg_ctlcluster --skip-systemctl-redirect "$PG_VERSION" main start >"$POSTGRES_START_LOG" 2>&1; then
|
|
fail_preview "pg_ctlcluster start failed: $(summarize_log_tail "$POSTGRES_START_LOG" pg_ctlcluster-start) | $(postgres_cluster_snapshot)"
|
|
fi
|
|
fi
|
|
|
|
# Wait for PostgreSQL to be ready
|
|
echo "Waiting for PostgreSQL to be ready..."
|
|
for i in {1..30}; do
|
|
if pg_isready -h localhost -U postgres > /dev/null 2>&1; then
|
|
echo "PostgreSQL is ready"
|
|
emit_status postgres-ready "postgres is ready"
|
|
POSTGRES_READY=1
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if [ "$POSTGRES_READY" -ne 1 ]; then
|
|
fail_preview "postgres did not become ready in time: $(postgres_cluster_snapshot)"
|
|
fi
|
|
|
|
# Create database user and database if they don't exist
|
|
echo "Setting up database..."
|
|
emit_status db-setup "setting up database"
|
|
psql -h localhost -U postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='rails'" | grep -q 1 || \
|
|
psql -h localhost -U postgres -c "CREATE USER rails WITH SUPERUSER PASSWORD 'rails';"
|
|
|
|
psql -h localhost -U postgres -tc "SELECT 1 FROM pg_database WHERE datname='sure_development'" | grep -q 1 || \
|
|
psql -h localhost -U postgres -c "CREATE DATABASE sure_development OWNER rails;"
|
|
|
|
# Set DATABASE_URL if not already set
|
|
export DATABASE_URL="${DATABASE_URL:-postgres://rails:rails@localhost:5432/sure_development}"
|
|
|
|
# Set REDIS_URL if not already set
|
|
export REDIS_URL="${REDIS_URL:-redis://localhost:6379/0}"
|
|
|
|
# Generate SECRET_KEY_BASE if not set
|
|
export SECRET_KEY_BASE="${SECRET_KEY_BASE:-$(openssl rand -hex 64)}"
|
|
|
|
# Run database migrations
|
|
echo "Running database migrations..."
|
|
emit_status db-prepare "running rails db:prepare"
|
|
/rails/bin/rails db:prepare
|
|
emit_status db-prepare-done "rails db:prepare finished"
|
|
|
|
# Defer all demo-data creation until after Rails is up so preview can boot first
|
|
echo "Checking demo dataset..."
|
|
emit_status demo-data-check "checking for default demo user"
|
|
DEMO_EMAIL="${DEMO_USER_EMAIL:-user@example.com}"
|
|
DEMO_EMAIL_SQL=${DEMO_EMAIL//\'/\'\'}
|
|
DEMO_SEED="${DEMO_DATA_SEED:-880}"
|
|
DEMO_HAS_USER=0
|
|
DEMO_HAS_DATA=0
|
|
|
|
if psql "$DATABASE_URL" -tAc "SELECT 1 FROM users WHERE email = '${DEMO_EMAIL_SQL}' LIMIT 1" | grep -q 1; then
|
|
DEMO_HAS_USER=1
|
|
emit_status demo-data-user-present "default demo user already exists"
|
|
fi
|
|
|
|
if psql "$DATABASE_URL" -tAc "SELECT 1 FROM accounts a JOIN users u ON u.family_id = a.family_id WHERE u.email = '${DEMO_EMAIL_SQL}' LIMIT 1" | grep -q 1; then
|
|
DEMO_HAS_DATA=1
|
|
emit_status demo-data-skip "demo financial data already exists"
|
|
else
|
|
emit_status demo-data-deferred "deferring demo data creation until after rails boot"
|
|
fi
|
|
|
|
# Release :3000 for the real server. The brief listener gap is handled by the
|
|
# worker, which catches containerFetch errors and serves its wait page.
|
|
kill "$PLACEHOLDER_PID" 2>/dev/null || true
|
|
wait "$PLACEHOLDER_PID" 2>/dev/null || true
|
|
|
|
# Execute the main command with an internal readiness probe
|
|
echo "Starting Rails server..."
|
|
emit_status rails-start "starting rails server"
|
|
"$@" > /tmp/rails.log 2>&1 &
|
|
RAILS_PID=$!
|
|
|
|
for i in {1..180}; do
|
|
if curl -fsS http://127.0.0.1:3000/up > /dev/null 2>&1; then
|
|
emit_status rails-up-ready "rails responded on localhost:3000/up"
|
|
|
|
if [ "$DEMO_HAS_USER" -ne 1 ] || [ "$DEMO_HAS_DATA" -ne 1 ]; then
|
|
emit_status demo-data-load "creating/backfilling demo dataset in background (seed=${DEMO_SEED})"
|
|
(
|
|
(
|
|
DEMO_USER_EMAIL="$DEMO_EMAIL" DEMO_DATA_SEED="$DEMO_SEED" /rails/bin/rails runner '
|
|
email = ENV.fetch("DEMO_USER_EMAIL")
|
|
generator = Demo::Generator.new(seed: ENV.fetch("DEMO_DATA_SEED"))
|
|
user = User.find_by(email: email)
|
|
|
|
unless user
|
|
generator.generate_empty_data!(skip_clear: true)
|
|
user = User.find_by!(email: email)
|
|
end
|
|
|
|
has_accounts = user.family.accounts.exists?
|
|
generator.generate_new_user_data_for!(user.family, email: user.email) unless has_accounts
|
|
'
|
|
) > /tmp/demo-data.log 2>&1 && \
|
|
emit_status demo-data-ready "default demo dataset loaded in background" || \
|
|
emit_status demo-data-failed "background demo dataset load failed: $(summarize_log_tail /tmp/demo-data.log demo-data)"
|
|
) &
|
|
fi
|
|
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if ! curl -fsS http://127.0.0.1:3000/up > /dev/null 2>&1; then
|
|
emit_status rails-up-timeout "rails did not answer localhost:3000/up in time"
|
|
emit_status rails-process-status "$(ps -o pid=,ppid=,stat=,comm=,args= -p "$RAILS_PID" 2>/dev/null | tr -s ' ' | sed 's/^ //')"
|
|
emit_status rails-process-wchan "$(cat /proc/$RAILS_PID/wchan 2>/dev/null | tr '\n' ' ' | cut -c 1-200)"
|
|
emit_status rails-process-children "$(ps -o pid=,ppid=,stat=,comm=,args= --ppid "$RAILS_PID" 2>/dev/null | tail -n +2 | tr '\n' '|' | cut -c 1-600)"
|
|
emit_status rails-socket-state "$(ruby -e 'hex="0BB8"; rows=File.readlines("/proc/net/tcp")+File.readlines("/proc/net/tcp6"); hits=rows.select{|l| l.include?(":#{hex} ")}.map{|l| l.strip.split[3] rescue nil}.compact; puts(hits.empty? ? "no-listener" : hits.join(","))' 2>&1 | tr '\n' ' ' | cut -c 1-400)"
|
|
emit_status rails-log-tail "$(tail -n 40 /tmp/rails.log 2>&1 | sed 's/"/'"'"'/g' | tr '\n' ' ' | cut -c 1-1200)"
|
|
fi
|
|
|
|
wait "$RAILS_PID"
|
|
ENTRYPOINT_EOF
|
|
RUN chmod 755 /rails/bin/preview-entrypoint && chown rails:rails /rails/bin/preview-entrypoint
|
|
|
|
USER 1000:1000
|
|
|
|
ENTRYPOINT ["/rails/bin/preview-entrypoint"]
|
|
|
|
EXPOSE 3000
|
|
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
|