Skip to content

feat: add Coastfile for local development#1058

Open
dahyman91 wants to merge 2 commits intosourcebot-dev:mainfrom
dahyman91:dan/add-coastfile
Open

feat: add Coastfile for local development#1058
dahyman91 wants to merge 2 commits intosourcebot-dev:mainfrom
dahyman91:dan/add-coastfile

Conversation

@dahyman91
Copy link
Copy Markdown

@dahyman91 dahyman91 commented Mar 28, 2026

Summary

  • Add a Coastfile so developers can use Coasts to run isolated dev environments with the full stack (Next.js, backend worker, zoekt, Postgres, Redis) in parallel for worktree-based workflows.
  • Update AUTH_URL in .env.development to support dynamic port assignment for multi-instance setups. Defaults to :3000 when WEB_DYNAMIC_PORT is not set, so no impact on existing workflows.

Note for Coast users: If your .env.development.local hardcodes AUTH_URL, remove that line or update it to AUTH_URL="http://localhost:${WEB_DYNAMIC_PORT:-3000}" so the dynamic port works.

Fixes #1056

Test plan

  • coast build && coast run dev — all services (web, backend, zoekt) start and are reachable
  • coast run dev-2 — second instance runs in parallel without lock conflicts
  • coast checkout dev then visit http://localhost:3000 — app loads and auth works
  • Verify yarn dev still works without Coast (AUTH_URL falls back to :3000)

Summary by CodeRabbit

  • Chores
    • Configured local development environment with integrated web, backend, and search services, including PostgreSQL and Redis infrastructure.

Add a Coastfile so developers can use Coasts to run isolated dev
environments with the full stack (Next.js, backend worker, zoekt,
Postgres, Redis) in parallel for worktree-based workflows.

Update AUTH_URL in .env.development to support dynamic port assignment
for multi-instance setups.

Fixes sourcebot-dev#1056
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

Walkthrough

A new Coastfile configuration is added to enable local development using the Coasts tool, defining a multi-service development environment with Next.js web, backend worker, and zoekt services, alongside shared Postgres and Redis services, with automatic setup, port management, caching, and rebuild triggers.

Changes

Cohort / File(s) Summary
Coastfile Configuration
Coastfile
New Coast project configuration with setup phase, three services (zoekt, web, backend), two shared services (postgres, redis), secret extractors (database_url, redis_url), port aliases, and service-specific caching and rebuild trigger rules.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add Coastfile for local development' directly and clearly summarizes the main change—adding a Coastfile for local development setup.
Linked Issues check ✅ Passed The pull request fully satisfies issue #1056 by adding a complete Coastfile that launches a full local stack (Next.js, backend, zoekt, Postgres, Redis) and supports multiple parallel instances for worktree-based workflows.
Out of Scope Changes check ✅ Passed All changes are directly related to adding the Coastfile configuration for local development as specified in issue #1056; no unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
Coastfile (1)

23-36: Redundant environment variables in commands vs secrets injection.

The secrets.database_url and secrets.redis_url sections inject DATABASE_URL and REDIS_URL as environment variables (lines 51-60). However, the command lines for web (line 26) and backend (line 34) also explicitly set these same variables inline. Similarly, the install commands hardcode these values.

This duplication could lead to drift if one location is updated but not the others.

♻️ Suggested cleanup: rely on secrets injection only

If the secrets injection works as expected before commands run, you can simplify:

 [services.web]
-install = ["cd /workspace && (test -f node_modules/.yarn-state.yml || DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/postgres make yarn)", "cd /workspace && test -f config.json || echo {} > config.json", "cd /workspace && DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/postgres yarn dev:prisma:migrate:dev"]
-command = "cd /workspace && DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/postgres REDIS_URL=redis://host.docker.internal:6379 yarn dev:web"
+install = ["cd /workspace && (test -f node_modules/.yarn-state.yml || make yarn)", "cd /workspace && test -f config.json || echo {} > config.json", "cd /workspace && yarn dev:prisma:migrate:dev"]
+command = "cd /workspace && yarn dev:web"

If the secrets are not available during install/command, consider documenting why inline values are needed.

Also applies to: 50-60

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Coastfile` around lines 23 - 36, The Coastfile duplicates DATABASE_URL and
REDIS_URL by inlining them in the install and command strings for services.web
and services.backend while the same values are injected via secrets.database_url
and secrets.redis_url; update the install and command entries for the
services.web and services.backend blocks to remove the inline DATABASE_URL=...
and REDIS_URL=... fragments and rely on the secrets injection (or, if secrets
are truly not available during install/command, add a short comment documenting
that fact and why the inline variables must remain).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.env.development:
- Line 15: Replace the shell-style expansion in AUTH_URL so the value loaded by
dotenv is a valid URL string (e.g., use a hardcoded localhost default rather
than "${WEB_DYNAMIC_PORT:-3000}") so env validation in
packages/shared/src/env.server.ts and the new URL(env.AUTH_URL) call in
packages/web/src/app/layout.tsx succeed; if dynamic ports for Coast are
required, document or set AUTH_URL via the Coastfile or instruct contributors to
override in .env.development.local instead of relying on shell parameter
expansion in .env.development.

---

Nitpick comments:
In `@Coastfile`:
- Around line 23-36: The Coastfile duplicates DATABASE_URL and REDIS_URL by
inlining them in the install and command strings for services.web and
services.backend while the same values are injected via secrets.database_url and
secrets.redis_url; update the install and command entries for the services.web
and services.backend blocks to remove the inline DATABASE_URL=... and
REDIS_URL=... fragments and rely on the secrets injection (or, if secrets are
truly not available during install/command, add a short comment documenting that
fact and why the inline variables must remain).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4fecfadd-652b-4c28-b075-27652870c99c

📥 Commits

Reviewing files that changed from the base of the PR and between 2fa86ff and ab50384.

📒 Files selected for processing (2)
  • .env.development
  • Coastfile

Add a Coastfile so developers can use Coasts to run isolated dev
environments with the full stack (Next.js, backend worker, zoekt,
Postgres, Redis) in parallel for worktree-based workflows.

AUTH_URL is set via the Coastfile command using the WEB_DYNAMIC_PORT
env var that Coast injects at runtime. No changes to .env.development
needed.

Fixes sourcebot-dev#1056
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Coastfile`:
- Line 17: The install command in Coastfile currently runs the build without
initializing submodules; update the install step that defines the install
variable to run a git submodule update --init --recursive (or equivalent) for
the vendor/zoekt path before running make so the Zoekt submodule declared in
.gitmodules is initialized on fresh clones (see the install variable and the
Makefile target that builds vendor/zoekt).
- Line 25: The rebuild triggers are missing Prisma schema/migration paths
causing migrations not to run on branch switches; update the Coastfile's
assign.rebuild_triggers to add "packages/db/prisma/schema.prisma" and
"packages/db/prisma/migrations" to both the web and backend arrays so that the
rebuild logic for web and backend (keys "web" and "backend" under
assign.rebuild_triggers) watches those files and re-runs the install/migrate
step when they change.
- Line 3: The Coastfile config currently forces shared_services.postgres and
shared_services.redis with DATABASE_URL/REDIS_URL hardcoded to
host.docker.internal which breaks worktree isolation and causes stale Prisma
schemas and advisory-lock contention because web runs yarn
dev:prisma:migrate:dev during install and only watches package.json/yarn.lock;
change to use per-worktree DB/Redis by default (use docker service names like
postgres/redis or generate a worktree-unique DB name via an env COAST_ID
appended to the DB name), remove hardcoded host.docker.internal from web and
backend and make these values configurable/overridable per-coast, move Prisma
migration invocation out of the one-time install step in web (yarn
dev:prisma:migrate:dev) into the container start/entrypoint or into an explicit
migrate step and expand watched files to include prisma schema/migrations so
switching branches triggers migrations; for services.zoekt.install, guard the
make step by ensuring vendor/zoekt is initialized (run git submodule update
--init --recursive or skip+log a clear error) before running make zoekt to avoid
silent failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1a95a40d-c136-4627-9593-16979f379b36

📥 Commits

Reviewing files that changed from the base of the PR and between ab50384 and 1d17878.

📒 Files selected for processing (1)
  • Coastfile

@@ -0,0 +1,81 @@
[coast]
name = "sourcebot"
compose = "./docker-compose-dev.yml"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's see the full Coastfile to understand the configuration
fd -type f -name "Coastfile" | head -20

Repository: sourcebot-dev/sourcebot

Length of output: 237


🏁 Script executed:

# Also get the docker-compose-dev.yml to check postgres/redis definitions
fd -type f -name "docker-compose-dev.yml"

Repository: sourcebot-dev/sourcebot

Length of output: 237


🏁 Script executed:

# Check for .gitmodules and Makefile
fd -type f -name ".gitmodules"
fd -type f -name "Makefile"

Repository: sourcebot-dev/sourcebot

Length of output: 408


🏁 Script executed:

# Find the Coastfile
fd -t f "Coastfile"

Repository: sourcebot-dev/sourcebot

Length of output: 76


🏁 Script executed:

# Find docker-compose-dev.yml
fd -t f "docker-compose-dev.yml"

Repository: sourcebot-dev/sourcebot

Length of output: 89


🏁 Script executed:

# Find .gitmodules and Makefile
fd -t f "\.gitmodules"
fd -t f "Makefile"

Repository: sourcebot-dev/sourcebot

Length of output: 75


🏁 Script executed:

cat -n Coastfile

Repository: sourcebot-dev/sourcebot

Length of output: 3573


🏁 Script executed:

cat -n docker-compose-dev.yml

Repository: sourcebot-dev/sourcebot

Length of output: 847


🏁 Script executed:

cat -n Makefile

Repository: sourcebot-dev/sourcebot

Length of output: 1626


🏁 Script executed:

# Also check for .gitmodules
cat -n .gitmodules

Repository: sourcebot-dev/sourcebot

Length of output: 201


Shared DB/cache across coasts conflicts with per-worktree isolation.

Coastfile explicitly configures [shared_services.postgres] and [shared_services.redis] (lines 39–48) with a comment stating "run on host Docker so all Coasts share one DB and cache." Combined with hardcoded DATABASE_URL and REDIS_URL to host.docker.internal in web and backend (lines 25–26, 33–34), this shared instance undermines worktree isolation. The web service runs yarn dev:prisma:migrate:dev at install time (line 25) without any rebuild trigger for migrations (lines 78–81 only watch package.json and yarn.lock), so switching worktrees on different branches will leave the schema stale and risk Prisma advisory lock contention if multiple coasts are running.

Additionally, services.zoekt.install (line 17) runs make zoekt which builds from vendor/zoekt (Makefile:12), but this git submodule may not be initialized if cloned without --recursive, causing a silent build failure.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Coastfile` at line 3, The Coastfile config currently forces
shared_services.postgres and shared_services.redis with DATABASE_URL/REDIS_URL
hardcoded to host.docker.internal which breaks worktree isolation and causes
stale Prisma schemas and advisory-lock contention because web runs yarn
dev:prisma:migrate:dev during install and only watches package.json/yarn.lock;
change to use per-worktree DB/Redis by default (use docker service names like
postgres/redis or generate a worktree-unique DB name via an env COAST_ID
appended to the DB name), remove hardcoded host.docker.internal from web and
backend and make these values configurable/overridable per-coast, move Prisma
migration invocation out of the one-time install step in web (yarn
dev:prisma:migrate:dev) into the container start/entrypoint or into an explicit
migrate step and expand watched files to include prisma schema/migrations so
switching branches triggers migrations; for services.zoekt.install, guard the
make step by ensuring vendor/zoekt is initialized (run git submodule update
--init --recursive or skip+log a clear error) before running make zoekt to avoid
silent failures.


# Zoekt code search server (Go binary built by `make`)
[services.zoekt]
install = "cd /workspace && (test -f bin/zoekt-webserver || make zoekt)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Initialize the Zoekt submodule before building.

Makefile:10-14 builds Zoekt from vendor/zoekt, and .gitmodules:1-3 declares that path as a submodule. On a normal clone, that submodule is missing until someone initializes it, so coast build can fail on first run unless developers remember an out-of-band setup step.

Possible hardening
-install = "cd /workspace && (test -f bin/zoekt-webserver || make zoekt)"
+install = "cd /workspace && git submodule update --init --recursive vendor/zoekt && (test -f bin/zoekt-webserver || make zoekt)"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
install = "cd /workspace && (test -f bin/zoekt-webserver || make zoekt)"
install = "cd /workspace && git submodule update --init --recursive vendor/zoekt && (test -f bin/zoekt-webserver || make zoekt)"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Coastfile` at line 17, The install command in Coastfile currently runs the
build without initializing submodules; update the install step that defines the
install variable to run a git submodule update --init --recursive (or
equivalent) for the vendor/zoekt path before running make so the Zoekt submodule
declared in .gitmodules is initialized on fresh clones (see the install variable
and the Makefile target that builds vendor/zoekt).


# Next.js frontend + API
[services.web]
install = ["cd /workspace && (test -f node_modules/.yarn-state.yml || DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/postgres make yarn)", "cd /workspace && test -f config.json || echo {} > config.json", "cd /workspace && DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/postgres yarn dev:prisma:migrate:dev"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd /workspace && find . -name "Coastfile" -type f | head -20

Repository: sourcebot-dev/sourcebot

Length of output: 127


🏁 Script executed:

cat -n Coastfile | head -100

Repository: sourcebot-dev/sourcebot

Length of output: 3573


🏁 Script executed:

# Look for Prisma schema and migration files
find . -name "schema.prisma" -o -name "*.sql" | grep -E "prisma|migrations" | head -20

Repository: sourcebot-dev/sourcebot

Length of output: 1756


🏁 Script executed:

find . -name "schema.prisma" -type f

Repository: sourcebot-dev/sourcebot

Length of output: 101


🏁 Script executed:

# Verify the backend service configuration at lines 74-80
sed -n '74,80p' Coastfile

Repository: sourcebot-dev/sourcebot

Length of output: 212


🏁 Script executed:

# Check if packages/db is used by both services
grep -r "packages/db" --include="*.json" --include="*.ts" --include="*.js" | grep -E "(package\.json|import|require)" | head -20

Repository: sourcebot-dev/sourcebot

Length of output: 49


Add Prisma schema/migration paths to rebuild triggers.

With web = "hot" and backend = "hot" modes, the install steps (yarn dev:prisma:migrate:dev) only run on initial setup. When switching branches with new Prisma migrations, if neither package.json nor yarn.lock changed, the migrations won't execute, leaving the database schema out of sync.

Add packages/db/prisma/schema.prisma and packages/db/prisma/migrations to the rebuild triggers for both services:

[assign.rebuild_triggers]
web = ["package.json", "yarn.lock", "packages/db/prisma/schema.prisma", "packages/db/prisma/migrations"]
backend = ["package.json", "yarn.lock", "packages/db/prisma/schema.prisma", "packages/db/prisma/migrations"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Coastfile` at line 25, The rebuild triggers are missing Prisma
schema/migration paths causing migrations not to run on branch switches; update
the Coastfile's assign.rebuild_triggers to add
"packages/db/prisma/schema.prisma" and "packages/db/prisma/migrations" to both
the web and backend arrays so that the rebuild logic for web and backend (keys
"web" and "backend" under assign.rebuild_triggers) watches those files and
re-runs the install/migrate step when they change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR] Add Coastfile for local development with Coasts

1 participant