diff --git a/.changes/unreleased/Features-20230119-141156.yaml b/.changes/unreleased/Features-20230119-141156.yaml new file mode 100644 index 00000000000..dde705b05c5 --- /dev/null +++ b/.changes/unreleased/Features-20230119-141156.yaml @@ -0,0 +1,6 @@ +kind: Features +body: add support for DBT_PROJECT_DIR env var +time: 2023-01-19T14:11:56.638325919+01:00 +custom: + Author: leo-schick + Issue: "6078" diff --git a/core/dbt/cli/params.py b/core/dbt/cli/params.py index 3ad3747e962..73532eb9a70 100644 --- a/core/dbt/cli/params.py +++ b/core/dbt/cli/params.py @@ -219,7 +219,7 @@ project_dir = click.option( "--project-dir", - envvar=None, + envvar="DBT_PROJECT_DIR", help="Which directory to look in for the dbt_project.yml file. Default is the current working directory and its parents.", default=default_project_dir(), type=click.Path(exists=True), diff --git a/core/dbt/config/runtime.py b/core/dbt/config/runtime.py index b0b74b9a222..05cbbff15b5 100644 --- a/core/dbt/config/runtime.py +++ b/core/dbt/config/runtime.py @@ -238,7 +238,7 @@ def collect_project( project_renderer: Optional[DbtProjectYamlRenderer] = None, ) -> Union[Project, PartialProject]: - project_root = args.project_dir if args.project_dir else os.getcwd() + project_root = flags.PROJECT_DIR if flags.PROJECT_DIR else os.getcwd() version_check = bool(flags.VERSION_CHECK) partial = Project.partial_load(project_root, verify_version=version_check) if project_renderer is None: diff --git a/core/dbt/flags.py b/core/dbt/flags.py index b7f8ae95ef2..6535e8d1d7b 100644 --- a/core/dbt/flags.py +++ b/core/dbt/flags.py @@ -47,6 +47,7 @@ CACHE_SELECTED_ONLY = None TARGET_PATH = None LOG_PATH = None +PROJECT_DIR = None _NON_BOOLEAN_FLAGS = [ "LOG_FORMAT", @@ -56,6 +57,7 @@ "TARGET_PATH", "LOG_PATH", "WARN_ERROR_OPTIONS", + "PROJECT_DIR", ] _NON_DBT_ENV_FLAGS = ["DO_NOT_TRACK"] @@ -86,6 +88,7 @@ "CACHE_SELECTED_ONLY": False, "TARGET_PATH": None, "LOG_PATH": None, + "PROJECT_DIR": None, } @@ -137,7 +140,7 @@ def set_from_args(args, user_config): global WRITE_JSON, PARTIAL_PARSE, USE_COLORS, STORE_FAILURES, PROFILES_DIR, DEBUG, LOG_FORMAT global INDIRECT_SELECTION, VERSION_CHECK, FAIL_FAST, SEND_ANONYMOUS_USAGE_STATS global PRINTER_WIDTH, WHICH, LOG_CACHE_EVENTS, QUIET, NO_PRINT, CACHE_SELECTED_ONLY - global TARGET_PATH, LOG_PATH + global TARGET_PATH, LOG_PATH, PROJECT_DIR STRICT_MODE = False # backwards compatibility # cli args without user_config or env var option @@ -168,6 +171,7 @@ def set_from_args(args, user_config): CACHE_SELECTED_ONLY = get_flag_value("CACHE_SELECTED_ONLY", args, user_config) TARGET_PATH = get_flag_value("TARGET_PATH", args, user_config) LOG_PATH = get_flag_value("LOG_PATH", args, user_config) + PROJECT_DIR = get_flag_value("PROJECT_DIR", args, user_config) _set_overrides_from_env() @@ -267,6 +271,7 @@ def get_flag_dict(): "cache_selected_only": CACHE_SELECTED_ONLY, "target_path": TARGET_PATH, "log_path": LOG_PATH, + "project_dir": PROJECT_DIR, } diff --git a/core/dbt/task/base.py b/core/dbt/task/base.py index 63449de10c7..399d30256d5 100644 --- a/core/dbt/task/base.py +++ b/core/dbt/task/base.py @@ -119,10 +119,10 @@ def interpret_results(self, results): def get_nearest_project_dir(args): # If the user provides an explicit project directory, use that # but don't look at parent directories. - if args.project_dir: - project_file = os.path.join(args.project_dir, "dbt_project.yml") + if flags.PROJECT_DIR: + project_file = os.path.join(flags.PROJECT_DIR, "dbt_project.yml") if os.path.exists(project_file): - return args.project_dir + return flags.PROJECT_DIR else: raise dbt.exceptions.DbtRuntimeError( "fatal: Invalid --project-dir flag. Not a dbt project. " diff --git a/core/dbt/task/debug.py b/core/dbt/task/debug.py index 5f3e3854759..014265b9d8e 100644 --- a/core/dbt/task/debug.py +++ b/core/dbt/task/debug.py @@ -66,8 +66,8 @@ def __init__(self, args, config): except dbt.exceptions.Exception: # we probably couldn't find a project directory. Set project dir # to whatever was given, or default to the current directory. - if args.project_dir: - self.project_dir = args.project_dir + if flags.PROJECT_DIR: + self.project_dir = flags.PROJECT_DIR else: self.project_dir = os.getcwd() self.project_path = os.path.join(self.project_dir, "dbt_project.yml") diff --git a/test/unit/test_flags.py b/test/unit/test_flags.py index 6f03ec22e92..0f20df28d40 100644 --- a/test/unit/test_flags.py +++ b/test/unit/test_flags.py @@ -280,6 +280,19 @@ def test__flags(self): os.environ.pop('DBT_LOG_PATH') delattr(self.args, 'log_path') + # project_dir + flags.set_from_args(self.args, self.user_config) + self.assertIsNone(flags.PROJECT_DIR) + os.environ['DBT_PROJECT_DIR'] = 'a/b/c' + flags.set_from_args(self.args, self.user_config) + self.assertEqual(flags.PROJECT_DIR, 'a/b/c') + setattr(self.args, 'project_dir', 'd/e/f') + flags.set_from_args(self.args, self.user_config) + self.assertEqual(flags.PROJECT_DIR, 'd/e/f') + # cleanup + os.environ.pop('DBT_PROJECT_DIR') + delattr(self.args, 'project_dir') + def test__flags_are_mutually_exclusive(self): # options from user config self.user_config.warn_error = False