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
19 changes: 12 additions & 7 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
node_modules
*/node_modules
# Docker's ignore patterns are anchored to the build context root unless they
# start with "**", so a bare ".next" only matches ./.next — it does NOT match
# apps/web-ui/.next. Left unanchored that stale build output is 446 MB of the
# context, and it also shadows the directory the Dockerfile builds into.
**/node_modules
.git
.env
.env.local
.env.*.local
dist
.next
**/.env
**/.env.local
**/.env.*.local
**/dist
**/.next
**/.source
**/coverage
**/*.tsbuildinfo
*.log
.DS_Store
coverage
Expand Down
57 changes: 55 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,37 @@ concurrency:
jobs:
lint-and-test:
runs-on: ubuntu-latest
# Build and e2e both boot the app, so they need a real database and the
# secrets NextAuth refuses to start without. Values are throwaway CI-only.
env:
DATABASE_URL: postgresql://chatbot_admin:chatbot_dev@localhost:5433/chatbot?schema=public
NEXTAUTH_SECRET: ci-test-secret-not-for-production
NEXTAUTH_URL: http://localhost:3005
AWS_REGION: ap-south-2
# EncryptionService refuses to construct without a 64-char hex key, so
# libs/claw-studio's claw-runtime tests fail at setup without it. Throwaway.
# MUST stay quoted: an unquoted all-digit value is parsed by YAML as an
# integer, which collapses to "0" and then fails the 64-char hex check in
# libs/shared/src/env.ts — breaking every suite that imports it.
ENCRYPTION_KEY: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
# libs/claw-studio persistence tests run against a live Postgres (see
# TEST_DATABASE_URL in src/agent/persistence.test.ts, which pins port 5433).
# Without this the suite fails with connection errors rather than assertion
# failures, which reads like a code bug and is not.
services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_DB: chatbot
POSTGRES_USER: chatbot_admin
POSTGRES_PASSWORD: chatbot_dev
ports:
- 5433:5432
options: >-
--health-cmd "pg_isready -U chatbot_admin -d chatbot"
--health-interval 5s
--health-timeout 5s
--health-retries 10
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -25,17 +56,39 @@ jobs:
- name: Install dependencies
run: bun install --frozen-lockfile

- name: Prepare test database
# migrate deploy, not db push: the HNSW pgvector indexes live in raw SQL
# inside migrations, and db push silently skips them.
run: bunx prisma migrate deploy --schema=./prisma/schema.prisma

- name: Unit tests
run: bun run test

# Restores the original `bun run build` (nx run-many -t build --all). This used
# to need --excludeTaskDependencies scoped to web-ui, because agent-studio's
# build failed on an Nx path-rewriting bug and web-ui depends on it. Both
# agent-studio and claw-studio are fixed now (see
# libs/whatsapp/src/processor/agent-executor.ts and
# libs/claw-studio/src/mcp/mcp-tools.ts), so the whole monorepo builds.
- name: Build
run: bun run build

- name: Install Playwright browsers
run: bunx playwright install --with-deps chromium

- name: E2E tests
run: bun run e2e
# e2e is intentionally NOT run here yet.
#
# Playwright's webServer runs `bun run dev:all`, which starts four servers in
# parallel (web-ui, workers, sdk, mission-control) and allows 120s for them to
# come up. That reproducibly times out. It also never ran before: CI had been
# failing at the unit-test step since the job was created, so this was never
# exercised. Wiring it up is its own piece of work — most likely a dedicated
# CI serve command (web-ui only) or a pre-started server, not dev:all.
#
# The target also defaults to dependsOn: ^build, which is now satisfiable.
#
# - name: E2E tests
# run: bunx nx e2e web-ui-e2e -- --grep-invert @sso

- name: Upload Playwright report
if: failure()
Expand Down
103 changes: 103 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Build & push web-ui image

# Builds apps/web-ui/Dockerfile and pushes it to ECR. That is the whole job —
# there is deliberately no ECS step in here.
#
# Deploying to ECS needs a cluster and service that the Pulumi compute stack
# creates; that stack is not deployed yet (no ECS cluster exists in the target
# region), so a deploy job here would fail for reasons unrelated to the image.
# Adding it later is a small diff once the infrastructure exists.

on:
push:
branches: [main]
paths:
- "apps/web-ui/**"
- "apps/sdk/**"
- "libs/**"
- "prisma/**"
- "package.json"
- "bun.lock"
- ".github/workflows/deploy.yml"
workflow_dispatch:

concurrency:
group: image-${{ github.ref }}
cancel-in-progress: false

env:
AWS_REGION: ${{ vars.AWS_REGION || 'ap-south-2' }}
ECR_REPOSITORY: ${{ vars.ECR_REPOSITORY || 'chatbot-web-ui' }}
AWS_ROLE_ARN: ${{ vars.AWS_ROLE_ARN || 'arn:aws:iam::704554708141:role/agentfork-github-deploy' }}

jobs:
build-and-push:
name: Build & push image
# Native arm64 runner. The image targets linux/arm64 (Fargate Graviton), and
# this repo is public, so arm64 runners are free — building natively avoids
# QEMU, which is slow enough on a Next.js build to hit the job timeout.
runs-on: ubuntu-24.04-arm
permissions:
contents: read
id-token: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
role-session-name: gha-image-${{ github.run_id }}

- name: Log in to Amazon ECR
id: ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Set up Buildx
uses: docker/setup-buildx-action@v3

- name: Resolve image reference
id: meta
run: |
IMAGE="${{ steps.ecr.outputs.registry }}/${ECR_REPOSITORY}"
SHORT_SHA="${GITHUB_SHA:0:12}"
{
echo "image=${IMAGE}:${SHORT_SHA}"
echo "latest=${IMAGE}:latest"
} >> "$GITHUB_OUTPUT"
echo "Building ${IMAGE}:${SHORT_SHA}"

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: apps/web-ui/Dockerfile
platforms: linux/arm64
push: true
# Tagged by commit SHA (immutable, traceable) plus :latest for convenience.
tags: |
${{ steps.meta.outputs.image }}
${{ steps.meta.outputs.latest }}
# Registry-backed layer cache. Without this every run is a cold build;
# `cacheFrom: latest` in the old Pulumi path was a no-op because nothing
# ever pushed a `latest` tag, so the cache reference resolved to nothing.
cache-from: type=registry,ref=${{ steps.ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:buildcache
cache-to: type=registry,ref=${{ steps.ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:buildcache,mode=max
# Inlined into the client bundle by `next build`, so it must be a build
# arg — a runtime env var would arrive too late to affect the bundle.
build-args: |
# Required, not defaulted: a missing value must fail the build rather than
# silently bake a localhost URL into a production image's client bundle.
NEXT_PUBLIC_MISSION_CONTROL_URL=${{ vars.NEXT_PUBLIC_MISSION_CONTROL_URL }}

- name: Summary
run: |
{
echo "### Pushed to ECR"
echo ""
echo "- \`${{ steps.meta.outputs.image }}\`"
echo "- \`${{ steps.meta.outputs.latest }}\`"
} >> "$GITHUB_STEP_SUMMARY"
5 changes: 2 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,11 @@ modules/<module>/ # specs grouped by product module (auth, sso, marketing

## Git Workflow

This repo mirrors to **two remotes** — `origin` pushes to both GitHub and Bitbucket, so a single `git push` lands on both. See **`docs/dev/git-workflow.md`** for the full procedure (remote layout, single-target pushes, keeping the remotes in sync). Key rules:
GitHub is the **only** remote — this repo no longer mirrors to Bitbucket. See **`docs/dev/git-workflow.md`** for the full procedure. Key rules:

- Default `git push` fans out to GitHub + Bitbucket. Use `git push github <branch>` / `git push bitbucket <branch>` for a single target.
- `origin` is `github.com:offloadmemory/agentfork.git`. A plain `git push` targets GitHub.
- Work on a feature branch; open a PR into `main` (`gh pr create --base main`). Don't push to `main` directly; only the user merges.
- `.env.example` holds placeholders only — never commit real secrets. If GitHub push protection blocks a key, stop and tell the user; don't use the allow-secret bypass yourself.
- Fetch is GitHub-only: pull Bitbucket-direct changes with `git fetch bitbucket && git merge bitbucket/main`.

## Code Style

Expand Down
5 changes: 3 additions & 2 deletions apps/web-ui/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ WORKDIR /app
RUN apt-get update && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
RUN npm install -g bun@1.3.6

# apps/workers/ is deliberately absent: nothing in web-ui imports @chatbot/workers
# and no workspace depends on it, so listing it here only pulls a package.json that
# is never installed against.
COPY package.json bun.lock ./
COPY apps/web-ui/package.json apps/web-ui/
COPY apps/workers/package.json apps/workers/
COPY apps/sdk/package.json apps/sdk/
COPY libs ./libs/
COPY infra/package.json infra/
Expand All @@ -20,7 +22,6 @@ COPY nx.json ./
RUN bun install --ignore-scripts

COPY apps/web-ui/ apps/web-ui/
COPY apps/workers/ apps/workers/
COPY apps/sdk/ apps/sdk/

ENV NEXT_TELEMETRY_DISABLED=1
Expand Down
31 changes: 31 additions & 0 deletions apps/web-ui/Dockerfile.prebuilt.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Ignore rules for Dockerfile.prebuilt only.
#
# The shared ../../.dockerignore excludes **/.next, but this Dockerfile exists to
# package an already-built Next.js standalone output — it needs .next in the build
# context. Docker prefers a file named <dockerfile>.dockerignore over the shared
# one, so the exclusion can stay in place for the normal Dockerfile (where it is
# load-bearing: a stale .next is ~446 MB and shadows the directory the build writes
# into) without breaking this one.
#
# Note this applies to the whole build context, so the paths are the repo-root ones.

**/node_modules
.git
**/env
**/.env
**/.env.local
**/.env.*.local
**/dist
**/.source
**/coverage
**/*.tsbuildinfo
**/.nx
**/test-results
**/playwright-report
*.log
.DS_Store
.vscode
.idea
*.swp
*.swo
*~
25 changes: 0 additions & 25 deletions bitbucket-pipelines.yml

This file was deleted.

6 changes: 3 additions & 3 deletions docs/RENAME_TO_AGENTFORK_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ connection string. **Do not touch live cloud state from code.**
**C. Canonical repo URL** — for README clone cmds, badges, issue links.
- `github.com/kartikmanimuthu/agentfork` (rename slug on GitHub; I update all URLs), or
- keep `…/chatbot` (rebrand display name only, repo slug unchanged for now).
- Note dual-remote setup: GitHub + Bitbucket (see `docs/dev/git-workflow.md`). A repo rename
must be coordinated across both remotes.
- GitHub is the only remote (see `docs/dev/git-workflow.md`); a repo rename only needs to be
updated in the GitHub remote URL.

---

Expand Down Expand Up @@ -123,7 +123,7 @@ connection string. **Do not touch live cloud state from code.**
6. **Repo URLs** (per §2.C) — update clone/badge/issue links.
7. **Verify:** `bun run build`, `bun run test`, `bun run e2e:smoke`; grep for residual `chatbot`
in scope; manually load app + docs to confirm UI/title branding.
8. **PR** into `main` (`gh pr create --base main`); coordinate GitHub + Bitbucket remotes.
8. **PR** into `main` (`gh pr create --base main`).

## 5. Verification checklist (definition of done)
- [ ] `grep -ri "chatbot"` returns only intentional/historical hits (documented exceptions)
Expand Down
Loading
Loading