Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
b5c57b4
Add dockerfile and compose and update makefile
ahmedxgouda Oct 14, 2025
1e9254b
Dump db-data
ahmedxgouda Oct 15, 2025
69092ce
Reorder makefile
ahmedxgouda Oct 15, 2025
4002a19
Dump db-data
ahmedxgouda Oct 15, 2025
0a05fdf
Remove e2e dockerfile
ahmedxgouda Oct 18, 2025
58507cc
Add CI/CD
ahmedxgouda Oct 18, 2025
36258b5
Merge branch 'main' into feature/e2e-backend
ahmedxgouda Oct 18, 2025
4119c73
Apply rabbit's suggestions
ahmedxgouda Oct 18, 2025
0688a77
Add postgres instead of pgvector
ahmedxgouda Oct 18, 2025
a66029c
Remove needs
ahmedxgouda Oct 18, 2025
9846482
Update envs
ahmedxgouda Oct 18, 2025
f8be096
Fix migrations step
ahmedxgouda Oct 18, 2025
fbac331
Add envs to docker
ahmedxgouda Oct 18, 2025
837c665
Remove migrations step
ahmedxgouda Oct 18, 2025
143ce39
Remove --without test from dockerfile
ahmedxgouda Oct 18, 2025
1a42d21
Copy tests in dockerfile and add needs to gh workflow
ahmedxgouda Oct 18, 2025
f619928
Update dockerfile
ahmedxgouda Oct 26, 2025
93f3180
Merge branch 'main' into feature/e2e-backend
ahmedxgouda Oct 26, 2025
8893db1
Apply suggestion
ahmedxgouda Oct 26, 2025
1e39448
Use the e2e instance in the frontend e2e tests
ahmedxgouda Oct 26, 2025
a659f0a
Update CI/CD
ahmedxgouda Oct 26, 2025
009b32c
Update CI/CD
ahmedxgouda Oct 26, 2025
54f09ee
Update CI/CD
ahmedxgouda Oct 26, 2025
f1b0af0
Update CI/CD
ahmedxgouda Oct 26, 2025
3376a65
Update CI/CD and dockerfile
ahmedxgouda Oct 26, 2025
3f76de1
Update CI/CD
ahmedxgouda Oct 26, 2025
0300e4e
Update CI/CD
ahmedxgouda Oct 26, 2025
89ad0a6
Update CI/CD
ahmedxgouda Oct 26, 2025
ee3055f
Update CI/CD
ahmedxgouda Oct 26, 2025
8c73507
Update CI/CD
ahmedxgouda Oct 26, 2025
e2f1162
Update CI/CD
ahmedxgouda Oct 26, 2025
bf347ef
Update CI/CD
ahmedxgouda Oct 26, 2025
c5909b3
Update CI/CD
ahmedxgouda Oct 26, 2025
fae06b4
Update CI/CD
ahmedxgouda Oct 26, 2025
78cd6c8
Update CI/CD
ahmedxgouda Oct 26, 2025
d054d25
Update CI/CD
ahmedxgouda Oct 26, 2025
dcd91be
Update CI/CD
ahmedxgouda Oct 26, 2025
913ffcb
Update CI/CD
ahmedxgouda Oct 26, 2025
ba9671b
Restore needs for the job
ahmedxgouda Oct 26, 2025
c080a41
Update Makefiles
ahmedxgouda Oct 27, 2025
f43728e
Update docs
ahmedxgouda Oct 27, 2025
14178dd
Merge branch 'feature/upstream-e2e-backend' into feature/e2e-backend
ahmedxgouda Nov 1, 2025
70562bf
Apply suggestions
ahmedxgouda Nov 1, 2025
2e7dd25
Update load-data
ahmedxgouda Nov 1, 2025
61551c3
Skip sonar error
ahmedxgouda Nov 1, 2025
eb0af68
update port numbers
ahmedxgouda Nov 1, 2025
55f717f
Update docs
ahmedxgouda Nov 1, 2025
da0bb58
Merge branch 'feature/e2e-backend' into pr/ahmedxgouda/2429
arkid15r Nov 23, 2025
6de7222
Update code
arkid15r Nov 23, 2025
ff08b13
Add required shell property back
arkid15r Nov 23, 2025
d3e48dd
Bump config.webServer timeout
arkid15r Nov 23, 2025
fc9f270
Update code
arkid15r Nov 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions .github/workflows/run-ci-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,31 @@ jobs:

run-frontend-e2e-tests:
name: Run frontend e2e tests
needs:
- scan-code
- scan-ci-dependencies
runs-on: ubuntu-latest
services:
db:
image: pgvector/pgvector:pg16
env:
POSTGRES_DB: nest_db_e2e
POSTGRES_PASSWORD: nest_user_e2e_password
POSTGRES_USER: nest_user_e2e
options: >-
--health-cmd="pg_isready -U nest_user_e2e -d nest_db_e2e -h localhost -p 5432"
--health-interval=5s
--health-timeout=5s
--health-retries=5
ports:
- 5432:5432
steps:
- name: Check out repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8

- name: Set up Docker buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435

- name: Setup E2E environment
uses: ./.github/workflows/setup-e2e-environment

- name: Build frontend end-to-end testing image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
with:
Expand Down
64 changes: 64 additions & 0 deletions .github/workflows/setup-e2e-environment/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Set up E2E environment
description: "Sets up the environment for end-to-end testing."

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
echo "Waiting for database..."
sleep 5
done
shell: bash

- name: Install PostgreSQL client
run: sudo apt-get install -y postgresql-client
shell: bash

- 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
Comment on lines +20 to +25
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.


- name: Build backend e2e image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
with:
cache-from: |
type=gha
cache-to: |
type=gha,compression=zstd
context: backend
file: backend/docker/Dockerfile
load: true
platforms: linux/amd64
tags: owasp/nest:test-backend-e2e-latest

- name: Start Backend in the background
run: |
docker run --rm --name nest-backend-e2e-runner \
--env-file backend/.env.example \
--network host \
-e DJANGO_SETTINGS_MODULE=settings.test \
-e DJANGO_DB_HOST=localhost \
-e DJANGO_DB_NAME=nest_db_e2e \
-e DJANGO_DB_USER=nest_user_e2e \
-e DJANGO_DB_PASSWORD=nest_user_e2e_password \
-e DJANGO_DB_PORT=5432 \
-p 8000:8000 \
owasp/nest:test-backend-e2e-latest \
sh -c '
python manage.py runserver 0.0.0.0:8000
'
shell: bash

- name: Waiting for the backend to be ready
run: |
until curl -s http://localhost:8000/graphql > /dev/null; do
echo "Waiting for backend..."
sleep 3
done
echo "Backend is up!"
shell: bash
20 changes: 20 additions & 0 deletions backend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@ exec-backend-command:
exec-backend-command-it:
@docker exec -it nest-backend $(CMD) 2>/dev/null

exec-backend-e2e-command:
@docker exec -it nest-backend-e2e $(CMD)


exec-db-command-it:
@docker exec -it nest-db $(CMD)

exec-db-e2e-command:
@docker exec -it nest-db-e2e $(CMD)

clear-cache:
@CMD="python manage.py clear_cache" $(MAKE) exec-backend-command

Expand All @@ -53,13 +60,18 @@ dump-data:
@CMD="sed -E -i 's/\"email\": *\"([^\"]|\\\")*\"/\"email\": \"\"/g' data/nest.json" $(MAKE) exec-backend-command
@CMD="gzip -f data/nest.json" $(MAKE) exec-backend-command

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

enrich-data: \
github-enrich-issues \
owasp-enrich-chapters \
owasp-enrich-committees \
owasp-enrich-events \
owasp-enrich-projects


generate-sitemap:
@CMD="python manage.py generate_sitemap" $(MAKE) exec-backend-command

Expand All @@ -69,6 +81,10 @@ index-data:
@CMD="python manage.py algolia_update_replicas" $(MAKE) exec-backend-command
@CMD="python manage.py algolia_update_synonyms" $(MAKE) exec-backend-command

load-data-e2e:
@echo "Loading Nest e2e data"
@CMD="python manage.py load_data" $(MAKE) exec-backend-e2e-command

load-data:
@echo "Loading Nest data"
@CMD="python manage.py load_data" $(MAKE) exec-backend-command
Expand Down Expand Up @@ -96,6 +112,10 @@ restore-backup:
@echo "Restoring Nest backup"
@CMD="python manage.py restore_backup" $(MAKE) exec-backend-command

run-backend-e2e:
@DOCKER_BUILDKIT=1 \
docker compose --project-name nest-e2e -f docker-compose/e2e.yaml up --build --remove-orphans --abort-on-container-exit

save-backup:
@echo "Saving Nest backup"
@CMD="python manage.py dumpdata --natural-primary --natural-foreign --indent=2" $(MAKE) exec-backend-command > backend/data/backup.json
Expand Down
Binary file added backend/data/nest-e2e.sql.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion backend/docker/Dockerfile
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?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is nest.json.gz file data. I loaded it first then dumped it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe we can add a command to dump the local backend instance

Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ RUN rm -rf /home/owasp/.cache && \

USER owasp

CMD ["/home/owasp/entrypoint.sh"]
EXPOSE 8000
74 changes: 74 additions & 0 deletions docker-compose/e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
services:
backend:
container_name: nest-backend-e2e
command: >
sh -c '
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000
'
build:
context: ../backend
dockerfile: docker/Dockerfile
depends_on:
db:
condition: service_healthy
env_file: ../backend/.env
environment:
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}
networks:
- nest-network
ports:
- 8000:8000
healthcheck:
interval: 10s
retries: 10
test: >
sh -c '
wget --spider http://backend:8000/graphql
'
timeout: 10s
start_period: 10s
db:
container_name: nest-db-e2e
image: pgvector/pgvector:pg16
environment:
POSTGRES_DB: ${DJANGO_DB_NAME:-nest_db_e2e}
POSTGRES_PASSWORD: ${DJANGO_DB_PASSWORD:-nest_user_e2e_password}
POSTGRES_USER: ${DJANGO_DB_USER:-nest_user_e2e}
healthcheck:
interval: 5s
retries: 5
test: [CMD-SHELL, pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB -h localhost -p 5432]
timeout: 5s
networks:
- nest-network
volumes:
- db-e2e-data:/var/lib/postgresql/data
ports:
- 5433:5432

frontend:
container_name: nest-frontend-e2e
build:
context: ../frontend
dockerfile: docker/Dockerfile.e2e.test
command: >
sh -c '
pnpm run test:e2e
'
depends_on:
backend:
condition: service_healthy
env_file: ../frontend/.env
networks:
- nest-network

volumes:
db-e2e-data:

networks:
nest-network:
1 change: 1 addition & 0 deletions docker-compose/production.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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.

image: owasp/nest:backend-production
env_file: .env.backend
depends_on:
Expand Down
1 change: 1 addition & 0 deletions docker-compose/staging.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
services:
staging-nest-backend:
container_name: staging-nest-backend
entrypoint: /home/owasp/entrypoint.sh
image: owasp/nest:backend-staging
env_file: .env.backend
depends_on:
Expand Down
Loading