Skip to content

Fix grant macros skipping roles with partial object coverage - #38

Merged
jonhopper-dataengineers merged 4 commits into
mainfrom
fix/grant-partial-coverage-skip-bug
Jul 21, 2026
Merged

Fix grant macros skipping roles with partial object coverage#38
jonhopper-dataengineers merged 4 commits into
mainfrom
fix/grant-partial-coverage-skip-bug

Conversation

@jonhopper-dataengineers

@jonhopper-dataengineers jonhopper-dataengineers commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixed a bug where grant macros would skip a role entirely if it had the privilege on ANY object in the schema, rather than checking ALL objects are covered
  • If a role had USAGE on 7 of 9 procedures (or OPERATE/MONITOR on 1 of N pipes/tasks), the remaining objects never received grants
  • Now each macro counts granted objects per role and only skips when granted_count >= total_count
  • Affected macros: grant_schema_procedure_usage_specific, grant_schema_operate_specific, grant_schema_monitor_specific, grant_schema_object_privileges

Test plan

  • Run grant macros against a schema with partial coverage (e.g. role has USAGE on 7/9 procs) and verify the remaining 2 get granted
  • Verify fully-covered roles are still correctly skipped (no unnecessary grant statements)
  • Verify revoke logic still works for roles not in grant_roles
  • Run with dry_run=true to inspect generated statements before live execution

.... Generated with Cortex Code

Summary by Sourcery

Fix grant and privilege macros to correctly handle roles with partial object coverage and support execution in dbt build context.

Bug Fixes:

  • Ensure grant macros only skip roles when they already have privileges on all relevant objects instead of any single object, preventing missed grants for partially covered roles.
  • Correct execute_task macro to reference the task_name parameter when locating matching task nodes.

Enhancements:

  • Extend grant, share, task, cleaning, dependency, and modelling macros to run in dbt build as well as dbt run and run-operation.
  • Improve grant and ownership helper macros to use per-role object coverage checks for more accurate privilege management.
  • Add logging when granting database usage for better observability of privilege operations.

Build:

  • Bump package version from 1.0.9 to 1.0.10 in dbt_project.yml.

Documentation:

  • Update changelog with details of the partial coverage grant fix and dbt build context support.

jonhopper-dataengineers and others added 2 commits July 15, 2026 09:00
All grant, share, task, clean, and dependency macros now recognise
build as a valid execution context alongside run and run-operation.
Also fixes execute_task referencing undefined root_task variable.

.... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code)

Co-Authored-By: Cortex Code <noreply@snowflake.com>
Previously, grant macros would skip a role entirely if it had the
privilege on ANY object in the schema. This meant that if a role had
USAGE on 7 of 9 procedures (or OPERATE/MONITOR on 1 of N pipes/tasks),
the remaining objects never received grants.

Now each macro counts granted objects per role and only skips when the
role already covers ALL objects (granted_count >= total_count).

Affected macros:
- grant_schema_procedure_usage_specific
- grant_schema_operate_specific
- grant_schema_monitor_specific
- grant_schema_object_privileges

.... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code)

Co-Authored-By: Cortex Code <noreply@snowflake.com>
@jonhopper-dataengineers

Copy link
Copy Markdown
Member Author

@sourcery-ai review

.... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code)

Co-Authored-By: Cortex Code <noreply@snowflake.com>
@jonhopper-dataengineers
jonhopper-dataengineers force-pushed the fix/grant-partial-coverage-skip-bug branch from 7580abe to 937a7ea Compare July 20, 2026 01:22
@sourcery-ai

sourcery-ai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Fix grant macros so roles are only skipped when they already have full object coverage, extend macros to run in dbt build contexts, and bump the package version and changelog accordingly.

File-Level Changes

Change Details Files
Ensure grant macros skip roles only when they already have full coverage of objects in a schema instead of when they have any existing grant.
  • For procedure USAGE grants, count procedures per schema and per-role granted procedures; treat a role as fully covered only when granted_count >= total procedure count and otherwise issue missing grants.
  • For OPERATE/MONITOR on pipes and tasks, compute total PIPE+TASK objects per schema and per-role granted objects, then only skip granting for roles whose granted_count covers all objects.
  • For generic schema object privileges, query per-role per-privilege granted object counts and only suppress grants when a role already has full coverage for that privilege.
macros/grants/grant_procedure_usage.sql
macros/grants/grant_schema_operate.sql
macros/grants/grant_schema_monitor.sql
macros/grants/grant_schema_object_privileges.sql
Improve revoke behavior for OPERATE and MONITOR so roles not in grant_roles are cleaned up while preserving grants for target roles.
  • Collect all roles that currently have OPERATE/MONITOR in each schema and, when revoke_current_grants is true, emit revoke-on-all-tasks/pipes statements only for roles not in the target grant_roles list.
  • Track fully_granted_roles separately from existing roles so revokes never touch target roles that should retain full coverage.
macros/grants/grant_schema_operate.sql
macros/grants/grant_schema_monitor.sql
Allow grant, share, task, clean, dependency, ownership, and modelling macros to execute in dbt build contexts in addition to run/run-operation.
  • Extend flags.WHICH checks across grants, shares, tasks, cleaning, dependency resolution, ownership helpers, and modelling macros to include 'build' as a valid context.
  • Ensure macros that previously early-returned when not in run/run-operation now also execute under dbt build, keeping logging messages aligned with the new behavior.
macros/grants/grant_schema_monitor.sql
macros/grants/grant_schema_operate.sql
macros/grants/grant_schema_object_privileges.sql
macros/grants/grant_procedure_usage.sql
macros/grants/grant_schema_read.sql
macros/grants/grant_semantic_views_privileges.sql
macros/grants/grant_share_read.sql
macros/grants/grant_database_usage.sql
macros/grants/grant_privileges.sql
macros/clean/clean_objects.sql
macros/dependancies/depends_on_ref.sql
macros/dependancies/depends_on_source.sql
macros/grants/grant_database_ownership.sql
macros/grants/grant_external_share_read.sql
macros/grants/grant_integration_ownership.sql
macros/grants/grant_integration_usage.sql
macros/grants/grant_internal_share_read.sql
macros/grants/grant_object.sql
macros/grants/grant_object_application.sql
macros/grants/grant_operate_to_application.sql
macros/grants/grant_schema_ownership.sql
macros/grants/grant_usage_to_application.sql
macros/grants/grants_smoke_test.sql
macros/grants/object_lists/get_functions.sql
macros/grants/object_lists/get_procedures.sql
macros/grants/ownerships/get_grant_functions_ownership_sql.sql
macros/grants/ownerships/get_grant_model_ownership_sql.sql
macros/grants/ownerships/get_grant_network_rule_ownership_sql.sql
macros/grants/ownerships/get_grant_other_ownership_sql.sql
macros/grants/ownerships/get_grant_procedure_ownership_sql.sql
macros/grants/ownerships/get_grant_schema_ownership_sql.sql
macros/grants/ownerships/get_grant_stream_ownership_sql.sql
macros/grants/ownerships/get_grant_task_ownership_sql.sql
macros/modelling/unknown_member.sql
macros/shares/create_internal_share.sql
macros/shares/create_share.sql
macros/tasks/enable_dependent_tasks.sql
Fix task execution macro to resolve the correct task node and to run under build/run-operation contexts.
  • Change execute_task to filter graph nodes by the task_name parameter instead of an undefined root_task variable.
  • Allow execute_task to trigger when flags.WHICH is 'run', 'build', or 'run-operation' so tasks can be executed from dbt build flows.
macros/tasks/execute_task.sql
Add logging and documentation, and bump the project version for the release containing these fixes.
  • Log when grant_database_usage applies database usage grants, including the target database name.
  • Update the changelog with v1.0.10 notes describing the partial coverage fix and dbt build context support, and bump dbt_project.yml version from 1.0.9 to 1.0.10.
macros/grants/grant_database_usage.sql
CHANGELOG.md
dbt_project.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

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.

Hey - I've found 2 issues, and left some high level feedback:

  • The conditions in grant_object and grant_object_application were inverted (if flags.WHICH in [...] instead of not in), but the log message still indicates a skip; as written these macros will now always return early in allowed contexts, so the guard should be restored to the original polarity or the log updated to match the intended behavior.
  • In grant_schema_monitor_specific and grant_schema_operate_specific, the object_count_query counts PIPE/TASK objects only where grantor is not null, which will undercount total objects and can misclassify roles as fully granted; consider basing total_monitor_objects/total_operate_objects on the existing SHOW results (or a table of objects) instead of filtering by existing privileges.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The conditions in `grant_object` and `grant_object_application` were inverted (`if flags.WHICH in [...]` instead of `not in`), but the log message still indicates a skip; as written these macros will now always return early in allowed contexts, so the guard should be restored to the original polarity or the log updated to match the intended behavior.
- In `grant_schema_monitor_specific` and `grant_schema_operate_specific`, the `object_count_query` counts PIPE/TASK objects only where `grantor is not null`, which will undercount total objects and can misclassify roles as fully granted; consider basing `total_monitor_objects`/`total_operate_objects` on the existing `SHOW` results (or a table of objects) instead of filtering by existing privileges.

## Individual Comments

### Comment 1
<location path="macros/grants/grant_object.sql" line_range="3-4" />
<code_context>
 {% macro clean_objects(database=target.database, clean_targets=['local-dev', 'unit-test', 'test', 'prod'], object_types= ['schemas', 'functions_and_procedures', 'data_metric_functions', 'tasks', 'streams', 'stages', 'tables_and_views', 'alerts', 'file_formats', 'semantic_views', 'agents']) %}
     {%if execute %}
-        {% if flags.WHICH in ('run', 'run-operation') %}
+        {% if flags.WHICH in ['run', 'build', 'run-operation'] %}
             {% if target.name in clean_targets %}
                 {% set dry_run = false %}
</code_context>
<issue_to_address>
**issue (bug_risk):** The context guard logic is inverted and will skip in the contexts where it should run.

With the current condition, the macro runs in all non-`run`/`build`/`run-operation` contexts and only skips in those three, which reverses the intended guard. Please restore the `not in` check (optionally adding `build`) or relocate the log/return to the `else` block so it only runs in the intended contexts.
</issue_to_address>

### Comment 2
<location path="macros/grants/grant_object_application.sql" line_range="3-4" />
<code_context>
 {% macro clean_objects(database=target.database, clean_targets=['local-dev', 'unit-test', 'test', 'prod'], object_types= ['schemas', 'functions_and_procedures', 'data_metric_functions', 'tasks', 'streams', 'stages', 'tables_and_views', 'alerts', 'file_formats', 'semantic_views', 'agents']) %}
     {%if execute %}
-        {% if flags.WHICH in ('run', 'run-operation') %}
+        {% if flags.WHICH in ['run', 'build', 'run-operation'] %}
             {% if target.name in clean_targets %}
                 {% set dry_run = false %}
</code_context>
<issue_to_address>
**issue (bug_risk):** The WHEN to-run guard is reversed here as well, causing the macro to run in non-run contexts.

This mirrors the issue in `grant_object`: wrapping the "Skipping ... not run/run-operation context" branch in `if flags.WHICH in ['run', 'build', 'run-operation']` reverses the logic, so the macro is skipped in allowed contexts and runs otherwise. Suggest reverting to the original `not in` condition (adding `build` if needed), or moving the skip block into the `else` branch so it only triggers outside the allowed contexts.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread macros/grants/grant_object.sql Outdated
Comment thread macros/grants/grant_object_application.sql Outdated
The condition used 'in' but contained skip/return logic, meaning the
macros were skipping in valid contexts and running in invalid ones.
Restored to 'not in' to match the intended guard pattern.

.... Generated with [Cortex Code](https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code)

Co-Authored-By: Cortex Code <noreply@snowflake.com>
@jonhopper-dataengineers
jonhopper-dataengineers merged commit 4770e6f into main Jul 21, 2026
2 checks passed
@jonhopper-dataengineers
jonhopper-dataengineers deleted the fix/grant-partial-coverage-skip-bug branch July 21, 2026 03:10
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