diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/after/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/after/dataproducts/analytics/prod/product.yaml deleted file mode 100644 index 54f7923..0000000 --- a/e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/after/dataproducts/analytics/prod/product.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: analytics -kind: source-aligned -rover_group: dataverse-source-analytics -warehouses: -- type: user - size: MEDIUM -- type: service_account - size: XSMALL -service_account: - dbt: true -tags: - data_product: analytics -data_product_db: -- database: analytics_db - presentation_schemas: - - name: marts - consumers: - - kind: data_product - name: journey diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/after/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/after/dataproducts/analytics/prod/product.yaml deleted file mode 100644 index 75f3726..0000000 --- a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/after/dataproducts/analytics/prod/product.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: customer-analytics -kind: source-aligned -rover_group: dataverse-source-analytics -warehouses: -- type: user - size: SMALL -- type: service_account - size: XSMALL -service_account: - dbt: true -tags: - data_product: analytics - pii: true -data_product_db: -- database: customer_analytics_db - presentation_schemas: - - name: marts - consumers: [] diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/before/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/before/dataproducts/analytics/prod/product.yaml deleted file mode 100644 index 5206e87..0000000 --- a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/before/dataproducts/analytics/prod/product.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: customer-analytics -kind: source-aligned -rover_group: dataverse-source-analytics -warehouses: -- type: user - size: SMALL -- type: service_account - size: XSMALL -service_account: - dbt: true -tags: - data_product: analytics -data_product_db: -- database: customer_analytics_db - presentation_schemas: - - name: marts - consumers: [] diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/scenario.yaml b/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/scenario.yaml deleted file mode 100644 index c1d6650..0000000 --- a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_product_sections/scenario.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: "Metadata-only product sections update" -description: "Changes only to metadata sections (name, tags, rover_group) in product.yaml should be auto-approved" - -expected: - decision: Approve - reason: "All files passed validation - all changes covered by approved rules" - approved: true - - comment_contains: - - "✅ **Auto-approved**" - - "TOC approval check" - -mr_metadata: - title: "Update product metadata sections" - author: "testuser" - source_branch: "metadata/update-product-info" - target_branch: "main" diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_readme/scenario.yaml b/e2e/testdata/scenarios/01_single_rule_single_file/metadata_readme/scenario.yaml deleted file mode 100644 index c03597f..0000000 --- a/e2e/testdata/scenarios/01_single_rule_single_file/metadata_readme/scenario.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: "README documentation update" -description: "README.md updates should be auto-approved as metadata-only changes" - -expected: - decision: Approve - reason: "All files passed validation - all changes covered by approved rules" - approved: true - - rules_evaluated: - - name: metadata_rule - section: documentation - decision: Approve - - comment_contains: - - "✅ **Auto-approved**" - - "Metadata validated" - -mr_metadata: - title: "Update analytics product documentation" - author: "testuser" - source_branch: "docs/update-analytics-readme" - target_branch: "main" diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/expected_comment.txt b/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/expected_comment.txt deleted file mode 100644 index b69fc75..0000000 --- a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/expected_comment.txt +++ /dev/null @@ -1,7 +0,0 @@ - -✅ **Auto-approved** - -**What was checked:** -• ✅ Metadata validated -• ✅ TOC approval check -• ✅ Warehouse configuration validated diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/expected_comment.txt b/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/expected_comment.txt deleted file mode 100644 index 4fe6a89..0000000 --- a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/expected_comment.txt +++ /dev/null @@ -1,10 +0,0 @@ - -⚠️ **Manual review required** - -**Why manual review is needed:** -One or more files require manual review - -**What was checked:** -• ✅ Metadata validated -• ✅ TOC approval check -• 🚫 Warehouse configuration validated: Warehouse size increase detected: user warehouse: SMALL → MEDIUM diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/after/dataproducts/marketing/prod/product.yaml b/e2e/testdata/scenarios/01_warehouse_decrease/after/dataproducts/marketing/prod/product.yaml similarity index 100% rename from e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/after/dataproducts/marketing/prod/product.yaml rename to e2e/testdata/scenarios/01_warehouse_decrease/after/dataproducts/marketing/prod/product.yaml diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/before/dataproducts/marketing/prod/product.yaml b/e2e/testdata/scenarios/01_warehouse_decrease/before/dataproducts/marketing/prod/product.yaml similarity index 100% rename from e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/before/dataproducts/marketing/prod/product.yaml rename to e2e/testdata/scenarios/01_warehouse_decrease/before/dataproducts/marketing/prod/product.yaml diff --git a/e2e/testdata/scenarios/01_warehouse_decrease/expected_comment.txt b/e2e/testdata/scenarios/01_warehouse_decrease/expected_comment.txt new file mode 100644 index 0000000..26c87c0 --- /dev/null +++ b/e2e/testdata/scenarios/01_warehouse_decrease/expected_comment.txt @@ -0,0 +1,12 @@ + +✅ **Auto-approved** + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• ✅ TOC approval check: Changes to existing products in non-critical environments +• ✅ Warehouse configuration validated: Warehouse size decrease saves costs and is safe to auto-approve + +
diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/scenario.yaml b/e2e/testdata/scenarios/01_warehouse_decrease/scenario.yaml similarity index 100% rename from e2e/testdata/scenarios/01_single_rule_single_file/warehouse_decrease/scenario.yaml rename to e2e/testdata/scenarios/01_warehouse_decrease/scenario.yaml diff --git a/e2e/testdata/scenarios/02_toc_approval/toc_new_prod/scenario.yaml b/e2e/testdata/scenarios/02_toc_approval/toc_new_prod/scenario.yaml deleted file mode 100644 index ea0865c..0000000 --- a/e2e/testdata/scenarios/02_toc_approval/toc_new_prod/scenario.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: "NEW product in prod environment" -description: "Brand new product.yaml file in prod requires TOC approval before deployment" - -expected: - decision: ManualReview - reason: "One or more files require manual review" - approved: false - - rules_evaluated: - - name: toc_approval_rule - section: full_file - decision: ManualReview - reason: "New data product being promoted to prod environment requires TOC" - - comment_contains: - - "⚠️ **Manual review required**" - - "TOC (Technical Oversight Committee) approval" - - "prod environment" - -mr_metadata: - title: "Deploy new sales analytics product to production" - author: "testuser" - source_branch: "feature/new-sales-product" - target_branch: "main" diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/after/dataproducts/marketing/prod/product.yaml b/e2e/testdata/scenarios/02_warehouse_increase/after/dataproducts/marketing/prod/product.yaml similarity index 100% rename from e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/after/dataproducts/marketing/prod/product.yaml rename to e2e/testdata/scenarios/02_warehouse_increase/after/dataproducts/marketing/prod/product.yaml diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/before/dataproducts/marketing/prod/product.yaml b/e2e/testdata/scenarios/02_warehouse_increase/before/dataproducts/marketing/prod/product.yaml similarity index 100% rename from e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/before/dataproducts/marketing/prod/product.yaml rename to e2e/testdata/scenarios/02_warehouse_increase/before/dataproducts/marketing/prod/product.yaml diff --git a/e2e/testdata/scenarios/02_warehouse_increase/expected_comment.txt b/e2e/testdata/scenarios/02_warehouse_increase/expected_comment.txt new file mode 100644 index 0000000..dbf0619 --- /dev/null +++ b/e2e/testdata/scenarios/02_warehouse_increase/expected_comment.txt @@ -0,0 +1,15 @@ + +⚠️ **Manual review required** + +**Why manual review is needed:** +One or more files require manual review + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• ✅ TOC approval check: Changes to existing products in non-critical environments +• 🚫 Warehouse configuration validated: Warehouse size increase detected: user warehouse: SMALL → MEDIUM + +
diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/scenario.yaml b/e2e/testdata/scenarios/02_warehouse_increase/scenario.yaml similarity index 100% rename from e2e/testdata/scenarios/01_single_rule_single_file/warehouse_increase/scenario.yaml rename to e2e/testdata/scenarios/02_warehouse_increase/scenario.yaml diff --git a/e2e/testdata/scenarios/02_toc_approval/toc_new_prod/after/dataproducts/sales/prod/product.yaml b/e2e/testdata/scenarios/03_toc_new_prod/after/dataproducts/sales/prod/product.yaml similarity index 76% rename from e2e/testdata/scenarios/02_toc_approval/toc_new_prod/after/dataproducts/sales/prod/product.yaml rename to e2e/testdata/scenarios/03_toc_new_prod/after/dataproducts/sales/prod/product.yaml index fbd6800..0382314 100644 --- a/e2e/testdata/scenarios/02_toc_approval/toc_new_prod/after/dataproducts/sales/prod/product.yaml +++ b/e2e/testdata/scenarios/03_toc_new_prod/after/dataproducts/sales/prod/product.yaml @@ -1,7 +1,7 @@ --- name: sales-analytics kind: source-aligned -rover_group: dataverse-source-sales +rover_group: example-sales warehouses: - type: user size: LARGE @@ -11,8 +11,8 @@ service_account: dbt: true tags: data_product: sales + tier: production data_product_db: -- database: sales_db presentation_schemas: - - name: marts + - name: reporting consumers: [] diff --git a/e2e/testdata/scenarios/03_toc_new_prod/expected_comment.txt b/e2e/testdata/scenarios/03_toc_new_prod/expected_comment.txt new file mode 100644 index 0000000..4221a5d --- /dev/null +++ b/e2e/testdata/scenarios/03_toc_new_prod/expected_comment.txt @@ -0,0 +1,15 @@ + +⚠️ **Manual review required** + +**Why manual review is needed:** +One or more files require manual review + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• 🚫 TOC approval check: Manual review required: New data product being promoted to prod environment requires TOC (Technical Oversight Committee) approval before deployment +• 🚫 Warehouse configuration validated: Warehouse size increase detected: New user warehouse: LARGE, New service_account warehouse: XSMALL + +
diff --git a/e2e/testdata/scenarios/03_toc_new_prod/scenario.yaml b/e2e/testdata/scenarios/03_toc_new_prod/scenario.yaml new file mode 100644 index 0000000..5cf0da5 --- /dev/null +++ b/e2e/testdata/scenarios/03_toc_new_prod/scenario.yaml @@ -0,0 +1,17 @@ +name: "New product.yaml in prod" +description: "New product.yaml in prod environment requires TOC approval" + +expected: + decision: ManualReview + reason: "One or more files require manual review" + approved: false + + comment_contains: + - "⚠️ **Manual review required**" + - "TOC approval" + +mr_metadata: + title: "Deploy new sales-analytics product to production" + author: "testuser" + source_branch: "feature/new-sales-product" + target_branch: "main" diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/before/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/04_consumer_only_prod/after/dataproducts/analytics/prod/product.yaml similarity index 70% rename from e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/before/dataproducts/analytics/prod/product.yaml rename to e2e/testdata/scenarios/04_consumer_only_prod/after/dataproducts/analytics/prod/product.yaml index b0792fe..b9e15d4 100644 --- a/e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/before/dataproducts/analytics/prod/product.yaml +++ b/e2e/testdata/scenarios/04_consumer_only_prod/after/dataproducts/analytics/prod/product.yaml @@ -1,7 +1,7 @@ --- name: analytics kind: source-aligned -rover_group: dataverse-source-analytics +rover_group: example-analytics warehouses: - type: user size: MEDIUM @@ -12,7 +12,10 @@ service_account: tags: data_product: analytics data_product_db: -- database: analytics_db presentation_schemas: - name: marts + consumers: + - name: journey + kind: data_product + - name: staging consumers: [] diff --git a/e2e/testdata/scenarios/04_integration/integration_uncovered_lines/before/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/04_consumer_only_prod/before/dataproducts/analytics/prod/product.yaml similarity index 79% rename from e2e/testdata/scenarios/04_integration/integration_uncovered_lines/before/dataproducts/analytics/prod/product.yaml rename to e2e/testdata/scenarios/04_consumer_only_prod/before/dataproducts/analytics/prod/product.yaml index b0792fe..75478cd 100644 --- a/e2e/testdata/scenarios/04_integration/integration_uncovered_lines/before/dataproducts/analytics/prod/product.yaml +++ b/e2e/testdata/scenarios/04_consumer_only_prod/before/dataproducts/analytics/prod/product.yaml @@ -1,7 +1,7 @@ --- name: analytics kind: source-aligned -rover_group: dataverse-source-analytics +rover_group: example-analytics warehouses: - type: user size: MEDIUM @@ -12,7 +12,8 @@ service_account: tags: data_product: analytics data_product_db: -- database: analytics_db presentation_schemas: - name: marts consumers: [] + - name: staging + consumers: [] diff --git a/e2e/testdata/scenarios/04_consumer_only_prod/expected_comment.txt b/e2e/testdata/scenarios/04_consumer_only_prod/expected_comment.txt new file mode 100644 index 0000000..480cb9e --- /dev/null +++ b/e2e/testdata/scenarios/04_consumer_only_prod/expected_comment.txt @@ -0,0 +1,10 @@ + +✅ **Auto-approved** + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ TOC approval check: Changes to existing products in non-critical environments + +
diff --git a/e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/scenario.yaml b/e2e/testdata/scenarios/04_consumer_only_prod/scenario.yaml similarity index 60% rename from e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/scenario.yaml rename to e2e/testdata/scenarios/04_consumer_only_prod/scenario.yaml index 145d808..939cced 100644 --- a/e2e/testdata/scenarios/01_single_rule_single_file/consumer_only_prod/scenario.yaml +++ b/e2e/testdata/scenarios/04_consumer_only_prod/scenario.yaml @@ -1,19 +1,13 @@ name: "Consumer-only changes in prod" -description: "Adding consumers to product.yaml should auto-approve (owner approval sufficient, no TOC needed)" +description: "Consumer-only changes should be auto-approved (owner approval sufficient)" expected: decision: Approve reason: "All files passed validation - all changes covered by approved rules" approved: true - rules_evaluated: - - name: dataproduct_consumer_rule - section: consumers - decision: Approve - comment_contains: - "✅ **Auto-approved**" - - "TOC approval check" mr_metadata: title: "Grant journey product access to analytics data" diff --git a/e2e/testdata/scenarios/04_integration/integration_uncovered_lines/scenario.yaml b/e2e/testdata/scenarios/04_integration/integration_uncovered_lines/scenario.yaml deleted file mode 100644 index 0083e1d..0000000 --- a/e2e/testdata/scenarios/04_integration/integration_uncovered_lines/scenario.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: "Uncovered lines trigger manual review" -description: "Files with lines not covered by any validation rule must require manual review (strict coverage policy)" - -expected: - decision: ManualReview - reason: "One or more files require manual review" - approved: false - - rules_evaluated: - - name: metadata_rule - section: name - decision: Approve - - name: metadata_rule - section: tags - decision: Approve - - comment_contains: - - "⚠️ **Manual review required**" - - "manual review" - -mr_metadata: - title: "Update product with uncovered sections" - author: "testuser" - source_branch: "feature/product-with-uncovered-sections" - target_branch: "main" diff --git a/e2e/testdata/scenarios/05_metadata_readme/after/dataproducts/analytics/README.md b/e2e/testdata/scenarios/05_metadata_readme/after/dataproducts/analytics/README.md new file mode 100644 index 0000000..4866414 --- /dev/null +++ b/e2e/testdata/scenarios/05_metadata_readme/after/dataproducts/analytics/README.md @@ -0,0 +1,18 @@ +# Analytics Product + +## Overview + +This is the analytics data product for our organization. + +## Setup Instructions + +New and improved setup instructions with detailed steps: + +1. Clone the repository +2. Configure your environment +3. Run the initialization script +4. Verify the setup + +## Contact + +Data Team - analytics@example.com diff --git a/e2e/testdata/scenarios/05_metadata_readme/before/dataproducts/analytics/README.md b/e2e/testdata/scenarios/05_metadata_readme/before/dataproducts/analytics/README.md new file mode 100644 index 0000000..6d446be --- /dev/null +++ b/e2e/testdata/scenarios/05_metadata_readme/before/dataproducts/analytics/README.md @@ -0,0 +1,13 @@ +# Analytics Product + +## Overview + +This is the analytics data product for our organization. + +## Setup Instructions + +Old setup instructions go here. + +## Contact + +Data Team diff --git a/e2e/testdata/scenarios/05_metadata_readme/expected_comment.txt b/e2e/testdata/scenarios/05_metadata_readme/expected_comment.txt new file mode 100644 index 0000000..673b692 --- /dev/null +++ b/e2e/testdata/scenarios/05_metadata_readme/expected_comment.txt @@ -0,0 +1,10 @@ + +✅ **Auto-approved** + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure + +
diff --git a/e2e/testdata/scenarios/05_metadata_readme/scenario.yaml b/e2e/testdata/scenarios/05_metadata_readme/scenario.yaml new file mode 100644 index 0000000..fe42cff --- /dev/null +++ b/e2e/testdata/scenarios/05_metadata_readme/scenario.yaml @@ -0,0 +1,16 @@ +name: "README.md update" +description: "README updates should be auto-approved (documentation only)" + +expected: + decision: Approve + reason: "All files passed validation - all changes covered by approved rules" + approved: true + + comment_contains: + - "✅ **Auto-approved**" + +mr_metadata: + title: "Update README with new setup instructions" + author: "testuser" + source_branch: "feature/update-docs" + target_branch: "main" diff --git a/e2e/testdata/scenarios/06_metadata_product_sections/after/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/06_metadata_product_sections/after/dataproducts/analytics/prod/product.yaml new file mode 100644 index 0000000..312d29f --- /dev/null +++ b/e2e/testdata/scenarios/06_metadata_product_sections/after/dataproducts/analytics/prod/product.yaml @@ -0,0 +1,7 @@ +--- +name: analytics-v2 +kind: source-aligned +rover_group: example-analytics +tags: + data_product: analytics + pii: true diff --git a/e2e/testdata/scenarios/06_metadata_product_sections/before/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/06_metadata_product_sections/before/dataproducts/analytics/prod/product.yaml new file mode 100644 index 0000000..9cad609 --- /dev/null +++ b/e2e/testdata/scenarios/06_metadata_product_sections/before/dataproducts/analytics/prod/product.yaml @@ -0,0 +1,6 @@ +--- +name: analytics +kind: source-aligned +rover_group: example-analytics +tags: + data_product: analytics diff --git a/e2e/testdata/scenarios/06_metadata_product_sections/expected_comment.txt b/e2e/testdata/scenarios/06_metadata_product_sections/expected_comment.txt new file mode 100644 index 0000000..9b7a68b --- /dev/null +++ b/e2e/testdata/scenarios/06_metadata_product_sections/expected_comment.txt @@ -0,0 +1,11 @@ + +✅ **Auto-approved** + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• ✅ TOC approval check: Changes to existing products in non-critical environments + +
diff --git a/e2e/testdata/scenarios/06_metadata_product_sections/scenario.yaml b/e2e/testdata/scenarios/06_metadata_product_sections/scenario.yaml new file mode 100644 index 0000000..e46f3d0 --- /dev/null +++ b/e2e/testdata/scenarios/06_metadata_product_sections/scenario.yaml @@ -0,0 +1,16 @@ +name: "Metadata-only sections in product.yaml" +description: "Metadata-only sections (name, tags) should be auto-approved" + +expected: + decision: Approve + reason: "All files passed validation - all changes covered by approved rules" + approved: true + + comment_contains: + - "✅ **Auto-approved**" + +mr_metadata: + title: "Update product name and add PII tag" + author: "testuser" + source_branch: "feature/update-metadata" + target_branch: "main" diff --git a/e2e/testdata/scenarios/07_integration_uncovered_lines/after/migrations/001_add_column.sql b/e2e/testdata/scenarios/07_integration_uncovered_lines/after/migrations/001_add_column.sql new file mode 100644 index 0000000..0f628cb --- /dev/null +++ b/e2e/testdata/scenarios/07_integration_uncovered_lines/after/migrations/001_add_column.sql @@ -0,0 +1,3 @@ +-- Migration: Add email column to users table +ALTER TABLE users ADD COLUMN email VARCHAR(255); +CREATE INDEX idx_users_email ON users(email); diff --git a/e2e/testdata/scenarios/07_integration_uncovered_lines/expected_comment.txt b/e2e/testdata/scenarios/07_integration_uncovered_lines/expected_comment.txt new file mode 100644 index 0000000..e4e51de --- /dev/null +++ b/e2e/testdata/scenarios/07_integration_uncovered_lines/expected_comment.txt @@ -0,0 +1,14 @@ + +⚠️ **Manual review required** + +**Why manual review is needed:** + +This MR contains files that Naysayer doesn't know how to validate. + +
+Files requiring manual approval (no automated rules configured) (1 file) + +**No validation rules configured for SQL migrations** (1 file) +- `migrations/001_add_column.sql` + +
diff --git a/e2e/testdata/scenarios/07_integration_uncovered_lines/scenario.yaml b/e2e/testdata/scenarios/07_integration_uncovered_lines/scenario.yaml new file mode 100644 index 0000000..e2e14f0 --- /dev/null +++ b/e2e/testdata/scenarios/07_integration_uncovered_lines/scenario.yaml @@ -0,0 +1,16 @@ +name: "Unknown file type requires manual review" +description: "Files without section configuration should trigger manual review (strict coverage policy)" + +expected: + decision: ManualReview + reason: "One or more files require manual review" + approved: false + + comment_contains: + - "⚠️ **Manual review required**" + +mr_metadata: + title: "Add SQL migration script" + author: "testuser" + source_branch: "feature/add-migration" + target_branch: "main" diff --git a/e2e/testdata/scenarios/04_integration/integration_uncovered_lines/after/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/after/dataproducts/analytics/prod/product.yaml similarity index 56% rename from e2e/testdata/scenarios/04_integration/integration_uncovered_lines/after/dataproducts/analytics/prod/product.yaml rename to e2e/testdata/scenarios/08_warehouse_multiple_mixed/after/dataproducts/analytics/prod/product.yaml index 4d72151..58d76c0 100644 --- a/e2e/testdata/scenarios/04_integration/integration_uncovered_lines/after/dataproducts/analytics/prod/product.yaml +++ b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/after/dataproducts/analytics/prod/product.yaml @@ -1,7 +1,7 @@ --- name: analytics kind: source-aligned -rover_group: dataverse-source-analytics +rover_group: example-analytics warehouses: - type: user size: LARGE @@ -11,8 +11,3 @@ service_account: dbt: true tags: data_product: analytics -data_product_db: -- database: analytics_db - presentation_schemas: - - name: marts - consumers: [] diff --git a/e2e/testdata/scenarios/08_warehouse_multiple_mixed/before/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/before/dataproducts/analytics/prod/product.yaml new file mode 100644 index 0000000..fa80c01 --- /dev/null +++ b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/before/dataproducts/analytics/prod/product.yaml @@ -0,0 +1,13 @@ +--- +name: analytics +kind: source-aligned +rover_group: example-analytics +warehouses: +- type: user + size: MEDIUM +- type: service_account + size: SMALL +service_account: + dbt: true +tags: + data_product: analytics diff --git a/e2e/testdata/scenarios/08_warehouse_multiple_mixed/expected_comment.txt b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/expected_comment.txt new file mode 100644 index 0000000..5c5c864 --- /dev/null +++ b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/expected_comment.txt @@ -0,0 +1,15 @@ + +⚠️ **Manual review required** + +**Why manual review is needed:** +One or more files require manual review + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• ✅ TOC approval check: Changes to existing products in non-critical environments +• 🚫 Warehouse configuration validated: Warehouse size increase detected: user warehouse: MEDIUM → LARGE + +
diff --git a/e2e/testdata/scenarios/08_warehouse_multiple_mixed/scenario.yaml b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/scenario.yaml new file mode 100644 index 0000000..2f4ae94 --- /dev/null +++ b/e2e/testdata/scenarios/08_warehouse_multiple_mixed/scenario.yaml @@ -0,0 +1,17 @@ +name: "Multiple warehouses with mixed changes" +description: "Multiple warehouses - some increase, some decrease - should require manual review (conservative)" + +expected: + decision: ManualReview + reason: "One or more files require manual review" + approved: false + + comment_contains: + - "⚠️ **Manual review required**" + - "Warehouse" + +mr_metadata: + title: "Rebalance warehouse resources" + author: "testuser" + source_branch: "feature/rebalance-warehouses" + target_branch: "main" diff --git a/e2e/testdata/scenarios/09_toc_new_preprod/after/dataproducts/sales/preprod/product.yaml b/e2e/testdata/scenarios/09_toc_new_preprod/after/dataproducts/sales/preprod/product.yaml new file mode 100644 index 0000000..c3d5871 --- /dev/null +++ b/e2e/testdata/scenarios/09_toc_new_preprod/after/dataproducts/sales/preprod/product.yaml @@ -0,0 +1,14 @@ +--- +name: sales-analytics +kind: source-aligned +rover_group: example-sales +warehouses: +- type: user + size: MEDIUM +- type: service_account + size: XSMALL +service_account: + dbt: true +tags: + data_product: sales + tier: preprod diff --git a/e2e/testdata/scenarios/09_toc_new_preprod/expected_comment.txt b/e2e/testdata/scenarios/09_toc_new_preprod/expected_comment.txt new file mode 100644 index 0000000..5b83aa4 --- /dev/null +++ b/e2e/testdata/scenarios/09_toc_new_preprod/expected_comment.txt @@ -0,0 +1,15 @@ + +⚠️ **Manual review required** + +**Why manual review is needed:** +One or more files require manual review + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• 🚫 TOC approval check: Manual review required: New data product being promoted to preprod environment requires TOC (Technical Oversight Committee) approval before deployment +• 🚫 Warehouse configuration validated: Warehouse size increase detected: New user warehouse: MEDIUM, New service_account warehouse: XSMALL + +
diff --git a/e2e/testdata/scenarios/09_toc_new_preprod/scenario.yaml b/e2e/testdata/scenarios/09_toc_new_preprod/scenario.yaml new file mode 100644 index 0000000..4e10bb0 --- /dev/null +++ b/e2e/testdata/scenarios/09_toc_new_preprod/scenario.yaml @@ -0,0 +1,17 @@ +name: "New product.yaml in preprod" +description: "New product.yaml in preprod environment requires TOC approval" + +expected: + decision: ManualReview + reason: "One or more files require manual review" + approved: false + + comment_contains: + - "⚠️ **Manual review required**" + - "TOC approval" + +mr_metadata: + title: "Deploy new sales-analytics product to preprod" + author: "testuser" + source_branch: "feature/new-sales-preprod" + target_branch: "main" diff --git a/e2e/testdata/scenarios/10_consumer_multiple_schemas/after/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/10_consumer_multiple_schemas/after/dataproducts/analytics/prod/product.yaml new file mode 100644 index 0000000..7e5ea7c --- /dev/null +++ b/e2e/testdata/scenarios/10_consumer_multiple_schemas/after/dataproducts/analytics/prod/product.yaml @@ -0,0 +1,14 @@ +--- +name: analytics +kind: source-aligned +rover_group: example-analytics +data_product_db: + presentation_schemas: + - name: marts + consumers: + - name: journey + kind: data_product + - name: staging + consumers: + - name: reporting + kind: data_product diff --git a/e2e/testdata/scenarios/10_consumer_multiple_schemas/before/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/10_consumer_multiple_schemas/before/dataproducts/analytics/prod/product.yaml new file mode 100644 index 0000000..b1ad217 --- /dev/null +++ b/e2e/testdata/scenarios/10_consumer_multiple_schemas/before/dataproducts/analytics/prod/product.yaml @@ -0,0 +1,10 @@ +--- +name: analytics +kind: source-aligned +rover_group: example-analytics +data_product_db: + presentation_schemas: + - name: marts + consumers: [] + - name: staging + consumers: [] diff --git a/e2e/testdata/scenarios/10_consumer_multiple_schemas/expected_comment.txt b/e2e/testdata/scenarios/10_consumer_multiple_schemas/expected_comment.txt new file mode 100644 index 0000000..480cb9e --- /dev/null +++ b/e2e/testdata/scenarios/10_consumer_multiple_schemas/expected_comment.txt @@ -0,0 +1,10 @@ + +✅ **Auto-approved** + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ TOC approval check: Changes to existing products in non-critical environments + +
diff --git a/e2e/testdata/scenarios/10_consumer_multiple_schemas/scenario.yaml b/e2e/testdata/scenarios/10_consumer_multiple_schemas/scenario.yaml new file mode 100644 index 0000000..a2666e8 --- /dev/null +++ b/e2e/testdata/scenarios/10_consumer_multiple_schemas/scenario.yaml @@ -0,0 +1,16 @@ +name: "Consumers in multiple presentation schemas" +description: "Consumer changes in multiple schemas should be auto-approved" + +expected: + decision: Approve + reason: "All files passed validation - all changes covered by approved rules" + approved: true + + comment_contains: + - "✅ **Auto-approved**" + +mr_metadata: + title: "Grant access to journey and reporting products" + author: "testuser" + source_branch: "feature/add-multiple-consumers" + target_branch: "main" diff --git a/e2e/testdata/scenarios/11_metadata_sourcebinding/after/dataproducts/analytics/prod/sourcebinding.yaml b/e2e/testdata/scenarios/11_metadata_sourcebinding/after/dataproducts/analytics/prod/sourcebinding.yaml new file mode 100644 index 0000000..8d6be6b --- /dev/null +++ b/e2e/testdata/scenarios/11_metadata_sourcebinding/after/dataproducts/analytics/prod/sourcebinding.yaml @@ -0,0 +1,4 @@ +--- +source: new_database +table: customers_v2 +schema: public diff --git a/e2e/testdata/scenarios/11_metadata_sourcebinding/before/dataproducts/analytics/prod/sourcebinding.yaml b/e2e/testdata/scenarios/11_metadata_sourcebinding/before/dataproducts/analytics/prod/sourcebinding.yaml new file mode 100644 index 0000000..268beb6 --- /dev/null +++ b/e2e/testdata/scenarios/11_metadata_sourcebinding/before/dataproducts/analytics/prod/sourcebinding.yaml @@ -0,0 +1,3 @@ +--- +source: old_database +table: customers_v1 diff --git a/e2e/testdata/scenarios/11_metadata_sourcebinding/expected_comment.txt b/e2e/testdata/scenarios/11_metadata_sourcebinding/expected_comment.txt new file mode 100644 index 0000000..673b692 --- /dev/null +++ b/e2e/testdata/scenarios/11_metadata_sourcebinding/expected_comment.txt @@ -0,0 +1,10 @@ + +✅ **Auto-approved** + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure + +
diff --git a/e2e/testdata/scenarios/11_metadata_sourcebinding/scenario.yaml b/e2e/testdata/scenarios/11_metadata_sourcebinding/scenario.yaml new file mode 100644 index 0000000..61df220 --- /dev/null +++ b/e2e/testdata/scenarios/11_metadata_sourcebinding/scenario.yaml @@ -0,0 +1,16 @@ +name: "Update sourcebinding.yaml" +description: "Sourcebinding updates should be auto-approved (safe config file)" + +expected: + decision: Approve + reason: "All files passed validation - all changes covered by approved rules" + approved: true + + comment_contains: + - "✅ **Auto-approved**" + +mr_metadata: + title: "Update source binding configuration" + author: "testuser" + source_branch: "feature/update-sourcebinding" + target_branch: "main" diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/CHANGELOG.md b/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/CHANGELOG.md new file mode 100644 index 0000000..9bc8c71 --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +## v1.1 +- Updated documentation + +## v1.0 +- Initial release diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/README.md b/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/README.md new file mode 100644 index 0000000..8f2ef95 --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/README.md @@ -0,0 +1,3 @@ +# Analytics Product + +New documentation with updated instructions diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/prod/product.yaml new file mode 100644 index 0000000..446a732 --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/after/dataproducts/analytics/prod/product.yaml @@ -0,0 +1,5 @@ +--- +name: analytics +warehouses: +- type: user + size: SMALL diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/CHANGELOG.md b/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/CHANGELOG.md new file mode 100644 index 0000000..43b61f4 --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/CHANGELOG.md @@ -0,0 +1,4 @@ +# Changelog + +## v1.0 +- Initial release diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/README.md b/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/README.md new file mode 100644 index 0000000..ea86ee6 --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/README.md @@ -0,0 +1,3 @@ +# Analytics Product + +Old documentation diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/prod/product.yaml b/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/prod/product.yaml new file mode 100644 index 0000000..c71d693 --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/before/dataproducts/analytics/prod/product.yaml @@ -0,0 +1,5 @@ +--- +name: analytics +warehouses: +- type: user + size: MEDIUM diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/expected_comment.txt b/e2e/testdata/scenarios/12_integration_multi_file_approve/expected_comment.txt new file mode 100644 index 0000000..2371c35 --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/expected_comment.txt @@ -0,0 +1,17 @@ + +✅ **Auto-approved** + +
+📋 Analysis Details (click to expand) + +**Files in this MR:** +• `dataproducts/analytics/CHANGELOG.md` ✅ +• `dataproducts/analytics/README.md` ✅ +• `dataproducts/analytics/prod/product.yaml` ✅ + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• ✅ TOC approval check: Changes to existing products in non-critical environments +• ✅ Warehouse configuration validated: Warehouse size decrease saves costs and is safe to auto-approve + +
diff --git a/e2e/testdata/scenarios/12_integration_multi_file_approve/scenario.yaml b/e2e/testdata/scenarios/12_integration_multi_file_approve/scenario.yaml new file mode 100644 index 0000000..15ed9fb --- /dev/null +++ b/e2e/testdata/scenarios/12_integration_multi_file_approve/scenario.yaml @@ -0,0 +1,16 @@ +name: "Multiple files all auto-approve" +description: "Multiple files where all should auto-approve (documentation release)" + +expected: + decision: Approve + reason: "All files passed validation - all changes covered by approved rules" + approved: true + + comment_contains: + - "✅ **Auto-approved**" + +mr_metadata: + title: "Documentation release with multiple updates" + author: "testuser" + source_branch: "feature/docs-release" + target_branch: "main" diff --git a/e2e/testdata/scenarios/13_integration_multi_file_mixed/after/dataproducts/analytics/README.md b/e2e/testdata/scenarios/13_integration_multi_file_mixed/after/dataproducts/analytics/README.md new file mode 100644 index 0000000..4fd0e6e --- /dev/null +++ b/e2e/testdata/scenarios/13_integration_multi_file_mixed/after/dataproducts/analytics/README.md @@ -0,0 +1,3 @@ +# Analytics Product + +Updated documentation diff --git a/e2e/testdata/scenarios/13_integration_multi_file_mixed/after/dataproducts/newproduct/prod/product.yaml b/e2e/testdata/scenarios/13_integration_multi_file_mixed/after/dataproducts/newproduct/prod/product.yaml new file mode 100644 index 0000000..83d04ba --- /dev/null +++ b/e2e/testdata/scenarios/13_integration_multi_file_mixed/after/dataproducts/newproduct/prod/product.yaml @@ -0,0 +1,6 @@ +--- +name: newproduct +kind: source-aligned +warehouses: +- type: user + size: LARGE diff --git a/e2e/testdata/scenarios/13_integration_multi_file_mixed/before/dataproducts/analytics/README.md b/e2e/testdata/scenarios/13_integration_multi_file_mixed/before/dataproducts/analytics/README.md new file mode 100644 index 0000000..fcd637f --- /dev/null +++ b/e2e/testdata/scenarios/13_integration_multi_file_mixed/before/dataproducts/analytics/README.md @@ -0,0 +1,3 @@ +# Analytics Product + +Documentation diff --git a/e2e/testdata/scenarios/13_integration_multi_file_mixed/expected_comment.txt b/e2e/testdata/scenarios/13_integration_multi_file_mixed/expected_comment.txt new file mode 100644 index 0000000..c8fd8a6 --- /dev/null +++ b/e2e/testdata/scenarios/13_integration_multi_file_mixed/expected_comment.txt @@ -0,0 +1,15 @@ + +⚠️ **Manual review required** + +**Why manual review is needed:** +One or more files require manual review + +
+📋 Analysis Details (click to expand) + +**What was checked:** +• ✅ Metadata validated: Product metadata changes (name, tags, kind) are safe and don't affect infrastructure +• 🚫 TOC approval check: Manual review required: New data product being promoted to prod environment requires TOC (Technical Oversight Committee) approval before deployment +• 🚫 Warehouse configuration validated: Warehouse size increase detected: New user warehouse: LARGE + +
diff --git a/e2e/testdata/scenarios/13_integration_multi_file_mixed/scenario.yaml b/e2e/testdata/scenarios/13_integration_multi_file_mixed/scenario.yaml new file mode 100644 index 0000000..32c310d --- /dev/null +++ b/e2e/testdata/scenarios/13_integration_multi_file_mixed/scenario.yaml @@ -0,0 +1,16 @@ +name: "Multiple files with mixed decisions" +description: "Multiple files where one requires manual review (conservative MR decision)" + +expected: + decision: ManualReview + reason: "One or more files require manual review" + approved: false + + comment_contains: + - "⚠️ **Manual review required**" + +mr_metadata: + title: "Documentation update with new production product" + author: "testuser" + source_branch: "feature/mixed-changes" + target_branch: "main" diff --git a/e2e/testdata/scenarios/14_integration_unknown_filetype/after/scripts/process_data.py b/e2e/testdata/scenarios/14_integration_unknown_filetype/after/scripts/process_data.py new file mode 100644 index 0000000..ac08ccb --- /dev/null +++ b/e2e/testdata/scenarios/14_integration_unknown_filetype/after/scripts/process_data.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +"""Data processing script""" + +def process_data(): + print("Processing data...") + +if __name__ == "__main__": + process_data() diff --git a/e2e/testdata/scenarios/14_integration_unknown_filetype/expected_comment.txt b/e2e/testdata/scenarios/14_integration_unknown_filetype/expected_comment.txt new file mode 100644 index 0000000..624c6c2 --- /dev/null +++ b/e2e/testdata/scenarios/14_integration_unknown_filetype/expected_comment.txt @@ -0,0 +1,14 @@ + +⚠️ **Manual review required** + +**Why manual review is needed:** + +This MR contains files that Naysayer doesn't know how to validate. + +
+Files requiring manual approval (no automated rules configured) (1 file) + +**No validation rules configured for Python scripts** (1 file) +- `scripts/process_data.py` + +
diff --git a/e2e/testdata/scenarios/14_integration_unknown_filetype/scenario.yaml b/e2e/testdata/scenarios/14_integration_unknown_filetype/scenario.yaml new file mode 100644 index 0000000..1239e5b --- /dev/null +++ b/e2e/testdata/scenarios/14_integration_unknown_filetype/scenario.yaml @@ -0,0 +1,16 @@ +name: "Unknown file type Python script" +description: "Unknown file types (.py) should require manual review (strict policy)" + +expected: + decision: ManualReview + reason: "One or more files require manual review" + approved: false + + comment_contains: + - "⚠️ **Manual review required**" + +mr_metadata: + title: "Add Python data processing script" + author: "testuser" + source_branch: "feature/add-python-script" + target_branch: "main" diff --git a/internal/webhook/messages.go b/internal/webhook/messages.go index 62a40e7..d3c86a5 100644 --- a/internal/webhook/messages.go +++ b/internal/webhook/messages.go @@ -79,6 +79,10 @@ func (mb *MessageBuilder) buildBasicSummary(result *shared.RuleEvaluation) strin func (mb *MessageBuilder) buildDetailedSummary(result *shared.RuleEvaluation) string { var summary strings.Builder + // Collapsible section for cleaner comments + summary.WriteString("
\n") + summary.WriteString("📋 Analysis Details (click to expand)\n\n") + // File list if 3+ files if result.TotalFiles >= 3 { if filesSummary := mb.buildFilesSummary(result); filesSummary != "" { @@ -92,6 +96,8 @@ func (mb *MessageBuilder) buildDetailedSummary(result *shared.RuleEvaluation) st summary.WriteString("**What was checked:**\n") summary.WriteString(mb.buildRulesSummary(result.FileValidations)) + summary.WriteString("\n
") + return summary.String() } @@ -145,7 +151,8 @@ func (mb *MessageBuilder) buildRulesSummary(fileValidations map[string]*shared.F case shared.Approve: // Only store if not already present if _, exists := ruleMessages[ruleName]; !exists { - ruleMessages[ruleName] = fmt.Sprintf("✅ %s", ruleName) + explanation := mb.getApprovalExplanation(ruleResult.RuleName, ruleResult.Reason) + ruleMessages[ruleName] = fmt.Sprintf("✅ %s%s", ruleName, explanation) } case shared.ManualReview: // Manual review messages always override @@ -188,10 +195,11 @@ func (mb *MessageBuilder) isNoiseMessage(message string) bool { // formatRuleName converts internal rule names to user-friendly descriptions func (mb *MessageBuilder) formatRuleName(ruleName string) string { friendlyNames := map[string]string{ - "warehouse_rule": "Warehouse configuration validated", - "service_account_rule": "Service account validated", - "toc_approval_rule": "TOC approval check", - "metadata_rule": "Metadata validated", + "warehouse_rule": "Warehouse configuration validated", + "service_account_rule": "Service account validated", + "toc_approval_rule": "TOC approval check", + "metadata_rule": "Metadata validated", + "dataproduct_consumer_rule": "Consumer access changes validated", } if friendly, ok := friendlyNames[ruleName]; ok { @@ -200,6 +208,27 @@ func (mb *MessageBuilder) formatRuleName(ruleName string) string { return ruleName } +// getApprovalExplanation provides meaningful context for why a rule auto-approved +func (mb *MessageBuilder) getApprovalExplanation(ruleName string, reason string) string { + switch ruleName { + case "metadata_rule": + return ": Product metadata changes (name, tags, kind) are safe and don't affect infrastructure" + case "dataproduct_consumer_rule": + return ": Data product owner can grant consumer access without TOC approval" + case "warehouse_rule": + if strings.Contains(reason, "decrease") { + return ": Warehouse size decrease saves costs and is safe to auto-approve" + } + return ": Warehouse configuration changes validated" + case "toc_approval_rule": + return ": Changes to existing products in non-critical environments" + case "service_account_rule": + return ": Service account configuration is valid" + default: + return "" + } +} + // hasUncoveredFiles checks if there are files without validation rules func (mb *MessageBuilder) hasUncoveredFiles(result *shared.RuleEvaluation) bool { for _, fileValidation := range result.FileValidations { @@ -274,7 +303,16 @@ func (mb *MessageBuilder) buildDetailedRulesSummary(fileValidations map[string]* func (mb *MessageBuilder) buildFilesSummary(result *shared.RuleEvaluation) string { var summary strings.Builder - for filePath, fileValidation := range result.FileValidations { + // Collect and sort file paths + var filePaths []string + for filePath := range result.FileValidations { + filePaths = append(filePaths, filePath) + } + sort.Strings(filePaths) + + // Output sorted file list + for _, filePath := range filePaths { + fileValidation := result.FileValidations[filePath] summary.WriteString(fmt.Sprintf("• `%s`", filePath)) // Add decision status @@ -295,7 +333,16 @@ func (mb *MessageBuilder) buildFilesSummary(result *shared.RuleEvaluation) strin func (mb *MessageBuilder) buildDetailedFilesSummary(result *shared.RuleEvaluation) string { var summary strings.Builder - for filePath, fileValidation := range result.FileValidations { + // Collect and sort file paths + var filePaths []string + for filePath := range result.FileValidations { + filePaths = append(filePaths, filePath) + } + sort.Strings(filePaths) + + // Output sorted detailed file list + for _, filePath := range filePaths { + fileValidation := result.FileValidations[filePath] summary.WriteString(fmt.Sprintf("**File: `%s`**\n", filePath)) summary.WriteString(fmt.Sprintf("• Total lines: %d\n", fileValidation.TotalLines)) summary.WriteString(fmt.Sprintf("• Decision: %s\n", fileValidation.FileDecision)) @@ -372,26 +419,71 @@ func (mb *MessageBuilder) buildDetailedManualReviewSummary(result *shared.RuleEv // Enhanced decision with WHY explanation if mb.hasUncoveredFiles(result) { - summary.WriteString("**Why manual review is needed:**\n") - summary.WriteString("This MR contains files that Naysayer doesn't know how to validate\n\n") + summary.WriteString("**Why manual review is needed:**\n\n") + summary.WriteString("This MR contains files that Naysayer doesn't know how to validate.\n\n") - summary.WriteString("**Files needing review:**\n") + // Group files by reason + filesByReason := make(map[string][]string) for filePath, fileValidation := range result.FileValidations { if fileValidation.FileDecision == shared.ManualReview && len(fileValidation.RuleResults) == 0 { - summary.WriteString(fmt.Sprintf("• `%s` - %s\n", filePath, mb.getUncoveredReason(filePath))) + reason := mb.getUncoveredReason(filePath) + filesByReason[reason] = append(filesByReason[reason], filePath) } } + + // Sort reasons alphabetically + var reasons []string + for reason := range filesByReason { + reasons = append(reasons, reason) + } + sort.Strings(reasons) + + // Use collapsible details for long lists + totalFiles := 0 + for _, files := range filesByReason { + totalFiles += len(files) + } + + // Always use collapsible section for file lists + summary.WriteString("
\n") + summary.WriteString(fmt.Sprintf("Files requiring manual approval (no automated rules configured) (%d file", totalFiles)) + if totalFiles != 1 { + summary.WriteString("s") + } + summary.WriteString(")\n\n") + + for _, reason := range reasons { + files := filesByReason[reason] + sort.Strings(files) + summary.WriteString(fmt.Sprintf("**%s** (%d file", reason, len(files))) + if len(files) != 1 { + summary.WriteString("s") + } + summary.WriteString(")\n") + for _, filePath := range files { + summary.WriteString(fmt.Sprintf("- `%s`\n", filePath)) + } + summary.WriteString("\n") + } + summary.WriteString("
\n") } else { - summary.WriteString(fmt.Sprintf("**Why manual review is needed:**\n%s\n", result.FinalDecision.Reason)) + summary.WriteString(fmt.Sprintf("**Why manual review is needed:**\n%s\n\n", result.FinalDecision.Reason)) + + // Collapsible section for analysis details + summary.WriteString("
\n") + summary.WriteString("📋 Analysis Details (click to expand)\n\n") // Show file list if 3+ files if result.TotalFiles >= 3 { - summary.WriteString("\n**Files in this MR:**\n") + summary.WriteString("**Files in this MR:**\n") summary.WriteString(mb.buildFilesSummary(result)) + summary.WriteString("\n") } - summary.WriteString("\n**What was checked:**\n") + summary.WriteString("**What was checked:**\n") summary.WriteString(mb.buildRulesSummary(result.FileValidations)) + + summary.WriteString("\n
") } return summary.String()