Commit f098e6d3 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 697d1c4e
...@@ -65,6 +65,7 @@ module Types ...@@ -65,6 +65,7 @@ module Types
raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone
raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason
raise ArgumentError, '`milestone` must be a `String`' unless milestone.is_a?(String)
deprecated_in = "Deprecated in #{milestone}" deprecated_in = "Deprecated in #{milestone}"
kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}" kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}"
......
...@@ -44,7 +44,7 @@ module Types ...@@ -44,7 +44,7 @@ module Types
field :latest_pipeline, field :latest_pipeline,
type: Types::Ci::PipelineType, type: Types::Ci::PipelineType,
null: true, null: true,
deprecated: { reason: 'Use `pipelines`', milestone: 12.5 }, deprecated: { reason: 'Use `pipelines`', milestone: '12.5' },
description: 'Latest pipeline of the commit', description: 'Latest pipeline of the commit',
resolver: Resolvers::CommitPipelinesResolver.last resolver: Resolvers::CommitPipelinesResolver.last
end end
......
...@@ -18,7 +18,7 @@ module Types ...@@ -18,7 +18,7 @@ module Types
description: 'Timestamp of the issue\'s last activity' description: 'Timestamp of the issue\'s last activity'
field :token, GraphQL::STRING_TYPE, null: false, field :token, GraphQL::STRING_TYPE, null: false,
deprecated: { reason: 'Plain text token has been masked for security reasons', milestone: 12.7 }, deprecated: { reason: 'Plain text token has been masked for security reasons', milestone: '12.7' },
description: 'API token for the Grafana integration' description: 'API token for the Grafana integration'
def token def token
......
...@@ -75,7 +75,7 @@ module Types ...@@ -75,7 +75,7 @@ module Types
field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false, calls_gitaly: true, field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false, calls_gitaly: true,
description: 'Indicates if there is a rebase currently in progress for the merge request' description: 'Indicates if there is a rebase currently in progress for the merge request'
field :merge_commit_message, GraphQL::STRING_TYPE, method: :default_merge_commit_message, null: true, field :merge_commit_message, GraphQL::STRING_TYPE, method: :default_merge_commit_message, null: true,
deprecated: { reason: 'Use `defaultMergeCommitMessage`', milestone: 11.8 }, deprecated: { reason: 'Use `defaultMergeCommitMessage`', milestone: '11.8' },
description: 'Default merge commit message of the merge request' description: 'Default merge commit message of the merge request'
field :default_merge_commit_message, GraphQL::STRING_TYPE, null: true, field :default_merge_commit_message, GraphQL::STRING_TYPE, null: true,
description: 'Default merge commit message of the merge request' description: 'Default merge commit message of the merge request'
......
...@@ -54,7 +54,7 @@ module Types ...@@ -54,7 +54,7 @@ module Types
field :container_registry_enabled, GraphQL::BOOLEAN_TYPE, null: true, field :container_registry_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if the project stores Docker container images in a container registry' description: 'Indicates if the project stores Docker container images in a container registry'
field :shared_runners_enabled, GraphQL::BOOLEAN_TYPE, null: true, field :shared_runners_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if shared runners are enabled on the project' description: 'Indicates if Shared Runners are enabled for the project'
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true, field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if the project has Large File Storage (LFS) enabled' description: 'Indicates if the project has Large File Storage (LFS) enabled'
field :merge_requests_ff_only_enabled, GraphQL::BOOLEAN_TYPE, null: true, field :merge_requests_ff_only_enabled, GraphQL::BOOLEAN_TYPE, null: true,
...@@ -68,14 +68,14 @@ module Types ...@@ -68,14 +68,14 @@ module Types
%i[issues merge_requests wiki snippets].each do |feature| %i[issues merge_requests wiki snippets].each do |feature|
field "#{feature}_enabled", GraphQL::BOOLEAN_TYPE, null: true, field "#{feature}_enabled", GraphQL::BOOLEAN_TYPE, null: true,
description: "(deprecated) Does this project have #{feature} enabled?. Use `#{feature}_access_level` instead", description: "Indicates if #{feature.to_s.titleize.pluralize} are enabled for the current user",
resolve: -> (project, args, ctx) do resolve: -> (project, args, ctx) do
project.feature_available?(feature, ctx[:current_user]) project.feature_available?(feature, ctx[:current_user])
end end
end end
field :jobs_enabled, GraphQL::BOOLEAN_TYPE, null: true, field :jobs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: '(deprecated) Enable jobs for this project. Use `builds_access_level` instead', description: 'Indicates if CI/CD pipeline jobs are enabled for the current user',
resolve: -> (project, args, ctx) do resolve: -> (project, args, ctx) do
project.feature_available?(:builds, ctx[:current_user]) project.feature_available?(:builds, ctx[:current_user])
end end
......
---
title: Cleanup the descriptions of some fields of GraphQL ProjectType
merge_request: 28735
author:
type: changed
---
title: Normalize signature mime types when filtering attachments in emails
merge_request: 28865
author: Diego Louzán
type: fixed
...@@ -52,6 +52,36 @@ management between systems: ...@@ -52,6 +52,36 @@ management between systems:
- [NetApp instructions](https://library.netapp.com/ecmdocs/ECMP1401220/html/GUID-24367A9F-E17B-4725-ADC1-02D86F56F78E.html) - [NetApp instructions](https://library.netapp.com/ecmdocs/ECMP1401220/html/GUID-24367A9F-E17B-4725-ADC1-02D86F56F78E.html)
- For non-NetApp devices, disable NFSv4 `idmapping` by performing opposite of [enable NFSv4 idmapper](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping) - For non-NetApp devices, disable NFSv4 `idmapping` by performing opposite of [enable NFSv4 idmapper](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping)
### Disable NFS server delegation
We recommend that all NFS users disable the NFS server delegation feature. This
is to avoid a [Linux kernel bug](https://bugzilla.redhat.com/show_bug.cgi?id=1552203)
which causes NFS clients to slow precipitously due to
[excessive network traffic from numerous `TEST_STATEID` NFS messages](https://gitlab.com/gitlab-org/gitlab-foss/issues/52017).
To disable NFS server delegation, do the following:
1. On the NFS server, run:
```shell
echo 0 > /proc/sys/fs/leases-enable
sysctl -w fs.leases-enable=0
```
1. Restart the NFS server process. For example, on CentOS run `service nfs restart`.
#### Important notes
The kernel bug may be fixed in
[more recent kernels with this commit](https://github.om/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140).
Red Hat Enterprise 7 [shipped a kernel update](https://access.redhat.com/errata/RHSA-2019:2029)
on August 6, 2019 that may also have resolved this problem.
You may not need to disable NFS server delegation if you know you are using a version of
the Linux kernel that has been fixed. That said, GitLab still encourages instance
administrators to keep NFS server delegation disabled.
### Improving NFS performance with GitLab ### Improving NFS performance with GitLab
#### Improving NFS performance with Unicorn #### Improving NFS performance with Unicorn
...@@ -78,33 +108,7 @@ If the Rugged feature flag is explicitly set to either true or false, GitLab wil ...@@ -78,33 +108,7 @@ If the Rugged feature flag is explicitly set to either true or false, GitLab wil
### Known issues ### Known issues
On some customer systems, we have seen NFS clients slow precipitously due to #### Avoid using AWS's Elastic File System (EFS)
[excessive network traffic from numerous `TEST_STATEID` NFS
messages](https://gitlab.com/gitlab-org/gitlab-foss/issues/52017). This is
likely due to a [Linux kernel
bug](https://bugzilla.redhat.com/show_bug.cgi?id=1552203) that may be fixed in
[more recent kernels with this
commit](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140).
NOTE: **Note** Red Hat Enterprise 7 [shipped a kernel
update](https://access.redhat.com/errata/RHSA-2019:2029) on August 6,
2019 that may have resolved this problem. The following instructions may
not be needed if the latest kernel is updated properly.
GitLab recommends all NFS users disable the NFS server
delegation feature. To disable NFS server delegations
on an Linux NFS server, do the following:
1. On the NFS server, run:
```shell
echo 0 > /proc/sys/fs/leases-enable
sysctl -w fs.leases-enable=0
```
1. Restart the NFS server process. For example, on CentOS run `service nfs restart`.
## Avoid using AWS's Elastic File System (EFS)
GitLab strongly recommends against using AWS Elastic File System (EFS). GitLab strongly recommends against using AWS Elastic File System (EFS).
Our support team will not be able to assist on performance issues related to Our support team will not be able to assist on performance issues related to
...@@ -120,12 +124,12 @@ stored on a local volume. ...@@ -120,12 +124,12 @@ stored on a local volume.
For more details on another person's experience with EFS, see this [Commit Brooklyn 2019 video](https://youtu.be/K6OS8WodRBQ?t=313). For more details on another person's experience with EFS, see this [Commit Brooklyn 2019 video](https://youtu.be/K6OS8WodRBQ?t=313).
## Avoid using CephFS and GlusterFS #### Avoid using CephFS and GlusterFS
GitLab strongly recommends against using CephFS and GlusterFS. GitLab strongly recommends against using CephFS and GlusterFS.
These distributed file systems are not well-suited for GitLab's input/output access patterns because Git uses many small files and access times and file locking times to propagate will make Git activity very slow. These distributed file systems are not well-suited for GitLab's input/output access patterns because Git uses many small files and access times and file locking times to propagate will make Git activity very slow.
## Avoid using PostgreSQL with NFS #### Avoid using PostgreSQL with NFS
GitLab strongly recommends against running your PostgreSQL database GitLab strongly recommends against running your PostgreSQL database
across NFS. The GitLab support team will not be able to assist on performance issues related to across NFS. The GitLab support team will not be able to assist on performance issues related to
......
...@@ -6093,7 +6093,7 @@ type Project { ...@@ -6093,7 +6093,7 @@ type Project {
): IssueConnection ): IssueConnection
""" """
(deprecated) Does this project have issues enabled?. Use `issues_access_level` instead Indicates if Issues are enabled for the current user
""" """
issuesEnabled: Boolean issuesEnabled: Boolean
...@@ -6128,7 +6128,7 @@ type Project { ...@@ -6128,7 +6128,7 @@ type Project {
): JiraImportConnection ): JiraImportConnection
""" """
(deprecated) Enable jobs for this project. Use `builds_access_level` instead Indicates if CI/CD pipeline jobs are enabled for the current user
""" """
jobsEnabled: Boolean jobsEnabled: Boolean
...@@ -6193,7 +6193,7 @@ type Project { ...@@ -6193,7 +6193,7 @@ type Project {
): MergeRequestConnection ): MergeRequestConnection
""" """
(deprecated) Does this project have merge_requests enabled?. Use `merge_requests_access_level` instead Indicates if Merge Requests are enabled for the current user
""" """
mergeRequestsEnabled: Boolean mergeRequestsEnabled: Boolean
...@@ -6406,7 +6406,7 @@ type Project { ...@@ -6406,7 +6406,7 @@ type Project {
serviceDeskEnabled: Boolean serviceDeskEnabled: Boolean
""" """
Indicates if shared runners are enabled on the project Indicates if Shared Runners are enabled for the project
""" """
sharedRunnersEnabled: Boolean sharedRunnersEnabled: Boolean
...@@ -6446,7 +6446,7 @@ type Project { ...@@ -6446,7 +6446,7 @@ type Project {
): SnippetConnection ): SnippetConnection
""" """
(deprecated) Does this project have snippets enabled?. Use `snippets_access_level` instead Indicates if Snippets are enabled for the current user
""" """
snippetsEnabled: Boolean snippetsEnabled: Boolean
...@@ -6542,7 +6542,7 @@ type Project { ...@@ -6542,7 +6542,7 @@ type Project {
webUrl: String webUrl: String
""" """
(deprecated) Does this project have wiki enabled?. Use `wiki_access_level` instead Indicates if Wikis are enabled for the current user
""" """
wikiEnabled: Boolean wikiEnabled: Boolean
} }
......
...@@ -18344,7 +18344,7 @@ ...@@ -18344,7 +18344,7 @@
}, },
{ {
"name": "issuesEnabled", "name": "issuesEnabled",
"description": "(deprecated) Does this project have issues enabled?. Use `issues_access_level` instead", "description": "Indicates if Issues are enabled for the current user",
"args": [ "args": [
], ],
...@@ -18425,7 +18425,7 @@ ...@@ -18425,7 +18425,7 @@
}, },
{ {
"name": "jobsEnabled", "name": "jobsEnabled",
"description": "(deprecated) Enable jobs for this project. Use `builds_access_level` instead", "description": "Indicates if CI/CD pipeline jobs are enabled for the current user",
"args": [ "args": [
], ],
...@@ -18589,7 +18589,7 @@ ...@@ -18589,7 +18589,7 @@
}, },
{ {
"name": "mergeRequestsEnabled", "name": "mergeRequestsEnabled",
"description": "(deprecated) Does this project have merge_requests enabled?. Use `merge_requests_access_level` instead", "description": "Indicates if Merge Requests are enabled for the current user",
"args": [ "args": [
], ],
...@@ -19125,7 +19125,7 @@ ...@@ -19125,7 +19125,7 @@
}, },
{ {
"name": "sharedRunnersEnabled", "name": "sharedRunnersEnabled",
"description": "Indicates if shared runners are enabled on the project", "description": "Indicates if Shared Runners are enabled for the project",
"args": [ "args": [
], ],
...@@ -19220,7 +19220,7 @@ ...@@ -19220,7 +19220,7 @@
}, },
{ {
"name": "snippetsEnabled", "name": "snippetsEnabled",
"description": "(deprecated) Does this project have snippets enabled?. Use `snippets_access_level` instead", "description": "Indicates if Snippets are enabled for the current user",
"args": [ "args": [
], ],
...@@ -19493,7 +19493,7 @@ ...@@ -19493,7 +19493,7 @@
}, },
{ {
"name": "wikiEnabled", "name": "wikiEnabled",
"description": "(deprecated) Does this project have wiki enabled?. Use `wiki_access_level` instead", "description": "Indicates if Wikis are enabled for the current user",
"args": [ "args": [
], ],
......
...@@ -901,13 +901,13 @@ Information about pagination in a connection. ...@@ -901,13 +901,13 @@ Information about pagination in a connection.
| `id` | ID! | ID of the project | | `id` | ID! | ID of the project |
| `importStatus` | String | Status of import background job of the project | | `importStatus` | String | Status of import background job of the project |
| `issue` | Issue | A single issue of the project | | `issue` | Issue | A single issue of the project |
| `issuesEnabled` | Boolean | (deprecated) Does this project have issues enabled?. Use `issues_access_level` instead | | `issuesEnabled` | Boolean | Indicates if Issues are enabled for the current user |
| `jiraImportStatus` | String | Status of Jira import background job of the project | | `jiraImportStatus` | String | Status of Jira import background job of the project |
| `jobsEnabled` | Boolean | (deprecated) Enable jobs for this project. Use `builds_access_level` instead | | `jobsEnabled` | Boolean | Indicates if CI/CD pipeline jobs are enabled for the current user |
| `lastActivityAt` | Time | Timestamp of the project last activity | | `lastActivityAt` | Time | Timestamp of the project last activity |
| `lfsEnabled` | Boolean | Indicates if the project has Large File Storage (LFS) enabled | | `lfsEnabled` | Boolean | Indicates if the project has Large File Storage (LFS) enabled |
| `mergeRequest` | MergeRequest | A single merge request of the project | | `mergeRequest` | MergeRequest | A single merge request of the project |
| `mergeRequestsEnabled` | Boolean | (deprecated) Does this project have merge_requests enabled?. Use `merge_requests_access_level` instead | | `mergeRequestsEnabled` | Boolean | Indicates if Merge Requests are enabled for the current user |
| `mergeRequestsFfOnlyEnabled` | Boolean | Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. | | `mergeRequestsFfOnlyEnabled` | Boolean | Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. |
| `name` | String! | Name of the project (without namespace) | | `name` | String! | Name of the project (without namespace) |
| `nameWithNamespace` | String! | Full name of the project with its namespace | | `nameWithNamespace` | String! | Full name of the project with its namespace |
...@@ -927,8 +927,8 @@ Information about pagination in a connection. ...@@ -927,8 +927,8 @@ Information about pagination in a connection.
| `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project | | `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project |
| `serviceDeskAddress` | String | E-mail address of the service desk. | | `serviceDeskAddress` | String | E-mail address of the service desk. |
| `serviceDeskEnabled` | Boolean | Indicates if the project has service desk enabled. | | `serviceDeskEnabled` | Boolean | Indicates if the project has service desk enabled. |
| `sharedRunnersEnabled` | Boolean | Indicates if shared runners are enabled on the project | | `sharedRunnersEnabled` | Boolean | Indicates if Shared Runners are enabled for the project |
| `snippetsEnabled` | Boolean | (deprecated) Does this project have snippets enabled?. Use `snippets_access_level` instead | | `snippetsEnabled` | Boolean | Indicates if Snippets are enabled for the current user |
| `sshUrlToRepo` | String | URL to connect to the project via SSH | | `sshUrlToRepo` | String | URL to connect to the project via SSH |
| `starCount` | Int! | Number of times the project has been starred | | `starCount` | Int! | Number of times the project has been starred |
| `statistics` | ProjectStatistics | Statistics of the project | | `statistics` | ProjectStatistics | Statistics of the project |
...@@ -938,7 +938,7 @@ Information about pagination in a connection. ...@@ -938,7 +938,7 @@ Information about pagination in a connection.
| `visibility` | String | Visibility of the project | | `visibility` | String | Visibility of the project |
| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each severity of vulnerability of the project. Available only when feature flag `first_class_vulnerabilities` is enabled | | `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each severity of vulnerability of the project. Available only when feature flag `first_class_vulnerabilities` is enabled |
| `webUrl` | String | Web URL of the project | | `webUrl` | String | Web URL of the project |
| `wikiEnabled` | Boolean | (deprecated) Does this project have wiki enabled?. Use `wiki_access_level` instead | | `wikiEnabled` | Boolean | Indicates if Wikis are enabled for the current user |
## ProjectPermissions ## ProjectPermissions
......
...@@ -45,8 +45,8 @@ For example, `app/graphql/types/issue_type.rb`: ...@@ -45,8 +45,8 @@ For example, `app/graphql/types/issue_type.rb`:
```ruby ```ruby
graphql_name 'Issue' graphql_name 'Issue'
field :iid, GraphQL::ID_TYPE, null: false field :iid, GraphQL::ID_TYPE, null: true
field :title, GraphQL::STRING_TYPE, null: false field :title, GraphQL::STRING_TYPE, null: true
# we also have a method here that we've defined, that extends `field` # we also have a method here that we've defined, that extends `field`
markdown_field :title_html, null: true markdown_field :title_html, null: true
...@@ -258,30 +258,78 @@ end ...@@ -258,30 +258,78 @@ end
## Feature flags ## Feature flags
Features controlled by feature flags often provide GraphQL functionality. When a feature Developers can add [feature flags](../development/feature_flags/index.md) to GraphQL
is enabled or disabled by a feature flag, the related GraphQL functionality should also fields in the following ways:
be enabled or disabled.
Fields can be put behind a feature flag so they can conditionally return the value for - Add the `feature_flag` property to a field. This will allow the field to be _hidden_
the field depending on if the feature has been enabled or not. from the GraphQL schema when the flag is disabled.
- Toggle the return value when resolving the field.
GraphQL feature flags use the common You can refer to these guidelines to decide which approach to use:
[GitLab feature flag](../development/feature_flags.md) system, and can be added to a
field using the `feature_flag` property.
For example: - If your field is experimental, and its name or type is subject to
change, use the `feature_flag` property.
- If your field is stable and its definition will not change, even after the flag is
removed, toggle the return value of the field instead. Note that
[all fields should be nullable](#nullable-fields) anyway.
### `feature_flag` property
The `feature_flag` property allows you to toggle the field's
[visibility](https://graphql-ruby.org/authorization/visibility.html)
within the GraphQL schema. This will remove the field from the schema
when the flag is disabled.
A description is [appended](https://gitlab.com/gitlab-org/gitlab/-/blob/497b556/app/graphql/types/base_field.rb#L44-53)
to the field indicating that it is behind a feature flag.
CAUTION: **Caution:**
If a client queries for the field when the feature flag is disabled, the query will
fail. Consider this when toggling the visibility of the feature on or off on
production.
The `feature_flag` property does not allow the use of
[feature gates based on actors](../development/feature_flags/development.md).
This means that the feature flag cannot be toggled only for particular
projects, groups, or users, but instead can only be toggled globally for
everyone.
Example:
```ruby ```ruby
field :test_field, type: GraphQL::STRING_TYPE, field :test_field, type: GraphQL::STRING_TYPE,
null: false, null: true,
description: 'Some test field', description: 'Some test field',
feature_flag: :some_feature_flag feature_flag: :my_feature_flag
``` ```
In the above example, the `test_field` field will only be returned if ### Toggle the value of a field
the `some_feature_flag` feature flag is enabled.
This method of using feature flags for fields is to toggle the
return value of the field. This can be done in the resolver, in the
type, or even in a model method, depending on your preference and
situation.
If the feature flag is not enabled, an error will be returned saying the field does not exist. When applying a feature flag to toggle the value of a field, the
`description` of the field must:
- State that the value of the field can be toggled by a feature flag.
- Name the feature flag.
- State what the field will return when the feature flag is disabled (or
enabled, if more appropriate).
Example:
```ruby
field :foo, GraphQL::STRING_TYPE,
null: true,
description: 'Some test field. Will always return `null`' \
'if `my_feature_flag` feature flag is disabled'
def foo
object.foo unless Feature.enabled?(:my_feature_flag, object)
end
```
## Deprecating fields ## Deprecating fields
...@@ -301,7 +349,7 @@ Example: ...@@ -301,7 +349,7 @@ Example:
```ruby ```ruby
field :token, GraphQL::STRING_TYPE, null: true, field :token, GraphQL::STRING_TYPE, null: true,
deprecated: { reason: 'Login via token has been removed', milestone: 10.0 }, deprecated: { reason: 'Login via token has been removed', milestone: '10.0' },
description: 'Token for login' description: 'Token for login'
``` ```
...@@ -321,7 +369,7 @@ Example: ...@@ -321,7 +369,7 @@ Example:
```ruby ```ruby
field :designs, ::Types::DesignManagement::DesignCollectionType, null: true, field :designs, ::Types::DesignManagement::DesignCollectionType, null: true,
deprecated: { reason: 'Use `designCollection`', milestone: 10.0 }, deprecated: { reason: 'Use `designCollection`', milestone: '10.0' },
description: 'The designs associated with this issue', description: 'The designs associated with this issue',
``` ```
...@@ -741,7 +789,7 @@ and handles time inputs. ...@@ -741,7 +789,7 @@ and handles time inputs.
Example: Example:
```ruby ```ruby
field :created_at, Types::TimeType, null: false, description: 'Timestamp of when the issue was created' field :created_at, Types::TimeType, null: true, description: 'Timestamp of when the issue was created'
``` ```
## Testing ## Testing
......
...@@ -30,7 +30,7 @@ Among numerous use cases for exporting issues for CSV, we can name a few: ...@@ -30,7 +30,7 @@ Among numerous use cases for exporting issues for CSV, we can name a few:
After selecting a project, from the issues page you can narrow down which issues to export using the search bar, along with the All/Open/Closed tabs. All issues returned will be exported, including those not shown on the first page. After selecting a project, from the issues page you can narrow down which issues to export using the search bar, along with the All/Open/Closed tabs. All issues returned will be exported, including those not shown on the first page.
![CSV export button](img/csv_export_button.png) ![CSV export button](img/csv_export_button_v12_9.png)
You will be asked to confirm the number of issues and email address for the export, after which the email will begin being prepared. You will be asked to confirm the number of issues and email address for the export, after which the email will begin being prepared.
......
...@@ -39,15 +39,22 @@ module Gitlab ...@@ -39,15 +39,22 @@ module Gitlab
# from the uploaded attachments # from the uploaded attachments
def filter_signature_attachments(message) def filter_signature_attachments(message)
attachments = message.attachments attachments = message.attachments
content_type = normalize_mime(message.content_type)
protocol = normalize_mime(message.content_type_parameters[:protocol])
if message.content_type&.starts_with?('multipart/signed') if content_type == 'multipart/signed' && protocol
signature_protocol = message.content_type_parameters[:protocol] attachments.delete_if { |attachment| protocol == normalize_mime(attachment.content_type) }
attachments.delete_if { |attachment| attachment.content_type.starts_with?(signature_protocol) } if signature_protocol.present?
end end
attachments attachments
end end
# normalizes mime-type ignoring case and removing extra data
# also removes potential "x-" prefix from subtype, since some MUAs mix them
# e.g. "application/x-pkcs7-signature" with "application/pkcs7-signature"
def normalize_mime(content_type)
MIME::Type.simplified(content_type, remove_x_prefix: true)
end
end end
end end
end end
User-Agent: Microsoft-MacOutlook/10.22.0.200209
Date: Mon, 17 Feb 2020 22:56:47 +0100
Subject: Re: htmltest | test issue (#1)
From: "Louzan Martinez, Diego (ext) (SI BP R&D ZG)"
<diego.louzan.ext@siemens.com>
To: Administrator / htmltest
<dlouzan.dummy+c034670b1623e617e15a3df64223d363@gmail.com>
Message-ID: <012E37D9-2A3F-4AC8-B79A-871F42914D86@siemens.com>
Thread-Topic: htmltest | test issue (#1)
References: <reply-c034670b1623e617e15a3df64223d363@169.254.169.254>
<issue_451@169.254.169.254>
<note_1797@169.254.169.254>
In-Reply-To: <note_1797@169.254.169.254>
Content-type: multipart/signed;
protocol="application/x-pkcs7-signature";
micalg=sha256;
boundary="B_3664825007_1904734766"
MIME-Version: 1.0
--B_3664825007_1904734766
Content-type: multipart/mixed;
boundary="B_3664825007_384940722"
--B_3664825007_384940722
Content-type: multipart/alternative;
boundary="B_3664825007_1519466360"
--B_3664825007_1519466360
Content-type: text/plain;
charset="UTF-8"
Content-transfer-encoding: quoted-printable
Me too, with an attachment
=20
From: Administrator <dlouzan.dummy@gmail.com>
Reply to: Administrator / htmltest <dlouzan.dummy+c034670b1623e617e15a3df64=
223d363@gmail.com>
Date: Monday, 17 February 2020 at 22:55
To: "Louzan Martinez, Diego (ext) (SOP IT STG XS)" <diego.louzan.ext@siemen=
s.com>
Subject: Re: htmltest | test issue (#1)
=20
Administrator commented:=20
I pity the foo !!!
=E2=80=94=20
Reply to this email directly or view it on GitLab.=20
You're receiving this email because of your account on 169.254.169.254. If =
you'd like to receive fewer emails, you can unsubscribe from this thread or =
adjust your notification settings.=20
--B_3664825007_1519466360
Content-type: text/html;
charset="UTF-8"
Content-transfer-encoding: quoted-printable
<html xmlns:o=3D"urn:schemas-microsoft-com:office:office" xmlns:w=3D"urn:schema=
s-microsoft-com:office:word" xmlns:m=3D"http://schemas.microsoft.com/office/20=
04/12/omml" xmlns=3D"http://www.w3.org/TR/REC-html40"><head><meta http-equiv=3DC=
ontent-Type content=3D"text/html; charset=3Dutf-8"><meta name=3DGenerator content=3D=
"Microsoft Word 15 (filtered medium)"><title>GitLab</title><style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
--></style></head><body lang=3Den-ES link=3Dblue vlink=3Dpurple><div class=3DWordSe=
ction1><p class=3DMsoNormal><span lang=3DEN-US style=3D'mso-fareast-language:EN-US=
'>Me too, with an attachment<o:p></o:p></span></p><p class=3DMsoNormal><span s=
tyle=3D'mso-fareast-language:EN-US'><o:p>&nbsp;</o:p></span></p><div style=3D'bo=
rder:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm'><p class=
=3DMsoNormal><b><span style=3D'font-size:12.0pt;color:black'>From: </span></b><s=
pan style=3D'font-size:12.0pt;color:black'>Administrator &lt;dlouzan.dummy@gma=
il.com&gt;<br><b>Reply to: </b>Administrator / htmltest &lt;dlouzan.dummy+c0=
34670b1623e617e15a3df64223d363@gmail.com&gt;<br><b>Date: </b>Monday, 17 Febr=
uary 2020 at 22:55<br><b>To: </b>&quot;Louzan Martinez, Diego (ext) (SOP IT =
STG XS)&quot; &lt;diego.louzan.ext@siemens.com&gt;<br><b>Subject: </b>Re: ht=
mltest | test issue (#1)<o:p></o:p></span></p></div><div><p class=3DMsoNormal>=
<o:p>&nbsp;</o:p></p></div><div><p><span style=3D'color:#777777'><a href=3D"http=
://localhost:3000/root">Administrator</a> commented: <o:p></o:p></span></p><=
div><p>I pity the foo !!!<o:p></o:p></p></div></div><div style=3D'margin-top:7=
.5pt'><p><span style=3D'font-size:12.0pt;color:#777777'>=E2=80=94 <br>Reply to this =
email directly or <a href=3D"http://localhost:3000/root/htmltest/issues/1#note=
_1797">view it on GitLab</a>. <br>You're receiving this email because of you=
r account on 169.254.169.254. If you'd like to receive fewer emails, you can=
<a href=3D"http://localhost:3000/sent_notifications/c034670b1623e617e15a3df64=
223d363/unsubscribe">unsubscribe</a> from this thread or adjust your notific=
ation settings. <o:p></o:p></span></p></div></div></body></html>
--B_3664825007_1519466360--
--B_3664825007_384940722
Content-type: image/png; name="gitlab_logo.png";
x-mac-creator="4F50494D";
x-mac-type="504E4766"
Content-disposition: attachment;
filename="gitlab_logo.png"
Content-transfer-encoding: base64
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
--B_3664825007_384940722--
--B_3664825007_1904734766
Content-type: application/pkcs7-signature; name="smime.p7s"
Content-transfer-encoding: base64
Content-disposition: attachment;
filename="smime.p7s"
MIIRpwYJKoZIhvcNAQcCoIIRmDCCEZQCAQExDzANBglghkgBZQMEAgEFADALBgkqhkiG9w0B
BwGggg8VMIIHojCCBYqgAwIBAgIEZ5a6PTANBgkqhkiG9w0BAQsFADCBtjELMAkGA1UEBhMC
REUxDzANBgNVBAgMBkJheWVybjERMA8GA1UEBwwITXVlbmNoZW4xEDAOBgNVBAoMB1NpZW1l
bnMxETAPBgNVBAUTCFpaWlpaWkE2MR0wGwYDVQQLDBRTaWVtZW5zIFRydXN0IENlbnRlcjE/
MD0GA1UEAww2U2llbWVucyBJc3N1aW5nIENBIE1lZGl1bSBTdHJlbmd0aCBBdXRoZW50aWNh
dGlvbiAyMDE2MB4XDTE5MTEyMTE0NDQ0N1oXDTIwMTEyMTE0NDQ0N1owdzERMA8GA1UEBRMI
WjAwM0gwOFQxDjAMBgNVBCoMBURpZWdvMRgwFgYDVQQEDA9Mb3V6YW4gTWFydGluZXoxGDAW
BgNVBAoMD1NpZW1lbnMtUGFydG5lcjEeMBwGA1UEAwwVTG91emFuIE1hcnRpbmV6IERpZWdv
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuInpNaC7NRYD+0pOpHDz2pk9xmPt
JGj860SF6Nmn6Eu9EMYKEDfneC6z5QcH+mPS2d0VWgqVVGbRXSPsxJtbi9TCWjQUZdHglEZK
z9zxoFDh2dvW5/+TOT5Jf78FXyqak0YtY6+oMjQ/i9RUqPL7sIlyXLrBYrILzQ9Afo+7bXZg
v3ypp6xtqAV2ctHzQWFi0onJzxLVYguiVb7fFF9rBEMvSZonuw5tvOwJIhbe5FDFOrDcfbyU
ofZ/wikIZ+A+CE5GryXuuQmGxJaC2QqOkRAWQDzLDx9nG+rKiEs5OvlfEZC7EV1PyjZ93coM
faCVdlAgcFZ5fvd37CjyjKl+1QIDAQABo4IC9DCCAvAwggEEBggrBgEFBQcBAQSB9zCB9DAy
BggrBgEFBQcwAoYmaHR0cDovL2FoLnNpZW1lbnMuY29tL3BraT9aWlpaWlpBNi5jcnQwQQYI
KwYBBQUHMAKGNWxkYXA6Ly9hbC5zaWVtZW5zLm5ldC9DTj1aWlpaWlpBNixMPVBLST9jQUNl
cnRpZmljYXRlMEkGCCsGAQUFBzAChj1sZGFwOi8vYWwuc2llbWVucy5jb20vQ049WlpaWlpa
QTYsbz1UcnVzdGNlbnRlcj9jQUNlcnRpZmljYXRlMDAGCCsGAQUFBzABhiRodHRwOi8vb2Nz
cC5wa2ktc2VydmljZXMuc2llbWVucy5jb20wHwYDVR0jBBgwFoAU+BVdRwxsd3tyxAIXkWii
tvdqCUQwDAYDVR0TAQH/BAIwADBFBgNVHSAEPjA8MDoGDSsGAQQBoWkHAgIEAQMwKTAnBggr
BgEFBQcCARYbaHR0cDovL3d3dy5zaWVtZW5zLmNvbS9wa2kvMIHKBgNVHR8EgcIwgb8wgbyg
gbmggbaGJmh0dHA6Ly9jaC5zaWVtZW5zLmNvbS9wa2k/WlpaWlpaQTYuY3JshkFsZGFwOi8v
Y2wuc2llbWVucy5uZXQvQ049WlpaWlpaQTYsTD1QS0k/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
TGlzdIZJbGRhcDovL2NsLnNpZW1lbnMuY29tL0NOPVpaWlpaWkE2LG89VHJ1c3RjZW50ZXI/
Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
AwQwDgYDVR0PAQH/BAQDAgeAMFUGA1UdEQROMEygLAYKKwYBBAGCNxQCA6AeDBxkaWVnby5s
b3V6YW4uZXh0QHNpZW1lbnMuY29tgRxkaWVnby5sb3V6YW4uZXh0QHNpZW1lbnMuY29tMB0G
A1UdDgQWBBQj8k8aqZey68w8ALYKGJSGMt5hZDANBgkqhkiG9w0BAQsFAAOCAgEAFDHqxpb1
R9cB4noC9vx09bkNbmXCpVfl3XCQUmAWTznC0nwEssTTjo0PWuIV4C3jnsp0MRUeHZ6lsyhZ
OzS1ETwYgvj6wzjb8RF3wgn7N/JOvFGaErMz5HZpKOfzGiNpW6/Rmd4hsRDjAwOVQOXUTqc/
0Bj3FMoLRCSWSnTp5HdyvrY2xOKHfTrTjzmcLdFaKE2F5n7+dBkwCKVfzut8CqfVq/I7ks4m
D1IHk93/P6l9U34R2FHPt6zRTNZcWmDirRSlMH4L18CnfiNPuDN/PtRYlt3Vng5EdYN0VCg2
NM/uees0U4ingCb0NFjg66uQ/tjfPQk55MN4Wpls4N6TkMoTCWLiqZzYTGdmVQexzroL6940
tmMr8LoN3TpPf0OdvdKEpyH7fzsx5QlmQyywIWec6X+Fx6+l0g91VJnPEtqACpfZIBZtviHl
gfX298w+SsvBK8C48Pqs8Ijh7tLrCxx7VMLVHZqwWWPK53ga+CDWmjoSQPxi+CPZF7kao6N5
4GrJWwSHlHh6WzTbLyLvTJZZ775Utp4W8s8xMUsQJ413iYzEaC8FcSeNjSk5UiDDiHrKmzpM
tbApD3pUXStblUMKYGTG1Mj9BcEBFkCdoGlw/ulszIrKFfOyRNDG3Ay+Dj/oMjoKsJphu3px
wyft82rTer7UW/I7o0h0DAG4lkMwggdrMIIFU6ADAgECAgR5nlqfMA0GCSqGSIb3DQEBCwUA
MIGeMQswCQYDVQQGEwJERTEPMA0GA1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjEQ
MA4GA1UECgwHU2llbWVuczERMA8GA1UEBRMIWlpaWlpaQTMxHTAbBgNVBAsMFFNpZW1lbnMg
VHJ1c3QgQ2VudGVyMScwJQYDVQQDDB5TaWVtZW5zIElzc3VpbmcgQ0EgRUUgRW5jIDIwMTYw
HhcNMTkwOTI3MDgwMTM5WhcNMjAwOTI3MDgwMTM3WjB3MREwDwYDVQQFEwhaMDAzSDA4VDEO
MAwGA1UEKgwFRGllZ28xGDAWBgNVBAQMD0xvdXphbiBNYXJ0aW5lejEYMBYGA1UECgwPU2ll
bWVucy1QYXJ0bmVyMR4wHAYDVQQDDBVMb3V6YW4gTWFydGluZXogRGllZ28wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyby5qKzZIrGYWRqxnaAyMt/a/uc0uMk0F3MjwxvPM
vh5DllUpqx0l8ZDakDjPhlEXTeoL4DHNgmh+CDCs76CppM3cNG/1W1Ajo/L2iwMoXaxYuQ/F
q7ED+02KEkWX2DDVVG3fhrUGP20QAq77xPDptmVWZnUnuobZBNYkC49Xfl9HJvkJL8P0+Jqb
Eae7p4roiEr7wNkGriwrVXgA3oPNF/W+OuI76JTNTajS/6PAK/GeqIvLjfuBXpdBZTY031nE
Cztca8vI1jUjQzVhS+0dWpvpfhkVumbvOnid8DI9lapYsX8dpZFsa3ya+T3tjUdGSOOKi0kg
lWf/XYyyfhmDAgMBAAGjggLVMIIC0TAdBgNVHQ4EFgQUprhTCDwNLfPImpSfWdq+QvPTo9Mw
JwYDVR0RBCAwHoEcZGllZ28ubG91emFuLmV4dEBzaWVtZW5zLmNvbTAOBgNVHQ8BAf8EBAMC
BDAwLAYDVR0lBCUwIwYIKwYBBQUHAwQGCisGAQQBgjcKAwQGCysGAQQBgjcKAwQBMIHKBgNV
HR8EgcIwgb8wgbyggbmggbaGJmh0dHA6Ly9jaC5zaWVtZW5zLmNvbS9wa2k/WlpaWlpaQTMu
Y3JshkFsZGFwOi8vY2wuc2llbWVucy5uZXQvQ049WlpaWlpaQTMsTD1QS0k/Y2VydGlmaWNh
dGVSZXZvY2F0aW9uTGlzdIZJbGRhcDovL2NsLnNpZW1lbnMuY29tL0NOPVpaWlpaWkEzLG89
VHJ1c3RjZW50ZXI/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDBFBgNVHSAEPjA8MDoGDSsG
AQQBoWkHAgIEAQMwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5zaWVtZW5zLmNvbS9wa2kv
MAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUoassbqB68NPCTeof8R4hivwMre8wggEEBggr
BgEFBQcBAQSB9zCB9DAyBggrBgEFBQcwAoYmaHR0cDovL2FoLnNpZW1lbnMuY29tL3BraT9a
WlpaWlpBMy5jcnQwQQYIKwYBBQUHMAKGNWxkYXA6Ly9hbC5zaWVtZW5zLm5ldC9DTj1aWlpa
WlpBMyxMPVBLST9jQUNlcnRpZmljYXRlMEkGCCsGAQUFBzAChj1sZGFwOi8vYWwuc2llbWVu
cy5jb20vQ049WlpaWlpaQTMsbz1UcnVzdGNlbnRlcj9jQUNlcnRpZmljYXRlMDAGCCsGAQUF
BzABhiRodHRwOi8vb2NzcC5wa2ktc2VydmljZXMuc2llbWVucy5jb20wDQYJKoZIhvcNAQEL
BQADggIBAF98ZMNg28LgkwdjOdvOGbC1QitsWjZTyotmQESF0nClDLUhb0O5675vVixntbrf
eB8xy1+KRiadk40GnAIJ0YzmNl4Tav6hPYv9VBWe5olsWG7C4qB3Q/SwhvW/e+owxv1cBra8
R3oRudiN81eTZQHyNghRephVqQG/dpPYqydoANfIhEpHa79QlpaCAeYl4896AZOS8HYbkDFs
hLdv7sEHtl79YuSWI1wBjbJl70c0Sb4wLRgCPuHyQj2Uw/vQ5xJlEvBDZAIXXe1TP/nqiuY6
7nweJbbeqfFE6ZP3kCe+mEIWGSaO0iThZyLGer8fHs1XiEmhhPgvC7P7KodzpXU6+hX+ZzbD
DxEjFfetV5sh0aNSXG9xx4hZmS9bpImBGR8MvZ7cgxqItvLtY2xvfUbYW244d4RcWesaCDq3
ZEIo6uCIzOzJAwjUdLIac+lLV0rxiHmb7O3cQ19kjpWDB31hmfrus/TKJ55pBKVWBX5m/mFv
K8Ep5USpGrNS0EzOP7I1kQZv2VsvAhSxk/m5FMLpDy8T0O8YgbLypTXoeJFWCF6RduSjVsaZ
lkAtTQYud683pjyOMxJXaQUYGU1PmEYSOonMkVsT9aBcxYkXLp+Ln/+8G0OCYu7dRdwnj+Ut
7yR/ltxtgDcaFApCb0qBTKbgbqZk1fASmkOp+kbdYmoUMYICVjCCAlICAQEwgb8wgbYxCzAJ
BgNVBAYTAkRFMQ8wDQYDVQQIDAZCYXllcm4xETAPBgNVBAcMCE11ZW5jaGVuMRAwDgYDVQQK
DAdTaWVtZW5zMREwDwYDVQQFEwhaWlpaWlpBNjEdMBsGA1UECwwUU2llbWVucyBUcnVzdCBD
ZW50ZXIxPzA9BgNVBAMMNlNpZW1lbnMgSXNzdWluZyBDQSBNZWRpdW0gU3RyZW5ndGggQXV0
aGVudGljYXRpb24gMjAxNgIEZ5a6PTANBglghkgBZQMEAgEFAKBpMC8GCSqGSIb3DQEJBDEi
BCAOR58AbNfSrI+vtMs+dgAQtn3IVZ3RjYC5hz3j9k+6TTAYBgkqhkiG9w0BCQMxCwYJKoZI
hvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMDAyMTcyMTU2NDdaMA0GCSqGSIb3DQEBAQUABIIB
AHLSBcFHhNHPevbwqvA2ecuVb/aKnj45CFF6l8esP1H5DRm1ee5qMKuIS84NFuFC9RUENNhW
DBzsB+BVGz64o1f8QgIklYVrIJ4JZ0q1abNG7NbkVKWIpS3CQo//YWShUTYg+JpKx4YbahGR
sP5zbufbU4eagrrqBChjPTLy+njdjwCNu0XPykBTKOOf6BMjnS33AYjHJyh83JOY7rw3IDLx
8POQH4g5EMRpl9354s0rEkIezMt7pfUAsqY3QnQ8hvlE4KTikPQ+tvLMK1l/ffcLAP8BdBNI
YA3ikb3qCoGNSLKieYzNnBPhNOIJELUtEEaljAFZYMQzMKCbI4JdiDs=
--B_3664825007_1904734766--
...@@ -203,7 +203,7 @@ describe Types::BaseField do ...@@ -203,7 +203,7 @@ describe Types::BaseField do
end end
it 'raises an error if a required property is missing', :aggregate_failures do it 'raises an error if a required property is missing', :aggregate_failures do
expect { test_field(deprecated: { milestone: 1.0 }) }.to raise_error( expect { test_field(deprecated: { milestone: '1.10' }) }.to raise_error(
ArgumentError, ArgumentError,
'Please provide a `reason` within `deprecated`' 'Please provide a `reason` within `deprecated`'
) )
...@@ -212,37 +212,44 @@ describe Types::BaseField do ...@@ -212,37 +212,44 @@ describe Types::BaseField do
'Please provide a `milestone` within `deprecated`' 'Please provide a `milestone` within `deprecated`'
) )
end end
it 'raises an error if milestone is not a String', :aggregate_failures do
expect { test_field(deprecated: { milestone: 1.10, reason: 'Deprecation reason' }) }.to raise_error(
ArgumentError,
'`milestone` must be a `String`'
)
end
end end
it 'adds a formatted `deprecated_reason` to the field' do it 'adds a formatted `deprecated_reason` to the field' do
field = test_field(deprecated: { milestone: 1.0, reason: 'Deprecation reason' }) field = test_field(deprecated: { milestone: '1.10', reason: 'Deprecation reason' })
expect(field.deprecation_reason).to eq('Deprecation reason. Deprecated in 1.0') expect(field.deprecation_reason).to eq('Deprecation reason. Deprecated in 1.10')
end end
it 'appends to the description if given' do it 'appends to the description if given' do
field = test_field( field = test_field(
deprecated: { milestone: 1.0, reason: 'Deprecation reason' }, deprecated: { milestone: '1.10', reason: 'Deprecation reason' },
description: 'Field description' description: 'Field description'
) )
expect(field.description).to eq('Field description. Deprecated in 1.0: Deprecation reason') expect(field.description).to eq('Field description. Deprecated in 1.10: Deprecation reason')
end end
it 'does not append to the description if it is absent' do it 'does not append to the description if it is absent' do
field = test_field(deprecated: { milestone: 1.0, reason: 'Deprecation reason' }) field = test_field(deprecated: { milestone: '1.10', reason: 'Deprecation reason' })
expect(field.description).to be_nil expect(field.description).to be_nil
end end
it 'interacts well with the `feature_flag` property' do it 'interacts well with the `feature_flag` property' do
field = test_field( field = test_field(
deprecated: { milestone: 1.0, reason: 'Deprecation reason' }, deprecated: { milestone: '1.10', reason: 'Deprecation reason' },
description: 'Field description', description: 'Field description',
feature_flag: 'foo_flag' feature_flag: 'foo_flag'
) )
expect(field.description).to eq('Field description. Available only when feature flag `foo_flag` is enabled. Deprecated in 1.0: Deprecation reason') expect(field.description).to eq('Field description. Available only when feature flag `foo_flag` is enabled. Deprecated in 1.10: Deprecation reason')
end end
end end
end end
...@@ -31,5 +31,20 @@ describe Gitlab::Email::AttachmentUploader do ...@@ -31,5 +31,20 @@ describe Gitlab::Email::AttachmentUploader do
expect(image_link[:url]).to include('gitlab_logo.png') expect(image_link[:url]).to include('gitlab_logo.png')
end end
end end
context 'with a signed message with mixed protocol prefix' do
let(:message_raw) { fixture_file("emails/valid_reply_signed_smime_mixed_protocol_prefix.eml") }
it 'uploads all attachments except the signature' do
links = described_class.new(message).execute(upload_parent: project, uploader_class: FileUploader)
expect(links).not_to include(a_hash_including(alt: 'smime.p7s'))
image_link = links.first
expect(image_link).not_to be_nil
expect(image_link[:alt]).to eq('gitlab_logo')
expect(image_link[:url]).to include('gitlab_logo.png')
end
end
end end
end end
...@@ -76,7 +76,7 @@ describe Gitlab::Graphql::Docs::Renderer do ...@@ -76,7 +76,7 @@ describe Gitlab::Graphql::Docs::Renderer do
Class.new(Types::BaseObject) do Class.new(Types::BaseObject) do
graphql_name 'DeprecatedTest' graphql_name 'DeprecatedTest'
field :foo, GraphQL::STRING_TYPE, null: false, deprecated: { reason: 'This is deprecated', milestone: 1.0 }, description: 'A description' field :foo, GraphQL::STRING_TYPE, null: false, deprecated: { reason: 'This is deprecated', milestone: '1.10' }, description: 'A description'
end end
end end
...@@ -86,7 +86,7 @@ describe Gitlab::Graphql::Docs::Renderer do ...@@ -86,7 +86,7 @@ describe Gitlab::Graphql::Docs::Renderer do
| Name | Type | Description | | Name | Type | Description |
| --- | ---- | ---------- | | --- | ---- | ---------- |
| `foo` **{warning-solid}** | String! | **Deprecated:** This is deprecated. Deprecated in 1.0 | | `foo` **{warning-solid}** | String! | **Deprecated:** This is deprecated. Deprecated in 1.10 |
DOC DOC
is_expected.to include(expectation) is_expected.to include(expectation)
......
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