Feat: Add projectId filter to duoWorkflowWorkflows GraphQL query

What does this MR do and why?

Adds a projectId argument to the duoWorkflowWorkflows GraphQL query so Duo Agent Platform sessions (flows/workflows) can be filtered to a single project by its Global ID. The query already accepted projectPath, but callers holding a project Global ID had to resolve a full path first to use it. GitLab's GraphQL styleguide says object identifiers should use Types::GlobalIDType[Model], so this adds a proper Global ID argument alongside the existing one. This is backend only; the Sessions page UI filter is separate follow-up work.

Changed files:

  • ee/app/graphql/resolvers/ai/duo_workflows/workflows_resolver.rb - new optional project_id argument of type Types::GlobalIDType[::Project]. The resolver unwraps the Global ID to a numeric ID before passing it to the finder, so the finder stays free of GraphQL types.
  • ee/app/finders/ai/duo_workflows/workflows_finder.rb - new resolve_project_id method. Looks up the project, checks the :duo_workflow ability for the current user (same ability already used for the projectPath filter), and scopes results to that project. Returns no results if the project doesn't exist or isn't accessible, rather than raising, matching GraphQL convention.
  • ee/spec/finders/ai/duo_workflows/workflows_finder_spec.rb - 3 new examples: user can access the project, user cannot access the project, project does not exist.
  • ee/spec/requests/api/graphql/ai/duo_workflows/workflows_spec.rb - 2 new request-spec examples next to the existing project_path coverage: filtering returns only that project's sessions, and a non-existent project Global ID returns an empty list.
  • doc/api/graphql/reference/_index.md - regenerated via bundle exec rake gitlab:graphql:compile_docs.
  • doc/development/ai_features/duo_agent_platform_observability.md - filter table for duoWorkflowWorkflows now lists projectId.

No database migration, no new query patterns beyond a single project lookup, no new feature flag.

Open question for reviewers: both projectPath and projectId are accepted. If a caller passes both and they point at different projects, the filters intersect and the result is an empty list rather than an error. Worth discussing whether the two arguments should be mutually exclusive instead, so passing both by mistake raises an error rather than silently returning nothing.

References

Screenshots or screen recordings

Backend-only GraphQL change with no UI. Screenshots don't apply.

How to set up and validate locally

  1. Check out the branch 622898-filter-sessions-by-project-id. In the GDK, make sure a project has Duo Agent Platform sessions - run a flow to create some, or use an existing project that already has sessions.

  2. Get the project's Global ID from a rails console:

    Project.find_by_full_path('flightjs/Flight').to_global_id.to_s
    # => "gid://gitlab/Project/7"
  3. Open GraphiQL at http://gdk.test:3000/-/graphql-explorer and run this query, substituting the Global ID from the previous step:

    query {
      duoWorkflowWorkflows(projectId: "gid://gitlab/Project/7") {
        nodes {
          id
          projectId
          project {
            fullPath
          }
        }
      }
    }

    Expected: only sessions whose projectId matches the one passed in.

  4. Run the same query without the projectId argument and confirm more sessions come back, including ones from other projects:

    query {
      duoWorkflowWorkflows {
        nodes {
          id
          projectId
          project {
            fullPath
          }
        }
      }
    }
  5. Pass a Global ID for a project the current user can't access, or one that doesn't exist, and confirm nodes is empty with no error:

    query {
      duoWorkflowWorkflows(projectId: "gid://gitlab/Project/999999") {
        nodes {
          id
        }
      }
    }
  6. Run the specs:

    bundle exec rspec ee/spec/finders/ai/duo_workflows/workflows_finder_spec.rb ee/spec/requests/api/graphql/ai/duo_workflows/workflows_spec.rb

MR acceptance checklist

Check this MR against the MR acceptance checklist.

Verified locally: RuboCop reports no offenses on all 4 changed Ruby files. bundle exec rspec ee/spec/requests/api/graphql/ai/duo_workflows/workflows_spec.rb ee/spec/finders/ai/duo_workflows/workflows_finder_spec.rb ran 129 examples, 0 failures.

Merge request reports

Loading
Loading