Skip to content

Add web platform features rules#2894

Open
jgraham wants to merge 1 commit into
mozilla:masterfrom
jgraham:web_platform_features_bugs
Open

Add web platform features rules#2894
jgraham wants to merge 1 commit into
mozilla:masterfrom
jgraham:web_platform_features_bugs

Conversation

@jgraham
Copy link
Copy Markdown
Member

@jgraham jgraham commented May 22, 2026

Bugs with the web-feature keyword are managed by the bot so that their lifetimes matches the lifetime of the related web-feature (specified in the user-story field) and are closed once the web feature is marked as implemented in Firefox.

This initial change implements the following functionality:

  • Automatically handling renames of existing web features
  • Removing web-feature labels in the user story which don't correspond to a real web-feature.
  • Updating links to external resources on web-features bugs.
  • Reopening web-features bugs that are closed when the corresponding feature isn't marked as supported.
  • Closing bugs once the corresponding web-feature is marked as supported.

Checklist

  • Type annotations added to new functions
  • Docs added to functions touched in main classes
  • Dry-run produced the expected results
  • The to-be-announced tag added if this is worth announcing

Bugs with the `web-feature` keyword are managed by the bot so that
their lifetimes matches the lifetime of the related
web-feature (specified in the user-story field) and are closed once
the web feature is marked as implemented in Firefox.

This initial change implements the following functionality:
* Automatically handling renames of existing web features
* Removing `web-feature` labels in the user story which don't
correspond to a real web-feature.
* Updating links to external resources on web-features bugs.
* Reopening web-features bugs that are closed when the corresponding
feature isn't marked as supported.
* Closing bugs once the corresponding web-feature is marked as supported.
@jgraham
Copy link
Copy Markdown
Member Author

jgraham commented May 22, 2026

@ksy36 maybe you would be able to take a look at this?

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new WebPlatformFeatures rule to keep Bugzilla bugs tagged with web-feature aligned with the corresponding Web Platform Feature status (as sourced from BigQuery), including metadata maintenance and automatic reopen/close behavior.

Changes:

  • Implemented BigQuery-driven update rules for feature renames, invalid feature ids, metadata/link updates, and auto close/reopen logic.
  • Expanded the rule’s email report to show a structured “Changes” breakdown (keywords, links, user story, status/resolution).
  • Added unit tests for user story parsing and for translating BugUpdate into Bugzilla-compatible change payloads.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 6 comments.

File Description
bugbot/rules/web_platform_features.py Replaces the old “add missing see_also” behavior with a full rule engine (data fetch + per-bug update plan + Bugzilla change generation).
templates/web_platform_features.html Updates the report email template to display the new structured per-bug change summary.
tests/rules/test_web_platform_features.py Adds tests for parsing and change-generation logic used by the new rule.
tests/rules/__init__.py No functional changes (file present as part of test package structure).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +38 to +45
user_story_re = re.compile(r"^\s*([^\s]+)\s*:\s*(.*)")
for line in user_story.splitlines():
key = None
value = None
m = user_story_re.match(line)
if m is not None:
maybe_key, maybe_value = m.groups()
if maybe_value:
Comment on lines +166 to +180
add = []
remove = []
has_links = [current_url] + current_see_also
has_link_keys = url_keys(has_links)
expected_link_keys = url_keys(self.see_also.keys())

for key, urls in expected_link_keys.items():
for url in urls:
add_url = self.see_also[url]
if add_url and key not in has_link_keys:
add.append(url)
elif not add_url and key in has_link_keys:
remove.append(url)

return AddRemoveChange(add=add, remove=remove)
Comment on lines +573 to +574
f"{feature_name} ([definition file](https://github.com/web-platform-dx/web-features/blob/main/features/{feature_name}.yml.dist))"
for feature_name in unsupported_features
Comment on lines +23 to +25
{% if changes.keywords != None %}
{% if changes.keywords.add %}
<li>
Comment on lines +73 to +85
<li>
<p>
Updated whiteboard from <code>{{ whiteboard }}</code> to <code>{{ changes.whiteboard }}</code>
</p>
</li>
{% endif -%}
{% if changes.user_story != None %}
<li>
<p>Updated user story from:</p>
<pre>{{ user_story }}</pre>
<p>to:</p>
<pre>{{ changes.user_story }}</pre>
</li>
Comment on lines +49 to +55
<li>
<p>
Added see_also
{% for item in changes.see_also.add %}
<code>{{ item }}</code>
{% if not loop.last %},{% endif %}
{% endfor %}


@dataclass
class BugUpdate:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Having classes with names BugChanges, and BugUpdate seems a bit confusing.

JOIN UNNEST(`webcompat_knowledge_base.EXTRACT_ARRAY`(bugs.user_story, "$.web-feature")) AS bug_feature
LEFT JOIN `web_features.features_latest` AS features ON features.feature = bug_feature
WHERE features.feature IS NULL
),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not sure if this is running both REPLACE and DELETE for features that are renamed (assuming previous-feature-name won't exist in web_features.features_latest?)

So it will have:
user_story_updates["web-feature"] = [REPLACE, DELETE]

and output_line will be set to new value with REPLACE, but then reset to None with DELETE here:

if change.type == UserStoryChangeType.DELETE:
        output_line = None
        has_updates = True
  elif change.type == UserStoryChangeType.REPLACE:
      assert change.new_value is not None
      output_line = (key, change.new_value)
      has_updates = True

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