From eec1cd22cbd7508ac093fd480783af39a356a231 Mon Sep 17 00:00:00 2001 From: Kenneth Obsequio Date: Sat, 29 Aug 2026 15:48:02 +0800 Subject: [PATCH] db migration testing live in another VM environment for self hosting Signed-off-by: Kenneth Obsequio --- ...01000067-create-completion-requirements.js | 4 +-- ...-create-completion-requirement-progress.js | 2 +- ...1000073-create-media-playback-positions.js | 2 +- ...ert-advertisements-badge-label-to-array.js | 2 +- apps/api/scripts/garage-init.sh | 31 ------------------- docker-compose.yml | 12 +++---- 6 files changed, 11 insertions(+), 42 deletions(-) delete mode 100755 apps/api/scripts/garage-init.sh diff --git a/apps/api/database/migrations/20270101000067-create-completion-requirements.js b/apps/api/database/migrations/20270101000067-create-completion-requirements.js index 25488b4..7fa91a7 100644 --- a/apps/api/database/migrations/20270101000067-create-completion-requirements.js +++ b/apps/api/database/migrations/20270101000067-create-completion-requirements.js @@ -9,9 +9,9 @@ module.exports = { await queryInterface.sequelize.query(` CREATE TABLE completion_requirements ( requirement_id UUID PRIMARY KEY, - entity_type STRING NOT NULL, + entity_type TEXT NOT NULL, entity_id BIGINT NOT NULL, - type STRING NOT NULL, + type TEXT NOT NULL, min_percent INTEGER NULL, button_label STRING NULL, is_required BOOLEAN NOT NULL DEFAULT true, diff --git a/apps/api/database/migrations/20270101000068-create-completion-requirement-progress.js b/apps/api/database/migrations/20270101000068-create-completion-requirement-progress.js index ca87c99..c340b42 100644 --- a/apps/api/database/migrations/20270101000068-create-completion-requirement-progress.js +++ b/apps/api/database/migrations/20270101000068-create-completion-requirement-progress.js @@ -9,7 +9,7 @@ module.exports = { progress_id UUID PRIMARY KEY, requirement_id UUID NOT NULL REFERENCES completion_requirements (requirement_id) ON DELETE CASCADE, user_id BIGINT NOT NULL REFERENCES users (user_id) ON DELETE CASCADE, - entity_type STRING NOT NULL, + entity_type TEXT NOT NULL, entity_id BIGINT NOT NULL, progress_percent INTEGER NULL, completed BOOLEAN NOT NULL DEFAULT false, diff --git a/apps/api/database/migrations/20270101000073-create-media-playback-positions.js b/apps/api/database/migrations/20270101000073-create-media-playback-positions.js index a030454..48c035b 100644 --- a/apps/api/database/migrations/20270101000073-create-media-playback-positions.js +++ b/apps/api/database/migrations/20270101000073-create-media-playback-positions.js @@ -13,7 +13,7 @@ module.exports = { position_id UUID PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users (user_id) ON DELETE CASCADE, lesson_id BIGINT NOT NULL REFERENCES lessons (lesson_id) ON DELETE CASCADE, - block_id STRING NOT NULL, + block_id TEXT NOT NULL, percent INTEGER NOT NULL, "createdAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, diff --git a/apps/api/database/migrations/20270101000085-convert-advertisements-badge-label-to-array.js b/apps/api/database/migrations/20270101000085-convert-advertisements-badge-label-to-array.js index e9b2cdd..878f24e 100644 --- a/apps/api/database/migrations/20270101000085-convert-advertisements-badge-label-to-array.js +++ b/apps/api/database/migrations/20270101000085-convert-advertisements-badge-label-to-array.js @@ -41,7 +41,7 @@ module.exports = { await queryInterface.sequelize.query(` ALTER TABLE advertisements - ALTER COLUMN badge_label TYPE STRING(100) + ALTER COLUMN badge_label TYPE TEXT USING ( CASE WHEN jsonb_array_length(badge_label) = 0 THEN NULL diff --git a/apps/api/scripts/garage-init.sh b/apps/api/scripts/garage-init.sh deleted file mode 100755 index 40cd1ff..0000000 --- a/apps/api/scripts/garage-init.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# Wraps the Garage daemon: starts it in the background, runs one-time cluster -# initialization using the local RPC connection, then hands control back to -# the daemon process. Safe to re-run — all operations are idempotent. -set -e - -garage server & -DAEMON_PID=$! - -echo "Waiting for Garage to be ready..." -until garage status > /dev/null 2>&1; do - sleep 2 -done -echo "Garage is up. Running cluster initialization..." - -NODE_ID=$(garage node id 2>/dev/null | head -1 | awk '{print $1}') -garage layout assign "$NODE_ID" -z dc1 -c 100G 2>/dev/null || true -garage layout apply --version 1 2>/dev/null || true - -garage bucket create "$S3_BUCKET" 2>/dev/null || true - -# --yes skips the interactive confirmation prompt. -garage key import "$S3_ACCESS_KEY" "$S3_SECRET_KEY" -n starr-app --yes 2>/dev/null || true - -garage bucket allow "$S3_BUCKET" --read --write --owner --key "$S3_ACCESS_KEY" 2>/dev/null || true - -# Flag file read by the healthcheck — ensures the backend waits for full init. -touch /var/lib/garage/meta/.ready -echo "Garage init complete." - -wait $DAEMON_PID diff --git a/docker-compose.yml b/docker-compose.yml index d40f757..26caa38 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,21 +82,21 @@ services: # to serve S3_PUBLIC_URL (e.g. https://cdn.yourdomain.com → http://garage:3900). # GARAGE_RPC_SECRET must be set in .env (generate with: openssl rand -hex 32). # - # garage-init.sh starts the daemon in the background, runs one-time cluster - # initialization (layout, bucket, key), then hands control back to the daemon. + # The dxflrs/garage image ships only the static `garage` binary — no shell, + # so it can't run garage-init.sh (and CMD-SHELL healthchecks can't run + # either, same reason). Cluster init (layout/bucket/key) is a one-time + # manual step after first `docker compose up` — see README/setup notes. garage: - image: dxflrs/garage - entrypoint: ["/bin/sh", "/garage-init.sh"] + image: dxflrs/garage:v2.3.0 volumes: - ./apps/api/config/garage.toml:/etc/garage.toml:ro - - ./apps/api/scripts/garage-init.sh:/garage-init.sh:ro - garage_meta:/var/lib/garage/meta - garage_data:/var/lib/garage/data ports: - "3900:3900" env_file: apps/api/.env healthcheck: - test: ["CMD-SHELL", "test -f /var/lib/garage/meta/.ready && garage status > /dev/null 2>&1"] + test: ["CMD", "/garage", "status"] interval: 10s timeout: 5s retries: 10