restored entire zip and config'd

This commit is contained in:
2026-10-07 15:37:45 -04:00
parent 4bd9264a29
commit 5ca605dcce
219 changed files with 43370 additions and 0 deletions

View File

@@ -0,0 +1,236 @@
#!/bin/bash
# Post-start setup for the Explore devcontainer.
#
# This runs on EVERY container start (wired as `postStartCommand` in
# devcontainer.json), unlike post-create.sh which runs only once when the
# container is first created. Its job is the lightweight work that has to
# happen on every boot: bring PostgreSQL back up. The heavy one-time work
# (installing dependencies, creating + migrating the database, seeding) stays
# in post-create.sh.
#
# Why this is needed: the container is started with an entrypoint that bypasses
# the image's own startup script, so nothing restarts postgres for you. After
# you stop the container or reboot your machine, postgres stays down until this
# script runs — previously you had to start it by hand every session.
#
# Safe to run repeatedly: if postgres is already accepting connections, the
# start step is skipped and this is effectively a no-op.
set -euo pipefail
REPO_NAME=$(node -e "try{process.stdout.write(require('/workspace/toolkit.json').repo)}catch{}" 2>/dev/null || true)
# Dead-end the deployed hostnames this estate's sources still name, so booting an app with a
# non-local environment setting can't send a login form (or anything else) to a live host. Has to
# happen on every start, not in the image: Docker remounts /etc/hosts per container, so a
# Dockerfile write to it never survives.
BLOCKED_HOSTS=$(node -e "try{process.stdout.write((require('/workspace/toolkit.json').blockedHosts||[]).join(' '))}catch{}" 2>/dev/null || true)
if [ -n "$BLOCKED_HOSTS" ] && ! grep -q "raccoon-blocked-hosts" /etc/hosts 2>/dev/null; then
printf '# raccoon-blocked-hosts\n127.0.0.1 %s\n::1 %s\n' "$BLOCKED_HOSTS" "$BLOCKED_HOSTS" \
| sudo tee -a /etc/hosts >/dev/null 2>&1 \
|| echo "warning: could not pin blocked hosts in /etc/hosts" >&2
fi
# Corpus viewer: when this toolkit ships a corpus search index, serve the viewer on
# container port 3002 (published as EXPLORE_CORPUS_PORT on the host). Only
# corpus-shipping toolkits package the viewer at all; where present, the script
# self-guards (no index / no python3 / already running → quiet no-op) and must never
# block container startup.
[ -f /workspace/corpus-viewer/view-corpus.sh ] &&
bash /workspace/corpus-viewer/view-corpus.sh start --quiet || true
# True when postgres is up and answering queries.
pg_ready() { sudo -u postgres psql -c "SELECT 1" >/dev/null 2>&1; }
# Block until postgres is ready, but never hang the container start forever:
# pg_isready alone races on cluster startup, so we poll an actual query with a
# bounded number of attempts (60s) and move on with a warning if it never comes
# up rather than wedging `devcontainer up`.
wait_for_pg() {
local n=0
until pg_ready; do
sleep 0.5
n=$((n + 1))
if [ "$n" -ge 120 ]; then
echo "warning: postgres did not become ready within 60s" >&2
return 0
fi
done
}
# Polyglot toolkit: REPO_NAME is empty (no single repo). Bring up Postgres + Redis
# (members need them; per-member DB setup is deferred to run-app/setup_repo), then done.
IS_POLYGLOT=$(node -e "try{process.stdout.write(require('/workspace/toolkit.json').polyglot?'1':'')}catch{}" 2>/dev/null || true)
if [ -n "$IS_POLYGLOT" ]; then
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
sudo service redis-server start >/dev/null 2>&1 || sudo redis-server --daemonize yes >/dev/null 2>&1 || true
wait_for_pg
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'secret_password';" >/dev/null 2>&1 || true
# Many members' committed .env / database.yml default the DB username to 'root'
# (dotenv-rails applies it at boot, overriding DEV_DB_USERNAME=postgres). The image's
# start-services.sh creates a root superuser, but devcontainers override the ENTRYPOINT so
# it never runs — create root here too, mirroring the harbor task env.
sudo -u postgres psql -c "CREATE ROLE root SUPERUSER LOGIN PASSWORD 'secret_password';" >/dev/null 2>&1 || true
# MongoDB, for the polyglot images that bake it (potion's flagship member stores everything
# in Mongo). `command -v mongod` is the switch, so the Mongo-less polyglot images skip this
# untouched. It has to happen here for the same reason postgres does — the devcontainer
# overrides the image ENTRYPOINT, so the baked start-services.sh never runs — and it matters
# more than a stopped postgres would: mongoose BUFFERS operations while disconnected instead
# of erroring, so a member whose Mongo is down doesn't fail loudly, it serves requests that
# hang forever and pages that never finish rendering. Readiness is a dependency-free TCP
# probe (no mongosh needed; mongoose connects lazily once the port is open).
if command -v mongod >/dev/null 2>&1; then
mongo_up() { (exec 3<>/dev/tcp/127.0.0.1/27017) 2>/dev/null && { exec 3>&- 3<&-; return 0; }; return 1; }
if ! mongo_up; then
sudo mkdir -p /data/db 2>/dev/null || mkdir -p /data/db 2>/dev/null || true
sudo chown -R "$(id -u)":"$(id -g)" /data/db 2>/dev/null || true
mongod --dbpath /data/db --bind_ip 127.0.0.1 --fork --logpath /tmp/mongod.log >/dev/null 2>&1 \
|| (sudo -b mongod --dbpath /data/db --bind_ip 127.0.0.1 --logpath /var/log/mongod.log >/dev/null 2>&1) || true
for _ in $(seq 1 60); do mongo_up && break; sleep 0.5; done
mongo_up || echo "warning: mongod did not come up within 30s" >&2
fi
fi
# OpenSearch, for the polyglot images that bake it — same reason as mongod (the devcontainer
# overrides the ENTRYPOINT, so the image's start-services.sh never runs). Presence of the
# binary is the switch, so images without it are untouched. Flags mirror the trial image's
# start-services block exactly; it runs as its own user because OpenSearch refuses to boot
# as root. Non-fatal: a member that doesn't use it shouldn't be blocked by a slow JVM.
if [ -x /opt/opensearch/bin/opensearch ]; then
os_up() { curl -s --max-time 2 localhost:9200 >/dev/null 2>&1; }
if ! os_up; then
sudo -u opensearch env OPENSEARCH_JAVA_OPTS='-Xms512m -Xmx512m' \
/opt/opensearch/bin/opensearch -Ediscovery.type=single-node \
-Eplugins.security.disabled=true >/tmp/opensearch.log 2>&1 &
for _ in $(seq 1 90); do os_up && break; sleep 2; done
os_up || echo "warning: opensearch did not come up within 180s (see /tmp/opensearch.log)" >&2
fi
fi
return 0 2>/dev/null || exit 0
fi
case "$REPO_NAME" in
ZenBill-006)
# Start is non-fatal: if it fails outright, wait_for_pg is the single
# gate — it warns and continues rather than aborting `devcontainer up`
# and leaving the worker with no shell.
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
wait_for_pg
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'secret_password';" >/dev/null 2>&1 || true
;;
zeta-heimdall)
# Bookworm base → `service postgresql start` (same as ZenBill). Non-fatal
# start; wait_for_pg is the single gate so a hiccup warns rather than wedging
# `devcontainer up` and leaving the worker with no shell.
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
wait_for_pg
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'secret_password';" >/dev/null 2>&1 || true
;;
zeta-platform)
# Postgres + Redis (sidekiq). Start both; wait_for_pg is the single gate.
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
sudo service redis-server start >/dev/null 2>&1 || sudo redis-server --daemonize yes >/dev/null 2>&1 || true
wait_for_pg
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'secret_password';" >/dev/null 2>&1 || true
;;
Palolo-031)
if ! pg_ready; then
PG_VERSION=$(pg_config --version | grep -oP '\d+' | head -1)
sudo pg_ctlcluster "${PG_VERSION}" main start || echo "warning: 'pg_ctlcluster ${PG_VERSION} main start' failed" >&2
fi
wait_for_pg
sudo -u postgres psql -c "CREATE USER test WITH SUPERUSER PASSWORD 'test';" >/dev/null 2>&1 || true
sudo -u postgres psql -c "CREATE DATABASE palolo OWNER test;" >/dev/null 2>&1 || true
;;
human-essentials)
# Bookworm base → `service postgresql start` (same as ZenBill). Non-fatal
# start; wait_for_pg is the single gate. Trust auth (set in the image), so
# no role password to seed — the app connects as postgres with no password.
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
wait_for_pg
;;
stocks-in-the-future)
# Postgres + Redis (background jobs). Start both; wait_for_pg is the gate.
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
sudo service redis-server start >/dev/null 2>&1 || sudo redis-server --daemonize yes >/dev/null 2>&1 || true
wait_for_pg
;;
casa)
# Postgres only. Non-fatal start; wait_for_pg is the gate.
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
wait_for_pg
;;
awbw)
# MySQL 8 (Percona). Start it (init the data dir first if empty), then ensure root
# is passwordless over TCP (mysql_native_password) for Trilogy. Self-contained —
# the pg_ready/wait_for_pg helpers above are Postgres-specific.
if ! mysqladmin ping >/dev/null 2>&1; then
sudo mkdir -p /var/run/mysqld && sudo chown -R mysql:mysql /var/run/mysqld /var/lib/mysql 2>/dev/null || true
[ -d /var/lib/mysql/mysql ] || sudo mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql 2>/dev/null || true
sudo service mysql start >/dev/null 2>&1 || (sudo mysqld_safe --user=mysql >/dev/null 2>&1 &) || echo "warning: mysql start failed" >&2
fi
for i in $(seq 1 120); do mysqladmin ping >/dev/null 2>&1 && break; sleep 0.5; done
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY ''; CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED WITH mysql_native_password BY ''; GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES;" >/dev/null 2>&1 || true
# Load MySQL tz tables (Ahoy charts use Groupdate/CONVERT_TZ). One-time.
[ "$(mysql -u root -N -e 'SELECT COUNT(*) FROM mysql.time_zone_name' 2>/dev/null || echo 0)" -gt 0 ] \
|| mysql_tzinfo_to_sql /usr/share/zoneinfo 2>/dev/null | mysql -u root mysql 2>/dev/null || true
;;
flaredown)
# Three datastores: Postgres (relational slice) + Redis (Sidekiq) + MongoDB (Mongoid,
# the primary store). Start all three; wait_for_pg gates the Postgres readiness, and
# we poll mongod separately. All starts are non-fatal so a hiccup warns rather than
# wedging `devcontainer up`. Trust auth on Postgres (set in the image).
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
sudo service redis-server start >/dev/null 2>&1 || sudo redis-server --daemonize yes >/dev/null 2>&1 || true
# MongoDB (server tarball → bin/mongod on PATH; no service unit). Launch mongod against
# a data dir if nothing is already listening on 27017. Readiness is a dependency-free
# TCP probe (no mongosh needed — Mongoid connects lazily once the port is open).
mongo_up() { (exec 3<>/dev/tcp/127.0.0.1/27017) 2>/dev/null && { exec 3>&- 3<&-; return 0; }; return 1; }
if ! mongo_up; then
sudo mkdir -p /data/db 2>/dev/null || mkdir -p /data/db 2>/dev/null || true
sudo chown -R "$(id -u)":"$(id -g)" /data/db 2>/dev/null || true
mongod --dbpath /data/db --bind_ip 127.0.0.1 --fork --logpath /tmp/mongod.log >/dev/null 2>&1 \
|| (sudo -b mongod --dbpath /data/db --bind_ip 127.0.0.1 --logpath /var/log/mongod.log >/dev/null 2>&1) || true
fi
wait_for_pg
for _ in $(seq 1 60); do mongo_up && break; sleep 0.5; done
;;
frepple)
# Provisioned at image build time (the CLI overrides ENTRYPOINT); just start it.
pg_ctlcluster "$(ls /etc/postgresql | head -1)" main start 2>/dev/null || true
for i in $(seq 1 60); do pg_isready -h 127.0.0.1 -q && break; sleep 0.5; done
;;
freeitsm)
# MySQL 8 (Percona). The database and app user are created at image BUILD time —
# the devcontainer CLI overrides ENTRYPOINT, so nothing there would run.
if ! mysqladmin ping >/dev/null 2>&1; then
sudo mkdir -p /var/run/mysqld && sudo chown -R mysql:mysql /var/run/mysqld /var/lib/mysql 2>/dev/null || true
sudo service mysql start >/dev/null 2>&1 || (sudo mysqld_safe --user=mysql >/dev/null 2>&1 &) || echo "warning: mysql start failed" >&2
fi
for i in $(seq 1 120); do mysqladmin ping >/dev/null 2>&1 && break; sleep 0.5; done
;;
breezy-complete)
# Postgres + Redis (Sidekiq). Start both; wait_for_pg is the gate. Trust
# auth (set in the image) — PGPASSWORD is baked but inert, no role seeding.
if ! pg_ready; then
sudo service postgresql start || echo "warning: 'service postgresql start' failed" >&2
fi
sudo service redis-server start >/dev/null 2>&1 || sudo redis-server --daemonize yes >/dev/null 2>&1 || true
wait_for_pg
;;
esac