Skip to content

Conversation

@ralf-berger
Copy link

@ralf-berger ralf-berger commented Aug 16, 2025

Which issue does this close?

Closes #4 and #7

@ralf-berger ralf-berger self-assigned this Aug 16, 2025
@ralf-berger ralf-berger linked an issue Aug 16, 2025 that may be closed by this pull request
@coderabbitai
Copy link

coderabbitai bot commented Aug 16, 2025

Summary by CodeRabbit

  • New Features

    • Added automated database migrations and seeding, including creation of an initial admin account via environment variables.
    • Improved service health checks to ensure components start in the correct order and are ready before use.
  • Chores

    • Simplified command tasks by removing the admin task and streamlining CLI invocation.
    • Hardened service startup scripts with stricter error handling for more reliable runtime behavior.
    • Updated container orchestration to use explicit health-based dependencies and clearer port/watch configurations.

Walkthrough

Removes the admin Taskfile task, adds executable scripts for migrations and seeds, restructures compose.yaml to add migrations/seeds services, swaps API/UI roles and ports, adds health-based depends_on and LL_ADMIN_* env vars, and enables strict shell handling in several bin/* scripts.

Changes

Cohort / File(s) Summary
Taskfile changes
Taskfile.docker.yaml
Removed public admin task; removed admin invocation from all; inlined cli cmds.
New startup scripts
bin/migrations, bin/seeds
Added executable scripts: migrations runs node cli/dist/server migrateMongo --up; seeds runs node cli/dist/server createSiteAdmin using required LL_ADMIN_* env vars.
Bin scripts: strict mode
bin/api, bin/cli, bin/entrypoint, bin/ui, bin/worker
Inserted set -eu after shebang in each launcher script to enable exit-on-error and nounset.
Compose: services & orchestration
compose.yaml
Added migrations and seeds services; swapped api/ui service blocks and ports (API → 8080, UI → 3000); added health-based depends_on for api and worker; seeds depends on migrations completion; migrations depends on mongo healthy; CLI service simplified (command/tty/depends changes).
Compose: common env and mongo
compose.yaml (x-common, mongo)
Added LL_ADMIN_EMAIL/ORG/PASSWORD to x-common; removed x-common depends_on; changed mongo image to mongo:4.4 and replaced mongosh-based healthcheck with mongo CLI-based check.
Compose: develop/watch & formatting
compose.yaml (develop/watch entries, ports, healthchecks)
Updated develop/watch paths to reflect api/ui swap; adjusted port/healthcheck formatting and minor formatting changes across services.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Compose as Docker Compose
  participant Mongo as mongo
  participant Migrate as migrations
  participant Seeds as seeds
  participant API as api
  participant Worker as worker
  participant CLI as cli

  Compose->>Mongo: start (healthcheck)
  Mongo-->>Compose: healthy

  Compose->>Migrate: start (depends_on: Mongo healthy)
  Migrate-->>Compose: completed_successfully

  Compose->>Seeds: start (depends_on: Migrate success)
  Seeds-->>Compose: completed_successfully (creates admin via LL_ADMIN_*)

  Compose->>API: start (depends_on: Mongo healthy, Seeds success, Redis healthy)
  Compose->>Worker: start (depends_on: Mongo/Redis healthy)
  Compose->>CLI: available (tty, no depends_on)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
Create admin user on startup (#4)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Swap of api/ui service declarations and port mappings (compose.yaml) Service role and port swaps are unrelated to creating an admin user on startup.
Mongo image change to mongo:4.4 and healthcheck command switch (compose.yaml) Downgrading Mongo and replacing mongosh with mongo does not affect admin creation objective.
CLI service runtime tweaks (command, tty, removal of depends_on) (compose.yaml) CLI invocation/TTY/profile adjustments are not required by the admin-seeding objective.
Worker depends_on expansion to include Redis health (compose.yaml) Adjusting worker dependencies does not impact admin user upsert requirement.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue/4-create-admin-user-on-startup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ff3b168 and 8bc9942.

📒 Files selected for processing (4)
  • Taskfile.docker.yaml (1 hunks)
  • bin/migrations (1 hunks)
  • bin/seeds (1 hunks)
  • compose.yaml (1 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
Taskfile.docker.yaml

[error] 41-41: too many spaces inside brackets

(brackets)


[error] 41-41: too many spaces inside brackets

(brackets)

compose.yaml

[error] 40-40: wrong indentation: expected 6 but found 4

(indentation)


[error] 42-42: wrong indentation: expected 6 but found 4

(indentation)


[error] 45-45: wrong indentation: expected 8 but found 6

(indentation)


[error] 51-51: too many spaces inside brackets

(brackets)


[error] 51-51: too many spaces inside brackets

(brackets)


[error] 63-63: wrong indentation: expected 8 but found 6

(indentation)


[error] 78-78: wrong indentation: expected 8 but found 6

(indentation)


[error] 88-88: wrong indentation: expected 8 but found 6

(indentation)


[error] 111-111: too many spaces inside brackets

(brackets)


[error] 111-111: too many spaces inside brackets

(brackets)


[error] 113-113: wrong indentation: expected 6 but found 4

(indentation)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build container image
🔇 Additional comments (4)
Taskfile.docker.yaml (1)

41-41: Fix flow-sequence bracket spacing and quote the command

Yamllint’s E211 rule flags the extra spaces after [ and before ]. Quoting the entire invocation also ensures $COMPOSE_CMD run cli is treated as a single list item.

  • File: Taskfile.docker.yaml, line 41
-    cmds: [ $COMPOSE_CMD run cli ]
+    cmds: ["$COMPOSE_CMD run cli"]

(Optional: to launch an interactive shell instead, you could use:

cmds: ["$COMPOSE_CMD run --rm --service-ports cli sh"]
```)

</details>
<details>
<summary>compose.yaml (3)</summary>

`39-46`: **Normalize `ports` list indentation**  
To satisfy yamllint’s indentation rules for YAML lists, update the `ports` entry in compose.yaml (lines 39–46) to use an inline list or correctly indent the block style. For example:

```diff
-    ports:
-    - "3000:3000"
+    ports: ["3000:3000"]

After applying this change, please re-run yamllint to confirm that the indentation warning for ports is resolved.


109-116: MongoDB downgrade to 4.4: confirm driver/migrations compatibility & streamline healthcheck

  • package.json shows
    • “mongodb”: “^2.1.4”
    • “mongoose”: “^5.4.0”
    These client versions predate MongoDB 4.x—please verify they fully support server 4.4 APIs and wire protocols.
  • Migrations live under cli/src/commands/v1-migrations/ and cli/src/commands/v2-migrations/ – review them for any commands or operators introduced after 4.4.
  • Replace the healthcheck with a simpler, deterministic command:
-      test: "mongo --nodb --eval 'disableTelemetry()'; echo 'db.runCommand({ping: 1}).ok' | mongo localhost:27017/test --quiet"
+      test: ["CMD-SHELL", "echo 'db.runCommand({ ping: 1 }).ok' | mongo localhost:27017/test --quiet"]

Let me know if you’d like an automated scan of your migration scripts.


93-93: Explicit command invocation confirmed

  • Dockerfile (lines 4, 20): WORKDIR is set to /opt/learninglocker
  • Dockerfile (line 36): COPY bin ./bin ensures the bin/ directory is included
  • File bin/seeds exists and is executable (-rwxr-xr-x)
-    command: seeds
+    command: ["bin/seeds"]

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🔭 Outside diff range comments (1)
bin/entrypoint (1)

2-10: Avoid CWD-dependent PATH by deriving bin dir from script location

Using ./bin assumes the entrypoint’s working directory. Derive the bin dir from the script’s directory so PATH is correct regardless of CWD.

 #!/usr/bin/env sh
 set -eu
 
 MONGO_HOST="${MONGO_HOST:-localhost}"
 MONGO_PORT="${MONGO_PORT:-27017}"
 MONGO_DATABASE="${MONGO_DATABASE:-learninglocker_v2}"
 export MONGODB_PATH="mongodb://${MONGO_HOST}:${MONGO_PORT}/${MONGO_DATABASE}"
 
-export PATH=./bin:$PATH
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+export PATH="$SCRIPT_DIR:$PATH"
 exec "$@"
♻️ Duplicate comments (3)
bin/migrations (1)

1-5: Follow-up: resolve CLI path relative to script and exec it

Good addition of strict mode. As previously noted, using a relative path for the CLI couples this script to the working directory. Resolve the path relative to this script and exec to propagate signals/exit codes cleanly.

 #!/usr/bin/env sh
 set -eu
 
 echo "Executing database migrations ..."
-node cli/dist/server migrateMongo --up
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+TARGET="$SCRIPT_DIR/../cli/dist/server"
+if [ ! -f "$TARGET" ]; then
+  echo "CLI entry not found at $TARGET (did you build the CLI?)" >&2
+  exit 1
+fi
+exec node "$TARGET" migrateMongo --up
bin/seeds (2)

5-5: Don’t pass secrets via argv; use stdin or env consumption in the CLI

Password on the command line is visible in process lists and logs. Prefer stdin or environment-based consumption by the CLI.

If the CLI can read the password from stdin, switch to a flag like --password-stdin and pipe the secret:

-echo "Setting up seed data ..."
-node cli/dist/server createSiteAdmin "${LL_ADMIN_EMAIL:?}" "${LL_ADMIN_ORG:?}" "${LL_ADMIN_PASSWORD:?}"
+echo "Setting up seed data ..."
+# Avoid leaking the password via argv; feed it on stdin if supported by the CLI:
+printf '%s' "${LL_ADMIN_PASSWORD:?}" | node cli/dist/server createSiteAdmin --email "${LL_ADMIN_EMAIL:?}" --org "${LL_ADMIN_ORG:?}" --password-stdin

If stdin is not yet supported, I can update the CLI to accept env/flags for non-interactive secrets (e.g., LL_ADMIN_PASSWORD or --password-env). Want me to open a follow-up PR?


5-5: Decouple from working directory for robust execution

Use a script-relative path so the seeds job works regardless of cwd/ENTRYPOINT.

 echo "Setting up seed data ..."
-node cli/dist/server createSiteAdmin "${LL_ADMIN_EMAIL:?}" "${LL_ADMIN_ORG:?}" "${LL_ADMIN_PASSWORD:?}"
+SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
+exec node "$SCRIPT_DIR/../cli/dist/server" createSiteAdmin "${LL_ADMIN_EMAIL:?}" "${LL_ADMIN_ORG:?}" "${LL_ADMIN_PASSWORD:?}"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8bc9942 and d0e5d0d.

📒 Files selected for processing (7)
  • bin/api (1 hunks)
  • bin/cli (1 hunks)
  • bin/entrypoint (1 hunks)
  • bin/migrations (1 hunks)
  • bin/seeds (1 hunks)
  • bin/ui (1 hunks)
  • bin/worker (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build container image
🔇 Additional comments (3)
bin/migrations (1)

4-5: Migrations and seeds are idempotent and correctly wired

– compose.yaml ensures the migrations service only starts after Mongo is healthy and the seeds service only runs once migrations complete successfully.
– bin/seeds invokes createSiteAdmin with LL_ADMIN_* vars, and createSiteAdmin uses find-or-create logic (with duplicate-key checks) to avoid recreating users or orgs.
– The migrateMongo CLI command delegates to the custom migrator (tested in migrateMongo-test.js), which records applied migrations and only runs outstanding ones, making it safe to re-run.

No further changes required.

bin/worker (1)

2-2: Good addition: enable strict mode early

set -eu is appropriate here and will fail fast on errors/unset vars.

bin/seeds (1)

1-2: Solid hardening: strict mode enabled

set -eu and the use of ${VAR:?} are good choices to fail fast and catch unset envs.

set -eu

echo "Setting up seed data ..."
node cli/dist/server createSiteAdmin "${LL_ADMIN_EMAIL:?}" "${LL_ADMIN_ORG:?}" "${LL_ADMIN_PASSWORD:?}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify idempotency/upsert semantics of createSiteAdmin

The PR objective requires creating or upserting an admin on startup. Please confirm the CLI operation is idempotent (no duplicate users, safe on re-runs).

Run this script to locate the implementation and check for upsert/exists handling:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching for CLI command createSiteAdmin definition and usage..."
rg -n -C3 -S '\bcreateSiteAdmin\b'

echo
echo "Scanning for idempotent patterns near user creation (upsert/exists/unique)..."
rg -n -C3 -iP 'upsert|onConflict|unique|ensureIndex|already exists|duplicate key|findOne|findUnique|findFirst'

echo
echo "If Prisma is used, look for upsert calls:"
rg -n -C3 -iP '\bupsert\s*\('

echo
echo "If Mongoose is used, check for findOneAndUpdate with upsert: true:"
rg -n -C3 -iP 'findOneAndUpdate\s*\(.*upsert\s*:\s*true'

Length of output: 133165


🏁 Script executed:

#!/bin/bash
# Display the key parts of createSiteAdmin implementation to verify idempotency
sed -n '1,200p' cli/src/commands/createSiteAdmin.js

Length of output: 3909


Fix idempotency in createSiteAdmin

The current implementation of createSiteAdmin is not idempotent because:

  • Organisation assignment always pushes a duplicate entry on every run.
  • Password‐force update silently fails to persist when the user is already a SITE_ADMIN.

Please update cli/src/commands/createSiteAdmin.js:

  • In ensureUserHasOrg (≈line 39), compare IDs—not name—to detect an existing org:
- const foundOrg = _.find(user.organisations, org => org.toString() === organisation.name);
+ const foundOrg = _.find(
+   user.organisations,
+   orgId => orgId.toString() === organisation._id.toString()
+ );
  • In ensureSiteAdmin (≈line 23), always save when forcing a password update (even if the SITE_ADMIN scope already exists):
- async function ensureSiteAdmin(user, password, forceUpdatePassword) {
-   if (forceUpdatePassword) user.password = password;
-   if (!_.includes(user.scopes, scopes.SITE_ADMIN)) {
-     user.scopes.push(scopes.SITE_ADMIN);
-     return await user.save();
-   }
-   return user;
- }
+ async function ensureSiteAdmin(user, password, forceUpdatePassword) {
+   let modified = false;
+   if (forceUpdatePassword) {
+     user.password = password;
+     modified = true;
+   }
+   if (!_.includes(user.scopes, scopes.SITE_ADMIN)) {
+     user.scopes.push(scopes.SITE_ADMIN);
+     modified = true;
+   }
+   if (modified) {
+     await user.save();
+   }
+   return user;
+ }

With these changes, rerunning bin/seeds will no longer accumulate duplicate organisations or drop intended password updates.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In cli/src/commands/createSiteAdmin.js around lines 23 and 39, fix idempotency:
in ensureUserHasOrg (≈line 39) check existing user.organisations by
organisation.id (not by name) and only push the org object if no matching id
exists to avoid duplicate entries; in ensureSiteAdmin (≈line 23) when
force-password is requested, always assign the new password and call await
user.save() even if the SITE_ADMIN scope is already present so the password
change persists. Ensure both checks use strict ID comparison and await any save
calls.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Duplicate organisation: Probably bad, should be investigated
  • Not updating password: Actually the intended behaviour once the account exists

@ralf-berger
Copy link
Author

@coderabbitai Recreate the sequence diagram, but include the redis service

@coderabbitai
Copy link

coderabbitai bot commented Aug 17, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

I'll recreate the sequence diagram including the Redis service. Let me first examine the current system architecture to understand all service interactions.

Now I'll create a comprehensive sequence diagram that includes Redis and shows the complete startup orchestration:

@ralf-berger Here's the updated sequence diagram that includes the Redis service and shows the complete startup orchestration:

sequenceDiagram
    participant User as User/Docker Compose
    participant Mongo as MongoDB
    participant Redis as Redis
    participant Migrations as Migrations Service
    participant Seeds as Seeds Service
    participant API as API Service
    participant UI as UI Service
    participant Worker as Worker Service
    participant XAPI as xAPI Service

    User->>Mongo: Start MongoDB
    User->>Redis: Start Redis
    
    Note over Mongo: Health check: mongo --nodb --eval<br/>Waits until healthy
    Note over Redis: Health check: redis-cli ping<br/>Waits until healthy
    
    Mongo-->>User: MongoDB healthy ✓
    Redis-->>User: Redis healthy ✓
    
    User->>Migrations: Start migrations service
    Migrations->>Mongo: Wait for healthy condition
    Mongo-->>Migrations: Healthy ✓
    Migrations->>Migrations: Execute: node cli/dist/server migrateMongo --up
    Note over Migrations: Database migrations completed
    Migrations-->>User: Service completed successfully ✓
    
    User->>Seeds: Start seeds service
    Seeds->>Migrations: Wait for completion
    Migrations-->>Seeds: Completed successfully ✓
    Seeds->>Seeds: Execute: node cli/dist/server createSiteAdmin<br/>with LL_ADMIN_EMAIL, LL_ADMIN_ORG, LL_ADMIN_PASSWORD
    Note over Seeds: Admin user created/upserted
    Seeds-->>User: Service completed (restart: on-failure) ✓
    
    User->>API: Start API service
    API->>Mongo: Wait for healthy condition
    API->>Redis: Wait for healthy condition
    API->>Seeds: Wait for successful completion
    Mongo-->>API: Healthy ✓
    Redis-->>API: Healthy ✓
    Seeds-->>API: Completed successfully ✓
    API->>API: Execute: node api/dist/server
    Note over API: API server running on port 8080<br/>Connected to MongoDB and Redis
    API-->>User: API service ready ✓
    
    User->>Worker: Start worker service
    Worker->>Mongo: Wait for healthy condition
    Worker->>Redis: Wait for healthy condition
    Mongo-->>Worker: Healthy ✓
    Redis-->>Worker: Healthy ✓
    Worker->>Worker: Execute: node worker/dist/server
    Note over Worker: Background worker running<br/>Connected to MongoDB and Redis
    Worker-->>User: Worker service ready ✓
    
    User->>UI: Start UI service
    UI->>API: Wait for API service
    API-->>UI: API ready ✓
    UI->>UI: Execute: node ui/dist/server
    Note over UI: Frontend running on port 3000<br/>Proxies to API service
    UI-->>User: UI service ready ✓
    
    User->>XAPI: Start xAPI service
    XAPI->>XAPI: Execute: node xapi/dist/server
    Note over XAPI: xAPI service running independently
    XAPI-->>User: xAPI service ready ✓

    Note over User,XAPI: All services operational with admin user created<br/>MongoDB and Redis provide data persistence and caching
Loading

This sequence diagram now includes:

  1. Redis Service: Shows Redis starting up with health checks alongside MongoDB
  2. Health Dependencies: Both API and Worker services wait for Redis to be healthy before starting
  3. Complete Orchestration: Shows the full startup sequence from infrastructure (MongoDB, Redis) through migrations, seeds, and finally all application services
  4. Admin User Creation: The Seeds service creates the admin user using the environment variables (LL_ADMIN_EMAIL, LL_ADMIN_ORG, LL_ADMIN_PASSWORD)
  5. Service Interdependencies: UI depends on API, while API and Worker both depend on Redis and MongoDB being healthy

The Redis service provides caching and session management capabilities to both the API and Worker services, ensuring they don't start until Redis is fully operational.


🏁 Script executed:

#!/bin/bash
# Read the compose.yaml to understand service dependencies and Redis integration
cat compose.yaml

Length of output: 3450


🏁 Script executed:

#!/bin/bash
# Read the new bin scripts to understand their functionality
echo "=== bin/migrations ==="
cat bin/migrations
echo -e "\n=== bin/seeds ==="
cat bin/seeds

Length of output: 412


@ralf-berger Here's the updated sequence diagram that accurately reflects the Redis service integration based on the actual compose.yaml configuration:

sequenceDiagram
    participant User as User/Docker Compose
    participant Mongo as MongoDB
    participant Redis as Redis
    participant Migrations as Migrations Service
    participant Seeds as Seeds Service
    participant API as API Service
    participant UI as UI Service
    participant Worker as Worker Service
    participant XAPI as xAPI Service

    User->>Mongo: Start MongoDB (mongo:4.4)
    User->>Redis: Start Redis (redis:7)
    
    Note over Mongo: Health check: mongo --nodb --eval<br/>+ ping command via mongo CLI
    Note over Redis: Health check: redis-cli ping<br/>Every 10s, start period 2s
    
    Mongo-->>User: MongoDB healthy ✓
    Redis-->>User: Redis healthy ✓
    
    User->>Migrations: Start migrations service
    Migrations->>Mongo: Wait for healthy condition (restart: true)
    Mongo-->>Migrations: Healthy ✓
    Migrations->>Migrations: Execute: node cli/dist/server migrateMongo --up
    Note over Migrations: "Executing database migrations ..."
    Migrations-->>User: Service completed successfully ✓
    
    User->>Seeds: Start seeds service
    Seeds->>Migrations: Wait for completion
    Migrations-->>Seeds: Completed successfully ✓
    Seeds->>Seeds: Execute: node cli/dist/server createSiteAdmin<br/>"${LL_ADMIN_EMAIL:?}" "${LL_ADMIN_ORG:?}" "${LL_ADMIN_PASSWORD:?}"
    Note over Seeds: "Setting up seed data ..."<br/>Admin: admin@mail.com, Org: soco<br/>(restart: on-failure)
    Seeds-->>User: Service completed successfully ✓
    
    User->>API: Start API service
    API->>Mongo: Wait for healthy condition (restart: true)
    API->>Redis: Wait for healthy condition (restart: true)
    API->>Seeds: Wait for successful completion
    Mongo-->>API: Healthy ✓
    Redis-->>API: Healthy ✓
    Seeds-->>API: Completed successfully ✓
    API->>API: Execute: node api/dist/server
    Note over API: API server on port 8080<br/>Health check via HTTP fetch<br/>QUEUE_PROVIDER: REDIS
    API-->>User: API service healthy ✓
    
    User->>Worker: Start worker service
    Worker->>Mongo: Wait for healthy condition (restart: true)
    Worker->>Redis: Wait for healthy condition (restart: true)
    Mongo-->>Worker: Healthy ✓
    Redis-->>Worker: Healthy ✓
    Worker->>Worker: Execute: node worker/dist/server
    Note over Worker: Background worker<br/>Uses Redis for queue processing
    Worker-->>User: Worker service ready ✓
    
    User->>UI: Start UI service
    UI->>API: Wait for API healthy condition
    API-->>UI: API healthy ✓
    UI->>UI: Execute: node ui/dist/server
    Note over UI: Frontend on port 3000<br/>Connects to API service
    UI-->>User: UI service ready ✓
    
    User->>XAPI: Start xAPI service
    XAPI->>Mongo: Wait for healthy condition
    XAPI->>Redis: Wait for healthy condition
    Mongo-->>XAPI: Healthy ✓
    Redis-->>XAPI: Healthy ✓
    XAPI->>XAPI: Execute xAPI service
    Note over XAPI: xAPI service on port 8081<br/>REDIS_URL: redis://redis:6379/0<br/>Platform: linux/amd64
    XAPI-->>User: xAPI service ready ✓

    Note over User,XAPI: Complete Learning Locker deployment<br/>✓ Admin user created (admin@mail.com)<br/>✓ Redis provides queuing and caching<br/>✓ All services connected to Redis cluster
Loading

Key Redis integrations shown in this diagram:

  1. Redis Health Checks: Redis uses redis-cli ping with 10s intervals and 2s start period
  2. Queue Provider: The system uses QUEUE_PROVIDER: REDIS for background job processing
  3. Service Dependencies: API, Worker, and xAPI services all explicitly depend on Redis being healthy
  4. Restart Policies: Redis dependencies have restart: true for resilient connections
  5. xAPI Integration: The xAPI service connects to Redis at redis://redis:6379/0 for data operations
  6. Worker Queues: The Worker service uses Redis for processing background tasks

The Redis service is critical infrastructure - without it being healthy, the core application services (API, Worker, xAPI) won't start, ensuring the system has proper queuing and caching capabilities before handling requests.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

♻️ Duplicate comments (2)
compose.yaml (2)

31-33: Remove LL_ADMIN_ from global env; scope to seeds and source from secrets/.env*

Leaking admin creds via x-common propagates them to all services and into VCS. Scope strictly to the seeds service and require them at runtime.

Apply:

   environment:
     QUEUE_PROVIDER: REDIS
@@
     APP_SECRET: "i-am-not-secure-please-change-me"
-    LL_ADMIN_EMAIL: "admin@mail.com"
-    LL_ADMIN_ORG: "soco"
-    LL_ADMIN_PASSWORD: "1234qweR"

Then add under seeds (see lines 95-102):

   seeds:
     <<: *common
-    command: seeds
+    command: seeds
     depends_on:
       migrations:
         condition: service_completed_successfully
     restart: on-failure
+    environment:
+      LL_ADMIN_EMAIL: ${LL_ADMIN_EMAIL:?}
+      LL_ADMIN_ORG: ${LL_ADMIN_ORG:?}
+      LL_ADMIN_PASSWORD: ${LL_ADMIN_PASSWORD:?}

Optional: I can wire Docker secrets (LL_ADMIN_PASSWORD_FILE) if you prefer not to use env vars. Want me to open a follow-up PR for that?


95-97: Make commands explicit to the intended scripts (avoid PATH ambiguity)

Be explicit about the executable to reduce surprises from PATH/env differences.

   seeds:
     <<: *common
-    command: seeds
+    command: ["bin/seeds"]
@@
   migrations:
     <<: *common
-    command: migrations
+    command: ["bin/migrations"]

Also applies to: 103-105

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d0e5d0d and fe829bb.

📒 Files selected for processing (1)
  • compose.yaml (2 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
compose.yaml

[error] 45-45: wrong indentation: expected 8 but found 6

(indentation)


[error] 67-67: wrong indentation: expected 8 but found 6

(indentation)


[error] 82-82: wrong indentation: expected 8 but found 6

(indentation)


[error] 92-92: wrong indentation: expected 8 but found 6

(indentation)


[error] 117-117: wrong indentation: expected 6 but found 4

(indentation)

🔇 Additional comments (1)
compose.yaml (1)

95-106: Seeds/migrations orchestration aligns with startup admin creation goal

Introducing dedicated migrations and seeds services with health/ordering semantics is a good approach and matches the PR objective.

@ralf-berger ralf-berger removed the request for review from shoebjoarder August 17, 2025 09:55
@ralf-berger ralf-berger merged commit 6b6132f into master Aug 17, 2025
1 check passed
@ralf-berger ralf-berger deleted the issue/4-create-admin-user-on-startup branch August 17, 2025 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create admin user on startup

3 participants