Expose isGroupLevel on the BranchRule GraphQL type

What does this MR do and why?

Exposes isGroupLevel on the BranchRule GraphQL type (EE, experiment).

BranchProtection#isGroupLevel sits behind read_protected_branch on the group-level protected branch, so branchProtection resolves to null for users without group permissions and the frontend cannot tell a group-level rule from a project rule with no readable protection. The rule-level field is readable by everyone who can read the rule, which the branch rule details page needs to explain inherited rules to users of every permission level.

Also replaces a vacuously passing request spec assertion that compared a JSON string id with a GlobalID object, and makes the branch rules specs order-independent.

This is the backend slice of Add empty state for group-level branch rule at project level (!245898), extracted per the maintainer's multiversion-compatibility review so the field lands before the frontend that queries it. !245898 (merged) rebases to frontend-only once this merges.

Part of #577324 (closed)

References

Screenshots or screen recordings

No UI changes (backend GraphQL field only).

How to set up and validate locally

  1. Create a group with a project, and a protected branch on the group (group Settings, Repository, Protected branches).

  2. In GraphiQL (/-/graphql-explorer), query the project's branch rules:

    {
      project(fullPath: "<group>/<project>") {
        branchRules {
          nodes {
            name
            isGroupLevel
          }
        }
      }
    }
  3. The group-level rule returns isGroupLevel: true; project-level rules return false. The field resolves for any user who can read the branch rule, including users with no group access.

Merge request reports

Loading
Loading