Skip to content

Moving away from dbt core operation blocks - #1435

Merged
Ishankoradia merged 9 commits into
mainfrom
feature/prefect-secret-blk
Jul 29, 2026
Merged

Moving away from dbt core operation blocks#1435
Ishankoradia merged 9 commits into
mainfrom
feature/prefect-secret-blk

Conversation

@Ishankoradia

@Ishankoradia Ishankoradia commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
  • Move away from dbt core operation blocks
  • Elementary apis cleanup
  • Ability to run elementary from EKS
  • Prefect runner docker image changes
  • Ability to add edr send report task in a pipeline if elementary is setup for the org
  • Ability to run elementary as a standalone deployment flow to generate its own profiles.yml here. So it cna be run on EKS also.

Commands/scripts to be run in this order

  • backfill_dbt_profile_secret_blocks.py: creates the secret block that will store the dbt profile creds information for an org
  • ensureedrsendreportdataflow.py (renamed) : used to only cretae edr dataflows, now does an upsert (create or update)
  • sync_edr_secret_block.py‎: update the secret block for S3 creds in prefect that is being used to push edr reports. Currently the S3 creds are in 3 separate prefect blocks, consolidate them.
  • patch_edr_deployment_env.py‎: update the current edr dataflows with the new task config so they now read from the dbt profile secret block, generate their own elementary_profiles/profiles.yml and run the report flow.

Summary by CodeRabbit

  • New Features

    • Added a streamlined Elementary setup workflow covering profile creation, dbt installation, and report scheduling.
    • Added Elementary configuration checks with clear “ready” or “needs repository changes” results.
    • Improved Elementary report retrieval to find recent reports from the previous three days.
    • Added support for displaying and running EDR transformation tasks.
    • Added automatic cleanup of Elementary reports and related resources.
  • Bug Fixes

    • Updated dbt profile handling so schema and warehouse credentials stay synchronized across workflows.
    • Standardized setup instructions and execution on dbt-core 1.10.19.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Ishankoradia, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a40f1a8f-ad9f-4396-a637-775aa3074b31

📥 Commits

Reviewing files that changed from the base of the PR and between ec084ec and 95ce579.

📒 Files selected for processing (1)
  • ddpui/migrations/0170_orgdbt_dbt_profile_secret_block.py

Walkthrough

Changes

The PR centralizes dbt profile generation and runner Secret propagation, replaces multiple Elementary endpoints with consolidated check/install flows, expands EDR orchestration and report cleanup, adds deployment migration commands, and standardizes local dbt setup on dbt-core 1.10.19.

DBT profile runtime

Layer / File(s) Summary
Centralized profile generation and propagation
ddpui/core/dbtfunctions.py, ddpui/ddpdbt/dbthelpers.py, ddpui/models/org.py, ddpui/migrations/*
Credentials are normalized into dbt profile outputs, runner Secret blocks are created or updated, and profiles.yml is written centrally.
Runtime integration and validation
ddpui/celeryworkers/tasks.py, ddpui/core/pipelinefunctions.py, ddpui/ddpdbt/dbt_service.py, ddpui/ddpairbyte/airbytehelpers.py, ddpui/tests/*
DBT and Elementary flows use generated profiles and Secret-block environment values, with updated failure propagation and tests.

Elementary and EDR workflow

Layer / File(s) Summary
Consolidated Elementary installation
ddpui/api/dbt_api.py, ddpui/celeryworkers/tasks.py, ddpui/ddpdbt/elementary_service.py, ddpui/tests/*
New check/install endpoints dispatch a step-indexed task that creates profiles, installs dbt packages, and ensures the EDR send-report dataflow.
EDR orchestration and reporting
ddpui/core/orchestrate/*, ddpui/core/pipelinefunctions.py, ddpui/api/orgtask_api.py, ddpui/ddpdbt/elementary_service.py, ddpui/utils/*
EDR tasks are included in transform ordering and responses, runner configuration no longer sets a custom dbt path, and reports are selected from a recent S3 lookback window.

Operational migration and cleanup

Layer / File(s) Summary
Deployment and Secret migrations
ddpui/management/commands/*, ddpui/ddpprefect/prefect_service.py
Commands backfill dbt profile Secrets, patch EDR deployment parameters, consolidate EDR Secrets, and migrate deployment entrypoints.
Resource cleanup
ddpui/services/org_cleanup_service.py, ddpui/utils/s3_utils.py
Transformation cleanup removes EDR tasks, dbt profile Secret blocks, and Elementary report objects from S3.

DBT version standardization

Layer / File(s) Summary
Local setup documentation
README.md, dbt_deps/*
Documentation now specifies dbt-core 1.10.19 with a single virtual environment setup; prior multi-version dependency artifacts and runner-image documentation were removed.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: himanshudube97

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main theme of the PR: replacing dbt core operation blocks with the new Elementary/dbt workflow.
Docstring Coverage ✅ Passed Docstring coverage is 81.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/prefect-secret-blk

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ddpui/services/org_cleanup_service.py (1)

260-290: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Move dbt-profile secret block cleanup to the transformation-layer teardown

delete_org() clears self.org.dbt before delete_warehouse() runs, so this lookup is None in the normal full-org delete path. If delete_warehouse() runs on its own, the same Prefect block can be deleted once per OrgWarehouse. Move this cleanup to delete_transformation_layer() while orgdbt is still available, and run it once.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/services/org_cleanup_service.py` around lines 260 - 290, The
dbt-profile secret block cleanup currently occurs in the per-warehouse delete
flow, after delete_org() may clear self.org.dbt and potentially repeats for each
OrgWarehouse. Remove that cleanup from delete_warehouse() and move it into
delete_transformation_layer(), using the available orgdbt record and executing
it once while preserving the Prefect deletion, error logging, and
OrgPrefectBlockv1 deletion behavior.
🧹 Nitpick comments (4)
ddpui/management/commands/sync_edr_secret_block.py (1)

112-117: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Broad except conflates "not found" with real failures.

Catching bare Exception here treats any failure from get_secret_block_by_name (auth errors, network issues, Prefect outage) the same as "block doesn't exist," printing a benign [skip] ... not present instead of surfacing the real error. Elsewhere in the codebase (e.g. org_cleanup_service.py) not-found lookups catch the specific HttpError rather than a blanket Exception.

♻️ Suggested narrower catch
             try:
                 block = prefect_service.get_secret_block_by_name(legacy_name)
-            except Exception:  # pylint: disable=broad-exception-caught
+            except HttpError:
                 # Block doesn't exist — nothing to delete.
                 self.stdout.write(f"  [skip] {legacy_name}: not present")
                 continue

Please confirm get_secret_block_by_name/prefect_get raises HttpError (vs. some other exception type) on a 404 so the narrower catch doesn't miss the legitimate not-found case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/sync_edr_secret_block.py` around lines 112 - 117,
Replace the broad exception handler around get_secret_block_by_name with the
specific HttpError type used by prefect_get for 404 responses, confirming that
exception type from the client implementation or established
org_cleanup_service.py pattern. Preserve the [skip] behavior only for not-found
errors, while allowing authentication, network, and other failures to propagate.
README.md (1)

146-152: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Sibling-directory assumption is implicit.

The cd ../prefect-proxy/docker/dbt-X.Y.Z/ paths assume prefect-proxy is cloned as a sibling directory to this repo, but Step 5 (which links to the prefect-proxy repo) doesn't say where to clone it relative to this repo. Worth a one-line clarification to avoid confusion for new setups.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 146 - 152, Clarify in Step 5 that the prefect-proxy
repository must be cloned as a sibling directory of the current repository,
matching the relative ../prefect-proxy/docker/dbt-X.Y.Z paths used in the dbt
setup instructions.
ddpui/tests/services/test_elementary_service.py (1)

881-1003: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Tests correctly validate install_elementary's step-wise progress emission and failure short-circuiting logic, but since run_dbt_commands.apply is mocked outright, they don't exercise the actual swallow-and-continue defect in run_dbt_commands flagged in ddpui/celeryworkers/tasks.py (lines 313-376). Consider adding one integration-style test that calls the real run_dbt_commands (with dbt subprocess calls mocked) to confirm install_elementary step 1 actually fails when dbt run fails.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/tests/services/test_elementary_service.py` around lines 881 - 1003, The
current tests mock run_dbt_commands.apply entirely and do not verify its real
failure propagation. Add an integration-style test for install_elementary that
invokes the actual run_dbt_commands implementation while mocking only its dbt
subprocess calls to fail, then assert step 1 emits failed, step 2 is not called,
and the exception propagates.
ddpui/core/pipelinefunctions.py (1)

108-141: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate dbt_profile_secret_block resolution logic across two functions.

setup_dbt_core_task_config and setup_edr_send_report_task_config both introduce the identical pattern of resolving org_task.org.dbt.dbt_profile_secret_block and warning if absent. Consider extracting a small helper, e.g. resolve_dbt_profile_secret_block(org_task) -> str | None, to avoid future drift between the two warning messages/behaviors.

♻️ Suggested helper
def _resolve_dbt_profile_secret_block(org_task: OrgTask, fail_hint: str) -> str | None:
    orgdbt = org_task.org.dbt
    if orgdbt and orgdbt.dbt_profile_secret_block:
        return orgdbt.dbt_profile_secret_block.block_name
    logger.warning(
        "OrgDbt for org=%s has no dbt_profile_secret_block — %s",
        org_task.org.slug,
        fail_hint,
    )
    return None

Also applies to: 220-253

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/core/pipelinefunctions.py` around lines 108 - 141, Extract the shared
dbt profile secret block lookup from setup_dbt_core_task_config and
setup_edr_send_report_task_config into a helper such as
_resolve_dbt_profile_secret_block. Have it return the block name when available,
otherwise log the warning with the supplied failure hint and return None; update
both task configuration functions to use this helper while preserving their
existing env and warning behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ddpui/celeryworkers/tasks.py`:
- Around line 313-376: Update the outer exception handler in run_dbt_commands so
failures from profile writing or dbt clean/deps/run operations are re-raised
after recording the failure and updating progress. Ensure the task result is
marked failed, allowing install_elementary’s apply(...).maybe_throw() to stop
step 1 instead of emitting completed and scheduling reports.

In `@ddpui/management/commands/patch_edr_deployment_env.py`:
- Around line 58-88: Before constructing new_params in the deployment loop,
inspect each deployment’s existing config.tasks and detect pipelines containing
tasks beyond the regenerated EDR task. For mixed pipelines, skip the deployment
without calling update_dataflow_v1 (and report it consistently); only replace
config.tasks for deployments that contain exclusively the EDR task, preserving
dry-run and patched/skipped accounting.

---

Outside diff comments:
In `@ddpui/services/org_cleanup_service.py`:
- Around line 260-290: The dbt-profile secret block cleanup currently occurs in
the per-warehouse delete flow, after delete_org() may clear self.org.dbt and
potentially repeats for each OrgWarehouse. Remove that cleanup from
delete_warehouse() and move it into delete_transformation_layer(), using the
available orgdbt record and executing it once while preserving the Prefect
deletion, error logging, and OrgPrefectBlockv1 deletion behavior.

---

Nitpick comments:
In `@ddpui/core/pipelinefunctions.py`:
- Around line 108-141: Extract the shared dbt profile secret block lookup from
setup_dbt_core_task_config and setup_edr_send_report_task_config into a helper
such as _resolve_dbt_profile_secret_block. Have it return the block name when
available, otherwise log the warning with the supplied failure hint and return
None; update both task configuration functions to use this helper while
preserving their existing env and warning behavior.

In `@ddpui/management/commands/sync_edr_secret_block.py`:
- Around line 112-117: Replace the broad exception handler around
get_secret_block_by_name with the specific HttpError type used by prefect_get
for 404 responses, confirming that exception type from the client implementation
or established org_cleanup_service.py pattern. Preserve the [skip] behavior only
for not-found errors, while allowing authentication, network, and other failures
to propagate.

In `@ddpui/tests/services/test_elementary_service.py`:
- Around line 881-1003: The current tests mock run_dbt_commands.apply entirely
and do not verify its real failure propagation. Add an integration-style test
for install_elementary that invokes the actual run_dbt_commands implementation
while mocking only its dbt subprocess calls to fail, then assert step 1 emits
failed, step 2 is not called, and the exception propagates.

In `@README.md`:
- Around line 146-152: Clarify in Step 5 that the prefect-proxy repository must
be cloned as a sibling directory of the current repository, matching the
relative ../prefect-proxy/docker/dbt-X.Y.Z paths used in the dbt setup
instructions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ddad13ab-628c-4814-8d9b-c58283f320ac

📥 Commits

Reviewing files that changed from the base of the PR and between f03abed and 78faa4f.

⛔ Files ignored due to path filters (3)
  • dbt_deps/dbt-1.10.19/uv.lock is excluded by !**/*.lock
  • dbt_deps/dbt-1.8.7/uv.lock is excluded by !**/*.lock
  • dbt_deps/dbt-1.9.8/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • README.md
  • dbt_deps/Dockerfile.prefect-job-runner
  • dbt_deps/README.md
  • dbt_deps/dbt-1.10.19/pyproject.toml
  • dbt_deps/dbt-1.8.7/pyproject.toml
  • dbt_deps/dbt-1.9.8/pyproject.toml
  • ddpui/api/dbt_api.py
  • ddpui/api/orgtask_api.py
  • ddpui/celeryworkers/tasks.py
  • ddpui/core/dbtfunctions.py
  • ddpui/core/orchestrate/pipeline_service.py
  • ddpui/core/pipelinefunctions.py
  • ddpui/ddpairbyte/airbytehelpers.py
  • ddpui/ddpdbt/dbt_service.py
  • ddpui/ddpdbt/dbthelpers.py
  • ddpui/ddpdbt/elementary_service.py
  • ddpui/management/commands/backfill_warehouse_secret_blocks.py
  • ddpui/management/commands/ensureedrsendreportdataflow.py
  • ddpui/management/commands/patch_edr_deployment_env.py
  • ddpui/management/commands/sync_edr_secret_block.py
  • ddpui/management/commands/updateedrsendreportdataflowtarget.py
  • ddpui/migrations/0169_orgdbt_dbt_profile_secret_block_and_more.py
  • ddpui/models/org.py
  • ddpui/models/tasks.py
  • ddpui/services/org_cleanup_service.py
  • ddpui/tests/api_tests/test_dbt_api.py
  • ddpui/tests/core/test_dbtfunctions.py
  • ddpui/tests/core/test_pipelinefunctions.py
  • ddpui/tests/services/test_elementary_service.py
  • ddpui/utils/constants.py
  • ddpui/utils/s3_utils.py
💤 Files with no reviewable changes (5)
  • dbt_deps/dbt-1.9.8/pyproject.toml
  • dbt_deps/dbt-1.8.7/pyproject.toml
  • dbt_deps/README.md
  • dbt_deps/dbt-1.10.19/pyproject.toml
  • dbt_deps/Dockerfile.prefect-job-runner

Comment thread ddpui/celeryworkers/tasks.py
Comment on lines +58 to +88
try:
dbt_project_params = DbtProjectManager.gather_dbt_project_params(org, orgdbt)
except Exception as err: # pylint: disable=broad-exception-caught
self.stdout.write(f" [skip] {org.slug}: gather_dbt_project_params failed ({err})")
skipped += 1
continue

task_config = setup_edr_send_report_task_config(orgtask, dbt_project_params.project_dir)
new_params = {
"config": {
"tasks": [task_config.to_json()],
"org_slug": org.slug,
}
}

for dot in DataflowOrgTask.objects.filter(orgtask=orgtask).select_related("dataflow"):
dataflow = dot.dataflow
if options["dry_run"]:
self.stdout.write(
f" [dry-run] {dataflow.deployment_name}: would rebuild deployment_params"
)
patched += 1
continue

try:
update_dataflow_v1(
dataflow.deployment_id,
PrefectDataFlowUpdateSchema3(
deployment_params=new_params, cron=dataflow.cron
),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

# Map relevant files first
ast-grep outline ddpui/management/commands/patch_edr_deployment_env.py --view expanded || true
echo '---'
fd -a 'pipeline_service.py' .
echo '---'
fd -a 'dataflow*' ddpui | head -n 50
echo '---'
rg -n "send report|send-report|deployment_params|DataflowOrgTask|tasks" ddpui -g'*.py' | head -n 250

Repository: DalgoT4D/DDP_backend

Length of output: 25476


🏁 Script executed:

set -euo pipefail

sed -n '70,210p' ddpui/core/orchestrate/pipeline_service.py
echo '---'
sed -n '430,520p' ddpui/ddpdbt/elementary_service.py
echo '---'
sed -n '150,330p' ddpui/core/orgtaskfunctions.py

Repository: DalgoT4D/DDP_backend

Length of output: 16034


🏁 Script executed:

set -euo pipefail

sed -n '1,220p' ddpui/management/commands/patch_edr_deployment_env.py

Repository: DalgoT4D/DDP_backend

Length of output: 4093


Guard against mixed EDR pipelines before rewriting deployment_params. ddpui/management/commands/patch_edr_deployment_env.py:58-88 replaces config.tasks with only the regenerated EDR task for every deployment attached to the orgtask. Orchestrated pipelines can already include EDR alongside other tasks, so this will drop the rest of the pipeline config. Skip those deployments or merge the existing tasks instead.

🧰 Tools
🪛 Ruff (0.15.21)

[warning] 60-60: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/patch_edr_deployment_env.py` around lines 58 - 88,
Before constructing new_params in the deployment loop, inspect each deployment’s
existing config.tasks and detect pipelines containing tasks beyond the
regenerated EDR task. For mixed pipelines, skip the deployment without calling
update_dataflow_v1 (and report it consistently); only replace config.tasks for
deployments that contain exclusively the EDR task, preserving dry-run and
patched/skipped accounting.

@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 51.52542% with 143 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.62%. Comparing base (82c019d) to head (95ce579).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
ddpui/ddpdbt/dbthelpers.py 32.20% 40 Missing ⚠️
ddpui/ddpdbt/elementary_service.py 42.59% 31 Missing ⚠️
ddpui/services/org_cleanup_service.py 45.00% 22 Missing ⚠️
ddpui/utils/s3_utils.py 15.38% 22 Missing ⚠️
ddpui/api/dbt_api.py 72.50% 11 Missing ⚠️
ddpui/core/pipelinefunctions.py 45.45% 6 Missing ⚠️
ddpui/ddpdbt/dbt_service.py 45.45% 6 Missing ⚠️
ddpui/core/orchestrate/pipeline_service.py 50.00% 2 Missing ⚠️
ddpui/ddpprefect/prefect_service.py 33.33% 2 Missing ⚠️
ddpui/api/orgtask_api.py 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1435      +/-   ##
==========================================
- Coverage   61.89%   61.62%   -0.27%     
==========================================
  Files         152      152              
  Lines       17816    17976     +160     
==========================================
+ Hits        11027    11078      +51     
- Misses       6789     6898     +109     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ddpui/management/commands/backfill_dbt_profile_secret_blocks.py`:
- Around line 41-53: The warehouse-processing flow in the backfill command must
handle organizations with multiple OrgWarehouse rows before upserting the shared
dbt profile block. Group warehouses by organization, then either select the
established designated warehouse or skip/fail ambiguous organizations
explicitly; ensure each org’s dbt-profile-<org.slug> is written at most once.
- Around line 99-103: Update the migration flow around
_patch_deployments_for_org so deployment patch failures are returned or
aggregated instead of only logged. Increment ok and report the organization as
migrated only after patching succeeds; propagate any failure through the
command’s final status so the command fails when any DBTCORE deployment cannot
be updated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 472c5828-a2e2-4c46-8052-0a6ac43b927f

📥 Commits

Reviewing files that changed from the base of the PR and between 78faa4f and 04abd1a.

📒 Files selected for processing (4)
  • ddpui/api/orgtask_api.py
  • ddpui/management/commands/backfill_dbt_profile_secret_blocks.py
  • ddpui/tests/helper/test_airbytehelpers.py
  • ddpui/tests/services/dbt_service/test_generate_manifest_json_for_dbt_project.py

Comment on lines +41 to +53
warehouses = OrgWarehouse.objects.select_related("org").all()
if options["org"]:
warehouses = warehouses.filter(org__slug=options["org"])

total = warehouses.count()
if total == 0:
print("No warehouses found")
return

print(f"Processing {total} warehouse(s)")
ok, skipped, failed = 0, 0, 0

for warehouse in warehouses:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Handle organizations with multiple warehouses explicitly.

At Line 41, each warehouse is processed independently, but every iteration writes the same dbt-profile-<org.slug> block. Since OrgWarehouse does not enforce one row per org, a multi-warehouse org ends with whichever credential payload is processed last. Select a designated warehouse or fail/skip ambiguous orgs before upserting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/backfill_dbt_profile_secret_blocks.py` around lines
41 - 53, The warehouse-processing flow in the backfill command must handle
organizations with multiple OrgWarehouse rows before upserting the shared dbt
profile block. Group warehouses by organization, then either select the
established designated warehouse or skip/fail ambiguous organizations
explicitly; ensure each org’s dbt-profile-<org.slug> is written at most once.

Comment on lines +99 to +103
print(f" [ok] {org.slug}: {block.block_name}")
ok += 1

# Patch deployments so DBTCORE task_configs carry the runner env key.
_patch_deployments_for_org(org)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not report an org as migrated when deployment patching fails.

ok is incremented before _patch_deployments_for_org, while Lines 157-158 only log update failures. The command can exit successfully even though DBTCORE tasks still lack dbt-profile-secret-block and will not use the new runner secret. Return/aggregate patch failures and mark the org/command failed when any deployment cannot be updated.

Also applies to: 148-158

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/backfill_dbt_profile_secret_blocks.py` around lines
99 - 103, Update the migration flow around _patch_deployments_for_org so
deployment patch failures are returned or aggregated instead of only logged.
Increment ok and report the organization as migrated only after patching
succeeds; propagate any failure through the command’s final status so the
command fails when any DBTCORE deployment cannot be updated.

@himanshudube97 himanshudube97 self-assigned this Jul 28, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ddpui/management/commands/migrate_deployments_to_runner_flow.py`:
- Around line 60-62: Update the dry-run branch in the deployment migration
command so it does not increment patched; instead increment a separate planned
counter, initialize and report that counter in the summary, while keeping
patched reserved for deployments actually modified.
- Around line 29-31: Update the queryset in the migration command before
iteration to exclude OrgDataFlowv1 records with a null deployment_id, while
preserving the existing optional org slug filter and select_related("org")
behavior.

In `@README.md`:
- Line 154: Update the fenced environment-variable code block in README.md to
declare the dotenv language by changing its opening fence to ```dotenv, while
preserving the block’s existing contents.
- Around line 144-159: Update the setup instructions around the uv sync command
to define and export DBT_VENV before invoking it, and retain the later .env
configuration with consistent path semantics. Ensure a fresh shell does not
expand an unset DBT_VENV into an unintended /venv destination.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 88b7a375-097d-4a71-8b78-15e6eb398826

📥 Commits

Reviewing files that changed from the base of the PR and between 04abd1a and 557e85b.

📒 Files selected for processing (3)
  • README.md
  • ddpui/ddpprefect/prefect_service.py
  • ddpui/management/commands/migrate_deployments_to_runner_flow.py

Comment on lines +29 to +31
qs = OrgDataFlowv1.objects.select_related("org")
if options["org"]:
qs = qs.filter(org__slug=options["org"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Skip dataflows without a deployment ID.

OrgDataFlowv1.deployment_id is nullable, so these rows call get_deployment(None) and generate avoidable proxy failures. Filter them before iterating.

Proposed fix
-        qs = OrgDataFlowv1.objects.select_related("org")
+        qs = (
+            OrgDataFlowv1.objects.select_related("org")
+            .exclude(deployment_id__isnull=True)
+            .exclude(deployment_id="")
+        )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
qs = OrgDataFlowv1.objects.select_related("org")
if options["org"]:
qs = qs.filter(org__slug=options["org"])
qs = (
OrgDataFlowv1.objects.select_related("org")
.exclude(deployment_id__isnull=True)
.exclude(deployment_id="")
)
if options["org"]:
qs = qs.filter(org__slug=options["org"])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/migrate_deployments_to_runner_flow.py` around lines
29 - 31, Update the queryset in the migration command before iteration to
exclude OrgDataFlowv1 records with a null deployment_id, while preserving the
existing optional org slug filter and select_related("org") behavior.

Comment on lines +60 to +62
if options["dry_run"]:
self.stdout.write(f" [dry-run] {label}: {OLD_ENTRYPOINT} → {NEW_ENTRYPOINT}")
patched += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not report dry-run operations as patches.

Incrementing patched here makes the final summary claim deployments were patched despite --dry-run performing no writes. Track a separate planned count.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/migrate_deployments_to_runner_flow.py` around lines
60 - 62, Update the dry-run branch in the deployment migration command so it
does not increment patched; instead increment a separate planned counter,
initialize and report that counter in the summary, while keeping patched
reserved for deployments actually modified.

Comment thread README.md
Comment on lines +144 to +159
All orgs run on dbt-core 1.10.19. Set up a local venv from the pinned pyproject.toml:

#### For DBT 1.8.7 (current production)
```bash
cd dbt_deps/dbt-1.8.7/
cd ../prefect-proxy/docker/dbt-1.10.19/
UV_PROJECT_ENVIRONMENT=$DBT_VENV/venv uv sync
```

#### For DBT 1.9.8 (migration target)
```bash
cd dbt_deps/dbt-1.9.8/
UV_PROJECT_ENVIRONMENT=$DBT_VENV/venv-1.9.8 uv sync
```
The `uv.lock` file is committed for reproducible versions.

#### For DBT 1.10.19
```bash
cd dbt_deps/dbt-1.10.19/
UV_PROJECT_ENVIRONMENT=$DBT_VENV/venv-1.10.19 uv sync
```

**Note**: The `uv.lock` files are committed to ensure reproducible dependency versions across all environments.

Set the DBT environment path in `.env`:
Set the DBT paths in `.env`:
```
CLIENTDBT_ROOT=/path/to/client/dbt/projects
DBT_VENV=/path/to/dbt/environments
```

This creates the structure:
```
$DBT_VENV/
├── venv/ # DBT 1.8.7
└── venv-1.9.8/ # DBT 1.9.8
```

Organizations use either `venv` or `venv-1.9.8` in their `dbt_venv` database field.
Django resolves the dbt binary as `$DBT_VENV/<orgdbt.dbt_venv>/bin/dbt` (default `dbt_venv` value is `venv`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Set DBT_VENV before running uv sync.

The command uses $DBT_VENV before the document defines it, and .env values are not automatically available in the shell. A fresh setup can target /venv instead. Define/export it before the command.

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 154-154: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 144 - 159, Update the setup instructions around the
uv sync command to define and export DBT_VENV before invoking it, and retain the
later .env configuration with consistent path semantics. Ensure a fresh shell
does not expand an unset DBT_VENV into an unintended /venv destination.

Comment thread README.md

Set the DBT environment path in `.env`:
Set the DBT paths in `.env`:
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Declare the .env fence language.

Use ```dotenv to satisfy the configured Markdown lint rule.

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 154-154: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 154, Update the fenced environment-variable code block in
README.md to declare the dotenv language by changing its opening fence to
```dotenv, while preserving the block’s existing contents.

Source: Linters/SAST tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
ddpui/management/commands/update_dbt_binary_path.py (4)

177-184: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Preserve the existing PATH entries.

Replacing PATH with only the new virtualenv directory can remove system paths and other required tooling from the EDR task. Prepend edr_bin_dir to the existing path using os.pathsep, rather than discarding old_path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/update_dbt_binary_path.py` around lines 177 - 184,
Update the EDR task PATH handling in the TASK_GENERATE_EDR branch to preserve
existing entries: construct the new PATH by prepending edr_bin_dir to old_path
with os.pathsep, while handling an empty old_path without an unnecessary
separator. Compare and assign this combined value, and keep the existing
modified flag and output behavior.

186-214: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Do not report successful migration after deployment failures.

The broad handler logs an error and continues, while OrgDbt.dbt_venv has already been saved. The command can therefore leave the database and Prefect deployments inconsistent, increment the success counters, and exit successfully. Catch only expected exceptions, record failures, and return a non-zero CommandError after processing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/update_dbt_binary_path.py` around lines 186 - 214,
The deployment loop’s broad exception handling allows failed updates to
increment success counters and the command to exit successfully after
OrgDbt.dbt_venv is saved. In the deployment-processing flow, catch only expected
exceptions, record whether any deployment failed, prevent failed organizations
from contributing to successful migration counters, and return a non-zero
CommandError after processing all entries when failures occurred.

Source: Linters/SAST tools


73-84: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Enumerate organizations rather than OrgDbt records.

The all-org path currently skips every configured organization whose dbt_venv is NULL, despite claiming to process all dbt-configured orgs. It also includes orphaned OrgDbt rows, and Org.objects.get(dbt=org_dbt) can raise MultipleObjectsReturned because Org.dbt is a non-unique foreign key. Query Org.objects.filter(dbt__isnull=False) and iterate each organization directly.

Also applies to: 104-111

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/update_dbt_binary_path.py` around lines 73 - 84,
Update the organization resolution and iteration in the command to enumerate Org
records directly: use Org.objects.filter(dbt__isnull=False) for the all-org path
and retain the single-org validation for org_slug. Iterate organizations and use
each organization’s dbt configuration, removing the OrgDbt-based filtering and
reverse lookup so NULL dbt_venv and duplicate references are handled correctly.

64-71: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Validate that the new path is an executable file.

Path.exists() also accepts directories and non-executable files, allowing the command to persist an unusable dbt path and fail later in Prefect.

Proposed fix
-            if not Path(new_binary_path).exists():
+            if not Path(new_binary_path).is_file() or not os.access(new_binary_path, os.X_OK):
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ddpui/management/commands/update_dbt_binary_path.py` around lines 64 - 71,
Update the new_dbt_venv validation in the command’s dry-run guard to require
new_binary_path to be a regular executable file, not merely an existing path.
Use the appropriate Path file and executable checks before allowing the command
to proceed, while preserving the existing CommandError and message for invalid
paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@ddpui/management/commands/update_dbt_binary_path.py`:
- Around line 177-184: Update the EDR task PATH handling in the
TASK_GENERATE_EDR branch to preserve existing entries: construct the new PATH by
prepending edr_bin_dir to old_path with os.pathsep, while handling an empty
old_path without an unnecessary separator. Compare and assign this combined
value, and keep the existing modified flag and output behavior.
- Around line 186-214: The deployment loop’s broad exception handling allows
failed updates to increment success counters and the command to exit
successfully after OrgDbt.dbt_venv is saved. In the deployment-processing flow,
catch only expected exceptions, record whether any deployment failed, prevent
failed organizations from contributing to successful migration counters, and
return a non-zero CommandError after processing all entries when failures
occurred.
- Around line 73-84: Update the organization resolution and iteration in the
command to enumerate Org records directly: use
Org.objects.filter(dbt__isnull=False) for the all-org path and retain the
single-org validation for org_slug. Iterate organizations and use each
organization’s dbt configuration, removing the OrgDbt-based filtering and
reverse lookup so NULL dbt_venv and duplicate references are handled correctly.
- Around line 64-71: Update the new_dbt_venv validation in the command’s dry-run
guard to require new_binary_path to be a regular executable file, not merely an
existing path. Use the appropriate Path file and executable checks before
allowing the command to proceed, while preserving the existing CommandError and
message for invalid paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3566d24f-08da-419f-890b-b52e1109eb21

📥 Commits

Reviewing files that changed from the base of the PR and between 557e85b and ec084ec.

📒 Files selected for processing (4)
  • ddpui/celeryworkers/tasks.py
  • ddpui/management/commands/update_dbt_binary_path.py
  • ddpui/migrations/0170_orgdbt_dbt_profile_secret_block.py
  • ddpui/tests/services/test_elementary_service.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • ddpui/celeryworkers/tasks.py

@Ishankoradia
Ishankoradia merged commit d8135f0 into main Jul 29, 2026
2 of 5 checks passed
@Ishankoradia
Ishankoradia deleted the feature/prefect-secret-blk branch July 29, 2026 05:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants