Browse Source

ona: add devcontainer + automations for BlackRock demo

- .devcontainer/devcontainer.json: Node 22 base image with Docker-in-Docker
  feature so the upstream docker/docker-compose.dev.yml can bring up
  Postgres + Redis inside the Ona VM.
- .devcontainer/post-create.sh: idempotent setup that seeds .env from
  .env.dev, fills the <INSERT_*> placeholders with safe dev defaults +
  random strings, prepulls images, runs npm ci.
- .ona/automations.yaml: three services (postgres-redis, api, client)
  plus manual 'seed' and 'dry-run-demo' tasks. First boot runs
  npm run database:setup and marks .ona/.db-initialized so subsequent
  restarts skip re-seeding.
- .ona/README.md: explainer of the changes and how to bring the env up.
- .gitignore: ignore the .db-initialized marker.
pull/6760/head
jrcoak 23 hours ago
parent
commit
a3fa261083
  1. 30
      .devcontainer/devcontainer.json
  2. 25
      .devcontainer/post-create.sh
  3. 3
      .gitignore
  4. 47
      .ona/README.md
  5. 77
      .ona/automations.yaml

30
.devcontainer/devcontainer.json

@ -0,0 +1,30 @@
{
"name": "Ghostfolio (Ona demo)",
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-22",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"moby": false,
"dockerDashComposeVersion": "v2"
},
"ghcr.io/devcontainers/features/git:1": {}
},
"forwardPorts": [3333, 4200, 5432, 6379],
"portsAttributes": {
"3333": { "label": "Ghostfolio API" },
"4200": { "label": "Ghostfolio Client" },
"5432": { "label": "PostgreSQL" },
"6379": { "label": "Redis" }
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
"remoteUser": "node",
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"Prisma.prisma",
"nrwl.angular-console"
]
}
}
}

25
.devcontainer/post-create.sh

@ -0,0 +1,25 @@
#!/usr/bin/env bash
# One-shot setup for the Ghostfolio dev container inside Ona.
# Idempotent: safe to re-run.
set -euo pipefail
cd "$(dirname "$0")/.."
echo "==> Seeding .env from .env.dev (if missing)"
if [ ! -f .env ]; then
cp .env.dev .env
# Fill in safe dev defaults — the upstream .env.dev has <INSERT_...> placeholders.
sed -i 's|<INSERT_REDIS_PASSWORD>|devredispassword|g' .env
sed -i 's|<INSERT_POSTGRES_PASSWORD>|devpostgrespassword|g' .env
sed -i 's|<INSERT_RANDOM_STRING>|'"$(openssl rand -hex 32)"'|g' .env
fi
echo "==> Pre-pulling Postgres + Redis images (cached into prebuild)"
docker pull postgres:15 >/dev/null 2>&1 || true
docker pull redis:7 >/dev/null 2>&1 || true
echo "==> Installing npm dependencies"
npm ci --no-audit --no-fund
echo "==> Done. Services will be brought up by Ona automations."

3
.gitignore

@ -44,3 +44,6 @@ testem.log
# System Files
.DS_Store
Thumbs.db
# Ona
.ona/.db-initialized

47
.ona/README.md

@ -0,0 +1,47 @@
# Ona demo setup — Ghostfolio fork
This fork is the target codebase for the **Apr 23 BlackRock deep-dive** demo.
## What this folder contains
- [`automations.yaml`](automations.yaml) — Ona services for Postgres, Redis, the
NestJS API, and the Angular client, plus manual `seed` and `dry-run-demo` tasks.
## What changed vs upstream
1. **`.devcontainer/devcontainer.json`** — new. Node 22 base image, Docker-in-Docker
feature enabled (needed so `docker compose -f docker/docker-compose.dev.yml up`
works for Postgres + Redis), ports forwarded, `postCreateCommand` wires up
`.env` and npm install.
2. **`.devcontainer/post-create.sh`** — new. Seeds `.env` from `.env.dev`,
replaces the `<INSERT_*>` placeholders with safe dev defaults, prepulls
`postgres:15` / `redis:7` images, runs `npm ci`. Idempotent.
3. **`.ona/automations.yaml`** — new. Starts the stack on
`postDevcontainerStart` / `postEnvironmentStart`. First boot runs
`npm run database:setup` (schema + seed), marks it with
`.ona/.db-initialized` so subsequent restarts skip re-seeding.
## How to bring it up
1. Open this repo in Ona.
2. Wait for the devcontainer build (DinD is heavy first time; subsequent opens
use the prebuild cache).
3. `gitpod automations service list` — all three services should go `ready`.
4. Open the forwarded port `4200` → Ghostfolio UI. First user created gets
`ADMIN`.
## Reset before a demo
```
gitpod automations task start seed
```
## Notes for the demo day
- Keep `5432` + `6379` forwarded but unadvertised. Port `4200` is the only UI.
- The `.env` generated by post-create uses throwaway dev passwords. DO NOT
commit a real `.env`.
- If DinD is slow to come up on first boot, `gitpod automations service logs postgres-redis`
tails the compose output.

77
.ona/automations.yaml

@ -0,0 +1,77 @@
# Ona automations for the Ghostfolio demo environment.
#
# Shape of the world when services are up:
# postgres (5432) + redis (6379) via docker compose on the host
# api (3333) via `npm run start:server`
# client (4200) via `npm run start:client`
#
# This is the "dev env == preprod test env" demo: the full Ghostfolio stack
# compiles, runs, and serves requests inside the same Ona VM that the
# agent (Claude Code / Cursor / Codex / Ona) operates in.
services:
postgres-redis:
name: PostgreSQL + Redis
description: Backing stores for Ghostfolio. Uses the upstream dev compose file.
triggeredBy:
- postDevcontainerStart
- postEnvironmentStart
commands:
start: docker compose -f docker/docker-compose.dev.yml up
ready: |
docker exec gf-postgres-dev pg_isready -U user -d ghostfolio-db && \
docker exec gf-redis-dev redis-cli --pass "$(grep ^REDIS_PASSWORD .env | cut -d= -f2)" ping | grep -q PONG
stop: docker compose -f docker/docker-compose.dev.yml down
api:
name: Ghostfolio API
description: NestJS backend, hot-reload, port 3333.
triggeredBy:
- postDevcontainerStart
- postEnvironmentStart
commands:
start: |
# Wait for DB to be ready, then sync schema + seed on first run.
until docker exec gf-postgres-dev pg_isready -U user -d ghostfolio-db >/dev/null 2>&1; do sleep 1; done
if [ ! -f .ona/.db-initialized ]; then
npm run database:setup
touch .ona/.db-initialized
fi
npm run start:server
ready: curl -sf http://localhost:3333/api/v1/health
client:
name: Ghostfolio Client
description: Angular frontend, hot-reload, port 4200.
triggeredBy:
- postDevcontainerStart
- postEnvironmentStart
commands:
start: npm run start:client
ready: curl -skf https://localhost:4200/en || curl -sf http://localhost:4200/en
tasks:
seed:
name: Reset + seed demo data
description: Wipe the DB and reseed. Use before a demo run.
triggeredBy:
- manual
command: |
rm -f .ona/.db-initialized
docker compose -f docker/docker-compose.dev.yml down -v
docker compose -f docker/docker-compose.dev.yml up -d
until docker exec gf-postgres-dev pg_isready -U user -d ghostfolio-db >/dev/null 2>&1; do sleep 1; done
npm run database:setup
touch .ona/.db-initialized
echo "✅ Ghostfolio DB reset + seeded."
dry-run-demo:
name: "Dry-run: local agent beat"
description: Sanity check that Claude Code + Ona agent can reach the API and run a test.
triggeredBy:
- manual
command: |
set -e
curl -sf http://localhost:3333/api/v1/health | jq .
npx nx test api --watch=false --passWithNoTests | tail -20
echo "✅ Local agent beat ready."
Loading…
Cancel
Save