Skip to content

Moving away from dbt core operation blocks#1435

Open
Ishankoradia wants to merge 5 commits into
mainfrom
feature/prefect-secret-blk
Open

Moving away from dbt core operation blocks#1435
Ishankoradia wants to merge 5 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 with configuration checks, installation progress, and automated report scheduling.
    • Improved support for dbt profiles across supported warehouses and dbt versions.
    • Added EDR tasks to transformation pipelines and pipeline details.
    • Reports now include schedule information and can be retrieved from a recent three-day window.
  • Bug Fixes

    • Updated warehouse and schema changes to refresh dbt configuration automatically.
    • Improved cleanup of Elementary reports and related configuration.
  • Documentation

    • Updated dbt setup instructions for the new directory locations.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

DBT profile generation and credential handling are centralized, Elementary installation is consolidated into new API and Celery workflows, EDR reporting and task orchestration are updated, and management commands support migration, deployment patching, secret consolidation, and cleanup.

Changes

DBT profile runtime and setup

Layer / File(s) Summary
Centralized DBT profiles and runner secrets
ddpui/core/dbtfunctions.py, ddpui/ddpdbt/dbthelpers.py, ddpui/models/org.py, ddpui/migrations/*, ddpui/celeryworkers/tasks.py
Credentials are normalized into dbt profile outputs, runner Secret blocks are persisted, and profiles.yml is generated through shared helpers and task wiring.
DBT integrations and validation
ddpui/api/dbt_api.py, ddpui/ddpairbyte/airbytehelpers.py, ddpui/ddpdbt/dbt_service.py, ddpui/tests/core/*, ddpui/tests/helper/*, ddpui/tests/services/dbt_service/*
Schema updates, destination refreshes, manifest generation, and related tests use the centralized profile-writing path.
DBT version setup documentation and sources
README.md, dbt_deps/*
README commands point to Prefect proxy Docker dbt sources, while the former dbt dependency Dockerfile, README, and version project files are removed.

Consolidated Elementary installation

Layer / File(s) Summary
Elementary API and Celery workflow
ddpui/api/dbt_api.py, ddpui/celeryworkers/tasks.py, ddpui/models/tasks.py
New check and install endpoints dispatch a three-step Elementary task covering profile creation, dbt installation, and EDR dataflow setup with progress reporting.
Elementary workflow tests
ddpui/tests/api_tests/test_dbt_api.py, ddpui/tests/services/test_elementary_service.py
Tests cover endpoint responses, task dispatch, successful installation, and failures at each installation step.

EDR reporting and orchestration

Layer / File(s) Summary
EDR reports and dataflows
ddpui/ddpdbt/elementary_service.py, ddpui/utils/s3_utils.py
Report retrieval uses a lookback window and schedule metadata, while dataflow creation becomes idempotent and S3 helpers support listing and bulk deletion.
EDR task planning and runtime configuration
ddpui/core/orchestrate/pipeline_service.py, ddpui/core/pipelinefunctions.py, ddpui/api/orgtask_api.py, ddpui/utils/constants.py
EDR tasks are included in transformation plans and listings, task environments use profile Secret blocks, and EDR task configuration no longer passes a virtualenv binary.
EDR command and service validation
ddpui/management/commands/ensureedrsendreportdataflow.py, ddpui/management/commands/updateedrsendreportdataflowtarget.py, ddpui/tests/services/test_elementary_service.py
Management commands and tests use the consolidated idempotent dataflow setup and updated task-config signature.

Migration, cleanup, and operational commands

Layer / File(s) Summary
Profile and EDR migration commands
ddpui/management/commands/backfill_dbt_profile_secret_blocks.py, ddpui/management/commands/patch_edr_deployment_env.py, ddpui/management/commands/sync_edr_secret_block.py
Commands backfill runner profile secrets, patch existing EDR deployment parameters, and consolidate legacy EDR Secret blocks.
Organization cleanup
ddpui/services/org_cleanup_service.py
Transformation cleanup removes EDR tasks and Elementary S3 reports, and warehouse cleanup removes the dbt profile Secret block and database record.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant DBTAPI
  participant ElementaryTask
  participant DBTProfile
  participant EDRDataflow

  Client->>DBTAPI: POST /elementary/install
  DBTAPI->>ElementaryTask: dispatch install_elementary
  ElementaryTask->>DBTProfile: create profile and run dbt
  DBTProfile-->>ElementaryTask: installation result
  ElementaryTask->>EDRDataflow: ensure send-report dataflow
  EDRDataflow-->>Client: task id and progress
Loading
sequenceDiagram
  participant ReportConsumer
  participant elementary_service
  participant S3

  ReportConsumer->>elementary_service: request latest report
  elementary_service->>S3: list reports within lookback window
  S3-->>elementary_service: newest matching object
  elementary_service->>S3: download report
  elementary_service-->>ReportConsumer: report metadata and schedule
Loading

Possibly related PRs

Suggested reviewers: himanshudube97

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 82.50% 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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the main theme of replacing dbt core operation blocks.
✨ Finishing Touches
📝 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 on lines +313 to +376
@app.task(bind=True)
def install_elementary(self, org_id: int, task_id: str, hashkey: str):
"""Consolidated Elementary setup — runs the three sub-steps as one task so
the frontend can render a single progress list.

Sub-steps (each emits {"stepIndex", "step", "status": running|completed}):
0. Create dbt profile → create_elementary_profile(org)
1. Install elementary package → run_dbt_commands (clean + deps + run --select elementary)
2. Schedule reports → ensure_edr_sendreport_dataflow(org, org_task, cron)

On failure: emits {"stepIndex", "step", "status": "failed", "message"} for
the sub-step that blew up, then re-raises so Celery marks the task failed.
"""
org: Org = Org.objects.get(id=org_id)
taskprogress = TaskProgress(task_id, hashkey)

steps = [
(0, "Creating dbt profile"),
(1, "Installing elementary package"),
(2, "Scheduling reports"),
]
current = steps[0]

def _emit(step, status, message=None):
payload = {"stepIndex": step[0], "step": step[1], "status": status}
if message:
payload["message"] = message
taskprogress.add(payload)

try:
current = steps[0]
_emit(current, "running")
result = create_elementary_profile(org)
if isinstance(result, dict) and "error" in result:
raise Exception(result["error"])
_emit(current, "completed")

current = steps[1]
_emit(current, "running")
# run_dbt_commands is a bound celery task; .apply() executes it
# synchronously in-process (returns an EagerResult). Use a separate
# inner task_id so its verbose dbt-output progress doesn't pollute
# the install stream — the frontend only polls the outer install
# task_id + hashkey. Use .maybe_throw() instead of .get() to re-raise
# inner-task exceptions without tripping celery's "no sync subtasks"
# guard (which fires for any .get() call inside a running task).
inner_task_id = str(uuid4())
run_dbt_commands.apply(
args=[org.id, org.dbt.id, inner_task_id, {"options": {"select": "elementary"}}]
).maybe_throw()
_emit(current, "completed")

current = steps[2]
_emit(current, "running")
result = ensure_edr_sendreport_dataflow(org, "0 0 * * *")
if isinstance(result, dict) and "error" in result:
raise Exception(result["error"])
_emit(current, "completed")

except Exception as err:
_emit(current, "failed", message=str(err))
raise


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 | 🔴 Critical | ⚡ Quick win

install_elementary step 1 can silently report "completed" even when dbt install actually fails.

run_dbt_commands's outer exception handler (unchanged, further down in this same function — the except Exception as e: block that logs "Job finished with a failure") catches all internal errors (including the newly-added write_dbt_profiles_yml failure at lines 162‑174, and the pre-existing dbt clean/deps/run failures) but never re-raises. .apply() therefore returns an EagerResult in SUCCESS state regardless of the actual outcome, so .maybe_throw() at line 362 never throws — contrary to the comment's stated intent ("re-raise inner-task exceptions"). As a result, install_elementary will emit "completed" for step 1 and proceed to schedule EDR reports (step 2) even when the elementary dbt package failed to install.

None of the current tests (test_install_elementary_step1_failure) catch this, since they mock run_dbt_commands.apply(...).maybe_throw() directly rather than exercising the real function.

🐛 Suggested fix (in `run_dbt_commands`)
     except Exception as e:
         taskprogress.add(
             {
                 "message": "Job finished with a failure",
                 "status": "failed",
             }
         )
+        raise
 
     finally:
         for task_lock in task_locks:
             task_lock.delete()

Worth double-checking that other .delay() callers of run_dbt_commands don't depend on it never raising (they should be fine, since they poll TaskProgress in Redis rather than the Celery result).

🤖 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/celeryworkers/tasks.py` around lines 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.

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.71233% with 141 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@f03abed). Learn more about missing BASE report.

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/api/orgtask_api.py 80.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1435   +/-   ##
=======================================
  Coverage        ?   61.63%           
=======================================
  Files           ?      152           
  Lines           ?    17973           
  Branches        ?        0           
=======================================
  Hits            ?    11077           
  Misses          ?     6896           
  Partials        ?        0           

☔ 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.

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.

1 participant