diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e69de29bb..cff5118d7 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,127 @@ +# Contributing to Autumn + +Hello! Thank you for your interest in contributing to Autumn :) + +## How to contribute + +1. First, set up Autumn locally using the installation guide [below](#installation-guide) + +2. Create a new branch for your changes + +```bash +git checkout -b feature/your-feature-name +# or +git checkout -b fix/your-bug-fix +``` + +3. Commit Your changes with clear, descriptive messages + +4. Fetch the latest updated repo and merge with your changes +```bash +git fetch upstream/staging +git merge upstream/staging +``` + +5. Push to your fork +``` +git push origin your-branch-name +``` + +6. Submit a Pull Request to the staging branch +- Go to your fork on GitHub and click "New Pull Request" +- Fill out the PR template completely +- Link any relevant issues +- Add screenshots for UI changes + +## Installation Guide + +#### Requirements +- Node.js +- pnpm + +### Quickstart + +Use this guide if you want to get Autumn up and running on your device in the fastest way possible! We help you spin up all the required services (database, tunnel, etc.) and env variables through our setup script. + +#### Step 0: Fork and Clone +1. Click the 'Fork' button at the top right of this repository +2. Clone your fork locally: `git clone https://github.com/YOUR-USERNAME/autumn.git` + +#### Step 1: Install Dependencies +```bash +pnpm install +``` + +#### Step 2: Run Setup +```bash +pnpm run setup +``` + +The `setup` script generates required environment variables to run Autumn locally. It performs two main functions: +- Auto-spins up a Supabase database and creates required tables (optional) +- Generates a localtunnel reserved key for receiving Stripe webhooks in development + +#### Step 3: Start Development Environment +```bash +docker compose -f docker-compose.dev.yml up +``` + +### Manual Setup + +Use this approach if you prefer to configure your own database or tunneling solution (e.g., ngrok, cloudflared) instead of our default localtunnel setup. + +1. Copy `server/.env.example` to `server/.env` and fill in environment variables according to the [Environment Variables](#environment-variables) guide +2. Copy `vite/.env.example` to `vite/.env` +3. Run the Docker command from Step 3 above + +--- +### Database Management +Autumn uses Postgres as it's database solution, and Drizzle ORM to manage our queries / migrations. + +Our cloud offering uses Supabase to host Postgres, but you can use any hosting solution you'd like. At the moment, our docker compose does not spin up a database for you, so you'll have to do this yourself (we help you set up Supabase super easily in our set up script). + +#### Creating Database Tables +Make sure you have the `DATABASE_URL` env variable set up in `server/.env` before you run any of the following commands. + +If you're setting up an Autumn DB for the first time, use the following command to generate the required tables +```bash +pnpm run db:push +``` + +#### Handling Migrations +When you need to create version-controlled migrations (e.g., for new releases): + +1. **Generate migration files:** + ```bash + pnpm run db:generate + ``` + This creates migration files based on schema changes. + +2. **Apply migrations:** + ```bash + pnpm run db:migrate + ``` + This applies pending migrations to your database. + + + \ No newline at end of file diff --git a/commands.sh b/commands.sh index db2950d37..23a7329de 100644 --- a/commands.sh +++ b/commands.sh @@ -7,10 +7,10 @@ docker compose -f docker-compose.db.yml up --build # Create DB tables pnpm -# docker volume rm autumn-oss_shared-node-modules autumn-oss_root-node-modules autumn-oss_vite-node-modules +# docker volume rm main-repo_shared-node-modules main-repo_root-node-modules main-repo_vite-node-modules # Dev docker compose -f docker-compose.dev.yml down -docker volume rm main-repo_shared-node-modules main-repo_root-node-modules main-repo_vite-node-modules +docker volume rm autumn-oss_shared-node-modules autumn-oss_root-node-modules autumn-oss_vite-node-modules docker compose -f docker-compose.dev.yml build --no-cache docker compose -f docker-compose.dev.yml up --build diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 154f91282..2b4b1c6aa 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,5 +1,5 @@ services: - # Run valkey + valkey: image: docker.io/bitnami/valkey:8.0 environment: @@ -86,6 +86,21 @@ services: - shared restart: unless-stopped + + # Run localtunnel + localtunnel: + image: node:20-alpine + build: + dockerfile: docker/dev.dockerfile + context: . + target: localtunnel + volumes: + - ./server:/app/server + depends_on: + - server + restart: unless-stopped + + volumes: # Shared package dist output shared-dist: diff --git a/docker/dev.dockerfile b/docker/dev.dockerfile index a022fdf97..2e8a86025 100644 --- a/docker/dev.dockerfile +++ b/docker/dev.dockerfile @@ -15,6 +15,12 @@ COPY vite/package*.json ./vite/ RUN pnpm install RUN npm install -g nodemon tsx +# Stage 1: /localtunnel +FROM base AS localtunnel +WORKDIR /app +COPY localtunnel-start.sh ./ +CMD ["sh", "localtunnel-start.sh"] + # Stage 2: /shared FROM base AS shared COPY shared/ ./shared/ diff --git a/localtunnel-start.sh b/localtunnel-start.sh new file mode 100755 index 000000000..ced231b8e --- /dev/null +++ b/localtunnel-start.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# Read LOCALTUNNEL_RESERVED_KEY from .env file +if [ -f "/app/server/.env" ]; then + export $(cat /app/server/.env | grep LOCALTUNNEL_RESERVED_KEY) +fi + +# Set default subdomain if env var not found +if [ -z "$LOCALTUNNEL_RESERVED_KEY" ]; then + LOCALTUNNEL_RESERVED_KEY="abcasdjnaslkjdnas" +fi + +echo "LOCALTUNNEL_RESERVED_KEY: ${LOCALTUNNEL_RESERVED_KEY}" + +echo "Installing localtunnel..." +npm install -g localtunnel + +echo "Starting localtunnel..." +lt --port 8080 --local-host server --subdomain ${LOCALTUNNEL_RESERVED_KEY} --print-requests \ No newline at end of file diff --git a/package.json b/package.json index e123421c1..a23e9bff5 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "setup": "node setup.js", "db:push": "pnpm -F shared db:push", "db:generate": "pnpm -F shared db:generate", - "db:migrate": "pnpm -F shared db:migrate" + "db:migrate": "pnpm -F shared db:migrate", + "docker:up": "docker compose -f docker-compose.dev.yml up --build" }, "dependencies": { "chalk": "^5.3.0", diff --git a/server/.env.example b/server/.env.example index 4ebbdeb85..11661b1da 100644 --- a/server/.env.example +++ b/server/.env.example @@ -6,11 +6,9 @@ CLIENT_URL=http://localhost:3000 # STRIPE REQUIRED ENCRYPTION_IV= ENCRYPTION_PASSWORD= -LOCALTUNNEL_RESERVED_KEY= STRIPE_WEBHOOK_URL= +LOCALTUNNEL_RESERVED_KEY= # DATABASE DATABASE_URL= -# IF using external redis -# REDIS_URL=redis://valkey:6379 \ No newline at end of file diff --git a/setup.js b/setup.js index b141ab92d..59e9acdcb 100644 --- a/setup.js +++ b/setup.js @@ -243,19 +243,22 @@ const handleLocalRunSetup = async () => { async function main() { // Step 1: Generate secrets console.log(chalk.magentaBright('\n================ Autumn Setup ================\n')); + const localtunnelReservedKey = genRandomSubdomain(32); const secrets = { BETTER_AUTH_SECRET: genUrlSafeBase64(64), ENCRYPTION_IV: genUrlSafeBase64(16), ENCRYPTION_PASSWORD: genUrlSafeBase64(64), BETTER_AUTH_URL: 'http://localhost:8080', CLIENT_URL: 'http://localhost:3000', + LOCALTUNNEL_RESERVED_KEY: localtunnelReservedKey, + STRIPE_WEBHOOK_URL: `https://${localtunnelReservedKey}.loca.lt`, }; let databaseUrl = ""; let stripeWebhookVars = []; databaseUrl = await handleDatabaseSetup(); - stripeWebhookVars = await handleLocalRunSetup(); + // stripeWebhookVars = await handleLocalRunSetup(); // Step 11: Write to server/.env console.log(chalk.magentaBright('\n================ Writing .env ================\n')); @@ -263,15 +266,23 @@ async function main() { // Autumn Auth section envSections.push( - '# Autumn Auth', + '# Auth', `BETTER_AUTH_SECRET=${secrets.BETTER_AUTH_SECRET}`, - `ENCRYPTION_IV=${secrets.ENCRYPTION_IV}`, - `ENCRYPTION_PASSWORD=${secrets.ENCRYPTION_PASSWORD}`, `BETTER_AUTH_URL=${secrets.BETTER_AUTH_URL}`, `CLIENT_URL=${secrets.CLIENT_URL}`, '' ); + // Stripe required section + envSections.push( + '# Stripe', + `LOCALTUNNEL_RESERVED_KEY=${secrets.LOCALTUNNEL_RESERVED_KEY}`, + `ENCRYPTION_IV=${secrets.ENCRYPTION_IV}`, + `ENCRYPTION_PASSWORD=${secrets.ENCRYPTION_PASSWORD}`, + `STRIPE_WEBHOOK_URL=${secrets.STRIPE_WEBHOOK_URL}`, + '' + ); + // Database section if (databaseUrl) { envSections.push( @@ -322,6 +333,10 @@ async function main() { } console.log(chalk.greenBright('✅ Successfully ran "pnpm run db:push".')); } + + console.log(chalk.cyan('\nNext steps:')); + console.log(chalk.cyan('Run the following command to start Autumn:')); + console.log(chalk.cyan(' docker compose -f docker-compose.dev.yml up')); } main(); \ No newline at end of file