Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
@@ -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
6 changes: 3 additions & 3 deletions .github/workflows/opencode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
model: alibaba-coding-plan/kimi-k2.5
2 changes: 1 addition & 1 deletion .github/workflows/web-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion apps/feed-updater/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:*"
Expand Down
11 changes: 11 additions & 0 deletions apps/web/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -482,6 +483,16 @@ async function initializeStaticRoutes(clientDirectory: string): Promise<PreloadR
async function initializeServer() {
log.header('Starting Production Server');

// Run database migrations before starting
log.info('Running database migrations...');
try {
await runMigrations();
log.success('Database migrations completed');
} catch (error) {
log.error(`Migration failed: ${String(error)}`);
process.exit(1);
}

// Load TanStack Start server handler
let handler: { fetch: (request: Request) => Response | Promise<Response> };
try {
Expand Down
3 changes: 1 addition & 2 deletions apps/web/src/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ function RootDocument({ children }: { children: React.ReactNode }) {
);
}

function NotFoundComponent(props: NotFoundRouteProps) {
console.log({ NotFoundProps: props });
function NotFoundComponent() {
return <p>This setting page doesn't exist!</p>;
}
118 changes: 35 additions & 83 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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:
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions packages/database/src/index.ts
Original file line number Diff line number Diff line change
@@ -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';
24 changes: 24 additions & 0 deletions packages/database/src/migrate.ts
Original file line number Diff line number Diff line change
@@ -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();
}
Loading