11from pathlib import Path
22
33from docker .models .networks import Network
4+ from loguru import logger
45
56from robotics_integration_tests .custom_containers .image_builder import build_image_once
67from robotics_integration_tests .custom_containers .stream_logging_docker_container import (
78 StreamLoggingDockerContainer ,
89)
910from robotics_integration_tests .settings .settings import settings
1011
12+ # Where a local checkout is mounted inside the migrations runner.
13+ _LOCAL_REPO_MOUNT = "/src"
14+
15+
16+ def _with_migrations_source (
17+ container : StreamLoggingDockerContainer ,
18+ source_dir : str ,
19+ project_folder : str ,
20+ setting_name : str ,
21+ ) -> StreamLoggingDockerContainer :
22+ """Take migrations from a local checkout instead of cloning from GitHub.
23+
24+ Mounted read-only; the entrypoint copies it into the container so that nothing
25+ can be written back into the working tree. The copy means uncommitted and
26+ untracked migrations are picked up, which is the reason to use this at all.
27+
28+ Validation is deliberately strict and happens here, before the container
29+ starts: silently falling back to the GitHub clone would leave you believing
30+ you had tested a local migration when you had not.
31+ """
32+ if not source_dir :
33+ return container
34+
35+ resolved : Path = Path (source_dir ).expanduser ().resolve ()
36+ if not resolved .is_dir ():
37+ raise ValueError (
38+ f"{ setting_name } is set to '{ source_dir } ' (resolved to '{ resolved } '), "
39+ "which is not a directory."
40+ )
41+
42+ project_dir : Path = resolved / project_folder
43+ if not list (project_dir .glob ("*.csproj" )):
44+ raise ValueError (
45+ f"{ setting_name } is set to '{ resolved } ', but no .csproj was found in "
46+ f"'{ project_dir } '. Point it at the repository root of the service, not "
47+ "at the project folder."
48+ )
49+
50+ logger .info (f"Using migrations from local checkout: { resolved } " )
51+ return container .with_volume_mapping (
52+ str (resolved ), _LOCAL_REPO_MOUNT , "ro"
53+ ).with_env ("LOCAL_REPO_PATH" , _LOCAL_REPO_MOUNT )
54+
1155
1256def create_migrations_runner_container (
1357 network : Network , postgres_connection_string : str , name : str = "flotilla_migrations" , test_id : str = ""
@@ -30,7 +74,12 @@ def create_migrations_runner_container(
3074 .with_env ("EF_PROJECT_PATH" , settings .BACKEND_PROJECT_FILE_FOLDER )
3175 .with_env ("EF_STARTUP_PATH" , settings .BACKEND_PROJECT_FILE_FOLDER )
3276 )
33- return container
77+ return _with_migrations_source (
78+ container ,
79+ source_dir = settings .FLOTILLA_MIGRATIONS_SOURCE_DIR ,
80+ project_folder = settings .BACKEND_PROJECT_FILE_FOLDER ,
81+ setting_name = "FLOTILLA_MIGRATIONS_SOURCE_DIR" ,
82+ )
3483
3584
3685def create_sara_migrations_runner_container (
@@ -54,4 +103,9 @@ def create_sara_migrations_runner_container(
54103 .with_env ("EF_PROJECT_PATH" , settings .SARA_BACKEND_PROJECT_FILE_FOLDER )
55104 .with_env ("EF_STARTUP_PATH" , settings .SARA_BACKEND_PROJECT_FILE_FOLDER )
56105 )
57- return container
106+ return _with_migrations_source (
107+ container ,
108+ source_dir = settings .SARA_MIGRATIONS_SOURCE_DIR ,
109+ project_folder = settings .SARA_BACKEND_PROJECT_FILE_FOLDER ,
110+ setting_name = "SARA_MIGRATIONS_SOURCE_DIR" ,
111+ )
0 commit comments