From a9139884684c68b4b3ab2d1f0464ed80f7ddf8f5 Mon Sep 17 00:00:00 2001 From: Omar Selo Date: Mon, 26 Jun 2023 10:50:37 +0300 Subject: [PATCH] Seed data fix (#32) * Fix seed script * Avoid skaffold rebuild when running ruff * Fix bug and add tests * fix mypy check on CI * Fix previous commit * Rename arguments to be clearer --- .github/workflows/test_backend.yml | 6 ++-- backend/.dockerignore | 1 + backend/scripts/seed_data.py | 11 ++++--- .../test_executions/test_executions.py | 31 ++++++++++++------- .../test_observer/data_access/repository.py | 20 +++++++++--- backend/tests/scripts/test_seed_data.py | 7 +++++ 6 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 backend/tests/scripts/test_seed_data.py diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml index b5a77942..223752b3 100644 --- a/.github/workflows/test_backend.yml +++ b/.github/workflows/test_backend.yml @@ -31,9 +31,9 @@ jobs: with: poetry-version: "1.5.1" - run: poetry install - - run: poetry run black --check test_observer tests migrations - - run: poetry run ruff test_observer tests migrations - - run: poetry run mypy test_observer tests migrations + - run: poetry run black --check test_observer tests migrations scripts + - run: poetry run ruff test_observer tests migrations scripts + - run: poetry run mypy --explicit-package-bases test_observer tests migrations scripts - run: poetry run pytest env: TEST_DB_URL: postgresql+pg8000://postgres:password@localhost:5432/postgres diff --git a/backend/.dockerignore b/backend/.dockerignore index 5b8d1eac..78f486dc 100644 --- a/backend/.dockerignore +++ b/backend/.dockerignore @@ -40,6 +40,7 @@ var/ *.egg .mypy_cache .pytest_cache +.ruff_cache # PyInstaller # Usually these files are written by a python script from a template diff --git a/backend/scripts/seed_data.py b/backend/scripts/seed_data.py index 28da5640..f83f81a0 100644 --- a/backend/scripts/seed_data.py +++ b/backend/scripts/seed_data.py @@ -1,9 +1,10 @@ import requests +from fastapi.testclient import TestClient -from test_observer.controllers.test_execution.models import StartTestExecutionRequest +from test_observer.controllers.test_executions.models import StartTestExecutionRequest BASE_URL = "http://localhost:30000/v1" -START_TEST_EXECUTION_URL = f"{BASE_URL}/test-execution/start" +START_TEST_EXECUTION_URL = f"{BASE_URL}/test-executions/start-test" REQUESTS = [ StartTestExecutionRequest( @@ -97,10 +98,10 @@ ] -def seed_data(): +def seed_data(client: TestClient | requests.Session): for request in REQUESTS: - requests.put(START_TEST_EXECUTION_URL, json=request.dict()) + client.put(START_TEST_EXECUTION_URL, json=request.dict()).raise_for_status() if __name__ == "__main__": - seed_data() + seed_data(requests.Session()) diff --git a/backend/test_observer/controllers/test_executions/test_executions.py b/backend/test_observer/controllers/test_executions/test_executions.py index 4d124ae4..16c7b2d9 100644 --- a/backend/test_observer/controllers/test_executions/test_executions.py +++ b/backend/test_observer/controllers/test_executions/test_executions.py @@ -54,33 +54,40 @@ def start_test_execution( artefact = get_or_create( db, Artefact, - name=request.name, - version=request.version, - source=request.source, - stage_id=stage.id, + filter_kwargs={ + "name": request.name, + "version": request.version, + "source": request.source, + }, + creation_kwargs={"stage_id": stage.id}, ) environment = get_or_create( db, Environment, - name=request.environment, - architecture=request.arch, + filter_kwargs={"name": request.environment, "architecture": request.arch}, ) artefact_build = get_or_create( db, ArtefactBuild, - architecture=request.arch, - revision=request.revision, - artefact_id=artefact.id, + filter_kwargs={ + "architecture": request.arch, + "revision": request.revision, + "artefact_id": artefact.id, + }, ) test_execution = get_or_create( db, TestExecution, - environment_id=environment.id, - artefact_build_id=artefact_build.id, - status=TestExecutionStatus.IN_PROGRESS, + filter_kwargs={ + "environment_id": environment.id, + "artefact_build_id": artefact_build.id, + }, + creation_kwargs={ + "status": TestExecutionStatus.IN_PROGRESS, + }, ) return {"id": test_execution.id} diff --git a/backend/test_observer/data_access/repository.py b/backend/test_observer/data_access/repository.py index d0f0824c..d39e36dd 100644 --- a/backend/test_observer/data_access/repository.py +++ b/backend/test_observer/data_access/repository.py @@ -99,22 +99,34 @@ def get_artefacts_by_family_name( return artefacts -def get_or_create(db: Session, model: type[DataModel], **kwargs) -> DataModel: +def get_or_create( + db: Session, + model: type[DataModel], + filter_kwargs: dict, + creation_kwargs: dict | None = None, +) -> DataModel: """ Creates an object if it doesn't exist, otherwise returns the existing one :db: DB session :model: model to create e.g. Stage, Family, Artefact - :kwargs: keyword arguments to pass to the model + :filter_kwargs: arguments to pass to the model when querying and creating + :creation_kwargs: extra arguments to pass to the model when creating only """ # Try to create first to avoid race conditions - stmt = insert(model).values([kwargs]).on_conflict_do_nothing().returning(model) + creation_kwargs = creation_kwargs or {} + stmt = ( + insert(model) + .values([{**filter_kwargs, **creation_kwargs}]) + .on_conflict_do_nothing() + .returning(model) + ) result = db.execute(stmt).scalar_one_or_none() db.commit() if result is None: # If the object already existed, we need to query it - result = db.query(model).filter_by(**kwargs).one() + result = db.query(model).filter_by(**filter_kwargs).one() return result diff --git a/backend/tests/scripts/test_seed_data.py b/backend/tests/scripts/test_seed_data.py new file mode 100644 index 00000000..e3c6e604 --- /dev/null +++ b/backend/tests/scripts/test_seed_data.py @@ -0,0 +1,7 @@ +from fastapi.testclient import TestClient + +from scripts.seed_data import seed_data + + +def test_seed_data_no_failure(test_client: TestClient): + seed_data(test_client)