Commit 73866ca7 authored by Eugenia Grieff's avatar Eugenia Grieff

Add mutation to export requirements

- Add export requirements policy
- Update schema
parent 4acb76d3
......@@ -9442,6 +9442,56 @@ enum EpicWildcardId {
NONE
}
"""
Autogenerated input type of ExportRequirements
"""
input ExportRequirementsInput {
"""
Filter requirements by author username.
"""
authorUsername: [String!]
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Full project path the requirements are associated with.
"""
projectPath: ID!
"""
Search query for requirement title.
"""
search: String
"""
List requirements by sort order.
"""
sort: Sort
"""
Filter requirements by state.
"""
state: RequirementState
}
"""
Autogenerated return type of ExportRequirements
"""
type ExportRequirementsPayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Errors encountered during execution of the mutation.
"""
errors: [String!]!
}
"""
Represents an external issue
"""
......@@ -15382,6 +15432,7 @@ type Mutation {
epicAddIssue(input: EpicAddIssueInput!): EpicAddIssuePayload
epicSetSubscription(input: EpicSetSubscriptionInput!): EpicSetSubscriptionPayload
epicTreeReorder(input: EpicTreeReorderInput!): EpicTreeReorderPayload
exportRequirements(input: ExportRequirementsInput!): ExportRequirementsPayload
httpIntegrationCreate(input: HttpIntegrationCreateInput!): HttpIntegrationCreatePayload
httpIntegrationDestroy(input: HttpIntegrationDestroyInput!): HttpIntegrationDestroyPayload
httpIntegrationResetToken(input: HttpIntegrationResetTokenInput!): HttpIntegrationResetTokenPayload
......
......@@ -26208,6 +26208,142 @@
],
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "ExportRequirementsInput",
"description": "Autogenerated input type of ExportRequirements",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "Full project path the requirements are associated with.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "sort",
"description": "List requirements by sort order.",
"type": {
"kind": "ENUM",
"name": "Sort",
"ofType": null
},
"defaultValue": null
},
{
"name": "state",
"description": "Filter requirements by state.",
"type": {
"kind": "ENUM",
"name": "RequirementState",
"ofType": null
},
"defaultValue": null
},
{
"name": "search",
"description": "Search query for requirement title.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "authorUsername",
"description": "Filter requirements by author username.",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "ExportRequirementsPayload",
"description": "Autogenerated return type of ExportRequirements",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "ExternalIssue",
......@@ -43800,6 +43936,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "exportRequirements",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "ExportRequirementsInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "ExportRequirementsPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "httpIntegrationCreate",
"description": null,
......@@ -1530,6 +1530,15 @@ Autogenerated return type of EpicTreeReorder.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### ExportRequirementsPayload
Autogenerated return type of ExportRequirements.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### ExternalIssue
Represents an external issue.
......
......@@ -25,6 +25,7 @@ module EE
mount_mutation ::Mutations::Iterations::Create
mount_mutation ::Mutations::Iterations::Update
mount_mutation ::Mutations::RequirementsManagement::CreateRequirement
mount_mutation ::Mutations::RequirementsManagement::ExportRequirements
mount_mutation ::Mutations::RequirementsManagement::UpdateRequirement
mount_mutation ::Mutations::Vulnerabilities::Dismiss
mount_mutation ::Mutations::Vulnerabilities::Resolve
......
# frozen_string_literal: true
module Mutations
module RequirementsManagement
class ExportRequirements < BaseMutation
include ResolvesProject
graphql_name 'ExportRequirements'
authorize :export_requirements
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'Full project path the requirements are associated with.'
argument :sort, Types::SortEnum,
required: false,
description: 'List requirements by sort order.'
argument :state, Types::RequirementsManagement::RequirementStateEnum,
required: false,
description: 'Filter requirements by state.'
argument :search, GraphQL::STRING_TYPE,
required: false,
description: 'Search query for requirement title.'
argument :author_username, [GraphQL::STRING_TYPE],
required: false,
description: 'Filter requirements by author username.'
def resolve(args)
project_path = args.delete(:project_path)
project = authorized_find!(full_path: project_path)
IssuableExportCsvWorker.perform_async(:requirement, current_user.id, project.id, args)
{
errors: []
}
end
private
def find_object(full_path:)
resolve_project(full_path: full_path)
end
end
end
end
......@@ -364,6 +364,7 @@ module EE
enable :admin_requirement
enable :update_requirement
enable :import_requirements
enable :export_requirements
end
rule { requirements_available & owner }.enable :destroy_requirement
......
---
title: Add GraphQL mutation to export Requirements
merge_request: 50546
author:
type: added
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::RequirementsManagement::ExportRequirements do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:requirement) { create(:requirement, project: project) }
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
describe '#resolve' do
shared_examples 'requirements not available' do
it 'raises a not accessible error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
subject do
mutation.resolve(
project_path: project.full_path,
author_username: user.username,
state: 'OPENED',
search: 'foo'
)
end
it_behaves_like 'requirements not available'
context 'when the user can update the requirement' do
before do
project.add_developer(user)
end
context 'when requirements feature is available' do
before do
stub_licensed_features(requirements: true)
end
it 'export requirements' do
args = { author_username: user.username, state: 'OPENED', search: 'foo' }
expect(IssuableExportCsvWorker).to receive(:perform_async)
.with(:requirement, user.id, project.id, args)
subject
end
end
context 'when requirements feature is disabled' do
before do
stub_licensed_features(requirements: false)
end
it_behaves_like 'requirements not available'
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment