Skip to content

Conversation

@ahmedxgouda
Copy link
Collaborator

Proposed change

Resolves #2422

Add the PR description here.

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.

@github-actions github-actions bot added backend docker Pull requests that update Docker code makefile labels Oct 15, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 15, 2025

Warning

Rate limit exceeded

@arkid15r has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 58 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d3e48dd and fc9f270.

📒 Files selected for processing (1)
  • .github/workflows/setup-e2e-environment/action.yaml (1 hunks)

Summary by CodeRabbit

  • Documentation

    • Added E2E testing setup instructions to contributor guide with one-time configuration steps.
    • Updated test coverage requirements to include frontend considerations.
  • Chores

    • Established E2E testing infrastructure with Docker Compose configuration and GitHub Actions workflow.
    • Added example environment files for E2E deployment.
    • Increased web server startup timeout for E2E tests.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds an end-to-end testing setup: new Makefile e2e targets, a docker-compose e2e stack and env examples, a composite GitHub Action to prepare the e2e environment, CI workflow updates to include Postgres and a setup step, and small Dockerfile/compose entrypoint adjustments plus settings and utils changes to support E2E mode.

Changes

Cohort / File(s) Summary
Makefile e2e targets
backend/Makefile
Added exec-backend-command-e2e, exec-db-command-e2e, dump-data-e2e, load-data-e2e, run-backend-e2e.
CI workflows
.github/workflows/run-ci-cd.yaml
Added db service (pgvector/pgvector:pg16) with env and healthcheck; inserted Setup E2E environment step in E2E jobs.
Composite GitHub Action
.github/workflows/setup-e2e-environment/action.yaml
New composite action to wait for Postgres, install psql, load gzipped SQL, build backend e2e image, run backend container, and poll readiness.
E2E compose stack
docker-compose/e2e.yaml
New compose file defining backend, db, and frontend services with builds, commands, env files, healthchecks, network, and DB volume.
Backend Dockerfile
backend/docker/Dockerfile
Removed the container startup CMD (entrypoint script) directive.
Compose entrypoint tweaks
docker-compose/production.yaml, docker-compose/staging.yaml
Added entrypoint: /home/owasp/entrypoint.sh to backend services.
Frontend Makefile
frontend/Makefile
Reworked test-frontend-e2e to use docker-compose/e2e.yaml up (project name, --build, --abort-on-container-exit) instead of manual docker build/run.
E2E env examples
backend/.env.e2e.example, frontend/.env.e2e.example
Added example e2e environment files with placeholders for required variables.
Playwright timeout
frontend/playwright.config.ts
Increased webServer.timeout from 120000 to 300000.
Docs / Gitignore
CONTRIBUTING.md, .gitignore
Added "Setting Up e2e Testing Environment" docs, updated coverage guidance, and unignored .env.e2e.example.
Backend settings & utils
backend/settings/base.py, backend/settings/e2e.py, backend/apps/common/utils.py
Added IS_E2E_ENVIRONMENT flag, new E2E settings class (including PUBLIC_IP_ADDRESS), and updated get_user_ip_address to treat E2E like local for PUBLIC_IP resolution.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • .github/workflows/setup-e2e-environment/action.yaml — secret/env usage, docker run flags, and network assumptions.
    • docker-compose/e2e.yaml — healthcheck timings, service dependency ordering, and port/volume mappings.
    • backend/docker/Dockerfile vs docker-compose/production.yaml and staging.yaml entrypoints — confirm startup semantics.
    • backend/apps/common/utils.py and new IS_E2E_ENVIRONMENT — verify PUBLIC_IP behavior is intended.

Possibly related PRs

Suggested labels

docker, frontend-tests

Suggested reviewers

  • kasya

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Establish an e2e backend instance locally and in CI/CD' clearly summarizes the main change—setting up e2e backend infrastructure for both local and CI/CD environments, which matches the changeset's additions of Makefiles, Docker Compose configs, and environment setup files.
Description check ✅ Passed The description references issue #2422 which concerns establishing a real Django backend test instance for e2e and fuzzing tests, directly relating to the changeset's e2e backend infrastructure additions.
Linked Issues check ✅ Passed The PR implements all primary requirements from issue #2422: provides a real backend instance via Docker Compose, ensures consistent setup across local and CI/CD environments, includes isolated test data (nest-e2e.sql.gz), adds documentation to CONTRIBUTING.md, and enables developers and CI/CD to launch and use the backend.
Out of Scope Changes check ✅ Passed All changes are within scope: Makefiles/Docker Compose/configs for e2e backend setup, GitHub Actions workflow updates for CI/CD integration, environment files, and documentation—all directly supporting the objective to establish an e2e backend instance.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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
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: 6

🧹 Nitpick comments (7)
docker-compose/backend.e2e.yaml (4)

16-22: Set DJANGO_SETTINGS_MODULE default for e2e.

Make the e2e stack independent of dev/prod .env.

     environment:
+      DJANGO_SETTINGS_MODULE: ${DJANGO_SETTINGS_MODULE:-settings.e2e}
       DJANGO_DB_HOST: ${DJANGO_DB_HOST:-db}
       DJANGO_DB_NAME: ${DJANGO_DB_NAME:-nest_db_e2e}
       DJANGO_DB_PASSWORD: ${DJANGO_DB_PASSWORD:-nest_user_e2e_password}
       DJANGO_DB_PORT: ${DJANGO_DB_PORT:-5432}
       DJANGO_DB_USER: ${DJANGO_DB_USER:-nest_user_e2e}

22-25: Add a backend healthcheck to enable compose --wait and reliable test gating.

Without a healthcheck, CI can race the server startup.

     ports:
       - 8000:8000
+    healthcheck:
+      test: ["CMD-SHELL", "python -c 'import socket,time,sys; \
+for _ in range(30): \
+  try: socket.create_connection((\"localhost\",8000),2).close(); sys.exit(0) \
+  except OSError: time.sleep(1) \
+sys.exit(1)'"]
+      interval: 5s
+      timeout: 3s
+      retries: 10
+      start_period: 10s

41-43: E2E DB volume persists across runs; add a clean target to avoid stale state.

Persistent volume improves speed but harms repeatability. Add a Makefile clean target that runs docker compose -p nest-e2e -f docker-compose/backend.e2e.yaml down -v.


17-21: Default DB creds committed (ok for test) — but prefer .env.e2e to avoid spreading defaults.

Low risk, but moving these to an .env.e2e keeps compose cleaner and avoids accidental reuse.

Also applies to: 29-33

backend/docker/Dockerfile.e2e (2)

23-24: Pin Poetry to a version for reproducible builds.

Unpinned Poetry can break builds unexpectedly.

-RUN --mount=type=cache,target=${PIP_CACHE_DIR} \
-    python -m pip install poetry --cache-dir ${PIP_CACHE_DIR}
+RUN --mount=type=cache,target=${PIP_CACHE_DIR} \
+    python -m pip install 'poetry==1.8.3' --cache-dir ${PIP_CACHE_DIR}

31-32: Install only runtime deps for a slimmer image.

If dev deps exist, prefer: poetry install --no-root --only main.

-    poetry install --no-root
+    poetry install --no-root --only main
backend/Makefile (1)

14-20: Add a clean target for the e2e stack (containers + volume).

Ensures repeatable runs and easy teardown.

 clean-backend-docker:
 	@docker container rm -f nest-backend >/dev/null 2>&1 || true
 	@docker container rm -f nest-cache >/dev/null 2>&1 || true
 	@docker container rm -f nest-db >/dev/null 2>&1 || true
 	@docker image rm -f nest-local-backend >/dev/null 2>&1 || true
 	@docker volume rm -f nest-local_backend-venv >/dev/null 2>&1 || true
+
+clean-backend-e2e-docker:
+	@docker compose --project-name nest-e2e -f docker-compose/backend.e2e.yaml down -v
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64074be and 4002a19.

⛔ Files ignored due to path filters (1)
  • backend/data/nest-e2e-data.sql.gz is excluded by !**/*.gz
📒 Files selected for processing (3)
  • backend/Makefile (4 hunks)
  • backend/docker/Dockerfile.e2e (1 hunks)
  • docker-compose/backend.e2e.yaml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (2)
backend/Makefile (1)

84-87: load-data-e2e is fine as long as backend is healthy.

No changes needed; verify it follows run-backend-e2e in CI to avoid races.

backend/docker/Dockerfile.e2e (1)

1-1: Ensure registry mirror sync and BuildKit enabled

  • python:3.13.7-alpine exists on Docker Hub—verify your mirror has this tag
  • CI environment didn’t expose BuildKit variables—enable BuildKit (DOCKER_BUILDKIT=1) for RUN --mount support

@github-actions github-actions bot added ci and removed docker Pull requests that update Docker code labels Oct 18, 2025
Copy link
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

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4002a19 and 58507cc.

📒 Files selected for processing (5)
  • .github/workflows/run-ci-cd.yaml (1 hunks)
  • backend/docker/Dockerfile (0 hunks)
  • docker-compose/backend.e2e.yaml (1 hunks)
  • docker-compose/production.yaml (1 hunks)
  • docker-compose/staging.yaml (1 hunks)
💤 Files with no reviewable changes (1)
  • backend/docker/Dockerfile
🚧 Files skipped from review as they are similar to previous changes (1)
  • docker-compose/backend.e2e.yaml
🧰 Additional context used
🪛 actionlint (1.7.8)
.github/workflows/run-ci-cd.yaml

188-188: unexpected key "environment" for "services" section. expected one of "credentials", "env", "image", "options", "ports", "volumes"

(syntax-check)

🔇 Additional comments (3)
docker-compose/production.yaml (1)

4-4: LGTM — verify entrypoint script exists in the backend image.

The explicit entrypoint aligns with the backend Dockerfile changes and provides consistent startup across environments.

Confirm that /home/owasp/entrypoint.sh is present in the backend Docker image (backend/docker/Dockerfile context).

docker-compose/staging.yaml (1)

4-4: LGTM — mirrors production entrypoint.

Consistent with production.yaml and backend Dockerfile updates.

.github/workflows/run-ci-cd.yaml (1)

233-238: The e2e test data file is properly committed and available.

The file backend/data/nest-e2e-data.sql.gz is tracked in git (commit 4002a19) and present on the PR branch. The workflow will successfully access it during execution. No action needed.

Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

It looks like the approach is nearly right -- we should create a PG instance for jobs we want to use it in, e.g. fuzzing and e2e testing jobs. Let's discuss it in Slack.

@github-actions github-actions bot added docs Improvements or additions to documentation frontend labels Oct 27, 2025
@ahmedxgouda ahmedxgouda marked this pull request as ready for review October 27, 2025 08:08
@ahmedxgouda ahmedxgouda requested a review from kasya as a code owner October 27, 2025 08:08
@ahmedxgouda ahmedxgouda requested a review from arkid15r October 27, 2025 08:08
@arkid15r arkid15r changed the base branch from main to feature/e2e-backend October 30, 2025 18:22
Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

Great start, let's shape it further 🚀

Copy link
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

♻️ Duplicate comments (3)
.github/workflows/setup-e2e-environment/action.yaml (2)

9-9: Critical: Hardcoded database credentials must be parameterized.

Database credentials (username, database name) are hardcoded in the pg_isready command. These should be accepted as action inputs to allow flexibility and avoid embedding credentials in source control.

Based on prior unresolved feedback, add action inputs:

+inputs:
+  db-user:
+    description: 'PostgreSQL user for e2e environment'
+    required: false
+    default: 'nest_user_e2e'
+  db-name:
+    description: 'PostgreSQL database name for e2e environment'
+    required: false
+    default: 'nest_db_e2e'
+  db-password:
+    description: 'PostgreSQL password (use GitHub secret)'
+    required: true
+
 runs:
   using: 'composite'
   steps:
     - name: Wait for database to be ready
       run: |
-        until docker exec ${{ job.services.db.id }} pg_isready -U nest_user_e2e -d nest_db_e2e; do
+        until docker exec ${{ job.services.db.id }} pg_isready -U ${{ inputs.db-user }} -d ${{ inputs.db-name }}; do

19-24: Critical: Remove hardcoded database password.

Line 21 embeds the database password nest_user_e2e_password in source control. This is a security vulnerability—passwords must never be committed to a repository, even for testing.

Use the db-password input from the previous suggestion:

      - name: Load Postgres data
        env:
-         PGPASSWORD: nest_user_e2e_password
+         PGPASSWORD: ${{ inputs.db-password }}
        run: |
-         gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U nest_user_e2e -d nest_db_e2e
+         gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U ${{ inputs.db-user }} -d ${{ inputs.db-name }}

Then update the calling workflow to pass the secret:

- name: Setup E2E environment
  uses: ./.github/workflows/setup-e2e-environment
  with:
    db-user: nest_user_e2e
    db-name: nest_db_e2e
    db-password: ${{ secrets.NEST_E2E_DB_PASSWORD }}

Ensure NEST_E2E_DB_PASSWORD is added to GitHub repository secrets.

backend/Makefile (1)

64-66: Critical: Shell redirection in CMD variable will not execute correctly.

The pipeline with | and > in the CMD variable will not be interpreted properly by Make. The redirection occurs inside the container's context, and the shell metacharacters may not expand as expected. The exec-db-e2e-command target passes CMD to docker exec, but the redirection should happen on the host side.

Run the dump pipeline from the host:

 dump-data-e2e:
 	@echo "Dumping Nest e2e data"
-	@CMD="pg_dumpall -U nest_user_e2e --clean | gzip -9 > backend/data/nest-e2e.sql.gz" $(MAKE) exec-db-e2e-command
+	@mkdir -p backend/data
+	@docker exec -i nest-db-e2e pg_dumpall -U nest_user_e2e --clean | gzip -9 > backend/data/nest-e2e.sql.gz

Note: Removed -t to avoid TTY artifacts in the dump, and removed -h to use the local socket.

🧹 Nitpick comments (2)
.github/workflows/setup-e2e-environment/action.yaml (2)

39-50: Backend startup mixes env file with explicit overrides.

Line 42 loads backend/.env.e2e.example but line 44 explicitly overrides DJANGO_DB_HOST=localhost. If the env file already contains the correct values, the explicit override is redundant. If different values are needed, consider accepting them as action inputs for flexibility.

Consider accepting database connection parameters as inputs and removing the hardcoded override, or document why DJANGO_DB_HOST must be overridden despite using an env file.


52-59: Use curl instead of wget for consistency.

Based on previous feedback noting "wget/curl inconsistent usage", consider standardizing on one tool. The codebase may prefer curl for HTTP checks.

       - name: Waiting for the backend to be ready
         run: |
-          until wget --spider http://localhost:8000/a; do
+          until curl -f -s http://localhost:8000/a > /dev/null; do
             echo "Waiting for backend..."
             sleep 3
           done
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f43728e and 70562bf.

📒 Files selected for processing (9)
  • .github/workflows/setup-e2e-environment/action.yaml (1 hunks)
  • .gitignore (1 hunks)
  • backend/.env.e2e.example (1 hunks)
  • backend/Makefile (4 hunks)
  • backend/apps/common/utils.py (1 hunks)
  • backend/settings/base.py (1 hunks)
  • backend/settings/e2e.py (1 hunks)
  • docker-compose/e2e.yaml (1 hunks)
  • frontend/.env.e2e.example (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docker-compose/e2e.yaml
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 2429
File: backend/Makefile:30-32
Timestamp: 2025-10-26T12:50:50.512Z
Learning: The `exec-backend-e2e-command` and `exec-db-e2e-command` Makefile targets in the backend/Makefile are intended for local development and debugging only, not for CI/CD execution, so the `-it` flags are appropriate.
📚 Learning: 2025-10-26T12:50:50.512Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 2429
File: backend/Makefile:30-32
Timestamp: 2025-10-26T12:50:50.512Z
Learning: The `exec-backend-e2e-command` and `exec-db-e2e-command` Makefile targets in the backend/Makefile are intended for local development and debugging only, not for CI/CD execution, so the `-it` flags are appropriate.

Applied to files:

  • backend/Makefile
🧬 Code graph analysis (1)
backend/settings/e2e.py (1)
backend/settings/base.py (1)
  • Base (9-213)
🪛 actionlint (1.7.8)
.github/workflows/setup-e2e-environment/action.yaml

1-1: "on" section is missing in workflow

(syntax-check)


1-1: "jobs" section is missing in workflow

(syntax-check)


2-2: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)


4-4: unexpected key "runs" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

🪛 dotenv-linter (4.0.0)
frontend/.env.e2e.example

[warning] 15-15: [UnorderedKey] The NEXTAUTH_SECRET key should go before the NEXT_PUBLIC_API_URL key

(UnorderedKey)


[warning] 16-16: [UnorderedKey] The NEXTAUTH_URL key should go before the NEXT_PUBLIC_API_URL key

(UnorderedKey)

backend/.env.e2e.example

[warning] 8-8: [UnorderedKey] The DJANGO_CONFIGURATION key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 9-9: [UnorderedKey] The DJANGO_DB_HOST key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 10-10: [UnorderedKey] The DJANGO_DB_NAME key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 11-11: [UnorderedKey] The DJANGO_DB_USER key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 12-12: [UnorderedKey] The DJANGO_DB_PASSWORD key should go before the DJANGO_DB_USER key

(UnorderedKey)


[warning] 13-13: [UnorderedKey] The DJANGO_DB_PORT key should go before the DJANGO_DB_USER key

(UnorderedKey)


[warning] 14-14: [UnorderedKey] The DJANGO_OPEN_AI_SECRET_KEY key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 15-15: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 15-15: [UnorderedKey] The DJANGO_PUBLIC_IP_ADDRESS key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 16-16: [UnorderedKey] The DJANGO_REDIS_HOST key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 17-17: [UnorderedKey] The DJANGO_REDIS_PASSWORD key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 18-18: [UnorderedKey] The DJANGO_RELEASE_VERSION key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 19-19: [UnorderedKey] The DJANGO_SECRET_KEY key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)


[warning] 20-20: [UnorderedKey] The DJANGO_SENTRY_DSN key should go before the DJANGO_SETTINGS_MODULE key

(UnorderedKey)

🔇 Additional comments (6)
.gitignore (1)

9-9: LGTM!

The change correctly unignores .env.e2e.example files, following the same pattern as the existing .env.example unignore rule on line 8.

frontend/.env.e2e.example (1)

1-16: LGTM!

The e2e example environment file is well-structured with appropriate placeholder values for local testing. The localhost URLs and placeholder secrets are suitable for an example file that developers will copy and customize.

backend/settings/base.py (1)

22-22: LGTM!

The new IS_E2E_ENVIRONMENT flag follows the established pattern of other environment indicators (lines 23-26) and provides a clean way to detect e2e testing contexts throughout the application.

backend/Makefile (1)

116-118: Running in foreground may block in CI contexts.

The docker compose up command runs in the foreground with --abort-on-container-exit. While suitable for local development (where blocking is expected), this would block CI pipelines if this target is ever used in automation.

Verify whether this target will be invoked by CI/CD pipelines. If yes, consider adding a detached variant:

run-backend-e2e-detached:
	@DOCKER_BUILDKIT=1 \
	docker compose --project-name nest-e2e -f docker-compose/e2e.yaml up -d --build --wait --remove-orphans backend db

If this target is strictly for local development, document that in a comment.

backend/apps/common/utils.py (1)

98-98: LGTM!

The updated logic correctly treats e2e environments like local environments for IP address resolution. In both cases, returning PUBLIC_IP_ADDRESS is appropriate since the request context won't have production-like forwarding headers.

backend/settings/e2e.py (1)

1-23: LGTM with observation: Consider whether disabling all logging is intentional.

The E2E configuration is well-structured and correctly sets IS_E2E_ENVIRONMENT = True (line 21) and DEBUG = False (line 20) for production-like testing. The CORS and CSRF origins appropriately cover both Docker service names and localhost URLs.

However, line 22 sets LOGGING = {}, which completely disables the logging configuration inherited from Base (Base.LOGGING includes console handler and django logger). This may make debugging e2e test failures more difficult.

Verify whether completely disabling logging is intentional for e2e tests. If test output needs to remain clean, consider setting log levels to WARNING/ERROR rather than removing all logging configuration:

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {
        "console": {
            "level": "WARNING",
            "class": "logging.StreamHandler",
        },
    },
    "loggers": {
        "django": {
            "handlers": ["console"],
            "level": "WARNING",
        },
    },
}

Copy link
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: 0

🧹 Nitpick comments (1)
frontend/.env.e2e.example (1)

1-16: Consider adding inline comments or a header explaining the e2e environment setup.

This example file would benefit from a brief comment block explaining its purpose and which variables are critical for the e2e tests to function. This aligns with the PR objective to "provide documentation explaining how to use the new test environment."

Example header:

+# E2E Testing Environment Configuration
+# This file defines environment variables for end-to-end and integration tests.
+# Copy this file to .env.e2e and update placeholders (GitHub OAuth, NEXTAUTH_SECRET).
+# Backend must be running on port 8001 for tests to work.
+
 NEXT_PUBLIC_API_URL=http://localhost:8001/
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 70562bf and 55f717f.

📒 Files selected for processing (5)
  • CONTRIBUTING.md (1 hunks)
  • backend/Makefile (4 hunks)
  • backend/settings/e2e.py (1 hunks)
  • docker-compose/e2e.yaml (1 hunks)
  • frontend/.env.e2e.example (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • backend/Makefile
  • CONTRIBUTING.md
  • docker-compose/e2e.yaml
  • backend/settings/e2e.py
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 2429
File: backend/Makefile:30-32
Timestamp: 2025-10-26T12:50:50.512Z
Learning: The `exec-backend-e2e-command` and `exec-db-e2e-command` Makefile targets in the backend/Makefile are intended for local development and debugging only, not for CI/CD execution, so the `-it` flags are appropriate.
🪛 dotenv-linter (4.0.0)
frontend/.env.e2e.example

[warning] 15-15: [UnorderedKey] The NEXTAUTH_SECRET key should go before the NEXT_PUBLIC_API_URL key

(UnorderedKey)


[warning] 16-16: [UnorderedKey] The NEXTAUTH_URL key should go before the NEXT_PUBLIC_API_URL key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (2)
frontend/.env.e2e.example (2)

3-3: Verify the environment label for e2e tests.

NEXT_PUBLIC_ENVIRONMENT=local may be semantically misleading for e2e testing context. Consider whether this should be set to "e2e" to clearly distinguish end-to-end test runs from local development, which could be important for conditional logic or analytics/monitoring.


1-4: Port and environment configuration verified as correct.

All backend endpoints in frontend/.env.e2e.example correctly target http://localhost:8001, which aligns with the docker-compose e2e setup (docker-compose/e2e.yaml port mapping 8001:8000). The NEXT_PUBLIC_ENVIRONMENT=local setting is intentionally configured for e2e tests, as confirmed by the Makefile and its usage in next.config.ts.

@ahmedxgouda ahmedxgouda requested a review from arkid15r November 1, 2025 10:50
Copy link
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: 2

♻️ Duplicate comments (2)
.github/workflows/setup-e2e-environment/action.yaml (2)

8-13: Parameterize hardcoded database credentials.

The database username and database name remain hardcoded in the readiness check. This issue was flagged in previous reviews but remains unresolved. Add action inputs for these values:

+inputs:
+  db-user:
+    description: 'PostgreSQL user for E2E environment'
+    required: false
+    default: 'nest_user_e2e'
+  db-name:
+    description: 'PostgreSQL database name for E2E environment'
+    required: false
+    default: 'nest_db_e2e'
+  db-password:
+    description: 'PostgreSQL password (use GitHub secret)'
+    required: true
+
 runs:
   using: 'composite'
   steps:
     - name: Wait for database to be ready
       run: |
-        until docker exec ${{ job.services.db.id }} pg_isready -U nest_user_e2e -d nest_db_e2e; do
+        until docker exec ${{ job.services.db.id }} pg_isready -U ${{ inputs.db-user }} -d ${{ inputs.db-name }}; do

18-22: Critical: Remove hardcoded database password from source control.

Line 20 contains a hardcoded password (nest_user_e2e_password) committed to the repository. This is a security vulnerability regardless of whether it's for testing purposes. Credentials must never be stored in source code.

This critical issue was flagged in multiple previous review comments but remains unresolved.

+inputs:
+  db-password:
+    description: 'PostgreSQL password (pass via GitHub secret)'
+    required: true

     - name: Load Postgres data
       env:
-        PGPASSWORD: nest_user_e2e_password
+        PGPASSWORD: ${{ inputs.db-password }}
       run: |
-        gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U nest_user_e2e -d nest_db_e2e
+        gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U ${{ inputs.db-user }} -d ${{ inputs.db-name }}

Update the caller workflow to pass the secret:

- name: Setup E2E environment
  uses: ./.github/workflows/setup-e2e-environment
  with:
    db-user: nest_user_e2e
    db-name: nest_db_e2e
    db-password: ${{ secrets.NEST_E2E_DB_PASSWORD }}

Ensure NEST_E2E_DB_PASSWORD is added to GitHub repository secrets.

🧹 Nitpick comments (2)
frontend/.env.e2e.example (1)

3-3: Consider using "e2e" for the environment identifier.

The NEXT_PUBLIC_ENVIRONMENT is set to "local", which might be confusing in an E2E-specific configuration file. If the E2E environment is distinct from local development, consider changing this to:

-NEXT_PUBLIC_ENVIRONMENT=local
+NEXT_PUBLIC_ENVIRONMENT=e2e

This would provide clearer distinction between local development and E2E testing environments in logs, analytics, and feature flags.

.github/workflows/setup-e2e-environment/action.yaml (1)

48-53: Consider using curl for consistency.

As noted in a previous review comment, there's inconsistent usage of wget and curl across workflows. For better consistency and simpler syntax, consider using curl:

      - name: Waiting for the backend to be ready
        run: |
-          until wget --spider http://localhost:9000/a/; do
+          until curl -f -s http://localhost:9000/a/ > /dev/null; do
            echo "Waiting for backend..."
            sleep 3
          done
          echo "Backend is up!"

The -f flag makes curl return an error on HTTP errors, and -s suppresses progress output.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55f717f and 6de7222.

📒 Files selected for processing (12)
  • .github/workflows/run-ci-cd.yaml (1 hunks)
  • .github/workflows/setup-e2e-environment/action.yaml (1 hunks)
  • .gitignore (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • backend/Makefile (4 hunks)
  • backend/apps/common/utils.py (1 hunks)
  • backend/docker/Dockerfile (0 hunks)
  • backend/settings/base.py (1 hunks)
  • docker-compose/e2e.yaml (1 hunks)
  • docker-compose/production.yaml (1 hunks)
  • docker-compose/staging.yaml (1 hunks)
  • frontend/.env.e2e.example (1 hunks)
💤 Files with no reviewable changes (1)
  • backend/docker/Dockerfile
🚧 Files skipped from review as they are similar to previous changes (7)
  • .gitignore
  • backend/apps/common/utils.py
  • docker-compose/e2e.yaml
  • CONTRIBUTING.md
  • .github/workflows/run-ci-cd.yaml
  • docker-compose/staging.yaml
  • backend/Makefile
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 2429
File: backend/Makefile:30-32
Timestamp: 2025-10-26T12:50:50.512Z
Learning: The `exec-backend-e2e-command` and `exec-db-e2e-command` Makefile targets in the backend/Makefile are intended for local development and debugging only, not for CI/CD execution, so the `-it` flags are appropriate.
📚 Learning: 2025-10-17T15:25:55.624Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 2431
File: infrastructure/providers.tf:1-3
Timestamp: 2025-10-17T15:25:55.624Z
Learning: The infrastructure code in the OWASP/Nest repository (infrastructure/ directory) is intended for quick testing purposes only, not for production deployment.

Applied to files:

  • docker-compose/production.yaml
🪛 actionlint (1.7.8)
.github/workflows/setup-e2e-environment/action.yaml

1-1: "on" section is missing in workflow

(syntax-check)


1-1: "jobs" section is missing in workflow

(syntax-check)


3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)


5-5: unexpected key "runs" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

🪛 dotenv-linter (4.0.0)
frontend/.env.e2e.example

[warning] 15-15: [UnorderedKey] The NEXTAUTH_SECRET key should go before the NEXT_PUBLIC_API_URL key

(UnorderedKey)


[warning] 16-16: [UnorderedKey] The NEXTAUTH_URL key should go before the NEXT_PUBLIC_API_URL key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (python)
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (2)
backend/settings/base.py (1)

22-22: LGTM!

The IS_E2E_ENVIRONMENT flag follows the established pattern for environment type indicators and integrates cleanly with the existing configuration structure.

.github/workflows/setup-e2e-environment/action.yaml (1)

24-35: LGTM!

The Docker build configuration properly uses GitHub Actions cache, targets the correct platform, and loads the image for subsequent steps.

services:
production-nest-backend:
container_name: production-nest-backend
entrypoint: /home/owasp/entrypoint.sh
Copy link
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

Verify the entrypoint script exists and is properly configured.

The production service now explicitly calls /home/owasp/entrypoint.sh. Ensure this script:

  • Exists in the Docker image at the specified path
  • Is executable (chmod +x)
  • Properly handles signals for graceful shutdown (especially SIGTERM)
  • Works correctly with the depends_on health checks for cache and database services

Run the following script to verify the entrypoint is present in the backend image:


🏁 Script executed:

#!/bin/bash
# Verify entrypoint script exists in the backend production image
docker run --rm --entrypoint ls owasp/nest:backend-production -la /home/owasp/entrypoint.sh 2>&1 || echo "Entrypoint script not found or image not available locally"

Length of output: 103


🏁 Script executed:

#!/bin/bash
# Search for entrypoint.sh in the repository
fd -t f entrypoint.sh

Length of output: 28


🏁 Script executed:

#!/bin/bash
# Find Dockerfile for the backend service
fd -t f -e Dockerfile | grep -i "backend\|nest" || fd -t f -e Dockerfile

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for references to the entrypoint path in docker-compose and Dockerfiles
rg -n "entrypoint.sh|/home/owasp" --type yaml --type dockerfile

Length of output: 34


🏁 Script executed:

#!/bin/bash
# Examine the entrypoint script content
cat backend/docker/entrypoint.sh

Length of output: 160


🏁 Script executed:

#!/bin/bash
# Find all Dockerfiles (remove type filter to avoid errors)
fd -t f "Dockerfile" -o "Dockerfile.*"

Length of output: 143


🏁 Script executed:

#!/bin/bash
# Look for Docker-related files in backend/docker directory
ls -la backend/docker/ 2>/dev/null || echo "Directory not found"

Length of output: 365


🏁 Script executed:

#!/bin/bash
# Search for COPY and ADD commands that reference entrypoint in any files
rg -n "COPY|ADD" -A 1 -B 1 | grep -A 2 -B 2 "entrypoint\|/home/owasp"

Length of output: 1355


🏁 Script executed:

#!/bin/bash
# View full backend/docker/Dockerfile to understand working directory and path resolution
cat backend/docker/Dockerfile

Length of output: 1731


🏁 Script executed:

#!/bin/bash
# Check if entrypoint.sh is marked executable in git
git ls-files -s backend/docker/entrypoint.sh

Length of output: 78


Add signal handlers to entrypoint script for graceful shutdown in production.

The script exists at /home/owasp/entrypoint.sh and is executable. However, it lacks signal handling for SIGTERM, which is critical for graceful shutdown. The script runs gunicorn directly without exec or trap handlers, meaning container shutdown signals won't propagate to the application.

Location: backend/docker/entrypoint.sh

Fix: Add signal forwarding before gunicorn:

#!/bin/sh
set -e

python manage.py migrate
python manage.py collectstatic --noinput
python manage.py clear_cache

exec gunicorn wsgi:application --bind 0.0.0.0:8000

The exec prefix ensures gunicorn receives signals directly (SIGTERM/SIGINT) from the container orchestrator for clean termination during deployments and restarts.

🤖 Prompt for AI Agents
In docker-compose/production.yaml around line 4 (entrypoint:
/home/owasp/entrypoint.sh) the referenced entrypoint script
backend/docker/entrypoint.sh lacks signal handling and runs gunicorn without
exec so container signals (SIGTERM/SIGINT) won’t reach the process; update the
entrypoint script to run initialization commands as-is but start gunicorn with
exec so it replaces the shell (exec gunicorn ...) and/or add a lightweight trap
for SIGTERM/SIGINT that forwards the signal to the gunicorn PID before exiting
to ensure graceful shutdown and allow the orchestrator to terminate the app
cleanly.

Copy link
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: 2

♻️ Duplicate comments (1)
.github/workflows/setup-e2e-environment/action.yaml (1)

8-14: Major security risk: Hardcoded database credentials in wait loop.

Lines 10 hardcodes the database username (nest_user_e2e) and name (nest_db_e2e). Parameterize these via action inputs for flexibility and to align with secrets management best practices.

Add action inputs for database configuration:

+inputs:
+  db-user:
+    description: 'PostgreSQL user for e2e environment'
+    required: false
+    default: 'nest_user_e2e'
+  db-name:
+    description: 'PostgreSQL database name for e2e environment'
+    required: false
+    default: 'nest_db_e2e'
+
 runs:
   using: composite
   steps:
     - name: Wait for database to be ready
       run: |
-        until docker exec ${{ job.services.db.id }} pg_isready -U nest_user_e2e -d nest_db_e2e; do
+        until docker exec ${{ job.services.db.id }} pg_isready -U ${{ inputs.db-user }} -d ${{ inputs.db-name }}; do
           echo "Waiting for database..."
           sleep 5
         done
       shell: bash

Also update the psql command on line 24 to use these inputs:

       run: |
-        gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U nest_user_e2e -d nest_db_e2e
+        gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U ${{ inputs.db-user }} -d ${{ inputs.db-name }}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6de7222 and d3e48dd.

📒 Files selected for processing (2)
  • .github/workflows/setup-e2e-environment/action.yaml (1 hunks)
  • frontend/playwright.config.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 2429
File: backend/Makefile:30-32
Timestamp: 2025-10-26T12:50:50.512Z
Learning: The `exec-backend-e2e-command` and `exec-db-e2e-command` Makefile targets in the backend/Makefile are intended for local development and debugging only, not for CI/CD execution, so the `-it` flags are appropriate.
📚 Learning: 2025-10-26T12:50:50.512Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 2429
File: backend/Makefile:30-32
Timestamp: 2025-10-26T12:50:50.512Z
Learning: The `exec-backend-e2e-command` and `exec-db-e2e-command` Makefile targets in the backend/Makefile are intended for local development and debugging only, not for CI/CD execution, so the `-it` flags are appropriate.

Applied to files:

  • .github/workflows/setup-e2e-environment/action.yaml
🪛 actionlint (1.7.8)
.github/workflows/setup-e2e-environment/action.yaml

1-1: "on" section is missing in workflow

(syntax-check)


1-1: "jobs" section is missing in workflow

(syntax-check)


3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)


5-5: unexpected key "runs" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
🔇 Additional comments (2)
.github/workflows/setup-e2e-environment/action.yaml (1)

40-50: Verify environment file adequacy for backend startup.

Line 43 loads environment variables from backend/.env.e2e.example, but there is no validation that all required Django settings are present. If the environment file is incomplete or contains invalid values (e.g., DJANGO_DB_HOST=None as noted in prior feedback), the backend container will fail to start or connect to the database.

Please confirm that backend/.env.e2e.example is properly configured with valid database connection parameters and all required Django settings.

frontend/playwright.config.ts (1)

32-36: Confirm that a 5‑minute webServer timeout is actually required

Bumping webServer.timeout to 300_000 ms is valid and will help with slow e2e startup, but it also means CI can hang for up to 5 minutes before failing if the app never comes up. Please confirm that your measured startup times under load/CI justify this much headroom; if not, consider a lower value so failures surface faster.

Comment on lines +20 to +25
- name: Load Postgres data
env:
PGPASSWORD: nest_user_e2e_password
run: |
gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U nest_user_e2e -d nest_db_e2e
shell: bash
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical security risk: Hardcoded database password in source code.

Line 22 embeds the database password nest_user_e2e_password in plaintext. Passwords must never be committed to the repository, even for test environments. Accept the password as a GitHub secret via action input instead.

Define the action input and replace the hardcoded value:

+inputs:
+  db-password:
+    description: 'PostgreSQL password for e2e environment (use GitHub secret)'
+    required: true
+
 runs:
   using: composite
   steps:
      - name: Load Postgres data
        env:
-         PGPASSWORD: nest_user_e2e_password
+         PGPASSWORD: ${{ inputs.db-password }}
        run: |
          gunzip -c backend/data/nest-e2e.sql.gz | psql -h localhost -U nest_user_e2e -d nest_db_e2e

Then update the caller in .github/workflows/run-ci-cd.yaml to pass the secret:

      - name: Setup E2E environment
        uses: ./.github/workflows/setup-e2e-environment
        with:
          db-password: ${{ secrets.NEST_E2E_DB_PASSWORD }}

Ensure NEST_E2E_DB_PASSWORD is configured in GitHub repository secrets.

🤖 Prompt for AI Agents
In .github/workflows/setup-e2e-environment/action.yaml around lines 20-25 the
Postgres password is hardcoded (security risk); change the action to accept a
db-password input and replace the hardcoded env value with the input reference,
then update the caller in .github/workflows/run-ci-cd.yaml to pass the secret
(e.g. db-password: ${{ secrets.NEST_E2E_DB_PASSWORD }}); finally ensure
NEST_E2E_DB_PASSWORD is set in the repository secrets.

@sonarqubecloud
Copy link

@arkid15r arkid15r enabled auto-merge (squash) November 23, 2025 20:33
Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

I'm not sure whether this setup works, as I got Server Error 500 for the :9000 port running locally

networks:
- nest-network
ports:
- 8001:8000
Copy link
Collaborator

Choose a reason for hiding this comment

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

8001 is already taken by docs

Copy link
Collaborator

Choose a reason for hiding this comment

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

How was this dump created and what data is already there?
And more important question -- how are we going to maintain this data and keep it up to date?

3. Load the data into the e2e db with the following command (in another terminal session):

```bash
make load-data-e2e
Copy link
Collaborator

Choose a reason for hiding this comment

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

This approach works for the initial set up. What about the following e2e dump data updates? Is it compact enough to include the data loading as part of e2e test run process?

-f frontend/docker/Dockerfile.e2e.test frontend \
-t nest-test-frontend-e2e
@docker run --env-file frontend/.env.example --rm nest-test-frontend-e2e pnpm run test:e2e
@DOCKER_BUILDKIT=1 NEXT_PUBLIC_ENVIRONMENT=local \
Copy link
Collaborator

Choose a reason for hiding this comment

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

It might be a good time to think about introducing e2e env for the frontend


- name: Waiting for the backend to be ready
run: |
until wget --spider http://localhost:9000/a; do
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems this waits forever (until GH jobs times out). Let's add some reasonable timeout?

@arkid15r arkid15r merged commit 133c89f into OWASP:feature/e2e-backend Nov 23, 2025
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend ci docs Improvements or additions to documentation frontend makefile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add real Django backend test instance for e2e and fuzzing tests

2 participants