diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index d6d7eddf25533ef64060c8fe6464f4ed52aaff46..0c618aa55a6fbed754576eb654ea0abd23560d5e 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -23,6 +23,10 @@ class ProjectsResolver < BaseResolver
required: false,
description: "Return only projects with merge requests enabled."
+ argument :archived, ::Types::Projects::ArchivedEnum,
+ required: false,
+ description: 'Filter projects by archived status.'
+
def resolve_with_lookahead(**args)
validate_args!(args)
@@ -64,7 +68,8 @@ def finder_params(args)
**project_finder_params(args),
with_issues_enabled: args[:with_issues_enabled],
with_merge_requests_enabled: args[:with_merge_requests_enabled],
- full_paths: args[:full_paths]
+ full_paths: args[:full_paths],
+ archived: args[:archived]
}
end
diff --git a/app/graphql/types/projects/archived_enum.rb b/app/graphql/types/projects/archived_enum.rb
new file mode 100644
index 0000000000000000000000000000000000000000..774f008466ec9fead1ee99ab9b36c58cc10395fa
--- /dev/null
+++ b/app/graphql/types/projects/archived_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module Projects
+ class ArchivedEnum < BaseEnum
+ graphql_name 'ProjectArchived'
+ description 'Values for the archived argument'
+
+ value 'ONLY', 'Only archived projects.', value: 'only'
+ value 'INCLUDE', 'Include archvied projects.', value: true
+ value 'EXCLUDE', 'Exclude archived projects.', value: false
+ end
+ end
+end
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 8ce3026624ba8a18f7d954998fb2ee64890c18a3..973a4dbdfcf6f79b408676a9a033479b69b7c0cf 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -909,6 +909,7 @@ four standard [pagination arguments](#pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| `aimedForDeletion` | [`Boolean`](#boolean) | Return only projects marked for deletion. |
+| `archived` | [`ProjectArchived`](#projectarchived) | Filter projects by archived status. |
| `fullPaths` | [`[String!]`](#string) | Filter projects by full paths. You cannot provide more than 50 full paths. |
| `ids` | [`[ID!]`](#id) | Filter projects by IDs. |
| `includeHidden` | [`Boolean`](#boolean) | Include hidden projects. |
@@ -27596,6 +27597,7 @@ four standard [pagination arguments](#pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| `aimedForDeletion` | [`Boolean`](#boolean) | Return only projects marked for deletion. |
+| `archived` | [`ProjectArchived`](#projectarchived) | Filter projects by archived status. |
| `fullPaths` | [`[String!]`](#string) | Filter projects by full paths. You cannot provide more than 50 full paths. |
| `ids` | [`[ID!]`](#id) | Filter projects by IDs. |
| `includeHidden` | [`Boolean`](#boolean) | Include hidden projects. |
@@ -36816,6 +36818,16 @@ Current state of the product analytics stack.
| `LOADING_INSTANCE` | Stack is currently initializing. |
| `WAITING_FOR_EVENTS` | Stack is waiting for events from users. |
+### `ProjectArchived`
+
+Values for the archived argument.
+
+| Value | Description |
+| ----- | ----------- |
+| `EXCLUDE` | Exclude archived projects. |
+| `INCLUDE` | Include archvied projects. |
+| `ONLY` | Only archived projects. |
+
### `ProjectFeatureAccessLevel`
Access level of a project feature.
diff --git a/spec/requests/api/graphql/projects/projects_spec.rb b/spec/requests/api/graphql/projects/projects_spec.rb
index 9dcf4020ed063df81914d4a86666df83740935a1..78acb5e9dc504be07d4c6c653804f2b720fc3934 100644
--- a/spec/requests/api/graphql/projects/projects_spec.rb
+++ b/spec/requests/api/graphql/projects/projects_spec.rb
@@ -9,6 +9,7 @@
let_it_be(:group) { create(:group, name: 'public-group', developers: current_user) }
let_it_be(:projects) { create_list(:project, 5, :public, group: group) }
let_it_be(:other_project) { create(:project, :public, group: group) }
+ let_it_be(:archived_project) { create(:project, :archived, group: group) }
let(:filters) { {} }
@@ -20,6 +21,46 @@
)
end
+ context 'when archived argument is ONLY' do
+ let(:filters) { { archived: :ONLY } }
+
+ it 'returns only archived projects' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:projects, :nodes))
+ .to contain_exactly(a_graphql_entity_for(archived_project))
+ end
+ end
+
+ context 'when archived argument is INCLUDE' do
+ let(:filters) { { archived: :INCLUDE } }
+
+ it 'returns archived and non-archived projects' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:projects, :nodes))
+ .to contain_exactly(
+ *projects.map { |project| a_graphql_entity_for(project) },
+ a_graphql_entity_for(other_project),
+ a_graphql_entity_for(archived_project)
+ )
+ end
+ end
+
+ context 'when archived argument is EXCLUDE' do
+ let(:filters) { { archived: :EXCLUDE } }
+
+ it 'returns only non-archived projects' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:projects, :nodes))
+ .to contain_exactly(
+ *projects.map { |project| a_graphql_entity_for(project) },
+ a_graphql_entity_for(other_project)
+ )
+ end
+ end
+
context 'when providing full_paths filter' do
let(:project_full_paths) { projects.map(&:full_path) }
let(:filters) { { full_paths: project_full_paths } }