From 3840f09a5e52c0578eb90d7a657387329ad64411 Mon Sep 17 00:00:00 2001 From: Chris H-C Date: Mon, 10 Aug 2026 15:32:05 -0400 Subject: [PATCH] bug 2062403 - Allow 'subcategories' longer than 29 characters --- CHANGELOG.md | 1 + .../schemas/metrics.2-0-0.schema.yaml | 2 +- tests/data/categories.yaml | 22 +++++++++++++ tests/data/schema-violation.yaml | 5 ++- tests/test_parser.py | 31 +++++++++++++++++++ 5 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/data/categories.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c2d3ffb0..5d4e09b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - BREAKING CHANGE: Generate labeled {custom|memory|timing} distribution for mobile ([#857](https://github.com/mozilla/glean_parser/pull/857)) +- Allow categories to have subcategories longer than 29 characters ([bug 2062403](https://bugzilla.mozilla.org/show_bug.cgi?id=2062403)) ## 20.2.0 - Allow renaming of fields when serializing metrics ([mozilla/glean-dictionary#2309](https://github.com/mozilla/glean-dictionary/issues/2309)) diff --git a/glean_parser/schemas/metrics.2-0-0.schema.yaml b/glean_parser/schemas/metrics.2-0-0.schema.yaml index 69cea2945..8545b76fd 100644 --- a/glean_parser/schemas/metrics.2-0-0.schema.yaml +++ b/glean_parser/schemas/metrics.2-0-0.schema.yaml @@ -21,7 +21,7 @@ definitions: dotted_snake_case: type: string - pattern: "^[a-z_][a-z0-9_]{0,29}(\\.[a-z_][a-z0-9_]{0,29})*$" + pattern: "^[a-z_][a-z0-9_]*(\\.[a-z_][a-z0-9_]*)*$" maxLength: 40 event_extra_key: diff --git a/tests/data/categories.yaml b/tests/data/categories.yaml new file mode 100644 index 000000000..95ae35d6e --- /dev/null +++ b/tests/data/categories.yaml @@ -0,0 +1,22 @@ +# Any copyright is dedicated to the Public Domain. +# https://creativecommons.org/publicdomain/zero/1.0/ + +--- +$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0 + +we_used_to_have_subcategory_length: + but_we_dont_any_more: &defaults + type: counter + expires: never + description: A test metric + bugs: [https://bugzil.la/2062403] + data_reviews: [https://www.example.com] + notification_emails: [glean-team@mozilla.com] + +it.may_matter_that_theres_a_dot_here: + so_we_will_test_that_too: + <<: *defaults + +a.b: + really_short_categories_are_allowed: + <<: *defaults diff --git a/tests/data/schema-violation.yaml b/tests/data/schema-violation.yaml index 55275bb4a..3af85173a 100644 --- a/tests/data/schema-violation.yaml +++ b/tests/data/schema-violation.yaml @@ -19,7 +19,7 @@ gleantest.lifetime: expires: never data_reviews: ['http://example.com'] gleantest.with.way.too.long.category.name: - test_event_inv_lt: + test_event_inv_lt: &valid_metric description: A test metric type: boolean bugs: @@ -27,6 +27,9 @@ gleantest.with.way.too.long.category.name: notification_emails: ['nobody@example.com'] expires: never data_reviews: ['http://example.com'] +gleantest_with_way_too_long_category_name_and_no_subcategories: + test_metric: + <<: *valid_metric gleantest.short.category: very_long_metric_name_this_is_too_long_as_well_since_it_has_sooooo_many_characters: description: A test metric diff --git a/tests/test_parser.py b/tests/test_parser.py index 4a7f3bfca..9801add29 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -357,6 +357,18 @@ def test_parser_schema_violation(): - `description`: **Required.** A description of the key. Valid when `type`_ is `event`. """, + """ + ``` + gleantest_with_way_too_long_category_name_and_no_subcategories + ... + ``` + + 'gleantest_with_way_too_long_category_name_and_no_subcategories' is not valid under any of + the given schemas + 'gleantest_with_way_too_long_category_name_and_no_subcategories' is too long + 'gleantest_with_way_too_long_category_name_and_no_subcategories' is not one of + ['$schema', '$tags'] + """, ] expected_errors = set( @@ -371,6 +383,14 @@ def test_parser_schema_violation(): for found_error, expected_error in zip(found, expected): assert found_error == expected_error + # If there are new errors and they're sorted after the expected list, + # the above checks won't find them. Log 'em, then assert 'em. + if len(found) > len(expected): + for i in range(len(expected), len(found)): + print(f"Unexpected error: {found[i]}") + + assert len(found) == len(expected) + def test_parser_empty(): """1507792: Get a good error message if the metrics.yaml file is empty.""" @@ -1593,3 +1613,14 @@ def test_overriden_expire_epoch_must_be_valid(invalid_epoch): list(all_metrics) del os.environ["SOURCE_DATE_EPOCH"] + + +def test_categories(): + """Test the basics of parsing oddly-named-or-structured categories.""" + all_metrics = parser.parse_objects( + [ROOT / "data" / "categories.yaml"], + config={"allow_reserved": False}, + ) + + errs = list(all_metrics) + assert len(errs) == 0