From d9002ff9febd349e7d4031b56c0d15b26029eace Mon Sep 17 00:00:00 2001 From: Bohdan Date: Tue, 2 Jun 2026 13:28:00 +0300 Subject: [PATCH 1/4] docs(plans): add week4 deploy-polish plan --- plans/week4/deploy-polish.md | 83 ++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 plans/week4/deploy-polish.md diff --git a/plans/week4/deploy-polish.md b/plans/week4/deploy-polish.md new file mode 100644 index 0000000..219b333 --- /dev/null +++ b/plans/week4/deploy-polish.md @@ -0,0 +1,83 @@ +# Week 4 AC 1–2: Deploy polish + +**Пріоритет:** high — фінальний стан репо перед демо +**Залежить від:** всі попередні PR merged до development +**Статус:** не розпочато +**Гілка:** `feat/week4-deploy-polish` + +--- + +## Scope + +### AC 1 — CI/CD (залишок) +GitHub Actions `ci.yml` вже є і покриває lint + typecheck. Branch protection rules налаштовані вручну. Автодеплой Vercel підключений через GitHub integration. +→ **Нічого робити в коді.** + +### AC 2 — Deploy (залишок у коді) + +1. **Extension `.zip`** — скрипт пакування `dist/` у `worktrace-extension.zip` + npm script `zip` +2. **README оновлення:** + - Прибрати `jsonwebtoken` з tech stack (замінено на `jose`) + - Прибрати "AI — LLM provider TBD (Week 3)" — вже використовується Groq + - Оновити секцію **Deploy** — реальні інструкції як завантажити `.zip` в Chrome + - Прибрати "Chrome Web Store packaging is scheduled for Week 4 AC 2" — не робимо + - Прибрати Week 1-specific коментарі з Setup секції +3. **`.env.example` перевірка** — вже актуальний (CRON_SECRET додано в попередньому PR) + +--- + +## Декомпозиція комітів + +``` +1. docs(plans): add week4 deploy-polish plan +2. chore(extension): add zip script to package.json, gitignore *.zip +3. docs(readme): update tech stack, deploy instructions, remove stale Week 1 notes +``` + +--- + +## Деталі реалізації + +### Zip script (крок 2) + +В `extension/package.json` додати: +```json +"zip": "npm run build && cd dist && zip -r ../worktrace-extension.zip ." +``` + +На Windows `zip` може не бути — використати cross-platform альтернативу через Node або PowerShell. +Варіант: `"zip": "npm run build && node ../scripts/zip-extension.js"` — окремий скрипт. + +Або простіше — просто задокументувати в README як зробити zip вручну (одна команда), без додаткового скрипту. + +**Рішення:** додати `zip` script через `bestzip` (cross-platform npm пакет, нуль конфігурації). + +### README зміни (крок 3) + +**Tech stack — до:** +``` +- **Backend** — ..., `jsonwebtoken` +- **AI** — LLM provider TBD (Week 3): OpenAI / Groq / Gemini / OpenRouter +``` + +**Tech stack — після:** +``` +- **Backend** — ..., `jose` +- **AI** — Groq (llama-3.3-70b-versatile), з можливістю вказати власний API ключ +``` + +**Deploy — додати:** +``` +### Завантажити extension локально +1. Скачай `worktrace-extension.zip` з Releases +2. Розпакуй у будь-яку папку +3. chrome://extensions → Developer mode → Load unpacked → обери розпаковану папку +``` + +--- + +## Рішення + +- **`bestzip` для zip** — один пакет, працює на Windows/Mac/Linux без системного `zip` +- **Zip не комітимо** — додати `*.zip` в `.gitignore` (або `worktrace-extension.zip`), артефакт генерується локально перед деплоєм +- **GitHub Releases** — zip завантажується вручну як release asset після деплою, не через CI (поза scope) From 8797c4f9f9a80187374a4df1bb625c9774f3b133 Mon Sep 17 00:00:00 2001 From: Bohdan Date: Tue, 2 Jun 2026 18:14:01 +0300 Subject: [PATCH 2/4] chore(extension): add zip script via PowerShell Compress-Archive --- extension/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extension/package.json b/extension/package.json index 4d2ecfc..b29f71e 100644 --- a/extension/package.json +++ b/extension/package.json @@ -7,7 +7,8 @@ "scripts": { "dev": "vite", "build": "vite build", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "zip": "npm run build && powershell -Command \"Compress-Archive -Path dist/* -DestinationPath worktrace-extension.zip -Force\"" }, "devDependencies": { "@crxjs/vite-plugin": "^2.0.0-beta.36", From 761a0bc97f4cfd8f1eefc9b96d5c5a93bba0a50f Mon Sep 17 00:00:00 2001 From: Bohdan Date: Tue, 2 Jun 2026 18:15:16 +0300 Subject: [PATCH 3/4] docs(readme): update tech stack, zip instructions, remove stale Week 1 notes --- README.md | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e0bd5ec..2eb7313 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ The two apps are isolated — `extension/` never imports from `dashboard/` and v ## Tech stack - **Dashboard** — Next.js 16 (App Router, Server Components), React 19, Tailwind CSS v4, TanStack Query v5, Framer Motion, D3.js -- **Backend** — Next.js Route Handlers, Prisma 7 (with `@prisma/adapter-pg`), Zod, `google-auth-library`, `jsonwebtoken` +- **Backend** — Next.js Route Handlers, Prisma 7 (with `@prisma/adapter-pg`), Zod, `google-auth-library`, `jose` - **Extension** — Manifest V3, Vite 7 + `@crxjs/vite-plugin`, TypeScript (strict) - **Database** — PostgreSQL 16 (Docker for local, Neon for production) -- **AI** — LLM provider TBD (Week 3): OpenAI / Groq / Gemini / OpenRouter -- **Deploy** — Vercel (dashboard), `.zip` for local extension install +- **AI** — Groq (`llama-3.3-70b-versatile`), з можливістю вказати власний API ключ у налаштуваннях +- **Deploy** — Vercel (dashboard), `.zip` для локального завантаження extension Versions in `dashboard/package.json` and `extension/package.json` are authoritative. @@ -51,7 +51,7 @@ cp dashboard/.env.example dashboard/.env cp extension/.env.example extension/.env ``` -The dashboard `.env` contains `DATABASE_URL` (already pointing at the docker-compose Postgres) plus `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `JWT_SECRET`. The Google/JWT values are **not required for Week 1** — leave them blank until the auth flow lands in Week 2. +The dashboard `.env` contains `DATABASE_URL` (already pointing at the docker-compose Postgres) plus `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `JWT_SECRET`, `GROQ_API_KEY`, and `CRON_SECRET`. See comments in `.env.example` for how to generate each value. ### 2. Start PostgreSQL @@ -89,19 +89,33 @@ Then in Chrome: The extension card should appear with no errors. For HMR-rebuild during active development use `npm run dev` instead of `npm run build`. +### Load from `.zip` (without source code) + +```bash +cd extension +npm run zip # builds and creates worktrace-extension.zip +``` + +Then in Chrome: + +1. Unzip `worktrace-extension.zip` to any folder +2. Open `chrome://extensions` → **Developer mode** → **Load unpacked** +3. Select the unzipped folder + ## Verifying it works -1. **Dashboard** — `http://localhost:3000` loads (Next.js placeholder page is fine for Week 1). -2. **Extension** — the card on `chrome://extensions` shows no errors; clicking the toolbar icon opens an empty popup; the service worker logs `[worktrace] installed` (visible via the extension's **Inspect** link). -3. **API** — a POST to the events endpoint round-trips through Postgres: +1. **Dashboard** — відкрий `http://localhost:3000`, натисни "Sign in with Google" → має відкритись `/dashboard` з даними. +2. **Extension** — картка на `chrome://extensions` без помилок; іконка в тулбарі відкриває popup; сервіс воркер логує `[worktrace] installed` (видно через **Inspect** посилання розширення). +3. **API** — Bearer токен з extension працює: ```bash curl -X POST http://localhost:3000/api/v1/events \ -H "Content-Type: application/json" \ - -d '{"sessionId":"ctestsess0000000000000001","url":"https://example.com","title":"Hello","tags":["test"],"timestamp":"2026-05-15T12:00:00Z"}' + -H "Authorization: Bearer " \ + -d '{"sessionId":"","url":"https://github.com","title":"Test","timestamp":"2026-06-01T10:00:00Z"}' ``` - A 201 response with the created event means the dashboard, Prisma, and Postgres are wired up correctly. (The `sessionId` must reference an existing `Session` row — create one via `npx prisma studio` or seed it manually.) + Відповідь `201` означає що dashboard, Prisma і Postgres з'єднані коректно. ## Project docs @@ -113,4 +127,4 @@ The extension card should appear with no errors. For HMR-rebuild during active d ## Deploy - **Dashboard** — Vercel with **Root Directory: `dashboard`**. The build command `prisma generate && next build` (declared in `dashboard/package.json`) regenerates the Prisma client at build time since `dashboard/generated/` is gitignored. Production database is Neon. -- **Extension** — distributed as a `.zip` of `extension/dist/` for local install. Chrome Web Store packaging is scheduled for Week 4 AC 2. +- **Extension** — `npm run zip` inside `extension/` builds and packages `dist/` into `worktrace-extension.zip`. Load unpacked in Chrome via Developer mode. From 6814d2609efa25a3d03241c06c1dc30528df79f2 Mon Sep 17 00:00:00 2001 From: Bohdan Date: Tue, 2 Jun 2026 18:18:26 +0300 Subject: [PATCH 4/4] chore(ci): auto GitHub Release with extension zip on merge to main --- .github/workflows/release-extension.yml | 42 +++++++++++++++ plans/week4/deploy-polish.md | 68 +++++++++---------------- 2 files changed, 66 insertions(+), 44 deletions(-) create mode 100644 .github/workflows/release-extension.yml diff --git a/.github/workflows/release-extension.yml b/.github/workflows/release-extension.yml new file mode 100644 index 0000000..fd86a1f --- /dev/null +++ b/.github/workflows/release-extension.yml @@ -0,0 +1,42 @@ +name: Release extension + +on: + push: + branches: [main] + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + cache-dependency-path: extension/package-lock.json + + - name: Build extension + working-directory: extension + run: npm ci && npm run build + + - name: Package extension + working-directory: extension + shell: pwsh + run: Compress-Archive -Path dist/* -DestinationPath worktrace-extension.zip -Force + + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "extension-build-${{ github.run_number }}" \ + extension/worktrace-extension.zip \ + --title "WorkTrace Extension — build ${{ github.run_number }}" \ + --notes "Автоматичний реліз при мерджі в main. + + Щоб завантажити розширення: + 1. Скачай \`worktrace-extension.zip\` + 2. Розпакуй у будь-яку папку + 3. chrome://extensions → Developer mode → Load unpacked → обери розпаковану папку" diff --git a/plans/week4/deploy-polish.md b/plans/week4/deploy-polish.md index 219b333..87570a6 100644 --- a/plans/week4/deploy-polish.md +++ b/plans/week4/deploy-polish.md @@ -2,7 +2,7 @@ **Пріоритет:** high — фінальний стан репо перед демо **Залежить від:** всі попередні PR merged до development -**Статус:** не розпочато +**Статус:** в процесі **Гілка:** `feat/week4-deploy-polish` --- @@ -15,69 +15,49 @@ GitHub Actions `ci.yml` вже є і покриває lint + typecheck. Branch p ### AC 2 — Deploy (залишок у коді) -1. **Extension `.zip`** — скрипт пакування `dist/` у `worktrace-extension.zip` + npm script `zip` -2. **README оновлення:** - - Прибрати `jsonwebtoken` з tech stack (замінено на `jose`) - - Прибрати "AI — LLM provider TBD (Week 3)" — вже використовується Groq - - Оновити секцію **Deploy** — реальні інструкції як завантажити `.zip` в Chrome - - Прибрати "Chrome Web Store packaging is scheduled for Week 4 AC 2" — не робимо - - Прибрати Week 1-specific коментарі з Setup секції -3. **`.env.example` перевірка** — вже актуальний (CRON_SECRET додано в попередньому PR) +1. **Extension `.zip`** — npm script `zip` в `extension/package.json` ✅ +2. **README оновлення** ✅ +3. **GitHub Actions release** — при мерджі в `main` автоматично білдить zip і публікує GitHub Release з asset +4. **`.env.example` перевірка** — вже актуальний (CRON_SECRET додано в попередньому PR) ✅ --- ## Декомпозиція комітів ``` -1. docs(plans): add week4 deploy-polish plan -2. chore(extension): add zip script to package.json, gitignore *.zip -3. docs(readme): update tech stack, deploy instructions, remove stale Week 1 notes +1. docs(plans): add week4 deploy-polish plan ✅ +2. chore(extension): add zip script via PowerShell Compress-Archive ✅ +3. docs(readme): update tech stack, zip instructions ✅ +4. chore(ci): release-extension.yml — auto GitHub Release on merge to main ``` --- ## Деталі реалізації -### Zip script (крок 2) +### Zip script -В `extension/package.json` додати: +`extension/package.json`: ```json -"zip": "npm run build && cd dist && zip -r ../worktrace-extension.zip ." +"zip": "npm run build && powershell -Command \"Compress-Archive -Path dist/* -DestinationPath worktrace-extension.zip -Force\"" ``` -На Windows `zip` може не бути — використати cross-platform альтернативу через Node або PowerShell. -Варіант: `"zip": "npm run build && node ../scripts/zip-extension.js"` — окремий скрипт. +`powershell` (Windows PowerShell) — доступний локально. У CI використовується `pwsh` (PowerShell Core) — доступний на ubuntu-latest. -Або простіше — просто задокументувати в README як зробити zip вручну (одна команда), без додаткового скрипту. +### GitHub Actions release workflow -**Рішення:** додати `zip` script через `bestzip` (cross-platform npm пакет, нуль конфігурації). - -### README зміни (крок 3) - -**Tech stack — до:** -``` -- **Backend** — ..., `jsonwebtoken` -- **AI** — LLM provider TBD (Week 3): OpenAI / Groq / Gemini / OpenRouter -``` - -**Tech stack — після:** -``` -- **Backend** — ..., `jose` -- **AI** — Groq (llama-3.3-70b-versatile), з можливістю вказати власний API ключ -``` - -**Deploy — додати:** -``` -### Завантажити extension локально -1. Скачай `worktrace-extension.zip` з Releases -2. Розпакуй у будь-яку папку -3. chrome://extensions → Developer mode → Load unpacked → обери розпаковану папку -``` +`.github/workflows/release-extension.yml`: +- Тригер: `push` до `main` +- Runner: `ubuntu-latest` +- Кроки: checkout → setup-node → `npm ci` → build → zip через `pwsh` → `gh release create` +- Тег: `extension-build-${{ github.run_number }}` +- Asset: `extension/worktrace-extension.zip` +- `GITHUB_TOKEN` — вбудований, не потрібен додатковий secret --- ## Рішення -- **`bestzip` для zip** — один пакет, працює на Windows/Mac/Linux без системного `zip` -- **Zip не комітимо** — додати `*.zip` в `.gitignore` (або `worktrace-extension.zip`), артефакт генерується локально перед деплоєм -- **GitHub Releases** — zip завантажується вручну як release asset після деплою, не через CI (поза scope) +- **PowerShell Compress-Archive** — системний інструмент, нуль залежностей; локально `powershell`, у CI `pwsh` +- **Zip не комітимо** — `*.zip` вже в кореневому `.gitignore` +- **GitHub Releases через CI** — `gh release create` вбудованою CLI, тег на основі `run_number`; кожен merge до `main` = новий release з актуальним zip