-
-
Notifications
You must be signed in to change notification settings - Fork 332
Fix running e2e backend #2710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix running e2e backend #2710
Changes from all commits
cafa25f
fd0aa86
9047b0b
1556873
f506341
c35e43f
a80f661
d2d8a58
a96185f
74bdb6c
9893384
3b4c9e2
f747481
ddae26b
95b1391
4d2e344
fd2219d
3ea8fc7
5e2c36c
d3f9aef
a1570cf
ddc7e32
e1d7272
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,23 +7,18 @@ runs: | |
| 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 | ||
| timeout 5m bash -c ' | ||
| 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 | ||
|
|
||
| - name: Build backend e2e image | ||
| uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 | ||
| with: | ||
|
|
@@ -42,18 +37,29 @@ runs: | |
| docker run -d --rm --name e2e-nest-backend \ | ||
| --env-file backend/.env.e2e.example \ | ||
| --network host \ | ||
| -e DJANGO_DB_HOST=localhost \ | ||
| -p 9000:9000 \ | ||
| owasp/nest:test-backend-e2e-latest \ | ||
| sh -c ' | ||
| python manage.py migrate && | ||
| gunicorn wsgi:application --bind 0.0.0.0:9000 | ||
| ' | ||
| shell: bash | ||
|
|
||
| - name: Waiting for the backend to be ready | ||
| run: | | ||
| until wget --spider http://localhost:9000/a; do | ||
| echo "Waiting for backend..." | ||
| sleep 5 | ||
| done | ||
| timeout 5m bash -c ' | ||
| until wget --spider http://localhost:9000/a; do | ||
| echo "Waiting for backend..." | ||
| sleep 5 | ||
| done | ||
| ' | ||
| echo "Backend is up!" | ||
| shell: bash | ||
|
|
||
| - name: Load Postgres data | ||
| env: | ||
| PGPASSWORD: nest_user_e2e_password | ||
| run: | | ||
| gunzip -c backend/data/nest.sql.gz | psql -h localhost -U nest_user_e2e -d nest_db_e2e | ||
| shell: bash | ||
|
Comment on lines
+60
to
+65
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SQL import: ensure it’s part of the “readiness” contract 🤖 Prompt for AI Agents |
||
ahmedxgouda marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| """Dump masked data from the database into a compressed file.""" | ||
|
|
||
| import contextlib | ||
| import os | ||
| from pathlib import Path | ||
| from subprocess import CalledProcessError, run | ||
|
|
||
| from django.conf import settings | ||
| from django.core.management.base import BaseCommand, CommandError | ||
| from psycopg2 import ProgrammingError, connect, sql | ||
|
|
||
| DEFAULT_DATABASE = settings.DATABASES["default"] | ||
| DB_HOST = DEFAULT_DATABASE.get("HOST", "localhost") | ||
| DB_PORT = str(DEFAULT_DATABASE.get("PORT", "5432")) | ||
| DB_USER = DEFAULT_DATABASE.get("USER", "") | ||
| DB_PASSWORD = DEFAULT_DATABASE.get("PASSWORD", "") | ||
| DB_NAME = DEFAULT_DATABASE.get("NAME", "") | ||
|
|
||
|
|
||
| class Command(BaseCommand): | ||
| help = "Create a dump of selected db tables." | ||
|
|
||
| def add_arguments(self, parser): | ||
| parser.add_argument( | ||
| "--output", | ||
| default=str(Path(settings.BASE_DIR) / "data" / "nest.sql.gz"), | ||
| help="Output dump path (default: data/nest.sql.gz)", | ||
| ) | ||
| parser.add_argument( | ||
| "-t", | ||
| "--table", | ||
| action="append", | ||
| dest="tables", | ||
| default=[ | ||
| "public.owasp_*", | ||
| "public.github_*", | ||
| "public.slack_members", | ||
| "public.slack_workspaces", | ||
| "public.slack_conversations", | ||
| "public.slack_messages", | ||
| ], | ||
| help="Table pattern to include", | ||
| ) | ||
|
|
||
| def handle(self, *args, **options): | ||
| output_path = Path(options["output"]).resolve() | ||
| output_path.parent.mkdir(parents=True, exist_ok=True) | ||
| tables = options["tables"] or [] | ||
|
|
||
| env = os.environ.copy() | ||
| env["PGPASSWORD"] = DB_PASSWORD | ||
|
|
||
| temp_db = f"temp_{DB_NAME}" | ||
| try: | ||
| self._execute_sql("postgres", [f"CREATE DATABASE {temp_db} TEMPLATE {DB_NAME};"]) | ||
|
|
||
| self.stdout.write(self.style.SUCCESS(f"Created temporary DB: {temp_db}")) | ||
|
|
||
| table_list = self._execute_sql(temp_db, [self._table_list_query()]) | ||
| self._execute_sql(temp_db, self._remove_emails([row[0] for row in table_list])) | ||
| self.stdout.write(self.style.SUCCESS("Removed emails from temporary DB")) | ||
|
|
||
| dump_cmd = [ | ||
| "pg_dump", | ||
| "-h", | ||
| DB_HOST, | ||
| "-p", | ||
| DB_PORT, | ||
| "-U", | ||
| DB_USER, | ||
| "-d", | ||
| temp_db, | ||
| "--compress=9", | ||
| "--clean", | ||
| ] | ||
| dump_cmd += [f"--table={table}" for table in tables] | ||
| dump_cmd += ["-f", str(output_path)] | ||
|
|
||
| run(dump_cmd, check=True, env=env) | ||
| self.stdout.write(self.style.SUCCESS(f"Created dump: {output_path}")) | ||
| except CalledProcessError as e: | ||
| message = f"Command failed: {e.cmd}" | ||
| raise CommandError(message) from e | ||
| finally: | ||
| try: | ||
| self._execute_sql("postgres", [f"DROP DATABASE IF EXISTS {temp_db};"]) | ||
| except CalledProcessError: | ||
| self.stderr.write( | ||
| self.style.WARNING(f"Failed to drop temp DB {temp_db} (ignored).") | ||
| ) | ||
|
|
||
| def _table_list_query(self) -> str: | ||
| return """ | ||
| SELECT table_name | ||
| FROM information_schema.columns | ||
| WHERE table_schema = 'public' AND column_name = 'email'; | ||
| """ | ||
|
|
||
| def _remove_emails(self, tables: list[str]) -> list[str]: | ||
| return [ | ||
| sql.SQL("UPDATE {table} SET email = '';").format(table=sql.Identifier(table)) | ||
| for table in tables | ||
| ] | ||
|
|
||
| def _execute_sql( | ||
| self, | ||
| dbname: str, | ||
| sql_queries: list[str], | ||
| ): | ||
| connection = connect( | ||
| dbname=dbname, | ||
| user=DB_USER, | ||
| password=DB_PASSWORD, | ||
| host=DB_HOST, | ||
| port=DB_PORT, | ||
| ) | ||
| connection.autocommit = True | ||
|
|
||
| rows = [] | ||
| with connection.cursor() as cursor: | ||
| for sql_query in sql_queries: | ||
| cursor.execute(sql_query) | ||
| with contextlib.suppress(ProgrammingError): | ||
| rows.extend(cursor.fetchall()) | ||
| connection.close() | ||
|
|
||
| return rows |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add
apt-get updateto reduce CI flakinessOn GitHub-hosted runners,
apt-get installcan intermittently fail without anapt-get updatefirst.📝 Committable suggestion
🤖 Prompt for AI Agents