diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..22db3e6 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,113 @@ +name: Deploy to Production + +on: + push: + branches: [prod] + +jobs: + test: + runs-on: ubuntu-24.04 + + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Enable corepack + run: corepack enable + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version-file: ".node-version" + cache: "pnpm" + cache-dependency-path: "pnpm-lock.yaml" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run tests + run: pnpm test:run + + - name: Run linter (without build artifacts) + run: rm -rf dist && rm -f hono/static/*.js hono/static/*.js.map && pnpm lint + + - name: Run build + run: pnpm build + + e2e: + runs-on: ubuntu-24.04 + + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Enable corepack + run: corepack enable + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version-file: ".node-version" + cache: "pnpm" + cache-dependency-path: "pnpm-lock.yaml" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps chromium + + - name: Build JavaScript files + run: pnpm build + + - name: Run database migrations + run: pnpm db:migrate + + - name: Seed database + run: pnpm db:seed + + - name: Run Playwright tests + env: + SESSION_SECRET: ${{ secrets.SESSION_SECRET }} + E2E_GMAIL_ACCOUNT: ${{ secrets.E2E_GMAIL_ACCOUNT }} + E2E_GMAIL_PASSWORD: ${{ secrets.E2E_GMAIL_PASSWORD }} + run: pnpm test:e2e + + - name: Upload test artifacts + uses: actions/upload-artifact@v5 + if: failure() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 + + deploy: + needs: [test, e2e] + runs-on: ubuntu-24.04 + + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Enable corepack + run: corepack enable + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version-file: ".node-version" + cache: "pnpm" + cache-dependency-path: "pnpm-lock.yaml" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Apply D1 database migrations + run: pnpm db:migrate:prod + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + + - name: Deploy to Cloudflare Workers + run: pnpm run deploy + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} diff --git a/README.md b/README.md index 5f45945..2446973 100644 --- a/README.md +++ b/README.md @@ -153,9 +153,40 @@ pnpm lint:fix pnpm run deploy ``` -### Subsequent Deployments +### Automated Deployment (CI/CD) -After the initial setup, deploy with: +Production deployments are automated via GitHub Actions. Pushing to the `prod` branch triggers the deployment pipeline defined in `.github/workflows/deploy.yml`. + +**Pipeline overview:** + +1. **`test` job** — Runs unit tests, linter, and full build +2. **`e2e` job** — Runs Playwright E2E tests (in parallel with `test`) +3. **`deploy` job** — Applies D1 migrations and deploys to Cloudflare Workers (only runs after both `test` and `e2e` pass) + +**Typical workflow:** + +```bash +# Merge main into prod to trigger a deployment +git checkout prod +git merge main +git push origin prod +``` + +**Required GitHub secret:** + +The deploy job authenticates with Cloudflare using the `CLOUDFLARE_API_TOKEN` repository secret. To set it up: + +1. Go to [Cloudflare Dashboard > API Tokens](https://dash.cloudflare.com/profile/api-tokens) and create a token with these permissions: + - **Workers Scripts: Edit** + - **D1: Edit** + - **Account Settings: Read** +2. Add the token as `CLOUDFLARE_API_TOKEN` in your GitHub repository under **Settings > Secrets and variables > Actions > New repository secret** + +The E2E job reuses the existing `SESSION_SECRET`, `E2E_GMAIL_ACCOUNT`, and `E2E_GMAIL_PASSWORD` secrets already configured for CI. + +### Manual Deployment + +You can still deploy manually if needed: ```bash pnpm run deploy