Skip to content

feat: add new granularities to gooddata-dbt and gooddata-pipelines - #1714

Merged
okrcmaGD merged 1 commit into
gooddata:masterfrom
okrcmaGD:okrc/cq-2783
Aug 10, 2026
Merged

feat: add new granularities to gooddata-dbt and gooddata-pipelines#1714
okrcmaGD merged 1 commit into
gooddata:masterfrom
okrcmaGD:okrc/cq-2783

Conversation

@okrcmaGD

@okrcmaGD okrcmaGD commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

JIRA: CQ-2783
risk: low

Summary by CodeRabbit

  • New Features

    • Added optional second-based timestamp granularities for date datasets.
    • Added configuration options for LDM Extension Manager and dbt deployment workflows.
    • The option is disabled by default and requires the corresponding platform feature flag.
  • Documentation

    • Documented configuration and feature-flag requirements.
  • Tests

    • Added coverage for default and enabled second-level date granularities.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds optional second-based date granularities to LDM extension and dbt workflows. The option is disabled by default. Documentation and tests cover both modes.

Changes

Second-based date granularities

Layer / File(s) Summary
LDM extension option propagation
packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/*, packages/gooddata-pipelines/tests/test_ldm_extension/*, docs/content/en/latest/pipelines/ldm_extension/_index.md
LdmExtensionManager forwards enable_second_granularities. LdmExtensionDataProcessor selects standard or second-based granularities. Tests and documentation cover both modes.
dbt granularity generation
packages/gooddata-dbt/src/gooddata_dbt/dbt/*, packages/gooddata-dbt/src/gooddata_dbt/args.py, packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py, packages/gooddata-dbt/tests/*, packages/gooddata-dbt/README.md
The deploy_ldm option flows into DbtModelTables. Timestamp datasets receive second-based granularities when enabled. DATE columns keep their existing granularity set. Tests and documentation cover the option.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LdmExtensionManager
  participant LdmExtensionDataProcessor
  participant date_from_field
  LdmExtensionManager->>LdmExtensionDataProcessor: Pass enable_second_granularities
  LdmExtensionDataProcessor->>date_from_field: Use configured date granularities
  date_from_field-->>LdmExtensionDataProcessor: Build date dataset
Loading
sequenceDiagram
  participant deploy_ldm
  participant DbtModelTables
  participant make_date_datasets
  deploy_ldm->>DbtModelTables: Pass CLI option
  DbtModelTables->>make_date_datasets: Add second timestamp granularities
  make_date_datasets-->>DbtModelTables: Return generated datasets
Loading

Possibly related PRs

Suggested reviewers: lupko, pcerny

Poem

A rabbit marks each second bright,
The dates now keep more time in sight.
The flag stays off unless supplied,
Tests check both paths side by side.
The datasets hop in time.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the addition of new granularities to both affected packages.
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.

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: 1

🤖 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
`@packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py`:
- Line 64: Restore the public LdmExtensionDataProcessor.DATE_GRANULARITIES class
attribute as a deprecated alias referencing _DATE_GRANULARITIES, preserving
existing caller access without duplicating the granularity values.
🪄 Autofix

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: e731f3c6-6548-4baf-bbfc-5d9c6522845b

📥 Commits

Reviewing files that changed from the base of the PR and between 17bcb5c and f21fd8b.

📒 Files selected for processing (10)
  • docs/content/en/latest/pipelines/ldm_extension/_index.md
  • packages/gooddata-dbt/README.md
  • packages/gooddata-dbt/src/gooddata_dbt/args.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/base.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py
  • packages/gooddata-dbt/tests/test_tables.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py
  • packages/gooddata-pipelines/tests/test_ldm_extension/test_input_processor.py

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.94737% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.00%. Comparing base (acfcc1a) to head (1bf575d).
⚠️ Report is 11 commits behind head on master.

Files with missing lines Patch % Lines
...a_pipelines/ldm_extension/ldm_extension_manager.py 60.00% 2 Missing ⚠️
...ckages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py 83.33% 1 Missing ⚠️
...ckages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1714      +/-   ##
==========================================
+ Coverage   78.30%   79.00%   +0.70%     
==========================================
  Files         271      271              
  Lines       18689    18779      +90     
==========================================
+ Hits        14634    14837     +203     
+ Misses       4055     3942     -113     

☔ 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 commented Aug 5, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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

🧹 Nitpick comments (1)
packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py (1)

85-99: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid sharing mutable granularity lists.

CatalogDeclarativeDateDataset retains the supplied list, and _date_from_field passes the same list to every dataset. Copy _date_granularities in __init__ and when constructing each dataset. Add ClassVar annotations if Ruff RUF012 is enabled.

🤖 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
`@packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py`
around lines 85 - 99, Prevent shared mutable granularity lists by copying
_date_granularities in CatalogDeclarativeDateDataset.__init__ and copying it
again when _date_from_field constructs each dataset. Annotate class-level
mutable granularity constants with ClassVar if required by Ruff RUF012.

Source: Linters/SAST tools

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

Nitpick comments:
In
`@packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py`:
- Around line 85-99: Prevent shared mutable granularity lists by copying
_date_granularities in CatalogDeclarativeDateDataset.__init__ and copying it
again when _date_from_field constructs each dataset. Annotate class-level
mutable granularity constants with ClassVar if required by Ruff RUF012.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 54f40155-b3eb-4148-bdd9-7d4e0953a987

📥 Commits

Reviewing files that changed from the base of the PR and between 17bcb5c and 1f3a106.

📒 Files selected for processing (10)
  • docs/content/en/latest/pipelines/ldm_extension/_index.md
  • packages/gooddata-dbt/README.md
  • packages/gooddata-dbt/src/gooddata_dbt/args.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/base.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py
  • packages/gooddata-dbt/tests/test_tables.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py
  • packages/gooddata-pipelines/tests/test_ldm_extension/test_input_processor.py
🚧 Files skipped from review as they are similar to previous changes (8)
  • docs/content/en/latest/pipelines/ldm_extension/_index.md
  • packages/gooddata-dbt/README.md
  • packages/gooddata-dbt/src/gooddata_dbt/args.py
  • packages/gooddata-pipelines/tests/test_ldm_extension/test_input_processor.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py
  • packages/gooddata-dbt/tests/test_tables.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/base.py

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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

🧹 Nitpick comments (2)
packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py (1)

85-99: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Own the granularity lists per processor and per date dataset.

_SECOND_DATE_GRANULARITIES is a mutable class list, which triggers RUF012. The constructor can also alias the class-level list, and every date dataset receives the same instance list. If a consumer mutates one list, later LDM output can change.

Mark both class-level constants as ClassVar, create an instance-owned list, and pass a copy to each date dataset.

Proposed fix
+from typing import ClassVar
+
-    DATE_GRANULARITIES: list[str] = [
+    DATE_GRANULARITIES: ClassVar[list[str]] = [
         ...
     ]

-    _SECOND_DATE_GRANULARITIES: list[str] = [
+    _SECOND_DATE_GRANULARITIES: ClassVar[list[str]] = [
         ...
     ]

-        self._date_granularities = (
-            self.DATE_GRANULARITIES + self._SECOND_DATE_GRANULARITIES
-            if enable_second_granularities
-            else self.DATE_GRANULARITIES
-        )
+        self._date_granularities = list(self.DATE_GRANULARITIES)
+        if enable_second_granularities:
+            self._date_granularities.extend(self._SECOND_DATE_GRANULARITIES)

-            granularities=self._date_granularities,
+            granularities=list(self._date_granularities),

Also applies to: 145-145

🤖 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
`@packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py`
around lines 85 - 99, Update the granularity declarations in the processor class
to use ClassVar for both class-level lists, then ensure __init__ builds an
instance-owned list rather than aliasing DATE_GRANULARITIES. When constructing
each date dataset, pass a copy of the processor’s granularity list so datasets
cannot mutate shared state.

Source: Linters/SAST tools

packages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py (1)

455-459: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Prevent granularity-list drift. SECOND_TIMESTAMP_GRANULARITIES and _SECOND_DATE_GRANULARITIES contain the same four values in the same order. Use one shared constant or add a cross-package contract test.

🤖 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 `@packages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py` around lines 455 - 459,
Update the granularity selection in the table logic around
_enable_second_granularities to avoid duplicating the four second-level values
between SECOND_TIMESTAMP_GRANULARITIES and _SECOND_DATE_GRANULARITIES. Reuse a
shared constant accessible to both definitions, preserving the current values
and ordering.
🤖 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.

Nitpick comments:
In `@packages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py`:
- Around line 455-459: Update the granularity selection in the table logic
around _enable_second_granularities to avoid duplicating the four second-level
values between SECOND_TIMESTAMP_GRANULARITIES and _SECOND_DATE_GRANULARITIES.
Reuse a shared constant accessible to both definitions, preserving the current
values and ordering.

In
`@packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py`:
- Around line 85-99: Update the granularity declarations in the processor class
to use ClassVar for both class-level lists, then ensure __init__ builds an
instance-owned list rather than aliasing DATE_GRANULARITIES. When constructing
each date dataset, pass a copy of the processor’s granularity list so datasets
cannot mutate shared state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ed2e4d9e-24c9-4416-bac3-c0d117a63abb

📥 Commits

Reviewing files that changed from the base of the PR and between 2f1a82f and ed280e9.

📒 Files selected for processing (11)
  • docs/content/en/latest/pipelines/ldm_extension/_index.md
  • packages/gooddata-dbt/README.md
  • packages/gooddata-dbt/src/gooddata_dbt/args.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/base.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py
  • packages/gooddata-dbt/tests/test_args.py
  • packages/gooddata-dbt/tests/test_tables.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py
  • packages/gooddata-pipelines/tests/test_ldm_extension/test_input_processor.py
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/gooddata-dbt/src/gooddata_dbt/args.py
  • docs/content/en/latest/pipelines/ldm_extension/_index.md
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/base.py
  • packages/gooddata-dbt/README.md
  • packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py
  • packages/gooddata-dbt/tests/test_tables.py
  • packages/gooddata-pipelines/tests/test_ldm_extension/test_input_processor.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py

janmatzek
janmatzek previously approved these changes Aug 6, 2026

To extend the LDM, you need to define the custom datasets and the fields they should contain. The script also checks the validity of analytical objects before and after the update. Updates introducing new invalid relations are automatically rolled back. You can opt out of this behavior by setting the `check_relations` parameter to False.

To create date datasets with the second-based granularities (`SECOND`, `SECOND_OF_MINUTE`, `SECOND_OF_DAY`, `MINUTE_OF_DAY`), set the `enable_second_granularities` parameter to True when creating the LdmExtensionManager. This requires the `enableSecondGranularities` feature flag to be enabled for your GoodData organization.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: do not mention ff here, please. Cloud customers do not about feature flags.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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

🧹 Nitpick comments (1)
packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py (1)

85-99: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Isolate mutable granularity configuration.

_SECOND_DATE_GRANULARITIES is a mutable class-level list, which triggers Ruff RUF012. The disabled branch also aliases DATE_GRANULARITIES, and _date_from_field passes the same list object to each date dataset.

Mark the class attributes with ClassVar, copy the selected values per processor, and pass a copy at Line 145.

Proposed fix
+from typing import ClassVar

-    DATE_GRANULARITIES: list[str] = [
+    DATE_GRANULARITIES: ClassVar[list[str]] = [

-    _SECOND_DATE_GRANULARITIES: list[str] = [
+    _SECOND_DATE_GRANULARITIES: ClassVar[list[str]] = [

-        self._date_granularities = (
-            self.DATE_GRANULARITIES + self._SECOND_DATE_GRANULARITIES
-            if enable_second_granularities
-            else self.DATE_GRANULARITIES
-        )
+        self._date_granularities = list(self.DATE_GRANULARITIES)
+        if enable_second_granularities:
+            self._date_granularities.extend(self._SECOND_DATE_GRANULARITIES)

-            granularities=self._date_granularities,
+            granularities=list(self._date_granularities),

Also applies to: 145-145

🤖 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
`@packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py`
around lines 85 - 99, Update the granularity declarations and initialization in
the input processor: annotate class-level DATE_GRANULARITIES and
_SECOND_DATE_GRANULARITIES with ClassVar, copy the selected granularity values
when assigning self._date_granularities so disabled mode does not alias
DATE_GRANULARITIES, and pass a copy in _date_from_field when constructing each
date dataset.

Source: Linters/SAST tools

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

Nitpick comments:
In
`@packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py`:
- Around line 85-99: Update the granularity declarations and initialization in
the input processor: annotate class-level DATE_GRANULARITIES and
_SECOND_DATE_GRANULARITIES with ClassVar, copy the selected granularity values
when assigning self._date_granularities so disabled mode does not alias
DATE_GRANULARITIES, and pass a copy in _date_from_field when constructing each
date dataset.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c29335e1-5da5-4649-8e3b-a34cca89d0e2

📥 Commits

Reviewing files that changed from the base of the PR and between cbd27a1 and 1bf575d.

📒 Files selected for processing (11)
  • docs/content/en/latest/pipelines/ldm_extension/_index.md
  • packages/gooddata-dbt/README.md
  • packages/gooddata-dbt/src/gooddata_dbt/args.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/base.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/tables.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py
  • packages/gooddata-dbt/tests/test_args.py
  • packages/gooddata-dbt/tests/test_tables.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/input_processor.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py
  • packages/gooddata-pipelines/tests/test_ldm_extension/test_input_processor.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/gooddata-dbt/src/gooddata_dbt/dbt_plugin.py
  • packages/gooddata-dbt/README.md
  • packages/gooddata-dbt/tests/test_args.py
  • packages/gooddata-dbt/src/gooddata_dbt/dbt/base.py
  • packages/gooddata-pipelines/src/gooddata_pipelines/ldm_extension/ldm_extension_manager.py
  • packages/gooddata-dbt/tests/test_tables.py
  • docs/content/en/latest/pipelines/ldm_extension/_index.md
  • packages/gooddata-dbt/src/gooddata_dbt/args.py
  • packages/gooddata-pipelines/tests/test_ldm_extension/test_input_processor.py

@okrcmaGD
okrcmaGD merged commit 91a45e3 into gooddata:master Aug 10, 2026
16 of 17 checks passed
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.

4 participants