Commit 196ada08 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent e380e59e
...@@ -12,6 +12,7 @@ module Types ...@@ -12,6 +12,7 @@ module Types
kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity]) kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity])
@feature_flag = kwargs[:feature_flag] @feature_flag = kwargs[:feature_flag]
kwargs = check_feature_flag(kwargs) kwargs = check_feature_flag(kwargs)
kwargs = handle_deprecated(kwargs)
super(*args, **kwargs, &block) super(*args, **kwargs, &block)
end end
...@@ -41,7 +42,7 @@ module Types ...@@ -41,7 +42,7 @@ module Types
attr_reader :feature_flag attr_reader :feature_flag
def feature_documentation_message(key, description) def feature_documentation_message(key, description)
"#{description}. Available only when feature flag `#{key}` is enabled." "#{description}. Available only when feature flag `#{key}` is enabled"
end end
def check_feature_flag(args) def check_feature_flag(args)
...@@ -51,6 +52,27 @@ module Types ...@@ -51,6 +52,27 @@ module Types
args args
end end
def handle_deprecated(kwargs)
if kwargs[:deprecation_reason].present?
raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields'
end
deprecation = kwargs.delete(:deprecated)
return kwargs unless deprecation
milestone, reason = deprecation.values_at(:milestone, :reason).map(&:presence)
raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone
raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason
deprecated_in = "Deprecated in #{milestone}"
kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}"
kwargs[:description] += ". #{deprecated_in}: #{reason}" if kwargs[:description]
kwargs
end
def field_complexity(resolver_class, current) def field_complexity(resolver_class, current)
return current if current.present? && current > 0 return current if current.present? && current > 0
......
...@@ -44,8 +44,8 @@ module Types ...@@ -44,8 +44,8 @@ module Types
field :latest_pipeline, field :latest_pipeline,
type: Types::Ci::PipelineType, type: Types::Ci::PipelineType,
null: true, null: true,
description: "Latest pipeline of the commit", deprecated: { reason: 'Use `pipelines`', milestone: 12.5 },
deprecation_reason: 'Use pipelines', description: 'Latest pipeline of the commit',
resolver: Resolvers::CommitPipelinesResolver.last resolver: Resolvers::CommitPipelinesResolver.last
end end
end end
...@@ -18,8 +18,8 @@ module Types ...@@ -18,8 +18,8 @@ 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,
deprecation_reason: 'Plain text token has been masked for security reasons', deprecated: { reason: 'Plain text token has been masked for security reasons', milestone: 12.7 },
description: 'API token for the Grafana integration. Field is permanently masked.' description: 'API token for the Grafana integration'
def token def token
object.masked_token object.masked_token
......
...@@ -74,8 +74,9 @@ module Types ...@@ -74,8 +74,9 @@ module Types
description: 'Rebase commit SHA of the merge request' description: 'Rebase commit SHA of the merge request'
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, deprecation_reason: "Renamed to defaultMergeCommitMessage", field :merge_commit_message, GraphQL::STRING_TYPE, method: :default_merge_commit_message, null: true,
description: 'Deprecated - renamed to defaultMergeCommitMessage' deprecated: { reason: 'Use `defaultMergeCommitMessage`', milestone: 11.8 },
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'
field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false, field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false,
......
...@@ -130,7 +130,7 @@ class Namespace < ApplicationRecord ...@@ -130,7 +130,7 @@ class Namespace < ApplicationRecord
return unless host.ends_with?(gitlab_host) return unless host.ends_with?(gitlab_host)
name = host.delete_suffix(gitlab_host) name = host.delete_suffix(gitlab_host)
Namespace.where(parent_id: nil).find_by_path(name) Namespace.where(parent_id: nil).by_path(name)
end end
# overridden in ee # overridden in ee
......
- sort_value = @sort - sort_value = @sort
- sort_title = issuable_sort_option_title(sort_value) - sort_title = issuable_sort_option_title(sort_value)
- viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues' - viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues'
- manual_sorting = viewing_issues && controller.controller_name != 'dashboard'
.dropdown.inline.prepend-left-10.issue-sort-dropdown .dropdown.inline.prepend-left-10.issue-sort-dropdown
.btn-group{ role: 'group' } .btn-group{ role: 'group' }
...@@ -18,6 +17,6 @@ ...@@ -18,6 +17,6 @@
= sortable_item(sort_title_due_date, page_filter_path(sort: sort_value_due_date), sort_title) if viewing_issues = sortable_item(sort_title_due_date, page_filter_path(sort: sort_value_due_date), sort_title) if viewing_issues
= sortable_item(sort_title_popularity, page_filter_path(sort: sort_value_popularity), sort_title) = sortable_item(sort_title_popularity, page_filter_path(sort: sort_value_popularity), sort_title)
= sortable_item(sort_title_label_priority, page_filter_path(sort: sort_value_label_priority), sort_title) = sortable_item(sort_title_label_priority, page_filter_path(sort: sort_value_label_priority), sort_title)
= sortable_item(sort_title_relative_position, page_filter_path(sort: sort_value_relative_position), sort_title) if manual_sorting = sortable_item(sort_title_relative_position, page_filter_path(sort: sort_value_relative_position), sort_title) if viewing_issues
= render_if_exists('shared/ee/issuable/sort_dropdown', viewing_issues: viewing_issues, sort_title: sort_title) = render_if_exists('shared/ee/issuable/sort_dropdown', viewing_issues: viewing_issues, sort_title: sort_title)
= issuable_sort_direction_button(sort_value) = issuable_sort_direction_button(sort_value)
---
title: Scope WAF Statistics anomalies to environment.external_url
merge_request: 27466
author:
type: fixed
...@@ -78,6 +78,58 @@ by another folder with the next 2 characters. They are both stored in a special ...@@ -78,6 +78,58 @@ by another folder with the next 2 characters. They are both stored in a special
"@hashed/#{hash[0..1]}/#{hash[2..3]}/#{hash}.wiki.git" "@hashed/#{hash[0..1]}/#{hash[2..3]}/#{hash}.wiki.git"
``` ```
### Translating hashed storage paths
Troubleshooting problems with the Git repositories, adding hooks, and other
tasks will require you translate between the human readable project name
and the hashed storage path.
#### From project name to hashed path
The hashed path is shown on the project's page in the [admin area](../user/admin_area/index.md#administering-projects).
To access the Projects page, go to **Admin Area > Overview > Projects** and then
open up the page for the project.
The "Gitaly relative path" is shown there, for example:
```
"@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
```
This is the path under `/var/opt/gitlab/git-data/repositories/` on a
default Omnibus installation.
In a [Rails console](troubleshooting/debug.md#starting-a-rails-console),
get this information using either the numeric project ID or the full path:
```ruby
Project.find(16).disk_path
Project.find_by_full_path('group/project').disk_path
```
#### From hashed path to project name
To translate from a hashed storage path to a project name:
1. Start a [Rails console](troubleshooting/debug.md#starting-a-rails-console).
1. Run the following:
```ruby
ProjectRepository.find_by(disk_path: '@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9').project
```
The quoted string in that command is the directory tree you'll find on your
GitLab server. For example, on a default Omnibus installation this would be
`/var/opt/gitlab/git-data/repositories/@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git`
with `.git` from the end of the directory name removed.
The output includes the project id and the project name:
```
=> #<Project id:16 it/supportteam/ticketsystem>
```
### Hashed object pools ### Hashed object pools
> [Introduced](https://gitlab.com/gitlab-org/gitaly/issues/1606) in GitLab 12.1. > [Introduced](https://gitlab.com/gitlab-org/gitaly/issues/1606) in GitLab 12.1.
......
...@@ -96,6 +96,10 @@ The hooks are searched and executed in this order: ...@@ -96,6 +96,10 @@ The hooks are searched and executed in this order:
The hooks of the same type are executed in order and execution stops on the The hooks of the same type are executed in order and execution stops on the
first script exiting with a non-zero value. first script exiting with a non-zero value.
For `<project>.git` you'll need to
[translate your project name into the hashed storage format](repository_storage_types.md#translating-hashed-storage-paths)
that GitLab uses.
## Custom error messages ## Custom error messages
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5073) in GitLab 8.10. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5073) in GitLab 8.10.
......
...@@ -3,22 +3,32 @@ ...@@ -3,22 +3,32 @@
Sometimes things don't work the way they should. Here are some tips on debugging issues out Sometimes things don't work the way they should. Here are some tips on debugging issues out
in production. in production.
## Mail not working ## Starting a Rails console
A common problem is that mails are not being sent for some reason. Suppose you configured Troubleshooting and debugging often requires a rails console.
an SMTP server, but you're not seeing mail delivered. Here's how to check the settings:
1. Run a Rails console: **For Omnibus installations**
```shell ```shell
sudo gitlab-rails console -e production sudo gitlab-rails console
``` ```
or for source installs: ---
```shell **For installations from source**
bundle exec rails console -e production
``` ```shell
bundle exec rails console production
```
Kubernetes: the console is in the task-runner pod, refer to our [Kubernetes cheat sheet](kubernetes_cheat_sheet.md#gitlab-specific-kubernetes-information) for details.
## Mail not working
A common problem is that mails are not being sent for some reason. Suppose you configured
an SMTP server, but you're not seeing mail delivered. Here's how to check the settings:
1. Run a [Rails console.](#starting-a-rails-console)
1. Look at the ActionMailer `delivery_method` to make sure it matches what you 1. Look at the ActionMailer `delivery_method` to make sure it matches what you
intended. If you configured SMTP, it should say `:smtp`. If you're using intended. If you configured SMTP, it should say `:smtp`. If you're using
...@@ -160,22 +170,17 @@ separate Rails process to debug the issue: ...@@ -160,22 +170,17 @@ separate Rails process to debug the issue:
1. Log in to your GitLab account. 1. Log in to your GitLab account.
1. Copy the URL that is causing problems (e.g. `https://gitlab.com/ABC`). 1. Copy the URL that is causing problems (e.g. `https://gitlab.com/ABC`).
1. Create a Personal Access Token for your user (Profile Settings -> Access Tokens). 1. Create a Personal Access Token for your user (Profile Settings -> Access Tokens).
1. Bring up the GitLab Rails console. For omnibus users, run: 1. Bring up the [GitLab Rails console.](#starting-a-rails-console)
```shell
sudo gitlab-rails console
```
1. At the Rails console, run: 1. At the Rails console, run:
```ruby ```ruby
[1] pry(main)> app.get '<URL FROM STEP 2>/?private_token=<TOKEN FROM STEP 3>' app.get '<URL FROM STEP 2>/?private_token=<TOKEN FROM STEP 3>'
``` ```
For example: For example:
```ruby ```ruby
[1] pry(main)> app.get 'https://gitlab.com/gitlab-org/gitlab-foss/issues/1?private_token=123456' app.get 'https://gitlab.com/gitlab-org/gitlab-foss/issues/1?private_token=123456'
``` ```
1. In a new window, run `top`. It should show this ruby process using 100% CPU. Write down the PID. 1. In a new window, run `top`. It should show this ruby process using 100% CPU. Write down the PID.
......
...@@ -306,7 +306,7 @@ type Commit { ...@@ -306,7 +306,7 @@ type Commit {
id: ID! id: ID!
""" """
Latest pipeline of the commit Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines`
""" """
latestPipeline( latestPipeline(
""" """
...@@ -323,7 +323,7 @@ type Commit { ...@@ -323,7 +323,7 @@ type Commit {
Filter pipelines by their status Filter pipelines by their status
""" """
status: PipelineStatusEnum status: PipelineStatusEnum
): Pipeline @deprecated(reason: "Use pipelines") ): Pipeline @deprecated(reason: "Use `pipelines`. Deprecated in 12.5")
""" """
Raw commit message Raw commit message
...@@ -2493,9 +2493,9 @@ type EpicIssue implements Noteable { ...@@ -2493,9 +2493,9 @@ type EpicIssue implements Noteable {
designCollection: DesignCollection designCollection: DesignCollection
""" """
Deprecated. Use `designCollection` The designs associated with this issue. Deprecated in 12.2: Use `designCollection`
""" """
designs: DesignCollection @deprecated(reason: "Use designCollection") designs: DesignCollection @deprecated(reason: "Use `designCollection`. Deprecated in 12.2")
""" """
Indicates discussion is locked on the issue Indicates discussion is locked on the issue
...@@ -2548,7 +2548,7 @@ type EpicIssue implements Noteable { ...@@ -2548,7 +2548,7 @@ type EpicIssue implements Noteable {
epicIssueId: ID! epicIssueId: ID!
""" """
Current health status. Available only when feature flag `save_issuable_health_status` is enabled. Current health status. Available only when feature flag `save_issuable_health_status` is enabled
""" """
healthStatus: HealthStatus healthStatus: HealthStatus
...@@ -2984,9 +2984,9 @@ type GrafanaIntegration { ...@@ -2984,9 +2984,9 @@ type GrafanaIntegration {
id: ID! id: ID!
""" """
API token for the Grafana integration. Field is permanently masked. API token for the Grafana integration. Deprecated in 12.7: Plain text token has been masked for security reasons
""" """
token: String! @deprecated(reason: "Plain text token has been masked for security reasons") token: String! @deprecated(reason: "Plain text token has been masked for security reasons. Deprecated in 12.7")
""" """
Timestamp of the issue's last activity Timestamp of the issue's last activity
...@@ -3489,9 +3489,9 @@ type Issue implements Noteable { ...@@ -3489,9 +3489,9 @@ type Issue implements Noteable {
designCollection: DesignCollection designCollection: DesignCollection
""" """
Deprecated. Use `designCollection` The designs associated with this issue. Deprecated in 12.2: Use `designCollection`
""" """
designs: DesignCollection @deprecated(reason: "Use designCollection") designs: DesignCollection @deprecated(reason: "Use `designCollection`. Deprecated in 12.2")
""" """
Indicates discussion is locked on the issue Indicates discussion is locked on the issue
...@@ -3539,7 +3539,7 @@ type Issue implements Noteable { ...@@ -3539,7 +3539,7 @@ type Issue implements Noteable {
epic: Epic epic: Epic
""" """
Current health status. Available only when feature flag `save_issuable_health_status` is enabled. Current health status. Available only when feature flag `save_issuable_health_status` is enabled
""" """
healthStatus: HealthStatus healthStatus: HealthStatus
...@@ -4242,9 +4242,9 @@ type MergeRequest implements Noteable { ...@@ -4242,9 +4242,9 @@ type MergeRequest implements Noteable {
): LabelConnection ): LabelConnection
""" """
Deprecated - renamed to defaultMergeCommitMessage Default merge commit message of the merge request. Deprecated in 11.8: Use `defaultMergeCommitMessage`
""" """
mergeCommitMessage: String @deprecated(reason: "Renamed to defaultMergeCommitMessage") mergeCommitMessage: String @deprecated(reason: "Use `defaultMergeCommitMessage`. Deprecated in 11.8")
""" """
SHA of the merge request commit (set once merged) SHA of the merge request commit (set once merged)
...@@ -6191,7 +6191,7 @@ type Project { ...@@ -6191,7 +6191,7 @@ type Project {
visibility: String visibility: String
""" """
Vulnerabilities reported on the project. Available only when feature flag `first_class_vulnerabilities` is enabled. Vulnerabilities reported on the project. Available only when feature flag `first_class_vulnerabilities` is enabled
""" """
vulnerabilities( vulnerabilities(
""" """
......
...@@ -968,7 +968,7 @@ ...@@ -968,7 +968,7 @@
}, },
{ {
"name": "latestPipeline", "name": "latestPipeline",
"description": "Latest pipeline of the commit", "description": "Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines`",
"args": [ "args": [
{ {
"name": "status", "name": "status",
...@@ -1007,7 +1007,7 @@ ...@@ -1007,7 +1007,7 @@
"ofType": null "ofType": null
}, },
"isDeprecated": true, "isDeprecated": true,
"deprecationReason": "Use pipelines" "deprecationReason": "Use `pipelines`. Deprecated in 12.5"
}, },
{ {
"name": "message", "name": "message",
...@@ -7244,7 +7244,7 @@ ...@@ -7244,7 +7244,7 @@
}, },
{ {
"name": "designs", "name": "designs",
"description": "Deprecated. Use `designCollection`", "description": "The designs associated with this issue. Deprecated in 12.2: Use `designCollection`",
"args": [ "args": [
], ],
...@@ -7254,7 +7254,7 @@ ...@@ -7254,7 +7254,7 @@
"ofType": null "ofType": null
}, },
"isDeprecated": true, "isDeprecated": true,
"deprecationReason": "Use designCollection" "deprecationReason": "Use `designCollection`. Deprecated in 12.2"
}, },
{ {
"name": "discussionLocked", "name": "discussionLocked",
...@@ -7397,7 +7397,7 @@ ...@@ -7397,7 +7397,7 @@
}, },
{ {
"name": "healthStatus", "name": "healthStatus",
"description": "Current health status. Available only when feature flag `save_issuable_health_status` is enabled.", "description": "Current health status. Available only when feature flag `save_issuable_health_status` is enabled",
"args": [ "args": [
], ],
...@@ -8659,7 +8659,7 @@ ...@@ -8659,7 +8659,7 @@
}, },
{ {
"name": "token", "name": "token",
"description": "API token for the Grafana integration. Field is permanently masked.", "description": "API token for the Grafana integration. Deprecated in 12.7: Plain text token has been masked for security reasons",
"args": [ "args": [
], ],
...@@ -8673,7 +8673,7 @@ ...@@ -8673,7 +8673,7 @@
} }
}, },
"isDeprecated": true, "isDeprecated": true,
"deprecationReason": "Plain text token has been masked for security reasons" "deprecationReason": "Plain text token has been masked for security reasons. Deprecated in 12.7"
}, },
{ {
"name": "updatedAt", "name": "updatedAt",
...@@ -9990,7 +9990,7 @@ ...@@ -9990,7 +9990,7 @@
}, },
{ {
"name": "designs", "name": "designs",
"description": "Deprecated. Use `designCollection`", "description": "The designs associated with this issue. Deprecated in 12.2: Use `designCollection`",
"args": [ "args": [
], ],
...@@ -10000,7 +10000,7 @@ ...@@ -10000,7 +10000,7 @@
"ofType": null "ofType": null
}, },
"isDeprecated": true, "isDeprecated": true,
"deprecationReason": "Use designCollection" "deprecationReason": "Use `designCollection`. Deprecated in 12.2"
}, },
{ {
"name": "discussionLocked", "name": "discussionLocked",
...@@ -10125,7 +10125,7 @@ ...@@ -10125,7 +10125,7 @@
}, },
{ {
"name": "healthStatus", "name": "healthStatus",
"description": "Current health status. Available only when feature flag `save_issuable_health_status` is enabled.", "description": "Current health status. Available only when feature flag `save_issuable_health_status` is enabled",
"args": [ "args": [
], ],
...@@ -12105,7 +12105,7 @@ ...@@ -12105,7 +12105,7 @@
}, },
{ {
"name": "mergeCommitMessage", "name": "mergeCommitMessage",
"description": "Deprecated - renamed to defaultMergeCommitMessage", "description": "Default merge commit message of the merge request. Deprecated in 11.8: Use `defaultMergeCommitMessage`",
"args": [ "args": [
], ],
...@@ -12115,7 +12115,7 @@ ...@@ -12115,7 +12115,7 @@
"ofType": null "ofType": null
}, },
"isDeprecated": true, "isDeprecated": true,
"deprecationReason": "Renamed to defaultMergeCommitMessage" "deprecationReason": "Use `defaultMergeCommitMessage`. Deprecated in 11.8"
}, },
{ {
"name": "mergeCommitSha", "name": "mergeCommitSha",
...@@ -18522,7 +18522,7 @@ ...@@ -18522,7 +18522,7 @@
}, },
{ {
"name": "vulnerabilities", "name": "vulnerabilities",
"description": "Vulnerabilities reported on the project. Available only when feature flag `first_class_vulnerabilities` is enabled.", "description": "Vulnerabilities reported on the project. Available only when feature flag `first_class_vulnerabilities` is enabled",
"args": [ "args": [
{ {
"name": "after", "name": "after",
......
...@@ -82,7 +82,7 @@ Represents a project or group board ...@@ -82,7 +82,7 @@ Represents a project or group board
| `authoredDate` | Time | Timestamp of when the commit was authored | | `authoredDate` | Time | Timestamp of when the commit was authored |
| `description` | String | Description of the commit message | | `description` | String | Description of the commit message |
| `id` | ID! | ID (global ID) of the commit | | `id` | ID! | ID (global ID) of the commit |
| `latestPipeline` **{warning-solid}** | Pipeline | **Deprecated:** Use pipelines | | `latestPipeline` **{warning-solid}** | Pipeline | **Deprecated:** Use `pipelines`. Deprecated in 12.5 |
| `message` | String | Raw commit message | | `message` | String | Raw commit message |
| `sha` | String! | SHA1 ID of the commit | | `sha` | String! | SHA1 ID of the commit |
| `signatureHtml` | String | Rendered HTML of the commit signature | | `signatureHtml` | String | Rendered HTML of the commit signature |
...@@ -413,13 +413,13 @@ Relationship between an epic and an issue ...@@ -413,13 +413,13 @@ Relationship between an epic and an issue
| `description` | String | Description of the issue | | `description` | String | Description of the issue |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | | `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `designCollection` | DesignCollection | Collection of design images associated with this issue | | `designCollection` | DesignCollection | Collection of design images associated with this issue |
| `designs` **{warning-solid}** | DesignCollection | **Deprecated:** Use designCollection | | `designs` **{warning-solid}** | DesignCollection | **Deprecated:** Use `designCollection`. Deprecated in 12.2 |
| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue | | `discussionLocked` | Boolean! | Indicates discussion is locked on the issue |
| `downvotes` | Int! | Number of downvotes the issue has received | | `downvotes` | Int! | Number of downvotes the issue has received |
| `dueDate` | Time | Due date of the issue | | `dueDate` | Time | Due date of the issue |
| `epic` | Epic | Epic to which this issue belongs | | `epic` | Epic | Epic to which this issue belongs |
| `epicIssueId` | ID! | ID of the epic-issue relation | | `epicIssueId` | ID! | ID of the epic-issue relation |
| `healthStatus` | HealthStatus | Current health status. Available only when feature flag `save_issuable_health_status` is enabled. | | `healthStatus` | HealthStatus | Current health status. Available only when feature flag `save_issuable_health_status` is enabled |
| `id` | ID | Global ID of the epic-issue relation | | `id` | ID | Global ID of the epic-issue relation |
| `iid` | ID! | Internal ID of the issue | | `iid` | ID! | Internal ID of the issue |
| `milestone` | Milestone | Milestone of the issue | | `milestone` | Milestone | Milestone of the issue |
...@@ -483,7 +483,7 @@ Autogenerated return type of EpicTreeReorder ...@@ -483,7 +483,7 @@ Autogenerated return type of EpicTreeReorder
| `enabled` | Boolean! | Indicates whether Grafana integration is enabled | | `enabled` | Boolean! | Indicates whether Grafana integration is enabled |
| `grafanaUrl` | String! | Url for the Grafana host for the Grafana integration | | `grafanaUrl` | String! | Url for the Grafana host for the Grafana integration |
| `id` | ID! | Internal ID of the Grafana integration | | `id` | ID! | Internal ID of the Grafana integration |
| `token` **{warning-solid}** | String! | **Deprecated:** Plain text token has been masked for security reasons | | `token` **{warning-solid}** | String! | **Deprecated:** Plain text token has been masked for security reasons. Deprecated in 12.7 |
| `updatedAt` | Time! | Timestamp of the issue's last activity | | `updatedAt` | Time! | Timestamp of the issue's last activity |
## Group ## Group
...@@ -535,12 +535,12 @@ Autogenerated return type of EpicTreeReorder ...@@ -535,12 +535,12 @@ Autogenerated return type of EpicTreeReorder
| `description` | String | Description of the issue | | `description` | String | Description of the issue |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | | `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `designCollection` | DesignCollection | Collection of design images associated with this issue | | `designCollection` | DesignCollection | Collection of design images associated with this issue |
| `designs` **{warning-solid}** | DesignCollection | **Deprecated:** Use designCollection | | `designs` **{warning-solid}** | DesignCollection | **Deprecated:** Use `designCollection`. Deprecated in 12.2 |
| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue | | `discussionLocked` | Boolean! | Indicates discussion is locked on the issue |
| `downvotes` | Int! | Number of downvotes the issue has received | | `downvotes` | Int! | Number of downvotes the issue has received |
| `dueDate` | Time | Due date of the issue | | `dueDate` | Time | Due date of the issue |
| `epic` | Epic | Epic to which this issue belongs | | `epic` | Epic | Epic to which this issue belongs |
| `healthStatus` | HealthStatus | Current health status. Available only when feature flag `save_issuable_health_status` is enabled. | | `healthStatus` | HealthStatus | Current health status. Available only when feature flag `save_issuable_health_status` is enabled |
| `iid` | ID! | Internal ID of the issue | | `iid` | ID! | Internal ID of the issue |
| `milestone` | Milestone | Milestone of the issue | | `milestone` | Milestone | Milestone of the issue |
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default | | `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
...@@ -644,7 +644,7 @@ Autogenerated return type of MarkAsSpamSnippet ...@@ -644,7 +644,7 @@ Autogenerated return type of MarkAsSpamSnippet
| `id` | ID! | ID of the merge request | | `id` | ID! | ID of the merge request |
| `iid` | String! | Internal ID of the merge request | | `iid` | String! | Internal ID of the merge request |
| `inProgressMergeCommitSha` | String | Commit SHA of the merge request if merge is in progress | | `inProgressMergeCommitSha` | String | Commit SHA of the merge request if merge is in progress |
| `mergeCommitMessage` **{warning-solid}** | String | **Deprecated:** Renamed to defaultMergeCommitMessage | | `mergeCommitMessage` **{warning-solid}** | String | **Deprecated:** Use `defaultMergeCommitMessage`. Deprecated in 11.8 |
| `mergeCommitSha` | String | SHA of the merge request commit (set once merged) | | `mergeCommitSha` | String | SHA of the merge request commit (set once merged) |
| `mergeError` | String | Error message due to a merge error | | `mergeError` | String | Error message due to a merge error |
| `mergeOngoing` | Boolean! | Indicates if a merge is currently occurring | | `mergeOngoing` | Boolean! | Indicates if a merge is currently occurring |
......
...@@ -283,6 +283,51 @@ the `some_feature_flag` feature flag is enabled. ...@@ -283,6 +283,51 @@ the `some_feature_flag` feature flag is enabled.
If the feature flag is not enabled, an error will be returned saying the field does not exist. If the feature flag is not enabled, an error will be returned saying the field does not exist.
## Deprecating fields
GitLab's GraphQL API is versionless, which means we maintain backwards
compatibility with older versions of the API with every change. Rather
than removing a field, we need to _deprecate_ the field instead. In
future, GitLab
[may remove deprecated fields](https://gitlab.com/gitlab-org/gitlab/issues/32292).
Fields are deprecated using the `deprecated` property. The value
of the property is a `Hash` of:
- `reason` - Reason for the deprecation.
- `milestone` - Milestone that the field was deprecated.
Example:
```ruby
field :token, GraphQL::STRING_TYPE, null: true,
deprecated: { reason: 'Login via token has been removed', milestone: 10.0 },
description: 'Token for login'
```
The original `description:` of the field should be maintained, and should
_not_ be updated to mention the deprecation.
### Deprecation reason styleguide
Where the reason for deprecation is due to the field being replaced
with another field, the `reason` must be:
```plaintext
Use `otherFieldName`
```
Example:
```ruby
field :designs, ::Types::DesignManagement::DesignCollectionType, null: true,
deprecated: { reason: 'Use `designCollection`', milestone: 10.0 },
description: 'The designs associated with this issue',
```
If the field is not being replaced by another field, a descriptive
deprecation `reason` should be given.
## Enums ## Enums
GitLab GraphQL enums are defined in `app/graphql/types`. When defining new enums, the GitLab GraphQL enums are defined in `app/graphql/types`. When defining new enums, the
......
...@@ -25,6 +25,10 @@ merge request. ...@@ -25,6 +25,10 @@ merge request.
![Container Scanning Widget](img/container_scanning_v12_9.png) ![Container Scanning Widget](img/container_scanning_v12_9.png)
## Contribute your scanner
The [Security Scanner Integration](../../../development/integrations/secure.md) documentation explains how to integrate other security scanners into GitLab.
## Use cases ## Use cases
If you distribute your application with Docker, then there's a great chance If you distribute your application with Docker, then there's a great chance
......
...@@ -67,6 +67,10 @@ The following languages and dependency managers are supported. ...@@ -67,6 +67,10 @@ The following languages and dependency managers are supported.
| Scala ([sbt](https://www.scala-sbt.org/)) | yes | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | | Scala ([sbt](https://www.scala-sbt.org/)) | yes | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| Go ([Go Modules](https://github.com/golang/go/wiki/Modules)) | yes ([alpha](https://gitlab.com/gitlab-org/gitlab/issues/7132)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | | Go ([Go Modules](https://github.com/golang/go/wiki/Modules)) | yes ([alpha](https://gitlab.com/gitlab-org/gitlab/issues/7132)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
## Contribute your scanner
The [Security Scanner Integration](../../../development/integrations/secure.md) documentation explains how to integrate other security scanners into GitLab.
## Configuration ## Configuration
For GitLab 11.9 and later, to enable Dependency Scanning, you must For GitLab 11.9 and later, to enable Dependency Scanning, you must
......
...@@ -90,6 +90,10 @@ The Java analyzers can also be used for variants like the ...@@ -90,6 +90,10 @@ The Java analyzers can also be used for variants like the
[Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html), [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html),
[Grails](https://grails.org/) and the [Maven wrapper](https://github.com/takari/maven-wrapper). [Grails](https://grails.org/) and the [Maven wrapper](https://github.com/takari/maven-wrapper).
## Contribute your scanner
The [Security Scanner Integration](../../../development/integrations/secure.md) documentation explains how to integrate other security scanners into GitLab.
## Configuration ## Configuration
NOTE: **Note:** NOTE: **Note:**
......
...@@ -175,7 +175,7 @@ describe Types::BaseField do ...@@ -175,7 +175,7 @@ describe Types::BaseField do
let(:flag) { :test_flag } let(:flag) { :test_flag }
it 'prepends the description' do it 'prepends the description' do
expect(field.description). to eq 'Test description. Available only when feature flag `test_flag` is enabled.' expect(field.description). to eq 'Test description. Available only when feature flag `test_flag` is enabled'
end end
context 'falsey feature_flag values' do context 'falsey feature_flag values' do
...@@ -196,4 +196,64 @@ describe Types::BaseField do ...@@ -196,4 +196,64 @@ describe Types::BaseField do
end end
end end
end end
describe '`deprecated` property' do
def test_field(args = {})
base_args = { name: 'test', type: GraphQL::STRING_TYPE, null: true }
described_class.new(**base_args.merge(args))
end
describe 'validations' do
it 'raises an informative error if `deprecation_reason` is used' do
expect { test_field(deprecation_reason: 'foo') }.to raise_error(
ArgumentError,
'Use `deprecated` property instead of `deprecation_reason`. ' \
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields'
)
end
it 'raises an error if a required property is missing', :aggregate_failures do
expect { test_field(deprecated: { milestone: 1.0 }) }.to raise_error(
ArgumentError,
'Please provide a `reason` within `deprecated`'
)
expect { test_field(deprecated: { reason: 'Deprecation reason' }) }.to raise_error(
ArgumentError,
'Please provide a `milestone` within `deprecated`'
)
end
end
it 'adds a formatted `deprecated_reason` to the field' do
field = test_field(deprecated: { milestone: 1.0, reason: 'Deprecation reason' })
expect(field.deprecation_reason).to eq('Deprecation reason. Deprecated in 1.0')
end
it 'appends to the description if given' do
field = test_field(
deprecated: { milestone: 1.0, reason: 'Deprecation reason' },
description: 'Field description'
)
expect(field.description).to eq('Field description. Deprecated in 1.0: Deprecation reason')
end
it 'does not append to the description if it is absent' do
field = test_field(deprecated: { milestone: 1.0, reason: 'Deprecation reason' })
expect(field.description).to be_nil
end
it 'interacts well with the `feature_flag` property' do
field = test_field(
deprecated: { milestone: 1.0, reason: 'Deprecation reason' },
description: 'Field description',
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')
end
end
end end
...@@ -6,7 +6,7 @@ describe Gitlab::Graphql::Docs::Renderer do ...@@ -6,7 +6,7 @@ describe Gitlab::Graphql::Docs::Renderer do
describe '#contents' do describe '#contents' do
# Returns a Schema that uses the given `type` # Returns a Schema that uses the given `type`
def mock_schema(type) def mock_schema(type)
query_type = Class.new(GraphQL::Schema::Object) do query_type = Class.new(Types::BaseObject) do
graphql_name 'QueryType' graphql_name 'QueryType'
field :foo, type, null: true field :foo, type, null: true
...@@ -27,7 +27,7 @@ describe Gitlab::Graphql::Docs::Renderer do ...@@ -27,7 +27,7 @@ describe Gitlab::Graphql::Docs::Renderer do
context 'A type with a field with a [Array] return type' do context 'A type with a field with a [Array] return type' do
let(:type) do let(:type) do
Class.new(GraphQL::Schema::Object) do Class.new(Types::BaseObject) do
graphql_name 'ArrayTest' graphql_name 'ArrayTest'
field :foo, [GraphQL::STRING_TYPE], null: false, description: 'A description' field :foo, [GraphQL::STRING_TYPE], null: false, description: 'A description'
...@@ -49,7 +49,7 @@ describe Gitlab::Graphql::Docs::Renderer do ...@@ -49,7 +49,7 @@ describe Gitlab::Graphql::Docs::Renderer do
context 'A type with fields defined in reverse alphabetical order' do context 'A type with fields defined in reverse alphabetical order' do
let(:type) do let(:type) do
Class.new(GraphQL::Schema::Object) do Class.new(Types::BaseObject) do
graphql_name 'OrderingTest' graphql_name 'OrderingTest'
field :foo, GraphQL::STRING_TYPE, null: false, description: 'A description of foo field' field :foo, GraphQL::STRING_TYPE, null: false, description: 'A description of foo field'
...@@ -73,10 +73,10 @@ describe Gitlab::Graphql::Docs::Renderer do ...@@ -73,10 +73,10 @@ describe Gitlab::Graphql::Docs::Renderer do
context 'A type with a deprecated field' do context 'A type with a deprecated field' do
let(:type) do let(:type) do
Class.new(GraphQL::Schema::Object) do Class.new(Types::BaseObject) do
graphql_name 'DeprecatedTest' graphql_name 'DeprecatedTest'
field :foo, GraphQL::STRING_TYPE, null: false, deprecation_reason: 'This is deprecated', description: 'A description' field :foo, GraphQL::STRING_TYPE, null: false, deprecated: { reason: 'This is deprecated', milestone: 1.0 }, 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 | | `foo` **{warning-solid}** | String! | **Deprecated:** This is deprecated. Deprecated in 1.0 |
DOC DOC
is_expected.to include(expectation) is_expected.to include(expectation)
......
...@@ -194,7 +194,7 @@ describe Namespace do ...@@ -194,7 +194,7 @@ describe Namespace do
describe '.find_by_pages_host' do describe '.find_by_pages_host' do
it 'finds namespace by GitLab Pages host and is case-insensitive' do it 'finds namespace by GitLab Pages host and is case-insensitive' do
namespace = create(:namespace, name: 'topnamespace') namespace = create(:namespace, name: 'topNAMEspace', path: 'topNAMEspace')
create(:namespace, name: 'annother_namespace') create(:namespace, name: 'annother_namespace')
host = "TopNamespace.#{Settings.pages.host.upcase}" host = "TopNamespace.#{Settings.pages.host.upcase}"
......
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