From ddb47ca9b7ad1c1b486755984ac67089d9a5e006 Mon Sep 17 00:00:00 2001 From: Khoirul Asfian Date: Thu, 19 Mar 2026 22:04:02 +0700 Subject: [PATCH 1/7] chore: add opencode pr review workflow --- .github/workflows/opencode-review.yml | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/opencode-review.yml diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml new file mode 100644 index 0000000..9ab5501 --- /dev/null +++ b/.github/workflows/opencode-review.yml @@ -0,0 +1,30 @@ +name: opencode-review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: anomalyco/opencode/github@latest + env: + ALIBABA_CODING_PLAN_API_KEY: ${{ secrets.ALIBABA_CODING_PLAN_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + model: alibaba-coding-plan/kimi-k2.5 + use_github_token: true + prompt: | + Review this pull request: + - Check for code quality issues + - Look for potential bugs + - Suggest improvements From bc84255ed10d685197cfbba0d47cb1a41ba2d674 Mon Sep 17 00:00:00 2001 From: Khoirul Asfian Date: Sat, 21 Mar 2026 01:00:38 +0700 Subject: [PATCH 2/7] chore: remove log --- apps/web/src/routes/__root.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx index 44d92f5..36c7c0c 100644 --- a/apps/web/src/routes/__root.tsx +++ b/apps/web/src/routes/__root.tsx @@ -102,7 +102,6 @@ function RootDocument({ children }: { children: React.ReactNode }) { ); } -function NotFoundComponent(props: NotFoundRouteProps) { - console.log({ NotFoundProps: props }); +function NotFoundComponent() { return

This setting page doesn't exist!

; } From 51cb111537771e808059df819371797eaa13ad4e Mon Sep 17 00:00:00 2001 From: Khoirul Asfian Date: Tue, 31 Mar 2026 14:48:15 +0700 Subject: [PATCH 3/7] feat: add better compose example --- docker-compose.yml | 118 ++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 83 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3a06878..45fe361 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,99 +1,51 @@ +# Reafrac - RSS Reader +# +# Create a .env file with the following variables: +# POSTGRES_PASSWORD=your-secure-password +# BETTER_AUTH_SECRET=your-auth-secret +# GOOGLE_CLIENT_ID=your-google-client-id (optional) +# GOOGLE_CLIENT_SECRET=your-google-client-secret (optional) +# VITE_SENTRY_DSN=your-sentry-dsn (optional) +# VITE_SENTRY_TRACES_SAMPLE_RATE=0.1 (optional) +# PROXY_URL=your-proxy-url (optional) +# ENABLE_FEED_CRON=true (optional, enables in-process feed fetching) + services: - app: - image: ghcr.io/${GITHUB_USERNAME}/reafrac:latest - container_name: reafrac-app + reafrac: + image: ghcr.io/rulasfia/reafrac:latest + container_name: reafrac restart: unless-stopped ports: - - '3000:3000' - environment: - - NODE_ENV=production - - PORT=3000 - - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} - depends_on: - postgres: - condition: service_healthy - networks: - - reafrac-network - healthcheck: - test: ['CMD', 'curl', '-f', 'http://localhost:3000/'] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - - # Migration service (run once and exit) - migrate: - image: ghcr.io/${GITHUB_USERNAME}/reafrac:latest - container_name: reafrac-migrate + - '${PORT:-3000}:3000' environment: - - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} - command: ['bun', 'run', 'db:migrate'] + - PORT=${PORT:-3000} + - DATABASE_URL=postgres://postgres:${POSTGRES_PASSWORD}@reafrac-pg:5432/reafrac + - VITE_SENTRY_DSN=${VITE_SENTRY_DSN} + - VITE_SENTRY_TRACES_SAMPLE_RATE=${VITE_SENTRY_TRACES_SAMPLE_RATE} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} + - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} + - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} + - PROXY_URL=${PROXY_URL} + - ENABLE_FEED_CRON=${ENABLE_FEED_CRON} depends_on: - postgres: + reafrac-pg: condition: service_healthy - networks: - - reafrac-network - restart: 'no' # Only run once - postgres: + reafrac-pg: image: postgres:17-alpine - container_name: reafrac-db + container_name: reafrac-pg restart: unless-stopped + volumes: + - reafrac-db:/var/lib/postgresql/data environment: - - POSTGRES_DB=${POSTGRES_DB:-reafrac} - - POSTGRES_USER=${POSTGRES_USER:-postgres} + - POSTGRES_USER=postgres + - POSTGRES_DB=reafrac - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C - volumes: - - postgres_data:/var/lib/postgresql/data - - ./migrations:/docker-entrypoint-initdb.d:ro - ports: - - '5432:5432' - networks: - - reafrac-network healthcheck: - test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-reafrac}'] - interval: 10s + test: ['CMD-SHELL', 'pg_isready -U postgres'] + interval: 5s timeout: 5s retries: 5 - start_period: 30s - # Optional: Add resource limits - deploy: - resources: - limits: - memory: 1024M - reservations: - memory: 256M - - # Optional: Add pgAdmin for database management - pgadmin: - image: dpage/pgadmin4:latest - container_name: reafrac-pgadmin - restart: unless-stopped - environment: - - PGADMIN_DEFAULT_EMAIL=${PGADMIN_EMAIL:-admin@example.com} - - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD} - - PGADMIN_CONFIG_SERVER_MODE=False - ports: - - '5050:80' - volumes: - - pgadmin_data:/var/lib/pgadmin - networks: - - reafrac-network - depends_on: - - postgres - profiles: - - admin # Use 'docker-compose --profile admin up' to include this service volumes: - postgres_data: - driver: local - pgadmin_data: - driver: local - -networks: - reafrac-network: - driver: bridge - ipam: - config: - - subnet: 172.20.0.0/16 + reafrac-db: From 312635976b15773c350b021babe713cca755daed Mon Sep 17 00:00:00 2001 From: Khoirul Asfian Date: Tue, 31 Mar 2026 14:48:50 +0700 Subject: [PATCH 4/7] chore: move main dockerfile to top dir --- .github/workflows/web-app.yml | 2 +- apps/web/Dockerfile => Dockerfile | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename apps/web/Dockerfile => Dockerfile (100%) diff --git a/.github/workflows/web-app.yml b/.github/workflows/web-app.yml index e3056d1..0442d64 100644 --- a/.github/workflows/web-app.yml +++ b/.github/workflows/web-app.yml @@ -154,7 +154,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . - file: ./apps/web/Dockerfile + file: ./Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/apps/web/Dockerfile b/Dockerfile similarity index 100% rename from apps/web/Dockerfile rename to Dockerfile From f915830e0db155c1ea0de351a91f622c023a27f2 Mon Sep 17 00:00:00 2001 From: Khoirul Asfian Date: Tue, 31 Mar 2026 14:56:40 +0700 Subject: [PATCH 5/7] feat: move the migration to run on app startup --- apps/web/server.ts | 11 +++++++++++ packages/database/src/index.ts | 1 + packages/database/src/migrate.ts | 24 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 packages/database/src/migrate.ts diff --git a/apps/web/server.ts b/apps/web/server.ts index 41f48cb..ab49c71 100644 --- a/apps/web/server.ts +++ b/apps/web/server.ts @@ -75,6 +75,7 @@ import path from 'node:path'; import * as Sentry from '@sentry/tanstackstart-react'; import { refetchFeeds } from '@reafrac/external-script'; +import { runMigrations } from '@reafrac/database'; const ENABLE_FEED_CRON = process.env.ENABLE_FEED_CRON === 'true'; const FEED_CRON_INTERVAL_MS = Number(process.env.FEED_CRON_INTERVAL_MS ?? 30 * 60 * 1000); @@ -482,6 +483,16 @@ async function initializeStaticRoutes(clientDirectory: string): Promise Response | Promise }; try { diff --git a/packages/database/src/index.ts b/packages/database/src/index.ts index 2a2ad53..fcc4c27 100644 --- a/packages/database/src/index.ts +++ b/packages/database/src/index.ts @@ -1,5 +1,6 @@ export * from './schema'; export * from './connection'; +export { runMigrations } from './migrate'; // re-export drizzle-orm to use in other packages. doing this will // prevent type errors 'shouldInlineParams' when importing directly from drizzle-orm export * from 'drizzle-orm'; diff --git a/packages/database/src/migrate.ts b/packages/database/src/migrate.ts new file mode 100644 index 0000000..beb0758 --- /dev/null +++ b/packages/database/src/migrate.ts @@ -0,0 +1,24 @@ +import { migrate } from 'drizzle-orm/postgres-js/migrator'; +import postgres from 'postgres'; +import { drizzle } from 'drizzle-orm/postgres-js'; +import * as schema from './schema'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +const DB_URL = process.env.DATABASE_URL; +if (!DB_URL) { + throw new Error('DATABASE_URL is not defined'); +} + +export async function runMigrations() { + const migrationClient = postgres(DB_URL!, { max: 1 }); + const db = drizzle(migrationClient, { schema }); + + // Migrations folder is relative to this file's location + const currentDir = path.dirname(fileURLToPath(import.meta.url)); + const migrationsFolder = path.join(currentDir, '../migrations'); + + await migrate(db, { migrationsFolder }); + + await migrationClient.end(); +} From 14da0542020530a1f9f5638b4d0250876b9f4e49 Mon Sep 17 00:00:00 2001 From: Khoirul Asfian Date: Tue, 31 Mar 2026 15:03:27 +0700 Subject: [PATCH 6/7] chore: easier dev script --- apps/feed-updater/package.json | 3 ++- package.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/feed-updater/package.json b/apps/feed-updater/package.json index 2ac38e6..29c2604 100644 --- a/apps/feed-updater/package.json +++ b/apps/feed-updater/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "build": "bun build ./src/index.ts --outdir ./dist --target bun", - "start": "bun run src/index.ts" + "start": "bun run src/index.ts", + "dev": "bun run src/index.ts" }, "dependencies": { "@reafrac/external-script": "workspace:*" diff --git a/package.json b/package.json index e247e50..bd6ed51 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ ], "scripts": { "dev": "turbo run dev", + "dev:proxy": "turbo run dev --filter @reafrac/feed-updater --filter @reafrac/web --filter @reafrac/content-proxy", "build": "turbo run build", "start": "turbo run start", "test": "turbo run test", From 78153f04781ff3eb07a7dec6b69080e20669f20d Mon Sep 17 00:00:00 2001 From: Khoirul Asfian Date: Tue, 31 Mar 2026 15:16:31 +0700 Subject: [PATCH 7/7] fix: oc workflow --- .github/workflows/opencode.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/opencode.yml b/.github/workflows/opencode.yml index ef0050e..8f150a8 100644 --- a/.github/workflows/opencode.yml +++ b/.github/workflows/opencode.yml @@ -17,8 +17,8 @@ jobs: permissions: id-token: write contents: read - pull-requests: read - issues: read + pull-requests: write + issues: write steps: - name: Checkout repository uses: actions/checkout@v6 @@ -30,4 +30,4 @@ jobs: env: ALIBABA_CODING_PLAN_API_KEY: ${{ secrets.ALIBABA_CODING_PLAN_API_KEY }} with: - model: alibaba-coding-plan/kimi-k2.5 \ No newline at end of file + model: alibaba-coding-plan/kimi-k2.5