Skip to content

Conversation

@abhayymishraa
Copy link
Collaborator

Resolves #1474

Add the PR description here.

  • Removed graphene
  • Added support for the strawberry
  • Updated nodes and queries

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 22, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Summary by CodeRabbit

  • New Features

    • Migrated the GraphQL API from Graphene to Strawberry, introducing a new backend for GraphQL queries and schema.
  • Improvements

    • All GraphQL nodes and queries now use Strawberry's modern, type-safe decorators and type annotations for improved schema clarity.
    • Enhanced type checking and developer experience with updated type stubs and mypy configuration.
  • Removals

    • Discontinued support for Graphene-based GraphQL endpoints.
  • Bug Fixes

    • Improved null safety and error handling in GraphQL field resolvers.
  • Chores

    • Updated dependencies and configuration to support Strawberry GraphQL integration.

Walkthrough

The codebase migrates its GraphQL implementation from Graphene (and graphene-django) to Strawberry (and strawberry-graphql-django). All GraphQL node and query definitions are refactored to use Strawberry’s decorators, type hints, and idioms, with corresponding configuration, dependency, and settings changes to remove Graphene and enable Strawberry.

Changes

Files/Paths Change Summary
.pre-commit-config.yaml, backend/pyproject.toml Updated type checking configuration and dependencies: removed Graphene, added Strawberry and strawberry-graphql-django, updated mypy plugin and overrides.
backend/settings/base.py, backend/settings/graphql.py, backend/settings/urls.py Removed Graphene and graphene-django from installed apps and configuration; switched schema and view setup to use Strawberry.
backend/apps/common/graphql/nodes.py, backend/apps/common/graphql/queries.py Deleted base GraphQL node and query classes used with Graphene.
backend/apps/github/graphql/nodes/*, backend/apps/owasp/graphql/nodes/* All GraphQL node classes migrated from Graphene (with BaseNode or graphene.ObjectType) to Strawberry and strawberry-django decorators (@strawberry.type, @strawberry_django.type), using Python type hints and field resolvers as methods. Meta classes replaced by decorator arguments; all field and resolver logic rewritten to Strawberry style.
backend/apps/github/graphql/queries/*, backend/apps/owasp/graphql/queries/* All GraphQL query classes and resolvers migrated from Graphene to Strawberry: class inheritance dropped, @strawberry.type decorators added, field and resolver definitions rewritten as Strawberry fields with Python type hints and method signatures.

Assessment against linked issues

Objective Addressed Explanation
Migrate all GraphQL node and query definitions from Graphene to Strawberry (#1474)
Remove Graphene and graphene-django dependencies and configuration (#1474)
Refactor Django integration to use strawberry-graphql-django and update type checking (#1474)
Update GraphQL schema/view setup and URL routing for Strawberry (#1474)
Adapt all field/resolver logic and signatures to Strawberry idioms and type hints (#1474)

Possibly related PRs

Suggested labels

backend, backend-tests

Suggested reviewers

  • kasya
  • arkid15r

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🔭 Outside diff range comments (1)
backend/apps/github/graphql/queries/repository_contributor.py (1)

13-23: 🛠️ Refactor suggestion

Missing info parameter and type annotation

The info parameter is missing from the method signature. In GraphQL, the info parameter provides context about the execution and is typically required for resolvers, even if unused. Additionally, the method signature doesn't match the docstring, which still references root and info.

 @strawberry.field
 def top_contributors(
     self,
+    info: strawberry.Info,
     limit: int = 15,
     chapter: str | None = None,
     committee: str | None = None,
     excluded_usernames: list[str] | None = None,
     organization: str | None = None,
     project: str | None = None,
     repository: str | None = None,
 ) -> list[RepositoryContributorNode]:
🧹 Nitpick comments (14)
backend/apps/owasp/graphql/queries/sponsor.py (1)

13-15: Method updated to use Strawberry field decorator with correct type annotation.

The method is correctly decorated with @strawberry.field and includes a proper return type annotation list[SponsorNode] which matches the function's return value.

However, the docstring still needs updating to reflect the new parameter structure.

-        """Resolve sponsors."""
+        """Resolve sponsors.
+        
+        Returns:
+            list[SponsorNode]: List of all sponsors sorted by sponsor type.
+        """
backend/apps/owasp/graphql/queries/committee.py (2)

15-25: Update docstring to match new method signature.

The docstring still references parameters from the Graphene implementation (root, info) that no longer exist in the method signature. Please update to reflect the current implementation.

        """Resolve committee by key.

        Args:
-            root: The root object.
-            info: GraphQL execution info.
+            self: The CommitteeQuery instance.
             key (str): The key of the committee.

        Returns:
            CommitteeNode: The committee object if found, otherwise None.

        """

15-24: Consider adding the GraphQL info parameter for consistency.

The organization query method in OrganizationQuery includes the info parameter which is commonly used in GraphQL resolvers, but this resolver doesn't. Consider adding it for consistency across query resolvers.

-    def committee(self, key: str) -> CommitteeNode | None:
+    def committee(
+        self,
+        info,
+        *,
+        key: str,
+    ) -> CommitteeNode | None:
backend/apps/owasp/graphql/nodes/stats.py (1)

6-14: Consider adding constructor or field descriptions.

Since the StatsNode is now a data class-like implementation with Strawberry, consider adding field descriptions using the description parameter in field definitions or adding docstrings for the fields.

@strawberry.type
class StatsNode:
    """Stats node."""

-    active_chapters_stats: int
-    active_projects_stats: int
-    contributors_stats: int
-    countries_stats: int
+    active_chapters_stats: int = strawberry.field(description="Number of active chapters")
+    active_projects_stats: int = strawberry.field(description="Number of active projects")
+    contributors_stats: int = strawberry.field(description="Number of contributors")
+    countries_stats: int = strawberry.field(description="Number of countries represented")
backend/apps/github/graphql/queries/milestone.py (1)

18-19: Verify if the 'info' parameter is necessary.

The 'info' parameter is retained in the method signature, but it doesn't appear to be used in the function body. Consider removing it if it's not needed.

    def recent_milestones(
        self,
-        info,
        *,
        distinct: bool = False,
        limit: int = 5,
        login: str | None = None,
        organization: str | None = None,
        state: str = "open",
    ) -> list[MilestoneNode]:
backend/apps/github/graphql/queries/issue.py (1)

17-18: Verify if the 'info' parameter is necessary.

The 'info' parameter is retained in the method signature, but it doesn't appear to be used in the function body. Consider removing it if it's not needed.

    def recent_issues(
        self,
-        info,
        *,
        distinct: bool = False,
        limit: int = 5,
        login: str | None = None,
        organization: str | None = None,
    ) -> list[IssueNode]:
backend/apps/github/graphql/queries/user.py (4)

15-20: Missing type annotation for info parameter

The info parameter lacks a type annotation. In Strawberry, this should be properly typed to Info from the strawberry library.

 @strawberry.field
 def top_contributed_repositories(
     self,
-    info,
+    info: strawberry.Info,
     login: str,
 ) -> list[RepositoryNode]:

21-39: Docstring needs update

The docstring still references parameters like they would appear in Graphene (e.g., mentioning info as the second parameter) but the method signature has changed to use self as the first parameter.

 """Resolve user top repositories.

 Args:
-    info (ResolveInfo): The GraphQL execution context.
-    login (str): The login of the user.
+    self: The instance of the query class.
+    info (strawberry.Info): The GraphQL execution context.
+    login (str): The login of the user.

 Returns:
     list: List of repositories the user has contributed to.

41-46: Missing type annotation for info parameter

The info parameter lacks a type annotation. In Strawberry, this should be properly typed.

 @strawberry.field
 def user(
     self,
-    info,
+    info: strawberry.Info,
     login: str,
 ) -> UserNode | None:

47-60: Docstring needs update

Similar to the previous method, the docstring still references the old parameter style and should be updated to reflect the new method signature with self as the first parameter.

 """Resolve user by login.

 Args:
-    info (ResolveInfo): The GraphQL execution context.
-    login (str): The login of the user.
+    self: The instance of the query class.
+    info (strawberry.Info): The GraphQL execution context.
+    login (str): The login of the user.

 Returns:
     User or None: The user object if found, otherwise None.
backend/apps/github/graphql/queries/repository_contributor.py (1)

24-40: Docstring needs update

The docstring still references the old Graphene parameter style with root and info, but the method signature has changed to use self as the first parameter and currently doesn't include the info parameter.

 """Resolve top contributors.

 Args:
-    root (Any): The root query object.
-    info (ResolveInfo): The GraphQL execution context.
+    self: The instance of the query class.
+    info (strawberry.Info): The GraphQL execution context.
     limit (int): Maximum number of contributors to return.
     chapter (str, optional): Chapter key to filter by.
     committee (str, optional): Committee key to filter by.
     organization (str, optional): Organization login to filter by.
     excluded_usernames (list[str], optional): Usernames to exclude from the results.
     project (str, optional): Project key to filter by.
     repository (str, optional): Repository name to filter by.

 Returns:
     list: List of top contributors with their details.
backend/apps/owasp/graphql/nodes/snapshot.py (1)

29-33: Consider exposing the key field directly in the type decorator.

The key resolver simply returns self.key without any transformation. Consider adding "key" to the fields list in the @strawberry_django.type decorator to reduce boilerplate, unless there's a specific reason for having this as a resolver.

backend/apps/owasp/graphql/nodes/project.py (2)

42-87: Well-structured field resolvers but consider database optimization.

All field resolvers have been properly migrated to use Strawberry's decorators and type annotations. The logic for retrieving related data is maintained from the previous implementation.

Consider optimizing database queries to prevent potential N+1 query issues, especially in list resolvers like recent_issues, recent_pull_requests, etc. You could use Django's prefetch_related more extensively:

    @strawberry.field
    def recent_issues(self) -> list[IssueNode]:
        """Resolve recent issues."""
-       return self.issues.select_related("author").order_by("-created_at")[:RECENT_ISSUES_LIMIT]
+       return self.issues.select_related("author").prefetch_related("labels", "assignees").order_by("-created_at")[:RECENT_ISSUES_LIMIT]

1-88: Consider handling potential None values explicitly.

In Strawberry, fields are non-nullable by default. Consider explicitly marking fields that might return None as Optional.

For example, if any of these resolvers might return None:

-    @strawberry.field
-    def key(self) -> str:
+    @strawberry.field
+    def key(self) -> typing.Optional[str]:

Also consider adding imports at the top:

import typing
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c92bc4 and 458fbae.

⛔ Files ignored due to path filters (1)
  • backend/poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (40)
  • .pre-commit-config.yaml (1 hunks)
  • backend/apps/common/graphql/nodes.py (0 hunks)
  • backend/apps/common/graphql/queries.py (0 hunks)
  • backend/apps/github/graphql/nodes/issue.py (1 hunks)
  • backend/apps/github/graphql/nodes/milestone.py (1 hunks)
  • backend/apps/github/graphql/nodes/organization.py (3 hunks)
  • backend/apps/github/graphql/nodes/pull_request.py (1 hunks)
  • backend/apps/github/graphql/nodes/release.py (1 hunks)
  • backend/apps/github/graphql/nodes/repository.py (2 hunks)
  • backend/apps/github/graphql/nodes/repository_contributor.py (1 hunks)
  • backend/apps/github/graphql/nodes/user.py (1 hunks)
  • backend/apps/github/graphql/queries/issue.py (1 hunks)
  • backend/apps/github/graphql/queries/milestone.py (2 hunks)
  • backend/apps/github/graphql/queries/organization.py (1 hunks)
  • backend/apps/github/graphql/queries/pull_request.py (3 hunks)
  • backend/apps/github/graphql/queries/release.py (1 hunks)
  • backend/apps/github/graphql/queries/repository.py (2 hunks)
  • backend/apps/github/graphql/queries/repository_contributor.py (1 hunks)
  • backend/apps/github/graphql/queries/user.py (2 hunks)
  • backend/apps/owasp/graphql/nodes/chapter.py (1 hunks)
  • backend/apps/owasp/graphql/nodes/committee.py (1 hunks)
  • backend/apps/owasp/graphql/nodes/common.py (1 hunks)
  • backend/apps/owasp/graphql/nodes/event.py (1 hunks)
  • backend/apps/owasp/graphql/nodes/post.py (1 hunks)
  • backend/apps/owasp/graphql/nodes/project.py (2 hunks)
  • backend/apps/owasp/graphql/nodes/snapshot.py (2 hunks)
  • backend/apps/owasp/graphql/nodes/sponsor.py (1 hunks)
  • backend/apps/owasp/graphql/nodes/stats.py (1 hunks)
  • backend/apps/owasp/graphql/queries/chapter.py (1 hunks)
  • backend/apps/owasp/graphql/queries/committee.py (2 hunks)
  • backend/apps/owasp/graphql/queries/event.py (1 hunks)
  • backend/apps/owasp/graphql/queries/post.py (1 hunks)
  • backend/apps/owasp/graphql/queries/project.py (1 hunks)
  • backend/apps/owasp/graphql/queries/snapshot.py (2 hunks)
  • backend/apps/owasp/graphql/queries/sponsor.py (1 hunks)
  • backend/apps/owasp/graphql/queries/stats.py (2 hunks)
  • backend/pyproject.toml (3 hunks)
  • backend/settings/base.py (0 hunks)
  • backend/settings/graphql.py (1 hunks)
  • backend/settings/urls.py (2 hunks)
💤 Files with no reviewable changes (3)
  • backend/apps/common/graphql/queries.py
  • backend/apps/common/graphql/nodes.py
  • backend/settings/base.py
🧰 Additional context used
🧬 Code Graph Analysis (24)
backend/apps/owasp/graphql/nodes/event.py (1)
backend/apps/owasp/models/event.py (1)
  • Event (22-293)
backend/apps/owasp/graphql/nodes/sponsor.py (1)
backend/apps/owasp/models/sponsor.py (1)
  • Sponsor (12-156)
backend/apps/owasp/graphql/queries/committee.py (2)
backend/apps/owasp/graphql/nodes/committee.py (1)
  • CommitteeNode (11-42)
backend/apps/owasp/models/committee.py (1)
  • Committee (15-86)
backend/apps/owasp/graphql/nodes/post.py (1)
backend/apps/owasp/models/post.py (1)
  • Post (11-80)
backend/apps/github/graphql/queries/release.py (2)
backend/apps/github/graphql/nodes/release.py (1)
  • ReleaseNode (20-46)
backend/apps/github/models/release.py (1)
  • Release (10-134)
backend/apps/owasp/graphql/queries/post.py (2)
backend/apps/owasp/graphql/nodes/post.py (1)
  • PostNode (18-19)
backend/apps/owasp/models/post.py (2)
  • Post (11-80)
  • recent_posts (37-39)
backend/apps/owasp/graphql/queries/sponsor.py (2)
backend/apps/owasp/graphql/nodes/sponsor.py (1)
  • SponsorNode (17-18)
backend/apps/owasp/models/sponsor.py (1)
  • Sponsor (12-156)
backend/apps/github/graphql/queries/organization.py (2)
backend/apps/github/graphql/nodes/organization.py (1)
  • OrganizationNode (39-76)
backend/apps/github/models/organization.py (1)
  • Organization (12-91)
backend/apps/owasp/graphql/nodes/committee.py (2)
backend/apps/owasp/graphql/nodes/common.py (1)
  • GenericEntityNode (9-35)
backend/apps/owasp/models/committee.py (1)
  • Committee (15-86)
backend/apps/github/graphql/queries/repository_contributor.py (2)
backend/apps/github/graphql/nodes/repository_contributor.py (1)
  • RepositoryContributorNode (7-15)
backend/apps/github/models/repository_contributor.py (1)
  • RepositoryContributor (14-207)
backend/apps/owasp/graphql/queries/project.py (2)
backend/apps/owasp/graphql/nodes/project.py (2)
  • ProjectNode (34-87)
  • key (43-45)
backend/apps/owasp/models/project.py (1)
  • Project (22-298)
backend/apps/github/graphql/nodes/release.py (6)
backend/apps/github/graphql/nodes/user.py (2)
  • UserNode (34-60)
  • url (58-60)
backend/apps/github/models/release.py (2)
  • Release (10-134)
  • url (63-65)
backend/apps/github/graphql/nodes/milestone.py (3)
  • author (24-26)
  • organization_name (29-35)
  • repository_name (38-40)
backend/apps/github/graphql/nodes/issue.py (3)
  • author (23-25)
  • organization_name (28-34)
  • repository_name (37-39)
backend/apps/github/graphql/nodes/pull_request.py (4)
  • author (21-23)
  • organization_name (26-28)
  • repository_name (31-33)
  • url (36-38)
backend/apps/github/graphql/nodes/repository.py (2)
  • organization (54-56)
  • url (84-86)
backend/apps/owasp/graphql/queries/chapter.py (2)
backend/apps/owasp/graphql/nodes/chapter.py (2)
  • ChapterNode (31-54)
  • key (47-49)
backend/apps/owasp/models/chapter.py (1)
  • Chapter (20-207)
backend/apps/owasp/graphql/queries/snapshot.py (2)
backend/apps/owasp/graphql/nodes/snapshot.py (2)
  • SnapshotNode (26-57)
  • key (30-32)
backend/apps/owasp/models/snapshot.py (1)
  • Snapshot (7-47)
backend/apps/github/graphql/nodes/issue.py (4)
backend/apps/github/graphql/nodes/user.py (1)
  • UserNode (34-60)
backend/apps/github/graphql/nodes/milestone.py (3)
  • author (24-26)
  • organization_name (29-35)
  • repository_name (38-40)
backend/apps/github/graphql/nodes/release.py (3)
  • author (24-26)
  • organization_name (29-31)
  • repository_name (39-41)
backend/apps/github/graphql/nodes/pull_request.py (3)
  • author (21-23)
  • organization_name (26-28)
  • repository_name (31-33)
backend/apps/github/graphql/queries/repository.py (3)
backend/apps/github/graphql/nodes/repository.py (2)
  • RepositoryNode (35-86)
  • organization (54-56)
backend/apps/github/models/repository.py (1)
  • Repository (25-348)
backend/apps/github/graphql/queries/organization.py (1)
  • organization (14-34)
backend/apps/github/graphql/queries/pull_request.py (2)
backend/apps/github/graphql/nodes/pull_request.py (1)
  • PullRequestNode (17-38)
backend/apps/github/models/pull_request.py (1)
  • PullRequest (11-146)
backend/apps/owasp/graphql/nodes/chapter.py (3)
backend/apps/owasp/graphql/nodes/common.py (1)
  • GenericEntityNode (9-35)
backend/apps/owasp/graphql/queries/chapter.py (1)
  • chapter (14-19)
backend/apps/owasp/models/chapter.py (1)
  • Chapter (20-207)
backend/apps/github/graphql/nodes/pull_request.py (2)
backend/apps/github/graphql/nodes/user.py (2)
  • UserNode (34-60)
  • url (58-60)
backend/apps/github/models/pull_request.py (1)
  • PullRequest (11-146)
backend/apps/github/graphql/nodes/organization.py (6)
backend/apps/github/graphql/nodes/repository.py (2)
  • organization (54-56)
  • url (84-86)
backend/apps/github/graphql/queries/organization.py (1)
  • organization (14-34)
backend/apps/github/models/organization.py (1)
  • Organization (12-91)
backend/apps/github/models/repository.py (1)
  • Repository (25-348)
backend/apps/github/models/repository_contributor.py (1)
  • RepositoryContributor (14-207)
backend/apps/github/graphql/nodes/user.py (1)
  • url (58-60)
backend/apps/owasp/graphql/nodes/common.py (3)
backend/apps/github/graphql/nodes/repository_contributor.py (1)
  • RepositoryContributorNode (7-15)
backend/apps/owasp/models/mixins/common.py (1)
  • idx_leaders (18-20)
backend/apps/github/graphql/queries/repository_contributor.py (1)
  • top_contributors (14-61)
backend/apps/github/graphql/nodes/milestone.py (4)
backend/apps/github/graphql/nodes/user.py (1)
  • UserNode (34-60)
backend/apps/github/models/milestone.py (1)
  • Milestone (10-107)
backend/apps/github/graphql/nodes/issue.py (3)
  • author (23-25)
  • organization_name (28-34)
  • repository_name (37-39)
backend/apps/github/graphql/nodes/repository.py (1)
  • organization (54-56)
backend/apps/owasp/graphql/queries/event.py (2)
backend/apps/owasp/graphql/nodes/event.py (1)
  • EventNode (22-23)
backend/apps/owasp/models/event.py (2)
  • Event (22-293)
  • upcoming_events (64-75)
backend/apps/github/graphql/queries/milestone.py (2)
backend/apps/github/graphql/nodes/milestone.py (1)
  • MilestoneNode (20-40)
backend/apps/github/models/milestone.py (1)
  • Milestone (10-107)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Run frontend e2e tests
🔇 Additional comments (160)
.pre-commit-config.yaml (1)

50-50: LGTM: Good addition of strawberry type stubs for mypy

Adding the strawberry-graphql-django package to the mypy additional dependencies ensures proper type checking for the new Strawberry GraphQL implementation. This is essential for maintaining type safety when migrating from Graphene to Strawberry.

backend/pyproject.toml (3)

52-52: LGTM: Strawberry GraphQL dependency added correctly

The addition of strawberry-graphql-django with version constraint ^0.59.1 properly replaces the removed Graphene dependency.


98-98: LGTM: Strawberry mypy plugin properly configured

Adding the strawberry.ext.mypy_plugin to mypy plugins ensures proper type checking for Strawberry-decorated classes and fields, which is essential for a type-safe GraphQL implementation.


108-110: LGTM: Appropriate mypy error code overrides for GraphQL modules

The configuration properly disables specific error codes for GraphQL modules, which is necessary when working with Strawberry's type system and decorator patterns.

backend/settings/urls.py (3)

13-13: LGTM: Updated GraphQL view import

The import has been correctly updated from Graphene to Strawberry's Django view.


20-20: LGTM: Direct schema import

Importing the schema directly from settings.graphql is a clean approach for integrating the new Strawberry schema.


29-29: LGTM: GraphQL endpoint correctly configured with Strawberry

The GraphQL endpoint now correctly uses Strawberry's view with explicit schema reference while maintaining the CSRF protection and conditional GraphiQL enablement based on DEBUG setting.

backend/settings/graphql.py (3)

3-3: LGTM: Imported Strawberry instead of Graphene

The import has been correctly updated to use Strawberry instead of Graphene.


9-10: LGTM: Query class properly decorated with Strawberry type

The Query class is correctly decorated with @strawberry.type, following Strawberry's pattern for defining GraphQL types. The class still inherits from both query classes, maintaining the same functionality.


14-14: LGTM: Schema instance updated to use Strawberry

The schema instantiation has been correctly updated to use strawberry.Schema instead of graphene.Schema, completing the migration to Strawberry.

backend/apps/owasp/graphql/nodes/sponsor.py (3)

3-4: Good import switch for the Strawberry migration.

The import change from the previous BaseNode to strawberry_django correctly implements the first step of migrating from Graphene to Strawberry GraphQL.


8-16: Well-structured Strawberry type declaration.

The @strawberry_django.type decorator properly connects the GraphQL type to the Django model with explicit field selection. This is the correct pattern for Strawberry-Django integration, replacing the previous Graphene pattern of using a Meta class.


17-18: Correctly removed inheritance in favor of decoration.

The class definition has been properly updated to remove the BaseNode inheritance, which aligns with Strawberry's decorator-based approach rather than Graphene's inheritance model.

backend/apps/owasp/graphql/nodes/event.py (3)

3-4: Correct import for Strawberry GraphQL implementation.

The import change from the previous BaseNode to strawberry_django is correct for the migration to Strawberry GraphQL.


8-21: Comprehensive field selection for EventNode.

The decorator properly specifies all the relevant fields from the Event model that should be exposed in the GraphQL API. The selection covers the core informational fields needed by clients.


22-23: Properly simplified class definition.

The class definition has been correctly updated to remove inheritance and rely on the decorator pattern, which is the idiomatic approach in Strawberry.

backend/apps/owasp/graphql/queries/event.py (3)

3-4: Correct import for Strawberry GraphQL queries.

The import of strawberry instead of the previously used Graphene-related imports is appropriate for the migration.


9-11: Proper query class definition with Strawberry.

The @strawberry.type decorator correctly transforms the class into a GraphQL type. The removal of inheritance from BaseQuery aligns with Strawberry's approach.


13-16: Well-structured field resolver with type annotations.

The query method has been properly transformed to:

  1. Use the @strawberry.field decorator
  2. Change from static method to instance method
  3. Add Python type annotations for parameters and return value
  4. Preserve the existing functionality

This implementation follows Strawberry's best practices for resolver methods.

backend/apps/owasp/graphql/nodes/post.py (3)

3-4: Correct import for Strawberry Django integration.

The import change from the previous BaseNode to strawberry_django is appropriate for the migration to Strawberry GraphQL.


8-17: Complete field selection for the Post node.

The @strawberry_django.type decorator correctly specifies all the necessary fields from the Post model. This matches exactly with the model fields defined in backend/apps/owasp/models/post.py and ensures all required data is exposed through the GraphQL API.


18-19: Properly simplified class definition.

The class definition correctly removes inheritance and relies on the decorator pattern, which is the idiomatic approach in Strawberry GraphQL.

backend/apps/owasp/graphql/queries/sponsor.py (2)

3-4: Successfully migrated import to Strawberry.

The import statement has been correctly updated from Graphene to Strawberry as part of the migration.


9-10: Class declaration correctly updated to use Strawberry decorator.

The SponsorQuery class is now properly decorated with @strawberry.type instead of inheriting from a base class, following Strawberry's pattern.

backend/apps/owasp/graphql/queries/committee.py (3)

3-4: Successfully migrated import to Strawberry.

The import statement has been correctly updated from Graphene to Strawberry as part of the migration.


9-10: Class declaration correctly updated to use Strawberry decorator.

The CommitteeQuery class is now properly decorated with @strawberry.type instead of inheriting from a base class, following Strawberry's pattern.


13-14: Method updated to use Strawberry field decorator with correct type annotation.

The method is correctly decorated with @strawberry.field and includes a proper return type annotation.

backend/apps/github/graphql/queries/organization.py (4)

3-4: Successfully migrated import to Strawberry.

The import statement has been correctly updated from Graphene to Strawberry as part of the migration.


9-10: Class declaration correctly updated to use Strawberry decorator.

The OrganizationQuery class is now properly decorated with @strawberry.type instead of inheriting from a base class, following Strawberry's pattern.


13-19: Method updated to use Strawberry field decorator with proper signature.

The method has been correctly updated to:

  1. Use the @strawberry.field decorator
  2. Accept self and info parameters
  3. Define login as a keyword-only parameter
  4. Include a proper return type annotation

This implementation follows Strawberry's recommended patterns.


20-30: Docstring properly updated to reflect new method signature.

The docstring has been correctly updated to document the new method parameters and return type, which is good practice.

backend/apps/owasp/graphql/nodes/stats.py (3)

3-4: Successfully migrated import to Strawberry.

The import statement has been correctly updated from Graphene to Strawberry as part of the migration.


6-7: Class declaration correctly updated to use Strawberry decorator.

The StatsNode class is now properly decorated with @strawberry.type instead of inheriting from a Graphene class.


10-13: Fields properly converted to use Python type annotations.

The fields have been correctly migrated from Graphene's field definitions to Strawberry's type annotation approach using standard Python type hints.

backend/apps/owasp/graphql/queries/post.py (4)

3-4: Good job with the import change.

Properly migrated from Graphene to Strawberry by updating the import statement.


9-10: Correct use of Strawberry type decorator.

Good job replacing the Graphene class inheritance with the Strawberry decorator pattern.


13-14: Default limit parameter has changed.

The default limit parameter value was changed from 6 to 5, which is now correctly reflected in the docstring. This is a behavior change, but since it's appropriately documented, it's acceptable.


14-16:

✅ Verification successful

Verify that all callers handle the removed 'info' parameter.

The info parameter was removed from the method signature. In Strawberry, this parameter is optional and only needed if resolver requires access to GraphQL execution context. Make sure no existing code depends on the presence of this parameter.


🏁 Script executed:

#!/bin/bash
# Look for places where recent_posts is being called to check if any are passing 'info'
rg -A 2 -B 2 "recent_posts.*info" --glob "*.py"

Length of output: 49


🏁 Script executed:

#!/bin/bash
# List all usages of recent_posts in the codebase with context to verify no callers pass 'info'
rg -n -C 2 "recent_posts\s*\\(" --glob "*.py"

Length of output: 1542


Confirmed: no callers pass the removed info parameter
A repository‐wide search for recent_posts( shows only parameterless invocations (e.g., in
backend/apps/slack/utils.py and tests), with no references to an info argument. No further changes needed.

backend/apps/owasp/graphql/queries/stats.py (4)

3-4: Good job with the import change.

Properly migrated from Graphene to Strawberry by updating the import statement.


11-13: Correct use of Strawberry type decorator.

Good job replacing the Graphene class inheritance with the Strawberry decorator pattern.


15-17: Clean resolver implementation with proper type annotation.

Well-structured resolver with appropriate type annotation. The 'info' parameter was removed, which is fine if it wasn't being used in the resolver.


29-34: Improved code readability with named arguments.

Using named arguments for the StatsNode constructor improves code clarity and maintainability.

backend/apps/github/graphql/queries/milestone.py (4)

3-6: Good job with the import change.

Properly migrated from Graphene to Strawberry by updating the import statement.


11-13: Correct use of Strawberry type decorator.

Good job replacing the Graphene class inheritance with the Strawberry decorator pattern.


15-25: Well-structured resolver with keyword-only arguments.

Good use of the * syntax to make all subsequent parameters keyword-only, which improves API clarity. The return type annotation is also correctly updated.


37-38: Good docstring update.

The docstring return type is properly updated to match the new type annotation syntax.

backend/apps/github/graphql/queries/issue.py (4)

3-5: Good job with the import change.

Properly migrated from Graphene to Strawberry by updating the import statement and ensuring all necessary Django imports are included.


10-12: Correct use of Strawberry type decorator.

Good job replacing the Graphene class inheritance with the Strawberry decorator pattern.


14-23: Well-structured resolver with keyword-only arguments.

Good use of the * syntax to make all subsequent parameters keyword-only, which improves API clarity. The return type annotation is also correctly updated.


34-35: Good docstring update.

The docstring return type is properly updated to match the new type annotation syntax.

backend/apps/github/graphql/queries/user.py (2)

3-3: Import looks good

The change from Graphene to Strawberry is appropriate and aligns with the PR's objective to migrate the GraphQL implementation.


11-12: Strawberry type decorator properly applied

The class has been correctly migrated from inheriting BaseQuery to using the @strawberry.type decorator, following Strawberry's approach to GraphQL schema definition.

backend/apps/github/graphql/queries/repository_contributor.py (3)

3-3: Import looks good

The change from Graphene to Strawberry is appropriate and aligns with the PR's objective to migrate the GraphQL implementation.


9-10: Strawberry type decorator properly applied

The class has been correctly migrated from inheriting BaseQuery to using the @strawberry.type decorator, following Strawberry's approach to GraphQL schema definition.


41-61: Implementation looks good

The implementation correctly calls the model's method to get top contributors and transforms the result into the appropriate GraphQL node type.

backend/apps/owasp/graphql/queries/snapshot.py (4)

3-3: Import looks good

The change from Graphene to Strawberry is appropriate and aligns with the PR's objective to migrate the GraphQL implementation.


9-10: Strawberry type decorator properly applied

The class has been correctly migrated from inheriting from a base query class to using the @strawberry.type decorator, following Strawberry's approach to GraphQL schema definition.


15-22: Implementation looks good

The implementation correctly handles the case when a snapshot is not found by returning None.


26-31: Implementation looks good

The implementation correctly filters snapshots by status and orders them by creation date.

backend/apps/owasp/graphql/queries/chapter.py (5)

3-3: Import looks good

The change from Graphene to Strawberry is appropriate and aligns with the PR's objective to migrate the GraphQL implementation.


9-10: Strawberry type decorator properly applied

The class has been correctly migrated from inheriting from a base query class to using the @strawberry.type decorator, following Strawberry's approach to GraphQL schema definition.


16-19: Implementation looks good

The implementation correctly handles the case when a chapter is not found by returning None.


24-24: Implementation looks good

The implementation correctly filters for active chapters and orders them by creation date.


13-15: 🛠️ Refactor suggestion

Missing info parameter

The info parameter is missing from the method signature. In GraphQL, the info parameter provides context about the execution and is typically required for resolvers, even if unused.

 @strawberry.field
-def chapter(self, key: str) -> ChapterNode | None:
+def chapter(self, info: strawberry.Info, key: str) -> ChapterNode | None:
     """Resolve chapter by key."""

Likely an incorrect or invalid review comment.

backend/apps/owasp/graphql/nodes/committee.py (4)

3-4: Correctly imported Strawberry libraries.

The imports have been properly updated to use Strawberry and Strawberry-Django instead of Graphene, which is consistent with the migration objective.


10-11: Good use of the @strawberry_django.type decorator.

The decorator appropriately connects the GraphQL type to the Django model and explicitly specifies which model fields should be exposed, following Strawberry best practices.


14-23: Properly implemented field resolvers for non-model fields.

The contributors_count and created_at resolvers are correctly decorated with @strawberry.field and include appropriate return type annotations. Note that created_at returns self.idx_created_at which suggests it's using an indexed value rather than directly accessing the model field.


24-42: Consistent implementation of remaining field resolvers.

All field resolvers follow the same pattern with proper type annotations and documentation. This maintains code consistency while migrating from Graphene to Strawberry.

backend/apps/github/graphql/nodes/repository_contributor.py (2)

3-3: Correct Strawberry import.

The import has been properly updated to use Strawberry instead of Graphene.


6-16: Clean implementation of Repository Contributor node using Strawberry.

The code has been significantly simplified by:

  1. Using the @strawberry.type decorator
  2. Replacing Graphene field declarations with Python type annotations
  3. Eliminating unnecessary boilerplate

This results in more readable, maintainable, and type-safe code that leverages Python's native type system.

backend/apps/owasp/graphql/nodes/snapshot.py (3)

3-4: Correctly imported Strawberry libraries.

The imports have been properly updated to use Strawberry and Strawberry-Django instead of Graphene.


17-25: Well-structured @strawberry_django.type decorator.

The decorator correctly lists all model fields that should be directly exposed in the GraphQL schema, following Strawberry best practices.


34-57: Correctly implemented collection resolvers with preserved ordering.

All collection resolvers (new_chapters, new_issues, new_projects, new_releases, new_users) are properly implemented with:

  1. Correct @strawberry.field decorators
  2. Appropriate return type annotations
  3. Preserved ordering and limiting logic

This ensures the GraphQL API behavior remains consistent after migration.

backend/apps/owasp/graphql/queries/project.py (4)

3-3: Correct Strawberry import.

The import has been properly updated to use Strawberry instead of Graphene.


9-10: Proper use of @strawberry.type decorator.

The ProjectQuery class correctly uses the @strawberry.type decorator instead of inheriting from BaseQuery, following Strawberry conventions.


13-27: Well-implemented project resolver with modern type annotations.

The resolver is correctly decorated with @strawberry.field and uses Python 3.10+ union type syntax (ProjectNode | None). The query logic is preserved while removing Graphene-specific parameters (root, info).


29-40: Correctly implemented recent_projects resolver.

The resolver is properly decorated with @strawberry.field, includes appropriate type annotations, and maintains the same query logic as before while adapting to Strawberry conventions.

backend/apps/github/graphql/nodes/issue.py (5)

3-7: Successful migration from Graphene to Strawberry

The imports have been properly updated to use Strawberry's libraries instead of Graphene.


10-19: Properly implemented Strawberry type decorator

The @strawberry_django.type decorator correctly links the GraphQL type to the Django model and explicitly exposes only the necessary fields.


22-25: Type annotation correctly implemented

The author field is properly implemented using Strawberry's field decorator with appropriate type annotation.


27-34: Good defensive programming with null checks

The implementation properly checks for both self.repository and self.repository.organization before accessing nested properties, preventing potential null reference errors.


36-39: Proper null check for repository

The implementation correctly checks for self.repository before accessing its properties.

backend/apps/github/graphql/nodes/milestone.py (5)

3-7: Successful migration from Graphene to Strawberry

The imports have been properly updated to use Strawberry's libraries instead of Graphene.


10-19: Properly implemented Strawberry type decorator

The @strawberry_django.type decorator correctly links the GraphQL type to the Django model and explicitly exposes the necessary fields.


23-26: Type annotation correctly implemented

The author field is properly implemented using Strawberry's field decorator with appropriate type annotation.


28-35: Good defensive programming with null checks

The implementation properly checks for both self.repository and self.repository.organization before accessing nested properties, preventing potential null reference errors.


37-40: Proper null check for repository

The implementation correctly checks for self.repository before accessing its properties.

backend/apps/github/graphql/nodes/release.py (4)

3-5: Successful migration from Graphene to Strawberry

The imports have been properly updated to use Strawberry's libraries instead of Graphene.


11-19: Properly implemented Strawberry type decorator

The @strawberry_django.type decorator correctly links the GraphQL type to the Django model and explicitly exposes the necessary fields.


23-27: Type annotation correctly implemented

The author field is properly implemented using Strawberry's field decorator with appropriate type annotation.


43-46: Type annotation correctly implemented for URL

The url field is properly implemented using Strawberry's field decorator with appropriate type annotation.

backend/apps/github/graphql/nodes/pull_request.py (4)

3-7: Successful migration from Graphene to Strawberry

The imports have been properly updated to use Strawberry's libraries instead of Graphene.


10-16: Properly implemented Strawberry type decorator

The @strawberry_django.type decorator correctly links the GraphQL type to the Django model and explicitly exposes the necessary fields.


20-23: Type annotation correctly implemented

The author field is properly implemented using Strawberry's field decorator with appropriate type annotation.


35-38: Well-implemented defensive check for URL

The url method properly checks if self.url exists before using it, with an appropriate fallback to an empty string.

backend/apps/github/graphql/queries/pull_request.py (6)

3-4: LGTM: Import changes for Strawberry migration

The imports have been correctly updated to replace Graphene with Strawberry, and Django's query expressions are properly imported.


11-12: LGTM: Class declaration updated for Strawberry

The class has been correctly updated to use Strawberry's type decorator instead of inheriting from BaseQuery.


15-26: LGTM: Method signature updated to Strawberry style

The method signature has been properly updated to use Strawberry's field decorator with appropriate type annotations for parameters and return value.


29-40: LGTM: Docstring updated to reflect new parameter structure

The docstring has been properly updated to reflect the changes in the method signature, particularly removing references to the root parameter and updating the return type documentation.


43-55: LGTM: Query construction remains consistent

The query construction remains unchanged and correctly handles the selection of related models and exclusion of bot authors.


57-91: LGTM: Filtering logic preserved during migration

The filtering logic for login, organization, project, repository, and distinct filtering has been preserved during the migration to Strawberry, maintaining the original functionality.

backend/apps/github/graphql/queries/repository.py (8)

3-3: LGTM: Import changes for Strawberry migration

The import has been correctly updated to use Strawberry instead of Graphene.


9-10: LGTM: Class declaration updated for Strawberry

The class has been correctly updated to use Strawberry's type decorator instead of inheriting from BaseQuery.


13-19: LGTM: Repository resolver updated to Strawberry style

The repository resolver method has been properly updated to use Strawberry's field decorator with the correct signature and return type annotation.


22-30: LGTM: Docstring properly updated

The docstring has been correctly updated to reflect the new parameter structure and return type, maintaining comprehensive documentation.


32-38: LGTM: Repository lookup logic preserved

The repository lookup logic with error handling has been preserved during migration, maintaining the original functionality.


40-47: LGTM: Repositories field updated to Strawberry style

The repositories resolver method has been properly updated to use Strawberry's field decorator with appropriate type annotations.


50-58: LGTM: Docstring properly updated for repositories field

The docstring has been correctly updated to reflect the new parameter structure and return type.


60-68: LGTM: Query logic preserved for repositories field

The query logic for fetching repositories has been preserved during the migration, maintaining the original functionality.

backend/apps/github/graphql/queries/release.py (6)

3-4: LGTM: Import changes for Strawberry migration

The imports have been correctly updated to replace Graphene with Strawberry, and Django's query expressions are properly imported.


10-11: LGTM: Class declaration updated for Strawberry

The class has been correctly updated to use Strawberry's type decorator instead of inheriting from BaseQuery.


14-23: LGTM: Method signature updated to Strawberry style

The method signature has been properly updated to use Strawberry's field decorator with appropriate type annotations for parameters and return value.


26-36: LGTM: Docstring updated to reflect new parameter structure

The docstring has been properly updated to reflect the changes in the method signature, including the self parameter and the return type documentation.


38-46: Optimization: Moved select_related up in the query chain

Good improvement by moving the select_related calls to the beginning of the query chain, ensuring related objects are fetched efficiently regardless of which filters are applied later.


53-69: LGTM: Distinct filtering logic preserved

The distinct filtering logic using subqueries has been preserved during the migration, maintaining the original functionality.

backend/apps/github/graphql/nodes/user.py (8)

3-5: LGTM: Import changes for Strawberry migration

The imports have been correctly updated to include both Strawberry and Strawberry Django for model integration.


9-15: LGTM: RepositoryType class updated to use Strawberry type decorators

The RepositoryType class has been nicely updated to use Strawberry's type decorator with Python type annotations instead of Graphene fields.


17-34: LGTM: UserNode uses Strawberry Django integration

Excellent implementation using @strawberry_django.type decorator to directly map to the Django model with explicit field listing. This approach is more concise and type-safe than the previous Graphene implementation.


37-41: LGTM: Field resolver updated to Strawberry style

The created_at field resolver has been properly updated to use Strawberry's field decorator with appropriate type annotation.


42-46: LGTM: Field resolver updated to Strawberry style

The issues_count field resolver has been properly updated to use Strawberry's field decorator with appropriate type annotation.


47-51: LGTM: Field resolver updated to Strawberry style

The releases_count field resolver has been properly updated to use Strawberry's field decorator with appropriate type annotation.


52-56: LGTM: Field resolver updated to Strawberry style

The updated_at field resolver has been properly updated to use Strawberry's field decorator with appropriate type annotation.


57-60: LGTM: Field resolver updated to Strawberry style

The url field resolver has been properly updated to use Strawberry's field decorator with appropriate type annotation.

backend/apps/owasp/graphql/nodes/chapter.py (7)

3-4: Appropriate library imports for Strawberry GraphQL

The imports have been correctly updated to use strawberry and strawberry_django for the new GraphQL implementation.


10-16: Well-defined type with proper annotations

The GeoLocationType has been correctly migrated from a Graphene ObjectType to a Strawberry type with proper type annotations for the latitude and longitude fields.


18-30: Properly configured Strawberry Django type

The @strawberry_django.type decorator is correctly applied with the Chapter model and appropriate field selection. This follows Strawberry's best practices for exposing Django model fields.


34-38: Added resolver for created_at

The created_at resolver has been properly implemented with the correct return type annotation and documentation.


39-44: Improved null handling in geo_location resolver

The geo_location resolver now properly handles the case when latitude or longitude is missing by explicitly returning None, making the nullable return type clear in the type annotation.


46-49: Key resolver with proper type annotation

The key resolver correctly uses the @strawberry.field decorator with a return type of str.


51-54: Suggested location resolver with nullable type

The suggested_location resolver properly uses the union type str | None to indicate that the field can be null.

backend/apps/github/graphql/nodes/organization.py (5)

3-4: Appropriate library imports for Strawberry GraphQL

The imports have been correctly updated to use strawberry and strawberry_django for the new GraphQL implementation.


12-21: Well-defined OrganizationStatsNode with type annotations

The OrganizationStatsNode has been properly migrated to a Strawberry type with explicit type annotations for all fields.


23-39: Properly configured OrganizationNode with field selection

The OrganizationNode is correctly decorated with @strawberry_django.type, linking it to the Organization model and explicitly listing all fields to be exposed.


42-71: Improved error handling in stats resolver

The stats resolver has been enhanced to use .get() with default values (lines 54-56) rather than direct dictionary access, which provides better protection against None values in the aggregated stats.


73-76: URL resolver with proper type annotation

The URL resolver correctly uses the @strawberry.field decorator with a return type of str.

backend/apps/owasp/graphql/nodes/common.py (7)

3-4: Correct import for Strawberry GraphQL

The import statement has been updated to use strawberry for the new GraphQL implementation.


8-9: Properly defined GenericEntityNode

The GenericEntityNode class is correctly decorated with @strawberry.type and no longer inherits from a base class, following Strawberry's composition-based approach.


12-15: Leaders resolver with appropriate type annotation

The leaders resolver correctly uses the @strawberry.field decorator with a return type of list[str].


17-20: Related URLs resolver with appropriate type annotation

The related_urls resolver correctly uses the @strawberry.field decorator with a return type of list[str].


22-26: Top contributors resolver with proper object mapping

The top_contributors resolver correctly maps each contributor dictionary to a RepositoryContributorNode instance using the dictionary unpacking operator.


27-30: Updated_at resolver with appropriate type annotation

The updated_at resolver correctly uses the @strawberry.field decorator with a return type of float.


32-35: URL resolver with appropriate type annotation

The URL resolver correctly uses the @strawberry.field decorator with a return type of str.

backend/apps/github/graphql/nodes/repository.py (13)

3-4: Appropriate library imports for Strawberry GraphQL

The imports have been correctly updated to use strawberry and strawberry_django for the new GraphQL implementation.


8-8: Added import for OrganizationNode

The OrganizationNode import has been added to support the new organization resolver.


17-35: Properly configured RepositoryNode with field selection

The RepositoryNode is correctly decorated with @strawberry_django.type, linking it to the Repository model and explicitly listing all fields to be exposed.


38-42: Issues resolver with proper return type

The issues resolver correctly uses the @strawberry.field decorator with a return type of list[IssueNode] and maintains the original query optimization with select_related.


43-47: Languages resolver with appropriate type annotation

The languages resolver correctly uses the @strawberry.field decorator with a return type of list[str].


48-52: Latest release resolver with appropriate type annotation

The latest_release resolver correctly uses the @strawberry.field decorator with a return type of str.


53-57: New organization resolver added

A new resolver for the organization field has been correctly added, returning an OrganizationNode type. This improves the API by providing direct access to the related organization.


58-62: Owner key resolver with appropriate type annotation

The owner_key resolver correctly uses the @strawberry.field decorator with a return type of str.


63-67: Recent milestones resolver with typed parameter

The recent_milestones resolver correctly uses the @strawberry.field decorator, properly types the limit parameter, and maintains the original query optimization.


68-72: Releases resolver properly implemented

The releases resolver has been correctly implemented as a method with the @strawberry.field decorator and appropriate return type annotation.


73-77: Top contributors resolver with appropriate type annotation

The top_contributors resolver correctly uses the @strawberry.field decorator with a return type of list[RepositoryContributorNode].


78-82: Topics resolver with appropriate type annotation

The topics resolver correctly uses the @strawberry.field decorator with a return type of list[str].


83-86: URL resolver with appropriate type annotation

The URL resolver correctly uses the @strawberry.field decorator with a return type of str.

backend/apps/owasp/graphql/nodes/project.py (5)

3-5: Appropriate imports for the Strawberry migration.

The import statements are correctly updated to use Strawberry packages instead of Graphene for GraphQL schema definition.


19-33: Good use of Strawberry's type system for model mapping.

The migration correctly uses @strawberry_django.type decorator to expose the Django model fields, which is more type-safe and easier to maintain than the previous Graphene approach with Meta classes.


37-40: Properly implemented field resolver with type annotations.

The resolver correctly uses Strawberry's field decorator and includes appropriate type annotations for return values.


65-67: Good code formatting for multiline statement.

The multiline formatting for the return statement is clean and readable.


34-34:

✅ Verification successful

Verify GenericEntityNode compatibility with Strawberry.

The class inherits from GenericEntityNode, but it's unclear if this base class has been properly migrated to Strawberry as well.


🏁 Script executed:

#!/bin/bash
# Check if GenericEntityNode is implemented with Strawberry
cat apps/owasp/graphql/nodes/common.py | grep -A 20 "class GenericEntityNode"

Length of output: 146


#!/bin/bash

Search for the definition of GenericEntityNode anywhere in the repo

rg --color=never "class GenericEntityNode" -A20 -n .


🏁 Script executed:

#!/bin/bash
# Search for the definition of GenericEntityNode anywhere in the repository
rg --color=never "class GenericEntityNode" -A20 -n .

Length of output: 1731


🏁 Script executed:

#!/bin/bash
# Display the top of GenericEntityNode to check for Strawberry type decorator
sed -n '1,30p' backend/apps/owasp/graphql/nodes/common.py
echo "-----"
# Display the top of ProjectNode to verify its Strawberry annotations
sed -n '1,50p' backend/apps/owasp/graphql/nodes/project.py

Length of output: 2276


Verified: GenericEntityNode is already a Strawberry type

GenericEntityNode in backend/apps/owasp/graphql/nodes/common.py is annotated with @strawberry.type, so ProjectNode inherits from a proper Strawberry-decorated base. No further migration work is needed.

Comment on lines +13 to +14
@strawberry.field
def snapshot(self, key: str) -> SnapshotNode | None:
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Missing info parameter

The info parameter is missing from the method signature. In GraphQL, the info parameter provides context about the execution and is typically required for resolvers, even if unused.

 @strawberry.field
-def snapshot(self, key: str) -> SnapshotNode | None:
+def snapshot(self, info: strawberry.Info, key: str) -> SnapshotNode | None:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def snapshot(self, key: str) -> SnapshotNode | None:
@strawberry.field
def snapshot(self, info: strawberry.Info, key: str) -> SnapshotNode | None:
🤖 Prompt for AI Agents
In backend/apps/owasp/graphql/queries/snapshot.py at lines 13 to 14, the
snapshot resolver method is missing the required info parameter. Add an info
parameter as the second argument to the method signature to receive GraphQL
execution context, even if it is not used within the method.

Comment on lines +24 to +25
@strawberry.field
def snapshots(self, limit: int = 12) -> list[SnapshotNode]:
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Missing info parameter

The info parameter is missing from the method signature. In GraphQL, the info parameter provides context about the execution and is typically required for resolvers.

 @strawberry.field
-def snapshots(self, limit: int = 12) -> list[SnapshotNode]:
+def snapshots(self, info: strawberry.Info, limit: int = 12) -> list[SnapshotNode]:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def snapshots(self, limit: int = 12) -> list[SnapshotNode]:
@strawberry.field
def snapshots(self, info: strawberry.Info, limit: int = 12) -> list[SnapshotNode]:
🤖 Prompt for AI Agents
In backend/apps/owasp/graphql/queries/snapshot.py around lines 24 to 25, the
snapshots resolver method is missing the required info parameter. Add the info
parameter as the first argument after self in the method signature to provide
the GraphQL execution context, following the standard resolver function
signature.

Comment on lines 21 to 23
@strawberry.field
def recent_chapters(self, limit: int = 8) -> list[ChapterNode]:
"""Resolve recent active chapters."""
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Missing info parameter

The info parameter is missing from the method signature. In GraphQL, the info parameter provides context about the execution and is typically required for resolvers.

 @strawberry.field
-def recent_chapters(self, limit: int = 8) -> list[ChapterNode]:
+def recent_chapters(self, info: strawberry.Info, limit: int = 8) -> list[ChapterNode]:
     """Resolve recent active chapters."""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def recent_chapters(self, limit: int = 8) -> list[ChapterNode]:
"""Resolve recent active chapters."""
@strawberry.field
def recent_chapters(self, info: strawberry.Info, limit: int = 8) -> list[ChapterNode]:
"""Resolve recent active chapters."""
🤖 Prompt for AI Agents
In backend/apps/owasp/graphql/queries/chapter.py around lines 21 to 23, the
recent_chapters resolver method is missing the required info parameter. Add info
as the first parameter after self in the method signature to receive GraphQL
execution context, updating it to def recent_chapters(self, info, limit: int =
8) -> list[ChapterNode].

Comment on lines 33 to 36
@strawberry.field
def project_name(self) -> str:
"""Return project name."""
return self.repository.project.name.lstrip(OWASP_ORGANIZATION_NAME)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing null checks for repository and project

The project_name method doesn't check if self.repository or self.repository.project exists before accessing them, which could lead to null reference errors.

Apply this diff to add the missing null checks:

def project_name(self) -> str:
    """Return project name."""
-   return self.repository.project.name.lstrip(OWASP_ORGANIZATION_NAME)
+   return self.repository.project.name.lstrip(OWASP_ORGANIZATION_NAME) if self.repository and self.repository.project else ""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def project_name(self) -> str:
"""Return project name."""
return self.repository.project.name.lstrip(OWASP_ORGANIZATION_NAME)
@strawberry.field
def project_name(self) -> str:
"""Return project name."""
return (
self.repository.project.name.lstrip(OWASP_ORGANIZATION_NAME)
if self.repository and self.repository.project
else ""
)
🤖 Prompt for AI Agents
In backend/apps/github/graphql/nodes/release.py around lines 33 to 36, the
project_name method accesses self.repository and self.repository.project without
checking if they are None, which can cause null reference errors. Add
conditional checks to verify that self.repository and self.repository.project
are not None before accessing their attributes. If either is None, return a safe
default value such as an empty string to avoid exceptions.

Comment on lines 38 to 41
@strawberry.field
def repository_name(self) -> str:
"""Return repository name."""
return self.repository.name
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing null check for repository

The repository_name method doesn't check if self.repository exists before accessing it, which could lead to a null reference error.

Apply this diff to add the missing null check:

def repository_name(self) -> str:
    """Return repository name."""
-   return self.repository.name
+   return self.repository.name if self.repository else ""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def repository_name(self) -> str:
"""Return repository name."""
return self.repository.name
@strawberry.field
def repository_name(self) -> str:
"""Return repository name."""
- return self.repository.name
+ return self.repository.name if self.repository else ""
🤖 Prompt for AI Agents
In backend/apps/github/graphql/nodes/release.py around lines 38 to 41, the
repository_name method accesses self.repository.name without checking if
self.repository is None, which can cause a null reference error. Add a null
check to verify if self.repository exists before accessing its name attribute,
and handle the case where it is None appropriately, such as returning None or an
empty string.

Comment on lines 28 to 31
@strawberry.field
def organization_name(self) -> str | None:
"""Return organization name."""
return self.repository.organization.login if self.repository.organization else None
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing null check for repository

The organization_name method doesn't check if self.repository exists before accessing it, which could lead to a null reference error.

Apply this diff to add the missing null check:

def organization_name(self) -> str | None:
    """Return organization name."""
-   return self.repository.organization.login if self.repository.organization else None
+   return self.repository.organization.login if self.repository and self.repository.organization else None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def organization_name(self) -> str | None:
"""Return organization name."""
return self.repository.organization.login if self.repository.organization else None
@strawberry.field
def organization_name(self) -> str | None:
"""Return organization name."""
- return self.repository.organization.login if self.repository.organization else None
+ return self.repository.organization.login if self.repository and self.repository.organization else None
🤖 Prompt for AI Agents
In backend/apps/github/graphql/nodes/release.py around lines 28 to 31, the
organization_name method accesses self.repository without checking if it is
None, which can cause a null reference error. Add a check to ensure
self.repository is not None before accessing self.repository.organization.
Return None if self.repository is None to safely handle the absence of a
repository.

Comment on lines 30 to 33
@strawberry.field
def repository_name(self) -> str:
"""Resolve repository name."""
return self.repository.name
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing null check for repository

The repository_name method doesn't check if self.repository exists before accessing it, which could lead to a null reference error.

Apply this diff to add the missing null check:

def repository_name(self) -> str:
    """Resolve repository name."""
-   return self.repository.name
+   return self.repository.name if self.repository else ""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def repository_name(self) -> str:
"""Resolve repository name."""
return self.repository.name
@strawberry.field
def repository_name(self) -> str:
"""Resolve repository name."""
return self.repository.name if self.repository else ""
🤖 Prompt for AI Agents
In backend/apps/github/graphql/nodes/pull_request.py around lines 30 to 33, the
repository_name method accesses self.repository.name without checking if
self.repository is None, which can cause a null reference error. Add a null
check to verify if self.repository exists before accessing its name, and handle
the case where it is None appropriately, such as returning None or an empty
string.

Comment on lines 25 to 28
@strawberry.field
def organization_name(self) -> str | None:
"""Return organization name."""
return self.repository.organization.login if self.repository.organization else None
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing null check for repository

The organization_name method doesn't check if self.repository exists before accessing it, which could lead to a null reference error.

Apply this diff to add the missing null check:

def organization_name(self) -> str | None:
    """Return organization name."""
-   return self.repository.organization.login if self.repository.organization else None
+   return self.repository.organization.login if self.repository and self.repository.organization else None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@strawberry.field
def organization_name(self) -> str | None:
"""Return organization name."""
return self.repository.organization.login if self.repository.organization else None
@strawberry.field
def organization_name(self) -> str | None:
"""Return organization name."""
return self.repository.organization.login if self.repository and self.repository.organization else None
🤖 Prompt for AI Agents
In backend/apps/github/graphql/nodes/pull_request.py around lines 25 to 28, the
method organization_name accesses self.repository without checking if it is
None, which can cause a null reference error. Add a check to ensure
self.repository is not None before accessing self.repository.organization.
Return None if self.repository is None to safely handle the absence of a
repository.

Comment on lines 48 to 51
if login:
queryset = queryset.select_related(
"author",
"repository",
"repository__organization",
).filter(
queryset = queryset.filter().filter(
author__login=login,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix duplicated filter() call

There's an unnecessary duplicated .filter() call that should be removed.

-            queryset = queryset.filter().filter(
+            queryset = queryset.filter(
                 author__login=login,
             )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if login:
queryset = queryset.select_related(
"author",
"repository",
"repository__organization",
).filter(
queryset = queryset.filter().filter(
author__login=login,
)
if login:
queryset = queryset.filter(
author__login=login,
)
🤖 Prompt for AI Agents
In backend/apps/github/graphql/queries/release.py around lines 48 to 51, there
is a duplicated .filter() call on the queryset. Remove the redundant .filter()
so that only a single .filter() is used with the author__login=login condition
inside it.

@aramattamara aramattamara changed the base branch from main to feature/strawberry May 23, 2025 00:23
@aramattamara
Copy link
Collaborator

aramattamara commented May 23, 2025

Changed base branch to the feature branch "feature/strawberry" @abhayymishraa

@abhayymishraa abhayymishraa marked this pull request as ready for review May 23, 2025 07:42
@abhayymishraa abhayymishraa requested a review from arkid15r as a code owner May 23, 2025 07:42
field = self._get_field_by_name("issues_count")
assert field is not None
assert str(field.type) == "[String]"
assert "int" in str(field.type).lower()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use

Suggested change
assert "int" in str(field.type).lower()
assert field.type is int

approach for all similar assertions.

assert field is not None
assert str(field.type) == "[RepositoryContributorNode]"
inner_type = getattr(field.type, "of_type", None) or field.type
assert "MilestoneNode" in str(inner_type)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here, I believe

Suggested change
assert "MilestoneNode" in str(inner_type)
assert inner_type is MilestoneNode

should work (needs to be imported)

@abhayymishraa abhayymishraa requested a review from arkid15r May 24, 2025 12:12
@github-actions github-actions bot added nestbot and removed backend labels May 25, 2025
@github-actions github-actions bot added backend and removed nestbot labels May 25, 2025
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
14.1% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@arkid15r arkid15r enabled auto-merge (squash) May 25, 2025 18:52
Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

LGTM

@arkid15r arkid15r merged commit 4a1d76b into OWASP:feature/strawberry May 25, 2025
19 of 20 checks passed
ahmedxgouda pushed a commit to ahmedxgouda/Nest that referenced this pull request May 26, 2025
* Initialised and setup for the Strawberry

* Updated Code

* Updated Tests

* Updated Code

* Update code

* updated tests according to suggestion

* Update code

---------

Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>
Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate GraphQL implementation from Graphene to Strawberry

3 participants