From 0e4ccc8f79f8acfcb21657835117b19de9864580 Mon Sep 17 00:00:00 2001 From: Igor Dabrowski Date: Fri, 24 Oct 2025 11:10:43 +0200 Subject: [PATCH 1/3] Add project ID flag support in CLI (issue: #12113) * Introduce --project-id flag to override dbt Cloud project ID * Update main.py to include project_id decorator * Modify requires.py to set project ID in dbt_cloud if provided --- core/dbt/cli/main.py | 1 + core/dbt/cli/params.py | 8 ++++++++ core/dbt/cli/requires.py | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/core/dbt/cli/main.py b/core/dbt/cli/main.py index f45f0e26dcd..d8cf5b121a0 100644 --- a/core/dbt/cli/main.py +++ b/core/dbt/cli/main.py @@ -144,6 +144,7 @@ def global_flags(func): @p.write_json @p.use_fast_test_edges @p.upload_artifacts + @p.project_id @functools.wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) diff --git a/core/dbt/cli/params.py b/core/dbt/cli/params.py index 361af3b1fb5..4f54c550393 100644 --- a/core/dbt/cli/params.py +++ b/core/dbt/cli/params.py @@ -795,3 +795,11 @@ def _version_callback(ctx, _param, value): help="Whether or not to upload the artifacts to the dbt Cloud API", default=False, ) + +project_id = _create_option_and_track_env_var( + "--project-id", + envvar="DBT_PROJECT_ID", + help="Override the dbt Cloud project ID. This value will be set in the dbt-cloud.project-id field of dbt_project.yml", + type=click.INT, + default=None, +) diff --git a/core/dbt/cli/requires.py b/core/dbt/cli/requires.py index 6b722c46773..c107ec43004 100644 --- a/core/dbt/cli/requires.py +++ b/core/dbt/cli/requires.py @@ -290,6 +290,13 @@ def wrapper(*args, **kwargs): project = load_project( flags.PROJECT_DIR, flags.VERSION_CHECK, ctx.obj["profile"], flags.VARS, validate=True ) + + # Override dbt-cloud.project-id if --project-id flag is provided + if hasattr(flags, 'PROJECT_ID') and flags.PROJECT_ID is not None: + if project.dbt_cloud is None: + project.dbt_cloud = {} + project.dbt_cloud['project-id'] = flags.PROJECT_ID + ctx.obj["project"] = project # Plugins From 50e81a71021d795454efaa58145fef29a3807f15 Mon Sep 17 00:00:00 2001 From: Igor Dabrowski Date: Fri, 24 Oct 2025 11:19:11 +0200 Subject: [PATCH 2/3] Add global --project-id flag to features documentation --- .changes/unreleased/Features-20251024-111854.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/unreleased/Features-20251024-111854.yaml diff --git a/.changes/unreleased/Features-20251024-111854.yaml b/.changes/unreleased/Features-20251024-111854.yaml new file mode 100644 index 00000000000..19c491216d6 --- /dev/null +++ b/.changes/unreleased/Features-20251024-111854.yaml @@ -0,0 +1,6 @@ +kind: Features +body: add --project-id global flag +time: 2025-10-24T11:18:54.505598+02:00 +custom: + Author: igor-dabrowski-affirm + Issue: "12113" From 33bd125f94350c5031212aec22af13a6137c18c1 Mon Sep 17 00:00:00 2001 From: Igor Dabrowski Date: Fri, 24 Oct 2025 11:46:04 +0200 Subject: [PATCH 3/3] Add unit tests for --project-id flag in CLI * Implement tests to verify parsing, optionality, and default behavior of the --project-id flag. * Ensure the flag is accessible across various commands and can be set via environment variables. * Confirm that CLI flag takes precedence over environment variable settings. --- tests/unit/cli/test_flags.py | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/unit/cli/test_flags.py b/tests/unit/cli/test_flags.py index 23da304a3d3..cb08d990c41 100644 --- a/tests/unit/cli/test_flags.py +++ b/tests/unit/cli/test_flags.py @@ -398,6 +398,57 @@ def test_set_project_only_flags(self, project_flags, run_context): # sanity check: ensure project_only_flag is not part of the click context assert project_only_flag not in run_context.params + def test_project_id_flag_parsing(self): + """Test that the --project-id flag is properly parsed and accessible.""" + context = self.make_dbt_context("run", ["--project-id", "1234", "run"]) + flags = Flags(context) + + # Check that the flag is accessible + assert hasattr(flags, "PROJECT_ID") + assert flags.PROJECT_ID == 1234 + + def test_project_id_flag_optional(self): + """Test that the --project-id flag is optional and defaults to None.""" + context = self.make_dbt_context("run", ["run"]) + flags = Flags(context) + + # When not provided, should be None + assert hasattr(flags, "PROJECT_ID") + assert flags.PROJECT_ID is None + + def test_project_id_flag_with_different_values(self): + """Test the --project-id flag with different integer values.""" + test_values = [1, 42, 999, 12345] + + for value in test_values: + context = self.make_dbt_context("run", ["--project-id", str(value), "run"]) + flags = Flags(context) + assert flags.PROJECT_ID == value + + def test_project_id_flag_available_on_all_commands(self): + """Test that --project-id flag is available on various commands.""" + commands = ["run", "build", "compile", "test", "seed", "snapshot", "docs", "parse"] + + for command in commands: + context = self.make_dbt_context(command, ["--project-id", "1234", command]) + flags = Flags(context) + assert hasattr(flags, "PROJECT_ID") + assert flags.PROJECT_ID == 1234 + + def test_project_id_flag_environment_variable(self, monkeypatch): + """Test that the --project-id flag can be set via environment variable.""" + monkeypatch.setenv("DBT_PROJECT_ID", "5678") + context = self.make_dbt_context("run", ["run"]) + flags = Flags(context) + assert flags.PROJECT_ID == 5678 + + def test_project_id_flag_cli_overrides_env_var(self, monkeypatch): + """Test that CLI flag overrides environment variable.""" + monkeypatch.setenv("DBT_PROJECT_ID", "5678") + context = self.make_dbt_context("run", ["--project-id", "9999", "run"]) + flags = Flags(context) + assert flags.PROJECT_ID == 9999 # CLI should override env var + def _create_flags_from_dict(self, cmd, d): write_file("", "profiles.yml") result = Flags.from_dict(cmd, d)