Skip to content

chore(infra): use per-service container WORKDIR#4253

Closed
mmabrouk wants to merge 1 commit intomainfrom
chore/infra/per-service-container-workdir
Closed

chore(infra): use per-service container WORKDIR#4253
mmabrouk wants to merge 1 commit intomainfrom
chore/infra/per-service-container-workdir

Conversation

@mmabrouk
Copy link
Copy Markdown
Member

@mmabrouk mmabrouk commented May 4, 2026

Summary

Containers were uniformly using /app as WORKDIR regardless of which
service they hosted, which made multi-service compose stacks ambiguous
(e.g. /app/oss/ could be either the API or the web app depending on
which container you were in) and produced confusing log paths.

This aligns container WORKDIR with the service that owns it:

Service WORKDIR
api/oss, api/ee /api
web/oss, web/ee /web
services/oss, services/ee /services

What changed

Containers:

  • api/{oss,ee}/docker/Dockerfile.{dev,gh}
  • web/{oss,ee}/docker/Dockerfile.{dev,gh}
  • services/{oss,ee}/docker/Dockerfile.{dev,gh}

Compose stacks: all WORKDIR-relative volume mounts, watchmedo
reload directories, and the cron command updated to use the new paths.

  • hosting/docker-compose/{oss,ee}/docker-compose.{dev,gh,gh.local,gh.ssl}.yml
  • hosting/docker-compose/run.sh
  • hosting/docker-compose/{oss,ee}/env.{oss,ee}.{dev,gh}.example

Helm:

  • hosting/helm/agenta-oss/templates/_helpers.tpl — 4 Alembic
    config-path defaults
  • hosting/helm/agenta-oss/templates/web-deployment.yaml
  • hosting/helm/agenta-oss/templates/cron-deployment.yaml

Railway:

  • All worker, cron, web, and alembic Dockerfiles
  • hosting/railway/oss/scripts/build-and-push-images.sh
  • hosting/railway/oss/scripts/deploy-from-images.sh
  • hosting/railway/oss/web/railway.json

Application code (path strings only):

  • api/oss/src/utils/env.pyAlembicConfig hardcoded fallback paths
  • api/oss/src/crons/queries.sh — crontab path in awk command
  • web/entrypoint.shENTRYPOINT_DIR default

Alembic:

  • 4 alembic.ini files — script_location
  • 4 migration README.md files — example commands

Public docs:

  • docs/docs/self-host/01-quick-start.mdx
  • docs/docs/self-host/02-configuration.mdx
  • docs/docs/self-host/03-upgrading.mdx

Diff

  • 51 files changed, 313 insertions, 261 deletions

Risks

  • High blast radius — every container in the stack changes. Any
    custom Dockerfile/compose override held outside this repo (e.g. a
    customer's compose file that mounts host paths into /app/...) will
    break. Internal customers should be notified before merge.
  • Helm chart values overrides: if any deployment overrides
    alembicCfgPath in their values file, those overrides reference the
    old /app/... path and need to be updated. Defaults in the chart's
    _helpers.tpl move to the new path.
  • Self-hosting docs are also updated. Anyone running migrations
    manually against an old container gets a stale command from cached
    docs — the upgrade flow includes both the container update and the
    doc update so this is consistent at release time.
  • No application logic changes. Only paths in Docker, compose,
    helm, alembic config, and env defaults move. The Python agenta
    package itself is not touched.

QA

  • CI green (the existing CI already exercises both Dockerfile.gh
    builds and the dev compose stack)
  • docker compose -f hosting/docker-compose/oss/docker-compose.dev.yml up
    starts cleanly; API responds on /health; web loads
  • EE equivalent: same with docker-compose.ee.dev.yml
  • Helm chart renders and applies cleanly: helm template against
    the OSS chart shows the new /api path in env vars
  • Run a test alembic migration against a dev container — verify the
    migration runs from /api/oss/databases/postgres/migrations/...
  • Cron container: kubectl logs <cron-pod> shows queries.sh
    executing from /api/
  • Self-host docs render correctly in Docusaurus preview

Notes

  • This is the first of a stack. PRs that follow (chore/sdk/relocate-...,
    feat/sdk/python-fern-client, feat/sdk/typescript-fern-client)
    layer onto this base.
  • Originally part of [chore] Review and cleanup fern #4239 — split out for independent review.

Containers were uniformly using /app as WORKDIR regardless of service
type, which made multi-service compose stacks ambiguous and produced
confusing log paths. This aligns the working directory with the
service that owns the container:

  - api/oss, api/ee   -> /api
  - web/oss, web/ee   -> /web
  - services/oss, ee  -> /services

Updates Dockerfiles (dev + gh), docker-compose stacks (oss + ee, dev
+ gh + gh.local + gh.ssl), Helm charts (alembic config defaults, web
and cron deployments), Railway Dockerfiles + scripts, alembic .ini
files, env .example files, migration READMEs, and self-hosting docs.
Also fixes alembic config fallback paths in api/oss/src/utils/env.py,
the crontab path in api/oss/src/crons/queries.sh, and the
ENTRYPOINT_DIR default in web/entrypoint.sh.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment May 4, 2026 10:55am

Request Review

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label May 4, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

📝 Walkthrough

Summary by CodeRabbit

  • Chores
    • Updated application deployment paths and directory structure across Docker, Kubernetes, and containerized environments.
    • Updated database migration configuration paths to align with new application layout.
    • Updated documentation and deployment examples to reflect updated environment paths and configurations.

Walkthrough

This PR reorganizes the application's directory layout: API code moves from /app to /api, services code to /services, web code to /web, and SDK/client paths standardize to /sdks/python and /clients/python. The changes propagate through all Docker, Kubernetes, Railway, Docker Compose, and configuration files, including Alembic migration paths and crontab locations.

Changes

Directory Layout Reorganization

Layer / File(s) Summary
Configuration & Environment
api/ee/databases/postgres/migrations/core/alembic.ini, api/ee/databases/postgres/migrations/tracing/alembic.ini, api/oss/databases/postgres/migrations/core/alembic.ini, api/oss/databases/postgres/migrations/tracing/alembic.ini, api/oss/src/utils/env.py, hosting/docker-compose/ee/env.ee.dev.example, hosting/docker-compose/ee/env.ee.gh.example, hosting/docker-compose/oss/env.oss.dev.example, hosting/docker-compose/oss/env.oss.gh.example, hosting/helm/agenta-oss/templates/_helpers.tpl, hosting/railway/oss/alembic/Dockerfile
Alembic script_location and ALEMBIC_CFG_PATH_* environment variables updated from /app/{ee,oss}/... to /api/{ee,oss}/... paths across all environments.
Docker API & Services Builds
api/ee/docker/Dockerfile.dev, api/ee/docker/Dockerfile.gh, api/oss/docker/Dockerfile.dev, api/oss/docker/Dockerfile.gh, services/ee/docker/Dockerfile.dev, services/ee/docker/Dockerfile.gh, services/oss/docker/Dockerfile.dev, services/oss/docker/Dockerfile.gh
Dockerfiles refactored to use /api (for API), /services (for services), update PYTHONPATH from /sdk to /sdks/python:/clients/python, and copy source code to new paths with .pth file configuration for Python imports.
Docker Web Builds
web/ee/docker/Dockerfile.dev, web/ee/docker/Dockerfile.gh, web/oss/docker/Dockerfile.dev, web/oss/docker/Dockerfile.gh, web/entrypoint.sh
WORKDIR switches from /app to /web, entrypoint script paths updated, cache directories retargeted to /web/.turbo and /web/.../.next/cache, and ENTRYPOINT_DIR variable updated.
Docker Compose Orchestration
hosting/docker-compose/ee/docker-compose.dev.yml, hosting/docker-compose/ee/docker-compose.gh.local.yml, hosting/docker-compose/ee/docker-compose.gh.yml, hosting/docker-compose/oss/docker-compose.dev.yml, hosting/docker-compose/oss/docker-compose.gh.local.yml, hosting/docker-compose/oss/docker-compose.gh.ssl.yml, hosting/docker-compose/oss/docker-compose.gh.yml
Volume mount targets updated from /app, /sdk to /api, /services, /web, /sdks/python, /clients/python; service commands updated to reference /api/crontab instead of /app/crontab; --reload-dir and --root-path arguments added for API/services uvicorn instances.
Build & Deployment Scripts
hosting/docker-compose/run.sh, hosting/railway/oss/scripts/build-and-push-images.sh, hosting/railway/oss/scripts/deploy-from-images.sh
Build script updated to handle separate sdks/ and clients/ directories with proper copy/cleanup logic; deployment script wrappers updated to reference /api, /services, /web paths.
Kubernetes/Helm Templates
hosting/helm/agenta-oss/templates/cron-deployment.yaml, hosting/helm/agenta-oss/templates/web-deployment.yaml
Helm cron and web deployment commands updated to reference /api/crontab and /web/entrypoint.sh respectively.
Railway Deployment
hosting/railway/oss/cron/Dockerfile, hosting/railway/oss/web/Dockerfile, hosting/railway/oss/web/railway.json, hosting/railway/oss/worker-evaluations/Dockerfile, hosting/railway/oss/worker-events/Dockerfile, hosting/railway/oss/worker-tracing/Dockerfile, hosting/railway/oss/worker-webhooks/Dockerfile
Railway Dockerfiles updated with new /api paths for Alembic configs and /api/crontab for cron; web entrypoint updated to /web/entrypoint.sh and railway.json deployment command adjusted.
Cron & Migration Utilities
api/oss/src/crons/queries.sh
Crontab source path in awk command updated from /app/crontab to /api/crontab.
Documentation
api/ee/databases/postgres/migrations/core/README.md, api/ee/databases/postgres/migrations/tracing/README copy.md, api/oss/databases/postgres/migrations/core/README.md, api/oss/databases/postgres/migrations/tracing/README.md, docs/docs/self-host/01-quick-start.mdx, docs/docs/self-host/02-configuration.mdx, docs/docs/self-host/03-upgrading.mdx
Migration READMEs, quick-start, configuration, and upgrade guides updated with new /api paths in command examples and environment variable defaults.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 60.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore(infra): use per-service container WORKDIR' accurately describes the primary change: containers now use service-specific working directories (/api, /web, /services) instead of the uniform /app.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the rationale, changes across multiple file types, risks, and QA steps.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/infra/per-service-container-workdir

Review rate limit: 8/10 reviews remaining, refill in 11 minutes and 54 seconds.

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

@dosubot dosubot Bot added devops documentation Improvements or additions to documentation refactoring A code change that neither fixes a bug nor adds a feature labels May 4, 2026
Copy link
Copy Markdown

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/ee/databases/postgres/migrations/tracing/README copy.md (1)

16-34: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

The tracing README still points at the core migrations directory.

Lines 16, 28, and 34 all use /api/ee/databases/postgres/migrations/core, so anyone following this doc will generate/apply/downgrade against the wrong Alembic config. These commands should stay under the tracing directory.

Suggested fix
-docker exec -e PYTHONPATH=/api -w /api/ee/databases/postgres/migrations/core agenta-ee-dev-api-1 alembic -c alembic.ini revision --autogenerate -m "migration message"
+docker exec -e PYTHONPATH=/api -w /api/ee/databases/postgres/migrations/tracing agenta-ee-dev-api-1 alembic -c alembic.ini revision --autogenerate -m "migration message"

-docker exec -e PYTHONPATH=/api -w /api/ee/databases/postgres/migrations/core agenta-ee-dev-api-1 alembic -c alembic.ini upgrade head
+docker exec -e PYTHONPATH=/api -w /api/ee/databases/postgres/migrations/tracing agenta-ee-dev-api-1 alembic -c alembic.ini upgrade head

-docker exec -e PYTHONPATH=/api -w /api/ee/databases/postgres/migrations/core agenta-ee-dev-api-1 alembic -c alembic.ini downgrade head
+docker exec -e PYTHONPATH=/api -w /api/ee/databases/postgres/migrations/tracing agenta-ee-dev-api-1 alembic -c alembic.ini downgrade head
🧹 Nitpick comments (1)
hosting/docker-compose/oss/docker-compose.dev.yml (1)

131-140: 💤 Low value

Consider adding SDK/client paths to watchmedo for consistency.

The watchmedo command only watches /api/ for changes, which means SDK or client code changes under /sdks/python and /clients/python won't trigger a worker restart. The api service handles this with explicit --reload-dir arguments for uvicorn.

For consistency, you could extend the watchmedo command to watch additional directories:

watchmedo auto-restart --directory=/api/ --directory=/sdks/python --directory=/clients/python --pattern=*.py --recursive --

This is optional since SDK changes are less frequent in typical development workflows.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8756d0a3-3fec-46b5-83e1-6a6a14b36cfa

📥 Commits

Reviewing files that changed from the base of the PR and between c63d6e9 and c5e3844.

📒 Files selected for processing (51)
  • api/ee/databases/postgres/migrations/core/README.md
  • api/ee/databases/postgres/migrations/core/alembic.ini
  • api/ee/databases/postgres/migrations/tracing/README copy.md
  • api/ee/databases/postgres/migrations/tracing/alembic.ini
  • api/ee/docker/Dockerfile.dev
  • api/ee/docker/Dockerfile.gh
  • api/oss/databases/postgres/migrations/core/README.md
  • api/oss/databases/postgres/migrations/core/alembic.ini
  • api/oss/databases/postgres/migrations/tracing/README.md
  • api/oss/databases/postgres/migrations/tracing/alembic.ini
  • api/oss/docker/Dockerfile.dev
  • api/oss/docker/Dockerfile.gh
  • api/oss/src/crons/queries.sh
  • api/oss/src/utils/env.py
  • docs/docs/self-host/01-quick-start.mdx
  • docs/docs/self-host/02-configuration.mdx
  • docs/docs/self-host/03-upgrading.mdx
  • hosting/docker-compose/ee/docker-compose.dev.yml
  • hosting/docker-compose/ee/docker-compose.gh.local.yml
  • hosting/docker-compose/ee/docker-compose.gh.yml
  • hosting/docker-compose/ee/env.ee.dev.example
  • hosting/docker-compose/ee/env.ee.gh.example
  • hosting/docker-compose/oss/docker-compose.dev.yml
  • hosting/docker-compose/oss/docker-compose.gh.local.yml
  • hosting/docker-compose/oss/docker-compose.gh.ssl.yml
  • hosting/docker-compose/oss/docker-compose.gh.yml
  • hosting/docker-compose/oss/env.oss.dev.example
  • hosting/docker-compose/oss/env.oss.gh.example
  • hosting/docker-compose/run.sh
  • hosting/helm/agenta-oss/templates/_helpers.tpl
  • hosting/helm/agenta-oss/templates/cron-deployment.yaml
  • hosting/helm/agenta-oss/templates/web-deployment.yaml
  • hosting/railway/oss/alembic/Dockerfile
  • hosting/railway/oss/cron/Dockerfile
  • hosting/railway/oss/scripts/build-and-push-images.sh
  • hosting/railway/oss/scripts/deploy-from-images.sh
  • hosting/railway/oss/web/Dockerfile
  • hosting/railway/oss/web/railway.json
  • hosting/railway/oss/worker-evaluations/Dockerfile
  • hosting/railway/oss/worker-events/Dockerfile
  • hosting/railway/oss/worker-tracing/Dockerfile
  • hosting/railway/oss/worker-webhooks/Dockerfile
  • services/ee/docker/Dockerfile.dev
  • services/ee/docker/Dockerfile.gh
  • services/oss/docker/Dockerfile.dev
  • services/oss/docker/Dockerfile.gh
  • web/ee/docker/Dockerfile.dev
  • web/ee/docker/Dockerfile.gh
  • web/entrypoint.sh
  • web/oss/docker/Dockerfile.dev
  • web/oss/docker/Dockerfile.gh

Comment on lines +123 to +124
| `ALEMBIC_CFG_PATH_CORE` | Core alembic path | `/api/oss/databases/postgres/migrations/core/alembic.ini` |
| `ALEMBIC_CFG_PATH_TRACING` | Tracing alembic path | `/api/oss/databases/postgres/migrations/tracing/alembic.ini` |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Document these Alembic defaults as license-specific.

These paths are correct for OSS, but this page also covers EE and the EE defaults live under /api/ee/.... As written, EE operators will copy the wrong values from the table.

Suggested doc tweak
-| `ALEMBIC_CFG_PATH_CORE` | Core alembic path | `/api/oss/databases/postgres/migrations/core/alembic.ini` |
-| `ALEMBIC_CFG_PATH_TRACING` | Tracing alembic path | `/api/oss/databases/postgres/migrations/tracing/alembic.ini` |
+| `ALEMBIC_CFG_PATH_CORE` | Core alembic path | `oss: /api/oss/databases/postgres/migrations/core/alembic.ini`, `ee: /api/ee/databases/postgres/migrations/core/alembic.ini` |
+| `ALEMBIC_CFG_PATH_TRACING` | Tracing alembic path | `oss: /api/oss/databases/postgres/migrations/tracing/alembic.ini`, `ee: /api/ee/databases/postgres/migrations/tracing/alembic.ini` |
📝 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
| `ALEMBIC_CFG_PATH_CORE` | Core alembic path | `/api/oss/databases/postgres/migrations/core/alembic.ini` |
| `ALEMBIC_CFG_PATH_TRACING` | Tracing alembic path | `/api/oss/databases/postgres/migrations/tracing/alembic.ini` |
| `ALEMBIC_CFG_PATH_CORE` | Core alembic path | `oss: /api/oss/databases/postgres/migrations/core/alembic.ini`, `ee: /api/ee/databases/postgres/migrations/core/alembic.ini` |
| `ALEMBIC_CFG_PATH_TRACING` | Tracing alembic path | `oss: /api/oss/databases/postgres/migrations/tracing/alembic.ini`, `ee: /api/ee/databases/postgres/migrations/tracing/alembic.ini` |

# === EXECUTION ============================================ #
init: true
command: supercronic /app/crontab
command: supercronic /api/crontab
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve cron startup compatibility for pinned EE image tags.

This compose change assumes the pulled API image already writes /api/crontab. Any deployment still pinned to an older AGENTA_API_IMAGE_TAG will break the cron service because those images still generate /app/crontab.

Suggested compatibility fallback
-        command: supercronic /api/crontab
+        command: sh -c "if [ -f /api/crontab ]; then exec supercronic /api/crontab; else exec supercronic /app/crontab; fi"
📝 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
command: supercronic /api/crontab
command: sh -c "if [ -f /api/crontab ]; then exec supercronic /api/crontab; else exec supercronic /app/crontab; fi"

# === EXECUTION ============================================ #
init: true
command: supercronic /app/crontab
command: supercronic /api/crontab
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the GHCR cron command backward-compatible with older API image tags.

This compose file can be upgraded independently from the published image tag. If an operator keeps an older AGENTA_API_IMAGE_TAG, that image still exposes /app/crontab, so the cron service will fail to start after this change.

Suggested compatibility fallback
-        command: supercronic /api/crontab
+        command: sh -c "if [ -f /api/crontab ]; then exec supercronic /api/crontab; else exec supercronic /app/crontab; fi"
📝 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
command: supercronic /api/crontab
command: sh -c "if [ -f /api/crontab ]; then exec supercronic /api/crontab; else exec supercronic /app/crontab; fi"

Comment on lines +312 to 319
echo "Copying local SDK and client into build contexts..."
rm -rf api/sdks services/sdks api/clients services/clients
cp -r sdks api/sdks
cp -r sdks services/sdks
cp -r clients api/clients
cp -r clients services/clients
cleanup_sdk_copies() { rm -rf api/sdks services/sdks api/clients services/clients; }
trap cleanup_sdk_copies EXIT
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Register cleanup trap before staging copies.

If a cp -r fails before Line 319, cleanup is never registered and partial api/{sdks,clients} or services/{sdks,clients} state can be left behind.

Suggested patch
 if [[ "$STAGE" == "gh.local" ]]; then
+    cleanup_sdk_copies() { rm -rf api/sdks services/sdks api/clients services/clients; }
+    trap cleanup_sdk_copies EXIT
+
+    [[ -d sdks ]] || error_exit "Missing directory: sdks"
+    [[ -d clients ]] || error_exit "Missing directory: clients"
+
     echo "Copying local SDK and client into build contexts..."
-    rm -rf api/sdks services/sdks api/clients services/clients
+    cleanup_sdk_copies
     cp -r sdks api/sdks
     cp -r sdks services/sdks
     cp -r clients api/clients
     cp -r clients services/clients
-    cleanup_sdk_copies() { rm -rf api/sdks services/sdks api/clients services/clients; }
-    trap cleanup_sdk_copies EXIT
 fi

@mmabrouk
Copy link
Copy Markdown
Member Author

mmabrouk commented May 4, 2026

Superseded by re-sliced PRs that fix CI failures. See new PR layout for details.

@mmabrouk mmabrouk closed this May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devops documentation Improvements or additions to documentation refactoring A code change that neither fixes a bug nor adds a feature size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant