Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
70a50740a2
commit
bbc36645d3
|
|
@ -31,6 +31,14 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
|
||||||
* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
|
* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
### Metrics
|
||||||
|
|
||||||
|
<!-- How are you going to track uage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
|
||||||
|
|
||||||
|
Create tracking issue using the Snowplow event tracking template. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Snowplow%20event%20tracking.md
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
### User experience goal
|
### User experience goal
|
||||||
|
|
||||||
<!-- What is the single user experience workflow this problem addresses?
|
<!-- What is the single user experience workflow this problem addresses?
|
||||||
|
|
|
||||||
|
|
@ -3064,6 +3064,13 @@ No changes.
|
||||||
- [Add missing metrics information](gitlab-org/gitlab@89cd7fe3b95323e635b2d73e08549b2e6153dc4d) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61772/edit))
|
- [Add missing metrics information](gitlab-org/gitlab@89cd7fe3b95323e635b2d73e08549b2e6153dc4d) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61772/edit))
|
||||||
- [Track usage of the resolve UI](gitlab-org/gitlab@35c8e30fce288cecefcf2f7c0077d4608e696519) ([merge request](gitlab-org/gitlab!61654))
|
- [Track usage of the resolve UI](gitlab-org/gitlab@35c8e30fce288cecefcf2f7c0077d4608e696519) ([merge request](gitlab-org/gitlab!61654))
|
||||||
|
|
||||||
|
## 13.12.14 (2021-11-03)
|
||||||
|
|
||||||
|
### Fixed (2 changes)
|
||||||
|
|
||||||
|
- [Allow nil for remaining ci cd settings](gitlab-org/gitlab@896fd7ecf23714fa9f710efa4af245a26c677dce) ([merge request](gitlab-org/gitlab!73522))
|
||||||
|
- [Allow nil on delegated CI/CD settings](gitlab-org/gitlab@d57a9ea79080fc473eb54c0ee696a50fd270e8a4) ([merge request](gitlab-org/gitlab!73522))
|
||||||
|
|
||||||
## 13.12.13 (2021-10-29)
|
## 13.12.13 (2021-10-29)
|
||||||
|
|
||||||
No changes.
|
No changes.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { pickBy } from 'lodash';
|
import { pickBy, isEmpty } from 'lodash';
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
|
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
|
||||||
|
|
@ -20,6 +20,11 @@ export default {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
eeFilters: {
|
||||||
|
required: false,
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -27,61 +32,6 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
urlParams() {
|
|
||||||
const {
|
|
||||||
authorUsername,
|
|
||||||
labelName,
|
|
||||||
assigneeUsername,
|
|
||||||
search,
|
|
||||||
milestoneTitle,
|
|
||||||
types,
|
|
||||||
weight,
|
|
||||||
epicId,
|
|
||||||
} = this.filterParams;
|
|
||||||
|
|
||||||
let notParams = {};
|
|
||||||
|
|
||||||
if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) {
|
|
||||||
notParams = pickBy(
|
|
||||||
{
|
|
||||||
'not[label_name][]': this.filterParams.not.labelName,
|
|
||||||
'not[author_username]': this.filterParams.not.authorUsername,
|
|
||||||
'not[assignee_username]': this.filterParams.not.assigneeUsername,
|
|
||||||
'not[types]': this.filterParams.not.types,
|
|
||||||
'not[milestone_title]': this.filterParams.not.milestoneTitle,
|
|
||||||
'not[weight]': this.filterParams.not.weight,
|
|
||||||
'not[epic_id]': this.filterParams.not.epicId,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...notParams,
|
|
||||||
author_username: authorUsername,
|
|
||||||
'label_name[]': labelName,
|
|
||||||
assignee_username: assigneeUsername,
|
|
||||||
milestone_title: milestoneTitle,
|
|
||||||
search,
|
|
||||||
types,
|
|
||||||
weight,
|
|
||||||
epic_id: getIdFromGraphQLId(epicId),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(['performSearch']),
|
|
||||||
handleFilter(filters) {
|
|
||||||
this.filterParams = this.getFilterParams(filters);
|
|
||||||
|
|
||||||
updateHistory({
|
|
||||||
url: setUrlParams(this.urlParams, window.location.href, true, false, true),
|
|
||||||
title: document.title,
|
|
||||||
replace: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.performSearch();
|
|
||||||
},
|
|
||||||
getFilteredSearchValue() {
|
getFilteredSearchValue() {
|
||||||
const {
|
const {
|
||||||
authorUsername,
|
authorUsername,
|
||||||
|
|
@ -203,6 +153,66 @@ export default {
|
||||||
|
|
||||||
return filteredSearchValue;
|
return filteredSearchValue;
|
||||||
},
|
},
|
||||||
|
urlParams() {
|
||||||
|
const {
|
||||||
|
authorUsername,
|
||||||
|
labelName,
|
||||||
|
assigneeUsername,
|
||||||
|
search,
|
||||||
|
milestoneTitle,
|
||||||
|
types,
|
||||||
|
weight,
|
||||||
|
epicId,
|
||||||
|
} = this.filterParams;
|
||||||
|
|
||||||
|
let notParams = {};
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) {
|
||||||
|
notParams = pickBy(
|
||||||
|
{
|
||||||
|
'not[label_name][]': this.filterParams.not.labelName,
|
||||||
|
'not[author_username]': this.filterParams.not.authorUsername,
|
||||||
|
'not[assignee_username]': this.filterParams.not.assigneeUsername,
|
||||||
|
'not[types]': this.filterParams.not.types,
|
||||||
|
'not[milestone_title]': this.filterParams.not.milestoneTitle,
|
||||||
|
'not[weight]': this.filterParams.not.weight,
|
||||||
|
'not[epic_id]': this.filterParams.not.epicId,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...notParams,
|
||||||
|
author_username: authorUsername,
|
||||||
|
'label_name[]': labelName,
|
||||||
|
assignee_username: assigneeUsername,
|
||||||
|
milestone_title: milestoneTitle,
|
||||||
|
search,
|
||||||
|
types,
|
||||||
|
weight,
|
||||||
|
epic_id: getIdFromGraphQLId(epicId),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!isEmpty(this.eeFilters)) {
|
||||||
|
this.filterParams = this.eeFilters;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['performSearch']),
|
||||||
|
handleFilter(filters) {
|
||||||
|
this.filterParams = this.getFilterParams(filters);
|
||||||
|
|
||||||
|
updateHistory({
|
||||||
|
url: setUrlParams(this.urlParams, window.location.href, true, false, true),
|
||||||
|
title: document.title,
|
||||||
|
replace: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.performSearch();
|
||||||
|
},
|
||||||
getFilterParams(filters = []) {
|
getFilterParams(filters = []) {
|
||||||
const notFilters = filters.filter((item) => item.value.operator === '!=');
|
const notFilters = filters.filter((item) => item.value.operator === '!=');
|
||||||
const equalsFilters = filters.filter(
|
const equalsFilters = filters.filter(
|
||||||
|
|
@ -266,7 +276,7 @@ export default {
|
||||||
namespace=""
|
namespace=""
|
||||||
:tokens="tokens"
|
:tokens="tokens"
|
||||||
:search-input-placeholder="$options.i18n.search"
|
:search-input-placeholder="$options.i18n.search"
|
||||||
:initial-filter-value="getFilteredSearchValue()"
|
:initial-filter-value="getFilteredSearchValue"
|
||||||
@onFilter="handleFilter"
|
@onFilter="handleFilter"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -49,3 +49,5 @@ export const PipelineKeyOptions = [
|
||||||
key: 'iid',
|
key: 'iid',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const TOAST_MESSAGE = s__('Pipeline|Creating pipeline.');
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/commo
|
||||||
import Poll from '~/lib/utils/poll';
|
import Poll from '~/lib/utils/poll';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import { validateParams } from '~/pipelines/utils';
|
import { validateParams } from '~/pipelines/utils';
|
||||||
import { CANCEL_REQUEST } from '../constants';
|
import { CANCEL_REQUEST, TOAST_MESSAGE } from '../constants';
|
||||||
import eventHub from '../event_hub';
|
import eventHub from '../event_hub';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -191,7 +191,10 @@ export default {
|
||||||
|
|
||||||
this.service
|
this.service
|
||||||
.runMRPipeline(options)
|
.runMRPipeline(options)
|
||||||
.then(() => this.updateTable())
|
.then(() => {
|
||||||
|
this.$toast.show(TOAST_MESSAGE);
|
||||||
|
this.updateTable();
|
||||||
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
createFlash({
|
createFlash({
|
||||||
message: __(
|
message: __(
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
|
||||||
apiVersion: 1,
|
apiVersion: 1,
|
||||||
apiMigrations: {
|
apiMigrations: {
|
||||||
'context-qsh': true,
|
'context-qsh': true,
|
||||||
'signed-install': signed_install_active?,
|
'signed-install': true,
|
||||||
gdpr: true
|
gdpr: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,4 @@ class JiraConnect::ApplicationController < ApplicationController
|
||||||
params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last
|
params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def signed_install_active?
|
|
||||||
Feature.enabled?(:jira_connect_asymmetric_jwt, default_enabled: :yaml)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,9 @@ class JiraConnect::EventsController < JiraConnect::ApplicationController
|
||||||
# See https://developer.atlassian.com/cloud/jira/software/app-descriptor/#lifecycle
|
# See https://developer.atlassian.com/cloud/jira/software/app-descriptor/#lifecycle
|
||||||
|
|
||||||
skip_before_action :verify_atlassian_jwt!
|
skip_before_action :verify_atlassian_jwt!
|
||||||
before_action :verify_asymmetric_atlassian_jwt!, if: :signed_install_active?
|
before_action :verify_asymmetric_atlassian_jwt!
|
||||||
|
|
||||||
before_action :verify_atlassian_jwt!, only: :uninstalled, unless: :signed_install_active?
|
|
||||||
before_action :verify_qsh_claim!, only: :uninstalled, unless: :signed_install_active?
|
|
||||||
|
|
||||||
def installed
|
def installed
|
||||||
return head :ok if !signed_install_active? && atlassian_jwt_valid?
|
|
||||||
|
|
||||||
return head :ok if current_jira_installation
|
return head :ok if current_jira_installation
|
||||||
|
|
||||||
installation = JiraConnectInstallation.new(event_params)
|
installation = JiraConnectInstallation.new(event_params)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: jira_connect_asymmetric_jwt
|
name: rate_limiter_safe_increment
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71080
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73343
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342808
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285352
|
||||||
milestone: '14.4'
|
milestone: '14.5'
|
||||||
type: development
|
type: development
|
||||||
group: group::integrations
|
group: group::project management
|
||||||
default_enabled: true
|
default_enabled: false
|
||||||
|
|
@ -8,8 +8,7 @@ product_stage: package
|
||||||
product_group: group::package
|
product_group: group::package
|
||||||
product_category: package registry
|
product_category: package registry
|
||||||
value_type: number
|
value_type: number
|
||||||
status: broken
|
status: active
|
||||||
repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
|
|
||||||
time_frame: 28d
|
time_frame: 28d
|
||||||
data_source: redis_hll
|
data_source: redis_hll
|
||||||
instrumentation_class: RedisHLLMetric
|
instrumentation_class: RedisHLLMetric
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ product_stage: package
|
||||||
product_group: group::package
|
product_group: group::package
|
||||||
product_category: package registry
|
product_category: package registry
|
||||||
value_type: number
|
value_type: number
|
||||||
status: broken
|
status: active
|
||||||
repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
|
|
||||||
time_frame: 28d
|
time_frame: 28d
|
||||||
data_source: redis_hll
|
data_source: redis_hll
|
||||||
instrumentation_class: RedisHLLMetric
|
instrumentation_class: RedisHLLMetric
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ product_stage: package
|
||||||
product_group: group::package
|
product_group: group::package
|
||||||
product_category: package registry
|
product_category: package registry
|
||||||
value_type: number
|
value_type: number
|
||||||
status: broken
|
status: active
|
||||||
repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455
|
|
||||||
time_frame: 7d
|
time_frame: 7d
|
||||||
data_source: redis_hll
|
data_source: redis_hll
|
||||||
instrumentation_class: RedisHLLMetric
|
instrumentation_class: RedisHLLMetric
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ POST /ci/lint
|
||||||
| ---------- | ------- | -------- | -------- |
|
| ---------- | ------- | -------- | -------- |
|
||||||
| `content` | string | yes | The CI/CD configuration content. |
|
| `content` | string | yes | The CI/CD configuration content. |
|
||||||
| `include_merged_yaml` | boolean | no | If the [expanded CI/CD configuration](#yaml-expansion) should be included in the response. |
|
| `include_merged_yaml` | boolean | no | If the [expanded CI/CD configuration](#yaml-expansion) should be included in the response. |
|
||||||
|
| `include_jobs` | boolean | no | If the list of jobs should be included in the response. This is false by default. |
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --header "Content-Type: application/json" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
|
curl --header "Content-Type: application/json" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
|
||||||
|
|
@ -91,7 +92,7 @@ work for CI configuration added with [`include: local`](../ci/yaml/index.md#incl
|
||||||
or with [`extends:`](../ci/yaml/index.md#extends).
|
or with [`extends:`](../ci/yaml/index.md#extends).
|
||||||
|
|
||||||
Example contents of a `.gitlab-ci.yml` passed to the CI Lint API with
|
Example contents of a `.gitlab-ci.yml` passed to the CI Lint API with
|
||||||
`include_merged_yaml` set as true:
|
`include_merged_yaml` and `include_jobs` set as true:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
include:
|
include:
|
||||||
|
|
@ -118,7 +119,39 @@ Example response:
|
||||||
{
|
{
|
||||||
"status": "valid",
|
"status": "valid",
|
||||||
"errors": [],
|
"errors": [],
|
||||||
"merged_yaml": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n"
|
"merged_yaml": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n",
|
||||||
|
"jobs": [
|
||||||
|
{
|
||||||
|
"name":"test",
|
||||||
|
"stage":"test",
|
||||||
|
"before_script":[],
|
||||||
|
"script":["echo 1"],
|
||||||
|
"after_script":[],
|
||||||
|
"tag_list":[],
|
||||||
|
"environment":null,
|
||||||
|
"when":"on_success",
|
||||||
|
"allow_failure":false,
|
||||||
|
"only":{
|
||||||
|
"refs":["branches","tags"]
|
||||||
|
},
|
||||||
|
"except":null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"another_test",
|
||||||
|
"stage":"test",
|
||||||
|
"before_script":[],
|
||||||
|
"script":["echo 2"],
|
||||||
|
"after_script":[],
|
||||||
|
"tag_list":[],
|
||||||
|
"environment":null,
|
||||||
|
"when":"on_success",
|
||||||
|
"allow_failure":false,
|
||||||
|
"only":{
|
||||||
|
"refs":["branches","tags"]
|
||||||
|
},
|
||||||
|
"except":null
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -137,6 +170,7 @@ POST /projects/:id/ci/lint
|
||||||
| ---------- | ------- | -------- | -------- |
|
| ---------- | ------- | -------- | -------- |
|
||||||
| `content` | string | yes | The CI/CD configuration content. |
|
| `content` | string | yes | The CI/CD configuration content. |
|
||||||
| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#pipeline-simulation), or only do static check. This is false by default. |
|
| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#pipeline-simulation), or only do static check. This is false by default. |
|
||||||
|
| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. |
|
||||||
|
|
||||||
Example request:
|
Example request:
|
||||||
|
|
||||||
|
|
@ -185,6 +219,7 @@ GET /projects/:id/ci/lint
|
||||||
| Attribute | Type | Required | Description |
|
| Attribute | Type | Required | Description |
|
||||||
| ---------- | ------- | -------- | -------- |
|
| ---------- | ------- | -------- | -------- |
|
||||||
| `dry_run` | boolean | no | Run pipeline creation simulation, or only do static check. |
|
| `dry_run` | boolean | no | Run pipeline creation simulation, or only do static check. |
|
||||||
|
| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. |
|
||||||
|
|
||||||
Example request:
|
Example request:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ We use the following terminology to describe the Service Ping components:
|
||||||
- **Metrics**: primarily made up of row counts for different tables in an instance's database. Each
|
- **Metrics**: primarily made up of row counts for different tables in an instance's database. Each
|
||||||
metric has a corresponding [metric definition](metrics_dictionary.md#metrics-definition-and-validation)
|
metric has a corresponding [metric definition](metrics_dictionary.md#metrics-definition-and-validation)
|
||||||
in a YAML file.
|
in a YAML file.
|
||||||
|
- **MAU**: monthly active users.
|
||||||
|
- **WAU**: weekly active users.
|
||||||
|
|
||||||
### Why should we enable Service Ping?
|
### Why should we enable Service Ping?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,124 +7,186 @@ type: index
|
||||||
|
|
||||||
# Admin Area settings **(FREE SELF)**
|
# Admin Area settings **(FREE SELF)**
|
||||||
|
|
||||||
As an administrator of a GitLab self-managed instance, you can manage the behavior of your deployment. To do so, select **Admin Area > Settings**.
|
As an administrator of a GitLab self-managed instance, you can manage the behavior of your
|
||||||
|
deployment.
|
||||||
|
|
||||||
The Admin Area is not accessible on GitLab.com, and settings can only be changed by the
|
The **Admin Area** is not accessible on GitLab.com, and settings can only be changed by the
|
||||||
GitLab.com administrators. See the [GitLab.com settings](../../gitlab_com/index.md)
|
GitLab.com administrators. For the settings and limits on the GitLab.com instance,
|
||||||
documentation for all current settings and limits on the GitLab.com instance.
|
read [GitLab.com settings](../../gitlab_com/index.md).
|
||||||
|
|
||||||
## General
|
## Access the Admin Area
|
||||||
|
|
||||||
To access the default page for Admin Area settings:
|
To access the **Admin Area**:
|
||||||
|
|
||||||
|
1. Sign in to your GitLab instance as an administrator.
|
||||||
1. On the top bar, select **Menu > Admin**.
|
1. On the top bar, select **Menu > Admin**.
|
||||||
1. On the left sidebar, select **Settings > General**.
|
1. On the left sidebar, select **Settings**, and the group of settings to view:
|
||||||
|
- [General](#general)
|
||||||
|
- [Geo](#geo)
|
||||||
|
- [CI/CD](#cicd)
|
||||||
|
- [Integrations](#integrations)
|
||||||
|
- [Metrics and profiling](#metrics-and-profiling)
|
||||||
|
- [Network](#network)
|
||||||
|
- [Preferences](#preferences)
|
||||||
|
- [Reporting](#reporting)
|
||||||
|
- [Repository](#repository)
|
||||||
|
- [Templates](#templates)
|
||||||
|
|
||||||
| Option | Description |
|
### General
|
||||||
| ------ | ----------- |
|
|
||||||
| [Visibility and access controls](visibility_and_access_controls.md) | Set default and restrict visibility levels. Configure import sources and Git access protocol. |
|
|
||||||
| [Account and limit](account_and_limit_settings.md) | Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan. |
|
|
||||||
| [Diff limits](../diff_limits.md) | Diff content limits. |
|
|
||||||
| [Sign-up restrictions](sign_up_restrictions.md) | Configure the way a user creates a new account. |
|
|
||||||
| [Sign in restrictions](sign_in_restrictions.md) | Set requirements for a user to sign in. Enable mandatory two-factor authentication. |
|
|
||||||
| [Terms of Service and Privacy Policy](terms.md) | Include a Terms of Service agreement and Privacy Policy that all users must accept. |
|
|
||||||
| [External Authentication](external_authorization.md#configuration) | External Classification Policy Authorization |
|
|
||||||
| [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) | Set max session time for web terminal. |
|
|
||||||
| [Web IDE](../../project/web_ide/index.md#enable-live-preview) | Manage Web IDE features. |
|
|
||||||
| [FLoC](floc.md) | Enable or disable [Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking. |
|
|
||||||
|
|
||||||
## Integrations
|
The **General** settings contain:
|
||||||
|
|
||||||
| Option | Description |
|
- [Visibility and access controls](visibility_and_access_controls.md) - Set default and
|
||||||
| ------ | ----------- |
|
restrict visibility levels. Configure import sources and Git access protocol.
|
||||||
| [Elasticsearch](../../../integration/elasticsearch.md#enable-advanced-search) | Elasticsearch integration. Elasticsearch AWS IAM. |
|
- [Account and limit](account_and_limit_settings.md) - Set projects and maximum size limits,
|
||||||
| [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) | Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io). |
|
session duration, user options, and check feature availability for namespace plan.
|
||||||
| [Mailgun](../../../administration/integration/mailgun.md) | Enable your GitLab instance to receive invite email bounce events from Mailgun, if it is your email provider. |
|
- [Diff limits](../diff_limits.md) - Diff content limits.
|
||||||
| [PlantUML](../../../administration/integration/plantuml.md) | Allow rendering of PlantUML diagrams in documents. |
|
- [Sign-up restrictions](sign_up_restrictions.md) - Configure the way a user creates a new account.
|
||||||
| [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). |
|
- [Sign in restrictions](sign_in_restrictions.md) - Set requirements for a user to sign in.
|
||||||
| [Third party offers](third_party_offers.md) | Control the display of third party offers. |
|
Enable mandatory two-factor authentication.
|
||||||
| [Snowplow](../../../development/snowplow/index.md) | Configure the Snowplow integration. |
|
- [Terms of Service and Privacy Policy](terms.md) - Include a Terms of Service agreement
|
||||||
| [Google GKE](../../project/clusters/add_gke_clusters.md) | Google GKE integration allows you to provision GKE clusters from GitLab. |
|
and Privacy Policy that all users must accept.
|
||||||
| [Amazon EKS](../../project/clusters/add_eks_clusters.md) | Amazon EKS integration allows you to provision EKS clusters from GitLab. |
|
- [External Authentication](external_authorization.md#configuration) - External Classification Policy Authorization.
|
||||||
|
- [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) -
|
||||||
|
Set max session time for web terminal.
|
||||||
|
- [Web IDE](../../project/web_ide/index.md#enable-live-preview) - Manage Web IDE features.
|
||||||
|
- [FLoC](floc.md) - Enable or disable
|
||||||
|
[Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking.
|
||||||
|
|
||||||
## Repository
|
### CI/CD
|
||||||
|
|
||||||
| Option | Description |
|
The **CI/CD** settings contain:
|
||||||
| ------ | ----------- |
|
|
||||||
| [Repository's custom initial branch name](../../project/repository/branches/default.md#instance-level-custom-initial-branch-name) | Set a custom branch name for new repositories created in your instance. |
|
|
||||||
| [Repository mirror](visibility_and_access_controls.md#enable-project-mirroring) | Configure repository mirroring. |
|
|
||||||
| [Repository storage](../../../administration/repository_storage_types.md) | Configure storage path settings. |
|
|
||||||
| Repository maintenance | ([Repository checks](../../../administration/repository_checks.md) and [Housekeeping](../../../administration/housekeeping.md)). Configure automatic Git checks and housekeeping on repositories. |
|
|
||||||
| [Repository static objects](../../../administration/static_objects_external_storage.md) | Serve repository static objects (for example, archives and blobs) from an external storage (for example, a CDN). |
|
|
||||||
|
|
||||||
## Templates **(PREMIUM SELF)**
|
- [Continuous Integration and Deployment](continuous_integration.md) -
|
||||||
|
Auto DevOps, runners and job artifacts.
|
||||||
|
- [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) -
|
||||||
|
Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/index.md).
|
||||||
|
This pipeline configuration is run after the project's own configuration.
|
||||||
|
- [Package Registry](continuous_integration.md#package-registry-configuration) -
|
||||||
|
Settings related to the use and experience of using the GitLab Package Registry. Some
|
||||||
|
[risks are involved](../../packages/container_registry/index.md#use-with-external-container-registries)
|
||||||
|
in enabling some of these settings.
|
||||||
|
|
||||||
| Option | Description |
|
### Geo **(PREMIUM SELF)**
|
||||||
| ------ | ----------- |
|
|
||||||
| [Templates](instance_template_repository.md#configuration) | Set instance-wide template repository. |
|
|
||||||
| [Custom project templates](../custom_project_templates.md) | Select the custom project template source group. |
|
|
||||||
|
|
||||||
## CI/CD
|
The **Geo** setting contains:
|
||||||
|
|
||||||
| Option | Description |
|
- [Geo](../../../administration/geo/index.md) - Replicate your GitLab instance to other
|
||||||
| ------ | ----------- |
|
geographical locations. Redirects to **Admin Area > Geo > Settings** are no
|
||||||
| [Continuous Integration and Deployment](continuous_integration.md) | Auto DevOps, runners and job artifacts. |
|
longer available at **Admin Area > Settings > Geo** in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/36896).
|
||||||
| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/index.md). This pipeline configuration is run after the project's own configuration. |
|
|
||||||
| [Package Registry](continuous_integration.md#package-registry-configuration) | Settings related to the use and experience of using the GitLab Package Registry. Note there are [risks involved](../../packages/container_registry/index.md#use-with-external-container-registries) in enabling some of these settings. |
|
|
||||||
|
|
||||||
## Reporting
|
### Integrations
|
||||||
|
|
||||||
| Option | Description |
|
The **Integrations** settings contain:
|
||||||
| ------ | ----------- |
|
|
||||||
| [Spam and Anti-bot Protection](../../../integration/recaptcha.md) | Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support [v2](https://developers.google.com/recaptcha/docs/versions). |
|
|
||||||
| [Abuse reports](../review_abuse_reports.md) | Set notification email for abuse reports. |
|
|
||||||
|
|
||||||
## Metrics and profiling
|
- [Elasticsearch](../../../integration/elasticsearch.md#enable-advanced-search) -
|
||||||
|
Elasticsearch integration. Elasticsearch AWS IAM.
|
||||||
|
- [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) -
|
||||||
|
Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io).
|
||||||
|
- [Mailgun](../../../administration/integration/mailgun.md) - Enable your GitLab instance
|
||||||
|
to receive invite email bounce events from Mailgun, if it is your email provider.
|
||||||
|
- [PlantUML](../../../administration/integration/plantuml.md) - Allow rendering of PlantUML
|
||||||
|
diagrams in documents.
|
||||||
|
- [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) -
|
||||||
|
Slack integration allows you to interact with GitLab via slash commands in a chat window.
|
||||||
|
This option is only available on GitLab.com, though it may be
|
||||||
|
[available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164).
|
||||||
|
- [Third party offers](third_party_offers.md) - Control the display of third-party offers.
|
||||||
|
- [Snowplow](../../../development/snowplow/index.md) - Configure the Snowplow integration.
|
||||||
|
- [Google GKE](../../project/clusters/add_gke_clusters.md) - Google GKE integration enables
|
||||||
|
you to provision GKE clusters from GitLab.
|
||||||
|
- [Amazon EKS](../../project/clusters/add_eks_clusters.md) - Amazon EKS integration enables
|
||||||
|
you to provision EKS clusters from GitLab.
|
||||||
|
|
||||||
| Option | Description |
|
### Metrics and profiling
|
||||||
| ------ | ----------- |
|
|
||||||
| [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) | Enable and configure Prometheus metrics. |
|
|
||||||
| [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) | Enable and configure Grafana. |
|
|
||||||
| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-for-non-administrators) | Enable access to the Performance Bar for non-administrator users in a given group. |
|
|
||||||
| [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#create-the-self-monitoring-project) | Enable or disable instance self monitoring. |
|
|
||||||
| [Usage statistics](usage_statistics.md) | Enable or disable version check and Service Ping. |
|
|
||||||
| [Pseudonymizer data collection](../../../administration/pseudonymizer.md) | Enable or disable the Pseudonymizer data collection. |
|
|
||||||
|
|
||||||
## Network
|
The **Metrics and profiling** settings contain:
|
||||||
|
|
||||||
| Option | Description |
|
- [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) -
|
||||||
| ------ | ----------- |
|
Enable and configure Prometheus metrics.
|
||||||
| Performance optimization | [Write to "authorized_keys" file](../../../administration/operations/fast_ssh_key_lookup.md#setting-up-fast-lookup-via-gitlab-shell) and [Push event activities limit and bulk push events](push_event_activities_limit.md). Various settings that affect GitLab performance. |
|
- [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) -
|
||||||
| [User and IP rate limits](user_and_ip_rate_limits.md) | Configure limits for web and API requests. |
|
Enable and configure Grafana.
|
||||||
| [Package Registry Rate Limits](package_registry_rate_limits.md) | Configure specific limits for Packages API requests that supersede the user and IP rate limits. |
|
- [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-for-non-administrators) -
|
||||||
| [Git LFS Rate Limits](git_lfs_rate_limits.md) | Configure specific limits for Git LFS requests that supersede the user and IP rate limits. |
|
Enable access to the Performance Bar for non-administrator users in a given group.
|
||||||
| [Files API Rate Limits](files_api_rate_limits.md) | Configure specific limits for Files API requests that supersede the user and IP rate limits. |
|
- [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#create-the-self-monitoring-project) -
|
||||||
| [Deprecated API Rate Limits](deprecated_api_rate_limits.md) | Configure specific limits for deprecated API requests that supersede the user and IP rate limits. |
|
Enable or disable instance self monitoring.
|
||||||
| [Outbound requests](../../../security/webhooks.md) | Allow requests to the local network from hooks and services. |
|
- [Usage statistics](usage_statistics.md) - Enable or disable version check and Service Ping.
|
||||||
| [Protected Paths](protected_paths.md) | Configure paths to be protected by Rack Attack. |
|
- [Pseudonymizer data collection](../../../administration/pseudonymizer.md) -
|
||||||
| [Incident Management](../../../operations/incident_management/index.md) Limits | Limit the number of inbound alerts that can be sent to a project. |
|
Enable or disable the Pseudonymizer data collection.
|
||||||
| [Notes creation limit](rate_limit_on_notes_creation.md)| Set a rate limit on the note creation requests. |
|
|
||||||
|
|
||||||
## Geo **(PREMIUM SELF)**
|
### Network
|
||||||
|
|
||||||
| Option | Description |
|
The **Network** settings contain:
|
||||||
| ------ | ----------- |
|
|
||||||
| [Geo](../../../administration/geo/index.md) | Geo allows you to replicate your GitLab instance to other geographical locations. Redirects to **Admin Area > Geo > Settings** are no longer available at **Admin Area > Settings > Geo** in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/36896). |
|
|
||||||
|
|
||||||
## Preferences
|
- Performance optimization - Various settings that affect GitLab performance, including:
|
||||||
|
- [Write to `authorized_keys` file](../../../administration/operations/fast_ssh_key_lookup.md#setting-up-fast-lookup-via-gitlab-shell).
|
||||||
|
- [Push event activities limit and bulk push events](push_event_activities_limit.md).
|
||||||
|
- [User and IP rate limits](user_and_ip_rate_limits.md) - Configure limits for web and API requests.
|
||||||
|
These rate limits can be overridden:
|
||||||
|
- [Package Registry Rate Limits](package_registry_rate_limits.md) - Configure specific
|
||||||
|
limits for Packages API requests that supersede the user and IP rate limits.
|
||||||
|
- [Git LFS Rate Limits](git_lfs_rate_limits.md) - Configure specific limits for
|
||||||
|
Git LFS requests that supersede the user and IP rate limits.
|
||||||
|
- [Files API Rate Limits](files_api_rate_limits.md) - Configure specific limits for
|
||||||
|
Files API requests that supersede the user and IP rate limits.
|
||||||
|
- [Deprecated API Rate Limits](deprecated_api_rate_limits.md) - Configure specific limits
|
||||||
|
for deprecated API requests that supersede the user and IP rate limits.
|
||||||
|
- [Outbound requests](../../../security/webhooks.md) - Allow requests to the local network from hooks and services.
|
||||||
|
- [Protected Paths](protected_paths.md) - Configure paths to be protected by Rack Attack.
|
||||||
|
- [Incident Management Limits](../../../operations/incident_management/index.md) - Limit the
|
||||||
|
number of inbound alerts that can be sent to a project.
|
||||||
|
- [Notes creation limit](rate_limit_on_notes_creation.md) - Set a rate limit on the note creation requests.
|
||||||
|
|
||||||
| Option | Description |
|
### Preferences
|
||||||
| ------ | ----------- |
|
|
||||||
| [Email](email.md) | Various email settings. |
|
|
||||||
| [What's new](../../../administration/whats-new.md) | Configure What's new drawer and content. |
|
|
||||||
| [Help page](help_page.md) | Help page text and support page URL. |
|
|
||||||
| [Pages](../../../administration/pages/index.md#custom-domain-verification) | Size and domain settings for static websites |
|
|
||||||
| [Polling interval multiplier](../../../administration/polling.md) | Configure how frequently the GitLab UI polls for updates. |
|
|
||||||
| [Gitaly timeouts](gitaly_timeouts.md) | Configure Gitaly timeouts. |
|
|
||||||
| Localization | [Default first day of the week](../../profile/preferences.md) and [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours). |
|
|
||||||
| [Sidekiq Job Limits](sidekiq_job_limits.md) | Limit the size of Sidekiq jobs stored in Redis. |
|
|
||||||
|
|
||||||
### Default first day of the week
|
The **Preferences** settings contain:
|
||||||
|
|
||||||
|
- [Email](email.md) - Various email settings.
|
||||||
|
- [What's new](../../../administration/whats-new.md) - Configure **What's new** drawer and content.
|
||||||
|
- [Help page](help_page.md) - Help page text and support page URL.
|
||||||
|
- [Pages](../../../administration/pages/index.md#custom-domain-verification) -
|
||||||
|
Size and domain settings for static websites.
|
||||||
|
- [Polling interval multiplier](../../../administration/polling.md) -
|
||||||
|
Configure how frequently the GitLab UI polls for updates.
|
||||||
|
- [Gitaly timeouts](gitaly_timeouts.md) - Configure Gitaly timeouts.
|
||||||
|
- Localization:
|
||||||
|
- [Default first day of the week](../../profile/preferences.md).
|
||||||
|
- [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours).
|
||||||
|
- [Sidekiq Job Limits](sidekiq_job_limits.md) - Limit the size of Sidekiq jobs stored in Redis.
|
||||||
|
|
||||||
|
### Reporting
|
||||||
|
|
||||||
|
The **Reporting** settings contain:
|
||||||
|
|
||||||
|
- [Spam and Anti-bot Protection](../../../integration/recaptcha.md) -
|
||||||
|
Enable anti-spam services, like reCAPTCHA or Akismet, and set IP limits.
|
||||||
|
- [Abuse reports](../review_abuse_reports.md) - Set notification email for abuse reports.
|
||||||
|
|
||||||
|
### Repository
|
||||||
|
|
||||||
|
The **Repository** settings contain:
|
||||||
|
|
||||||
|
- [Repository's custom initial branch name](../../project/repository/branches/default.md#instance-level-custom-initial-branch-name) -
|
||||||
|
Set a custom branch name for new repositories created in your instance.
|
||||||
|
- [Repository mirror](visibility_and_access_controls.md#enable-project-mirroring) -
|
||||||
|
Configure repository mirroring.
|
||||||
|
- [Repository storage](../../../administration/repository_storage_types.md) - Configure storage path settings.
|
||||||
|
- Repository maintenance:
|
||||||
|
- [Repository checks](../../../administration/repository_checks.md) - Configure
|
||||||
|
automatic Git checks on repositories.
|
||||||
|
- [Housekeeping](../../../administration/housekeeping.md)). Configure automatic
|
||||||
|
Git housekeeping on repositories.
|
||||||
|
- [Repository static objects](../../../administration/static_objects_external_storage.md) -
|
||||||
|
Serve repository static objects (for example, archives and blobs) from an external storage (for example, a CDN).
|
||||||
|
|
||||||
|
### Templates **(PREMIUM SELF)**
|
||||||
|
|
||||||
|
The **Templates** settings contain:
|
||||||
|
|
||||||
|
- [Templates](instance_template_repository.md#configuration) - Set instance-wide template repository.
|
||||||
|
- [Custom project templates](../custom_project_templates.md) - Select the custom project template source group.
|
||||||
|
|
||||||
|
## Default first day of the week
|
||||||
|
|
||||||
You can change the [Default first day of the week](../../profile/preferences.md)
|
You can change the [Default first day of the week](../../profile/preferences.md)
|
||||||
for the entire GitLab instance:
|
for the entire GitLab instance:
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ in Microsoft Teams. To integrate the services, you must:
|
||||||
|
|
||||||
To configure Microsoft Teams to listen for notifications from GitLab:
|
To configure Microsoft Teams to listen for notifications from GitLab:
|
||||||
|
|
||||||
1. In Microsoft Teams, search for "incoming webhook" in the search bar, and select the
|
1. In Microsoft Teams, type `incoming webhook` in the search bar, and select
|
||||||
**Incoming Webhook** item:
|
**Incoming Webhook**:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
@ -34,11 +34,12 @@ To configure Microsoft Teams to listen for notifications from GitLab:
|
||||||
After you configure Microsoft Teams to receive notifications, you must configure
|
After you configure Microsoft Teams to receive notifications, you must configure
|
||||||
GitLab to send the notifications:
|
GitLab to send the notifications:
|
||||||
|
|
||||||
1. Sign in to GitLab as a user with [Administrator](../../permissions.md) and go
|
1. Sign in to GitLab as an administrator.
|
||||||
to your project's page.
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
1. Go to **Settings > Integrations** and select **Microsoft Teams Notification**.
|
1. On the left sidebar, select **Settings > Integrations**.
|
||||||
1. Select **Active** to enable the integration.
|
1. Select **Microsoft Teams notifications**.
|
||||||
1. Select the checkbox next to each **Trigger** to enable:
|
1. To enable the integration, select **Active**.
|
||||||
|
1. In the **Trigger** section, select the checkbox next to each event to enable it:
|
||||||
- Push
|
- Push
|
||||||
- Issue
|
- Issue
|
||||||
- Confidential issue
|
- Confidential issue
|
||||||
|
|
@ -46,11 +47,11 @@ GitLab to send the notifications:
|
||||||
- Note
|
- Note
|
||||||
- Confidential note
|
- Confidential note
|
||||||
- Tag push
|
- Tag push
|
||||||
- Pipeline - If you enable this trigger, you can also select **Notify only broken pipelines** to be notified only about failed pipelines.
|
- Pipeline
|
||||||
- Wiki page
|
- Wiki page
|
||||||
1. In **Webhook**, paste the URL you copied when you
|
1. In **Webhook**, paste the URL you copied when you
|
||||||
[configured Microsoft Teams](#configure-microsoft-teams).
|
[configured Microsoft Teams](#configure-microsoft-teams).
|
||||||
1. (Optional) If you enabled the pipeline trigger, you can select the
|
1. Optional. If you enable the pipeline trigger, select the
|
||||||
**Notify only broken pipelines** checkbox to push notifications only when pipelines break.
|
**Notify only broken pipelines** checkbox to push notifications only when pipelines break.
|
||||||
1. Select the branches you want to send notifications for.
|
1. Select the branches you want to send notifications for.
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ group: Code Review
|
||||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||||
---
|
---
|
||||||
|
|
||||||
# GitLab Workflow VS Code extension **(FREE)**
|
# GitLab Workflow extension for VS Code **(FREE)**
|
||||||
|
|
||||||
The [GitLab VS Code Extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
|
The [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
|
||||||
integrates GitLab with Visual Studio Code. You can decrease context switching and
|
integrates GitLab with Visual Studio Code. You can decrease context switching and
|
||||||
do more day-to-day tasks in Visual Studio Code, such as:
|
do more day-to-day tasks in Visual Studio Code, such as:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ module API
|
||||||
expose :errors
|
expose :errors
|
||||||
expose :warnings
|
expose :warnings
|
||||||
expose :merged_yaml
|
expose :merged_yaml
|
||||||
|
expose :jobs, if: -> (result, options) { options[:include_jobs] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ module API
|
||||||
params do
|
params do
|
||||||
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
|
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
|
||||||
optional :include_merged_yaml, type: Boolean, desc: 'Whether or not to include merged CI config yaml in the response'
|
optional :include_merged_yaml, type: Boolean, desc: 'Whether or not to include merged CI config yaml in the response'
|
||||||
|
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
|
||||||
end
|
end
|
||||||
post '/lint' do
|
post '/lint' do
|
||||||
unauthorized! if (Gitlab::CurrentSettings.signup_disabled? || Gitlab::CurrentSettings.signup_limited?) && current_user.nil?
|
unauthorized! if (Gitlab::CurrentSettings.signup_disabled? || Gitlab::CurrentSettings.signup_limited?) && current_user.nil?
|
||||||
|
|
@ -17,7 +18,7 @@ module API
|
||||||
.validate(params[:content], dry_run: false)
|
.validate(params[:content], dry_run: false)
|
||||||
|
|
||||||
status 200
|
status 200
|
||||||
Entities::Ci::Lint::Result.represent(result, current_user: current_user).serializable_hash.tap do |presented_result|
|
Entities::Ci::Lint::Result.represent(result, current_user: current_user, include_jobs: params[:include_jobs]).serializable_hash.tap do |presented_result|
|
||||||
presented_result[:status] = presented_result[:valid] ? 'valid' : 'invalid'
|
presented_result[:status] = presented_result[:valid] ? 'valid' : 'invalid'
|
||||||
presented_result.delete(:merged_yaml) unless params[:include_merged_yaml]
|
presented_result.delete(:merged_yaml) unless params[:include_merged_yaml]
|
||||||
end
|
end
|
||||||
|
|
@ -30,6 +31,7 @@ module API
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
|
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
|
||||||
|
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
|
||||||
end
|
end
|
||||||
get ':id/ci/lint' do
|
get ':id/ci/lint' do
|
||||||
authorize! :download_code, user_project
|
authorize! :download_code, user_project
|
||||||
|
|
@ -39,7 +41,7 @@ module API
|
||||||
.new(project: user_project, current_user: current_user)
|
.new(project: user_project, current_user: current_user)
|
||||||
.validate(content, dry_run: params[:dry_run])
|
.validate(content, dry_run: params[:dry_run])
|
||||||
|
|
||||||
present result, with: Entities::Ci::Lint::Result, current_user: current_user
|
present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -50,6 +52,7 @@ module API
|
||||||
params do
|
params do
|
||||||
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
|
requires :content, type: String, desc: 'Content of .gitlab-ci.yml'
|
||||||
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
|
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
|
||||||
|
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
|
||||||
end
|
end
|
||||||
post ':id/ci/lint' do
|
post ':id/ci/lint' do
|
||||||
authorize! :create_pipeline, user_project
|
authorize! :create_pipeline, user_project
|
||||||
|
|
@ -59,7 +62,7 @@ module API
|
||||||
.validate(params[:content], dry_run: params[:dry_run])
|
.validate(params[:content], dry_run: params[:dry_run])
|
||||||
|
|
||||||
status 200
|
status 200
|
||||||
present result, with: Entities::Ci::Lint::Result, current_user: current_user
|
present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,6 @@ module Gitlab
|
||||||
# @param key [Symbol] Key attribute registered in `.rate_limits`
|
# @param key [Symbol] Key attribute registered in `.rate_limits`
|
||||||
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
|
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
|
||||||
# @option threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
|
# @option threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
|
||||||
# @option interval [Integer] Optional interval value to override default one registered in `.rate_limits`
|
|
||||||
# @option users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user.
|
# @option users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user.
|
||||||
#
|
#
|
||||||
# @return [Boolean] Whether or not a request should be throttled
|
# @return [Boolean] Whether or not a request should be throttled
|
||||||
|
|
@ -77,7 +76,7 @@ module Gitlab
|
||||||
|
|
||||||
threshold_value = options[:threshold] || threshold(key)
|
threshold_value = options[:threshold] || threshold(key)
|
||||||
threshold_value > 0 &&
|
threshold_value > 0 &&
|
||||||
increment(key, options[:scope], options[:interval]) > threshold_value
|
increment(key, options[:scope]) > threshold_value
|
||||||
end
|
end
|
||||||
|
|
||||||
# Increments the given cache key and increments the value by 1 with the
|
# Increments the given cache key and increments the value by 1 with the
|
||||||
|
|
@ -85,12 +84,13 @@ module Gitlab
|
||||||
#
|
#
|
||||||
# @param key [Symbol] Key attribute registered in `.rate_limits`
|
# @param key [Symbol] Key attribute registered in `.rate_limits`
|
||||||
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
|
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
|
||||||
# @option interval [Integer] Optional interval value to override default one registered in `.rate_limits`
|
|
||||||
#
|
#
|
||||||
# @return [Integer] incremented value
|
# @return [Integer] incremented value
|
||||||
def increment(key, scope, interval = nil)
|
def increment(key, scope)
|
||||||
|
return safe_increment(key, scope) if Feature.enabled?(:rate_limiter_safe_increment, default_enabled: :yaml)
|
||||||
|
|
||||||
value = 0
|
value = 0
|
||||||
interval_value = interval || interval(key)
|
interval_value = interval(key)
|
||||||
|
|
||||||
::Gitlab::Redis::RateLimiting.with do |redis|
|
::Gitlab::Redis::RateLimiting.with do |redis|
|
||||||
cache_key = action_key(key, scope)
|
cache_key = action_key(key, scope)
|
||||||
|
|
@ -101,6 +101,32 @@ module Gitlab
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Increments a cache key that is based on the current time and interval.
|
||||||
|
# So that when time passes to the next interval, the key changes and the count starts again from 0.
|
||||||
|
#
|
||||||
|
# Based on https://github.com/rack/rack-attack/blob/886ba3a18d13c6484cd511a4dc9b76c0d14e5e96/lib/rack/attack/cache.rb#L63-L68
|
||||||
|
#
|
||||||
|
# @param key [Symbol] Key attribute registered in `.rate_limits`
|
||||||
|
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
|
||||||
|
#
|
||||||
|
# @return [Integer] incremented value
|
||||||
|
def safe_increment(key, scope)
|
||||||
|
interval_value = interval(key)
|
||||||
|
|
||||||
|
period_key, time_elapsed_in_period = Time.now.to_i.divmod(interval_value)
|
||||||
|
|
||||||
|
cache_key = "#{action_key(key, scope)}:#{period_key}"
|
||||||
|
# We add a 1 second buffer to avoid timing issues when we're at the end of a period
|
||||||
|
expiry = interval_value - time_elapsed_in_period + 1
|
||||||
|
|
||||||
|
::Gitlab::Redis::RateLimiting.with do |redis|
|
||||||
|
redis.pipelined do
|
||||||
|
redis.incr(cache_key)
|
||||||
|
redis.expire(cache_key, expiry)
|
||||||
|
end.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Logs request using provided logger
|
# Logs request using provided logger
|
||||||
#
|
#
|
||||||
# @param request [Http::Request] - Web request to be logged
|
# @param request [Http::Request] - Web request to be logged
|
||||||
|
|
|
||||||
|
|
@ -8216,9 +8216,6 @@ msgstr ""
|
||||||
msgid "Code"
|
msgid "Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Code Coverage: %{coveragePercentage}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
|
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -14075,6 +14072,12 @@ msgstr ""
|
||||||
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
|
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ExternalWikiService|External wiki"
|
msgid "ExternalWikiService|External wiki"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -19655,9 +19658,6 @@ msgstr ""
|
||||||
msgid "JiraService|No available statuses"
|
msgid "JiraService|No available statuses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "JiraService|Open Jira"
|
msgid "JiraService|Open Jira"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -19688,9 +19688,6 @@ msgstr ""
|
||||||
msgid "JiraService|This is an Ultimate feature"
|
msgid "JiraService|This is an Ultimate feature"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|This issue is synchronized with Jira"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "JiraService|Transition Jira issues to their final state:"
|
msgid "JiraService|Transition Jira issues to their final state:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -25534,6 +25531,9 @@ msgstr ""
|
||||||
msgid "Pipeline|Created"
|
msgid "Pipeline|Created"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Pipeline|Creating pipeline."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Pipeline|Date"
|
msgid "Pipeline|Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -29002,6 +29002,9 @@ msgstr ""
|
||||||
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
|
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "RepositoriesAnalytics|Coverage"
|
msgid "RepositoriesAnalytics|Coverage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -29023,6 +29026,9 @@ msgstr ""
|
||||||
msgid "RepositoriesAnalytics|Jobs with Coverage"
|
msgid "RepositoriesAnalytics|Jobs with Coverage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "RepositoriesAnalytics|Last Update"
|
msgid "RepositoriesAnalytics|Last Update"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -29041,6 +29047,9 @@ msgstr ""
|
||||||
msgid "RepositoriesAnalytics|Projects with Coverage"
|
msgid "RepositoriesAnalytics|Projects with Coverage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "RepositoriesAnalytics|Test Code Coverage"
|
msgid "RepositoriesAnalytics|Test Code Coverage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -39914,15 +39923,9 @@ msgstr ""
|
||||||
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
|
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "ZenTaoIntegration|This is a ZenTao user."
|
msgid "ZenTaoIntegration|This is a ZenTao user."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "ZenTaoIntegration|ZenTao user"
|
msgid "ZenTaoIntegration|ZenTao user"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -40304,6 +40307,9 @@ msgstr ""
|
||||||
msgid "ciReport|Failed to load %{reportName} report"
|
msgid "ciReport|Failed to load %{reportName} report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ciReport|Failed to load Code Quality report"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ciReport|Fixed"
|
msgid "ciReport|Fixed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -40336,6 +40342,9 @@ msgstr ""
|
||||||
msgid "ciReport|Loading %{reportName} report"
|
msgid "ciReport|Loading %{reportName} report"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ciReport|Loading Code Quality report"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ciReport|Manage licenses"
|
msgid "ciReport|Manage licenses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -40372,6 +40381,9 @@ msgstr ""
|
||||||
msgid "ciReport|Security scanning failed loading any results"
|
msgid "ciReport|Security scanning failed loading any results"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "ciReport|Solution"
|
msgid "ciReport|Solution"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,17 +90,5 @@ RSpec.describe JiraConnect::AppDescriptorController do
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when jira_connect_asymmetric_jwt is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(jira_connect_asymmetric_jwt: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
specify do
|
|
||||||
get :show
|
|
||||||
|
|
||||||
expect(json_response).to include('apiMigrations' => include('signed-install' => false))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -77,18 +77,6 @@ RSpec.describe JiraConnect::EventsController do
|
||||||
expect(installation.base_url).to eq('https://test.atlassian.net')
|
expect(installation.base_url).to eq('https://test.atlassian.net')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when jira_connect_asymmetric_jwt is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(jira_connect_asymmetric_jwt: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'saves the jira installation data without JWT validation' do
|
|
||||||
expect(Atlassian::JiraConnect::AsymmetricJwt).not_to receive(:new)
|
|
||||||
|
|
||||||
expect { subject }.to change { JiraConnectInstallation.count }.by(1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when it is a version update and shared_secret is not sent' do
|
context 'when it is a version update and shared_secret is not sent' do
|
||||||
let(:params) do
|
let(:params) do
|
||||||
{
|
{
|
||||||
|
|
@ -110,22 +98,6 @@ RSpec.describe JiraConnect::EventsController do
|
||||||
expect { subject }.not_to change { JiraConnectInstallation.count }
|
expect { subject }.not_to change { JiraConnectInstallation.count }
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when jira_connect_asymmetric_jwt is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(jira_connect_asymmetric_jwt: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'decodes the JWT token in authorization header and returns 200 without creating a new installation' do
|
|
||||||
request.headers["Authorization"] = "Bearer #{Atlassian::Jwt.encode({ iss: client_key }, shared_secret)}"
|
|
||||||
|
|
||||||
expect(Atlassian::JiraConnect::AsymmetricJwt).not_to receive(:new)
|
|
||||||
|
|
||||||
expect { subject }.not_to change { JiraConnectInstallation.count }
|
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -153,23 +125,6 @@ RSpec.describe JiraConnect::EventsController do
|
||||||
it 'does not delete the installation' do
|
it 'does not delete the installation' do
|
||||||
expect { post_uninstalled }.not_to change { JiraConnectInstallation.count }
|
expect { post_uninstalled }.not_to change { JiraConnectInstallation.count }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when jira_connect_asymmetric_jwt is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(jira_connect_asymmetric_jwt: false)
|
|
||||||
request.headers['Authorization'] = 'JWT invalid token'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns 403' do
|
|
||||||
post_uninstalled
|
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:forbidden)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not delete the installation' do
|
|
||||||
expect { post_uninstalled }.not_to change { JiraConnectInstallation.count }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when JWT is valid' do
|
context 'when JWT is valid' do
|
||||||
|
|
@ -197,36 +152,6 @@ RSpec.describe JiraConnect::EventsController do
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when jira_connect_asymmetric_jwt is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(jira_connect_asymmetric_jwt: false)
|
|
||||||
|
|
||||||
request.headers['Authorization'] = "JWT #{Atlassian::Jwt.encode({ iss: installation.client_key, qsh: qsh }, installation.shared_secret)}"
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:qsh) { Atlassian::Jwt.create_query_string_hash('https://gitlab.test/events/uninstalled', 'POST', 'https://gitlab.test') }
|
|
||||||
|
|
||||||
it 'calls the DestroyService and returns ok in case of success' do
|
|
||||||
expect_next_instance_of(JiraConnectInstallations::DestroyService, installation, jira_base_path, jira_event_path) do |destroy_service|
|
|
||||||
expect(destroy_service).to receive(:execute).and_return(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
post_uninstalled
|
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'calls the DestroyService and returns unprocessable_entity in case of failure' do
|
|
||||||
expect_next_instance_of(JiraConnectInstallations::DestroyService, installation, jira_base_path, jira_event_path) do |destroy_service|
|
|
||||||
expect(destroy_service).to receive(:execute).and_return(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
post_uninstalled
|
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { __ } from '~/locale';
|
||||||
import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
|
import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
|
||||||
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
|
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
|
||||||
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
|
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
|
||||||
|
import { createStore } from '~/boards/stores';
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
|
@ -42,17 +43,13 @@ describe('BoardFilteredSearch', () => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const createComponent = ({ initialFilterParams = {} } = {}) => {
|
const createComponent = ({ initialFilterParams = {}, props = {} } = {}) => {
|
||||||
store = new Vuex.Store({
|
store = createStore();
|
||||||
actions: {
|
|
||||||
performSearch: jest.fn(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
wrapper = shallowMount(BoardFilteredSearch, {
|
wrapper = shallowMount(BoardFilteredSearch, {
|
||||||
provide: { initialFilterParams, fullPath: '' },
|
provide: { initialFilterParams, fullPath: '' },
|
||||||
store,
|
store,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
...props,
|
||||||
tokens,
|
tokens,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -68,11 +65,7 @@ describe('BoardFilteredSearch', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
|
|
||||||
jest.spyOn(store, 'dispatch');
|
jest.spyOn(store, 'dispatch').mockImplementation();
|
||||||
});
|
|
||||||
|
|
||||||
it('renders FilteredSearch', () => {
|
|
||||||
expect(findFilteredSearch().exists()).toBe(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the correct tokens to FilteredSearch', () => {
|
it('passes the correct tokens to FilteredSearch', () => {
|
||||||
|
|
@ -99,6 +92,22 @@ describe('BoardFilteredSearch', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when eeFilters is not empty', () => {
|
||||||
|
it('passes the correct initialFilterValue to FitleredSearchBarRoot', () => {
|
||||||
|
createComponent({ props: { eeFilters: { labelName: ['label'] } } });
|
||||||
|
|
||||||
|
expect(findFilteredSearch().props('initialFilterValue')).toEqual([
|
||||||
|
{ type: 'label_name', value: { data: 'label', operator: '=' } },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders FilteredSearch', () => {
|
||||||
|
createComponent();
|
||||||
|
|
||||||
|
expect(findFilteredSearch().exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
describe('when searching', () => {
|
describe('when searching', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,13 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
import Api from '~/api';
|
import Api from '~/api';
|
||||||
import PipelinesTable from '~/commit/pipelines/pipelines_table.vue';
|
import PipelinesTable from '~/commit/pipelines/pipelines_table.vue';
|
||||||
|
import { TOAST_MESSAGE } from '~/pipelines/constants';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
|
|
||||||
|
const $toast = {
|
||||||
|
show: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
describe('Pipelines table in Commits and Merge requests', () => {
|
describe('Pipelines table in Commits and Merge requests', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
let pipeline;
|
let pipeline;
|
||||||
|
|
@ -30,6 +35,9 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
||||||
errorStateSvgPath: 'foo',
|
errorStateSvgPath: 'foo',
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
|
mocks: {
|
||||||
|
$toast,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -178,6 +186,12 @@ describe('Pipelines table in Commits and Merge requests', () => {
|
||||||
await waitForPromises();
|
await waitForPromises();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('displays a toast message during pipeline creation', async () => {
|
||||||
|
await findRunPipelineBtn().trigger('click');
|
||||||
|
|
||||||
|
expect($toast.show).toHaveBeenCalledWith(TOAST_MESSAGE);
|
||||||
|
});
|
||||||
|
|
||||||
it('on desktop, shows a loading button', async () => {
|
it('on desktop, shows a loading button', async () => {
|
||||||
await findRunPipelineBtn().trigger('click');
|
await findRunPipelineBtn().trigger('click');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,53 +3,29 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Gitlab::ApplicationRateLimiter do
|
RSpec.describe Gitlab::ApplicationRateLimiter do
|
||||||
let(:redis) { double('redis') }
|
let_it_be(:user) { create(:user) }
|
||||||
let(:user) { create(:user) }
|
let_it_be(:project) { create(:project) }
|
||||||
let(:project) { create(:project) }
|
|
||||||
let(:rate_limits) do
|
|
||||||
{
|
|
||||||
test_action: {
|
|
||||||
threshold: 1,
|
|
||||||
interval: 2.minutes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:key) { rate_limits.keys[0] }
|
|
||||||
|
|
||||||
subject { described_class }
|
subject { described_class }
|
||||||
|
|
||||||
before do
|
|
||||||
allow(Gitlab::Redis::RateLimiting).to receive(:with).and_yield(redis)
|
|
||||||
allow(described_class).to receive(:rate_limits).and_return(rate_limits)
|
|
||||||
end
|
|
||||||
|
|
||||||
shared_examples 'action rate limiter' do
|
|
||||||
it 'increases the throttle count and sets the expiration time' do
|
|
||||||
expect(redis).to receive(:incr).with(cache_key).and_return(1)
|
|
||||||
expect(redis).to receive(:expire).with(cache_key, 120)
|
|
||||||
|
|
||||||
expect(subject.throttled?(key, scope: scope)).to be_falsy
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true if the key is throttled' do
|
|
||||||
expect(redis).to receive(:incr).with(cache_key).and_return(2)
|
|
||||||
expect(redis).not_to receive(:expire)
|
|
||||||
|
|
||||||
expect(subject.throttled?(key, scope: scope)).to be_truthy
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when throttling is disabled' do
|
|
||||||
it 'returns false and does not set expiration time' do
|
|
||||||
expect(redis).not_to receive(:incr)
|
|
||||||
expect(redis).not_to receive(:expire)
|
|
||||||
|
|
||||||
expect(subject.throttled?(key, scope: scope, threshold: 0)).to be_falsy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.throttled?' do
|
describe '.throttled?' do
|
||||||
|
let(:rate_limits) do
|
||||||
|
{
|
||||||
|
test_action: {
|
||||||
|
threshold: 1,
|
||||||
|
interval: 2.minutes
|
||||||
|
},
|
||||||
|
another_action: {
|
||||||
|
threshold: 2,
|
||||||
|
interval: 3.minutes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(described_class).to receive(:rate_limits).and_return(rate_limits)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when the key is invalid' do
|
context 'when the key is invalid' do
|
||||||
context 'is provided as a Symbol' do
|
context 'is provided as a Symbol' do
|
||||||
context 'but is not defined in the rate_limits Hash' do
|
context 'but is not defined in the rate_limits Hash' do
|
||||||
|
|
@ -80,27 +56,116 @@ RSpec.describe Gitlab::ApplicationRateLimiter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the key is an array of only ActiveRecord models' do
|
context 'when rate_limiter_safe_increment is disabled' do
|
||||||
let(:scope) { [user, project] }
|
let(:redis) { double('redis') }
|
||||||
|
let(:key) { rate_limits.keys[0] }
|
||||||
|
|
||||||
let(:cache_key) do
|
before do
|
||||||
"application_rate_limiter:test_action:user:#{user.id}:project:#{project.id}"
|
allow(Gitlab::Redis::RateLimiting).to receive(:with).and_yield(redis)
|
||||||
|
|
||||||
|
stub_feature_flags(rate_limiter_safe_increment: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'action rate limiter'
|
shared_examples 'action rate limiter' do
|
||||||
|
it 'increases the throttle count and sets the expiration time' do
|
||||||
|
expect(redis).to receive(:incr).with(cache_key).and_return(1)
|
||||||
|
expect(redis).to receive(:expire).with(cache_key, 120)
|
||||||
|
|
||||||
|
expect(subject.throttled?(key, scope: scope)).to be_falsy
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true if the key is throttled' do
|
||||||
|
expect(redis).to receive(:incr).with(cache_key).and_return(2)
|
||||||
|
expect(redis).not_to receive(:expire)
|
||||||
|
|
||||||
|
expect(subject.throttled?(key, scope: scope)).to be_truthy
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when throttling is disabled' do
|
||||||
|
it 'returns false and does not set expiration time' do
|
||||||
|
expect(redis).not_to receive(:incr)
|
||||||
|
expect(redis).not_to receive(:expire)
|
||||||
|
|
||||||
|
expect(subject.throttled?(key, scope: scope, threshold: 0)).to be_falsy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the key is an array of only ActiveRecord models' do
|
||||||
|
let(:scope) { [user, project] }
|
||||||
|
|
||||||
|
let(:cache_key) do
|
||||||
|
"application_rate_limiter:test_action:user:#{user.id}:project:#{project.id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'action rate limiter'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the key is a combination of ActiveRecord models and strings' do
|
||||||
|
let(:project) { create(:project, :public, :repository) }
|
||||||
|
let(:commit) { project.repository.commit }
|
||||||
|
let(:path) { 'app/controllers/groups_controller.rb' }
|
||||||
|
let(:scope) { [project, commit, path] }
|
||||||
|
|
||||||
|
let(:cache_key) do
|
||||||
|
"application_rate_limiter:test_action:project:#{project.id}:commit:#{commit.sha}:#{path}"
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'action rate limiter'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when they key a combination of ActiveRecord models and strings' do
|
context 'when rate_limiter_safe_increment is enabled', :clean_gitlab_redis_rate_limiting do
|
||||||
let(:project) { create(:project, :public, :repository) }
|
before do
|
||||||
let(:commit) { project.repository.commit }
|
stub_feature_flags(rate_limiter_safe_increment: true)
|
||||||
let(:path) { 'app/controllers/groups_controller.rb' }
|
|
||||||
let(:scope) { [project, commit, path] }
|
|
||||||
|
|
||||||
let(:cache_key) do
|
|
||||||
"application_rate_limiter:test_action:project:#{project.id}:commit:#{commit.sha}:#{path}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'action rate limiter'
|
shared_examples 'throttles based on key and scope' do
|
||||||
|
let(:start_time) { Time.current.beginning_of_hour }
|
||||||
|
|
||||||
|
it 'returns true when threshold is exceeded' do
|
||||||
|
travel_to(start_time) do
|
||||||
|
expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to(start_time + 1.minute) do
|
||||||
|
expect(subject.throttled?(:test_action, scope: scope)).to eq(true)
|
||||||
|
|
||||||
|
# Assert that it does not affect other actions or scope
|
||||||
|
expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
|
||||||
|
expect(subject.throttled?(:test_action, scope: [user])).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false when interval has elapsed' do
|
||||||
|
travel_to(start_time) do
|
||||||
|
expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
|
||||||
|
|
||||||
|
# another_action has a threshold of 3 so we simulate 2 requests
|
||||||
|
expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
|
||||||
|
expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
travel_to(start_time + 2.minutes) do
|
||||||
|
expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
|
||||||
|
|
||||||
|
# Assert that another_action has its own interval that hasn't elapsed
|
||||||
|
expect(subject.throttled?(:another_action, scope: scope)).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when using ActiveRecord models as scope' do
|
||||||
|
let(:scope) { [user, project] }
|
||||||
|
|
||||||
|
it_behaves_like 'throttles based on key and scope'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when using ActiveRecord models and strings as scope' do
|
||||||
|
let(:scope) { [project, 'app/controllers/groups_controller.rb'] }
|
||||||
|
|
||||||
|
it_behaves_like 'throttles based on key and scope'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -134,7 +199,7 @@ RSpec.describe Gitlab::ApplicationRateLimiter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a current_user' do
|
context 'with a current_user' do
|
||||||
let(:current_user) { create(:user) }
|
let(:current_user) { user }
|
||||||
|
|
||||||
let(:attributes) do
|
let(:attributes) do
|
||||||
base_attributes.merge({
|
base_attributes.merge({
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,13 @@ RSpec.describe API::Lint do
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
expect(json_response).to have_key('merged_yaml')
|
expect(json_response).to have_key('merged_yaml')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'outputs jobs' do
|
||||||
|
post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true }
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
expect(json_response).to have_key('jobs')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with valid .gitlab-ci.yaml with warnings' do
|
context 'with valid .gitlab-ci.yaml with warnings' do
|
||||||
|
|
@ -136,6 +143,13 @@ RSpec.describe API::Lint do
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
expect(json_response).to have_key('merged_yaml')
|
expect(json_response).to have_key('merged_yaml')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'outputs jobs' do
|
||||||
|
post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true }
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
expect(json_response).to have_key('jobs')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with invalid configuration' do
|
context 'with invalid configuration' do
|
||||||
|
|
@ -156,6 +170,13 @@ RSpec.describe API::Lint do
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
expect(json_response).to have_key('merged_yaml')
|
expect(json_response).to have_key('merged_yaml')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'outputs jobs' do
|
||||||
|
post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true }
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
expect(json_response).to have_key('jobs')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -171,10 +192,11 @@ RSpec.describe API::Lint do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET /projects/:id/ci/lint' do
|
describe 'GET /projects/:id/ci/lint' do
|
||||||
subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run } }
|
subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, include_jobs: include_jobs } }
|
||||||
|
|
||||||
let(:project) { create(:project, :repository) }
|
let(:project) { create(:project, :repository) }
|
||||||
let(:dry_run) { nil }
|
let(:dry_run) { nil }
|
||||||
|
let(:include_jobs) { nil }
|
||||||
|
|
||||||
RSpec.shared_examples 'valid config with warnings' do
|
RSpec.shared_examples 'valid config with warnings' do
|
||||||
it 'passes validation with warnings' do
|
it 'passes validation with warnings' do
|
||||||
|
|
@ -359,6 +381,30 @@ RSpec.describe API::Lint do
|
||||||
it_behaves_like 'valid config without warnings'
|
it_behaves_like 'valid config without warnings'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when running with include jobs' do
|
||||||
|
let(:include_jobs) { true }
|
||||||
|
|
||||||
|
it_behaves_like 'valid config without warnings'
|
||||||
|
|
||||||
|
it 'returns jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when running without include jobs' do
|
||||||
|
let(:include_jobs) { false }
|
||||||
|
|
||||||
|
it_behaves_like 'valid config without warnings'
|
||||||
|
|
||||||
|
it 'does not return jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).not_to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'With warnings' do
|
context 'With warnings' do
|
||||||
let(:yaml_content) { { job: { script: 'ls', rules: [{ when: 'always' }] } }.to_yaml }
|
let(:yaml_content) { { job: { script: 'ls', rules: [{ when: 'always' }] } }.to_yaml }
|
||||||
|
|
||||||
|
|
@ -386,15 +432,40 @@ RSpec.describe API::Lint do
|
||||||
|
|
||||||
it_behaves_like 'invalid config'
|
it_behaves_like 'invalid config'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when running with include jobs' do
|
||||||
|
let(:include_jobs) { true }
|
||||||
|
|
||||||
|
it_behaves_like 'invalid config'
|
||||||
|
|
||||||
|
it 'returns jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when running without include jobs' do
|
||||||
|
let(:include_jobs) { false }
|
||||||
|
|
||||||
|
it_behaves_like 'invalid config'
|
||||||
|
|
||||||
|
it 'does not return jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).not_to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST /projects/:id/ci/lint' do
|
describe 'POST /projects/:id/ci/lint' do
|
||||||
subject(:ci_lint) { post api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, content: yaml_content } }
|
subject(:ci_lint) { post api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, content: yaml_content, include_jobs: include_jobs } }
|
||||||
|
|
||||||
let(:project) { create(:project, :repository) }
|
let(:project) { create(:project, :repository) }
|
||||||
let(:dry_run) { nil }
|
let(:dry_run) { nil }
|
||||||
|
let(:include_jobs) { nil }
|
||||||
|
|
||||||
let_it_be(:api_user) { create(:user) }
|
let_it_be(:api_user) { create(:user) }
|
||||||
|
|
||||||
|
|
@ -562,6 +633,30 @@ RSpec.describe API::Lint do
|
||||||
|
|
||||||
it_behaves_like 'valid project config'
|
it_behaves_like 'valid project config'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when running with include jobs param' do
|
||||||
|
let(:include_jobs) { true }
|
||||||
|
|
||||||
|
it_behaves_like 'valid project config'
|
||||||
|
|
||||||
|
it 'contains jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when running without include jobs param' do
|
||||||
|
let(:include_jobs) { false }
|
||||||
|
|
||||||
|
it_behaves_like 'valid project config'
|
||||||
|
|
||||||
|
it 'does not contain jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).not_to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with invalid .gitlab-ci.yml content' do
|
context 'with invalid .gitlab-ci.yml content' do
|
||||||
|
|
@ -580,6 +675,30 @@ RSpec.describe API::Lint do
|
||||||
|
|
||||||
it_behaves_like 'invalid project config'
|
it_behaves_like 'invalid project config'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when running with include jobs set to false' do
|
||||||
|
let(:include_jobs) { false }
|
||||||
|
|
||||||
|
it_behaves_like 'invalid project config'
|
||||||
|
|
||||||
|
it 'does not contain jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).not_to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when running with param include jobs' do
|
||||||
|
let(:include_jobs) { true }
|
||||||
|
|
||||||
|
it_behaves_like 'invalid project config'
|
||||||
|
|
||||||
|
it 'contains jobs key' do
|
||||||
|
ci_lint
|
||||||
|
|
||||||
|
expect(json_response).to have_key('jobs')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue