diff --git a/CLAUDE.md b/CLAUDE.md index fb681a7..5b824ee 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,6 +33,10 @@ Authentication/profile prototype for Codebar using [Better Auth](https://www.bet npm run dev ``` +## Deployment + +See [HEROKU.md](HEROKU.md) for Heroku deployment instructions. + ## Development Commands **Running the app:** diff --git a/HEROKU.md b/HEROKU.md new file mode 100644 index 0000000..fa4752f --- /dev/null +++ b/HEROKU.md @@ -0,0 +1,114 @@ +# Heroku Deployment + +Deploy this application to Heroku using `app.json` for infrastructure-as-code. + +## Prerequisites + +- Heroku CLI installed and authenticated (`heroku login`) +- GitHub OAuth app created at https://github.com/settings/developers +- Admin access to the codebar/auth GitHub repository + +## Infrastructure Overview + +| Component | Configuration | +| ------------ | --------------------------------- | +| **Dyno** | Basic (always-on) | +| **Database** | Heroku Postgres Essential-0 (1GB) | +| **Stack** | heroku-24 | +| **Node.js** | >= 24.0.0 | + +## Deployment Method + +**Automatic deployments** from GitHub merges are the standard workflow. Heroku deploys the application automatically when code merges to the `main` branch. + +## Initial Setup + +### 1. Create Heroku App + +```bash +# Create app from app.json (provisions dyno, database, and env vars) +heroku create codebar-auth-production --manifest + +# Set GitHub OAuth credentials +heroku config:set GITHUB_CLIENT_ID=your_client_id +heroku config:set GITHUB_CLIENT_SECRET=your_client_secret +``` + +### 2. Connect GitHub Repository + +1. Open the Heroku Dashboard: `heroku open` +2. Navigate to the **Deploy** tab +3. In **Deployment method**, select **GitHub** +4. Search for and connect to the `codebar/auth` repository +5. In **Automatic deploys**, select the `main` branch +6. Click **Enable Automatic Deploys** + +### 3. First Deploy + +The `main` branch is protected from direct pushes. Merge this infrastructure PR to trigger the first deployment. + +Heroku deploys automatically when the PR merges to `main`. The release phase runs database migrations before dynos start. + +## GitHub OAuth Configuration + +After deploying, update your GitHub OAuth app settings: + +- **Homepage URL:** `https://auth.codebar.io` +- **Authorization callback URL:** `https://auth.codebar.io/api/auth/callback/github` + +## Automatic Deployments + +Once enabled, every merge to `main` triggers: + +1. Heroku pulls the latest code +2. Build phase installs dependencies +3. Release phase runs database migrations +4. New dynos start serving traffic + +No manual intervention required. + +## Manual Deployment (Emergency Only) + +Use manual deployment only when automatic deploys fail or during incidents requiring immediate hotfixes. + +```bash +# Break-the-glass: bypass automatic deploys +git push heroku main --force +``` + +**Warning:** Manual deployment bypasses GitHub branch protection and CI checks. Use sparingly. + +## Rollback + +```bash +# Rollback to previous release +heroku releases:rollback + +# Rollback to specific version +heroku releases:rollback v42 +``` + +## Monitoring + +```bash +heroku logs --tail # View app logs +heroku ps # Check dyno status +heroku releases # View deployment history +``` + +## Environment Variables + +| Variable | Source | Description | +| ---------------------- | ---------------- | ---------------------------- | +| `DATABASE_URL` | Auto-provisioned | PostgreSQL connection string | +| `GITHUB_CLIENT_ID` | Required | GitHub OAuth client ID | +| `GITHUB_CLIENT_SECRET` | Required | GitHub OAuth client secret | +| `BETTER_AUTH_SECRET` | Auto-generated | Session encryption key | +| `CODEBAR_AUTH_URL` | Auto-set | Application base URL | +| `PORT` | Heroku | Dyno port | + +## Files + +- `app.json` - App manifest +- `Procfile` - Process definitions +- `scripts/heroku-release.sh` - Release tasks diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..9701d60 --- /dev/null +++ b/Procfile @@ -0,0 +1,2 @@ +web: npm start +release: ./scripts/heroku-release.sh diff --git a/app.json b/app.json new file mode 100644 index 0000000..3733f8a --- /dev/null +++ b/app.json @@ -0,0 +1,44 @@ +{ + "name": "Codebar Auth", + "description": "Authentication service for Codebar using Better Auth", + "repository": "https://github.com/codebar/auth", + "website": "https://auth.codebar.io", + "success_url": "/health", + "stack": "heroku-24", + "formation": { + "web": { + "quantity": 1, + "size": "basic" + } + }, + "addons": [ + { + "plan": "heroku-postgresql:essential-0", + "as": "DATABASE" + } + ], + "env": { + "GITHUB_CLIENT_ID": { + "description": "GitHub OAuth App Client ID (create at https://github.com/settings/developers)", + "required": true + }, + "GITHUB_CLIENT_SECRET": { + "description": "GitHub OAuth App Client Secret", + "required": true + }, + "BETTER_AUTH_SECRET": { + "description": "Secret key for Better Auth session encryption", + "generator": "secret" + }, + "CODEBAR_AUTH_URL": { + "description": "Base URL for auth service", + "value": "https://auth.codebar.io" + } + }, + + "buildpacks": [ + { + "url": "heroku/nodejs" + } + ] +} diff --git a/package.json b/package.json index d47fde5..443cbdc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,9 @@ { "name": "auth-auth", "type": "module", + "engines": { + "node": ">= 24.0.0" + }, "scripts": { "dev": "node --watch src/index.js", "db:generate": "npx @better-auth/cli generate --yes", diff --git a/scripts/heroku-release.sh b/scripts/heroku-release.sh new file mode 100755 index 0000000..977cdfa --- /dev/null +++ b/scripts/heroku-release.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Release phase script - runs after build, before new dynos start. +# Using a script file (vs inline in Procfile) allows: +# - Explicit error handling with set -e (fails release if migrations fail) +# - Clear logging of release phase progress +# - Easy extension for future release tasks (seeding, cache warming, etc.) +set -e + +echo "Running database migrations..." +npm run db:migrate + +echo "Release phase complete!" diff --git a/src/auth.js b/src/auth.js index e96eaa8..9eb62c3 100644 --- a/src/auth.js +++ b/src/auth.js @@ -37,7 +37,7 @@ export { db }; export const auth = betterAuth({ database: db, - baseURL: `http://${appConfig.host}:${appConfig.port}`, + baseURL: appConfig.base_url, logger: { disabled: false, level: "debug",