Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-03-31 12:08:55 +00:00
parent 2c6c1c4dce
commit ea1dcaef18
74 changed files with 809 additions and 645 deletions

View File

@ -182,8 +182,6 @@ Rails/SaveBang:
- 'spec/controllers/groups/runners_controller_spec.rb'
- 'spec/controllers/groups/uploads_controller_spec.rb'
- 'spec/controllers/groups_controller_spec.rb'
- 'spec/controllers/oauth/authorizations_controller_spec.rb'
- 'spec/controllers/omniauth_callbacks_controller_spec.rb'
- 'spec/controllers/profiles/emails_controller_spec.rb'
- 'spec/controllers/profiles/notifications_controller_spec.rb'
- 'spec/controllers/projects_controller_spec.rb'
@ -197,16 +195,10 @@ Rails/SaveBang:
- 'spec/features/admin/admin_sees_project_statistics_spec.rb'
- 'spec/features/admin/admin_sees_projects_statistics_spec.rb'
- 'spec/features/admin/admin_users_impersonation_tokens_spec.rb'
- 'spec/features/boards/sidebar_spec.rb'
- 'spec/features/calendar_spec.rb'
- 'spec/features/commits_spec.rb'
- 'spec/features/dashboard/datetime_on_tooltips_spec.rb'
- 'spec/features/dashboard/issuables_counter_spec.rb'
- 'spec/features/dashboard/project_member_activity_index_spec.rb'
- 'spec/features/dashboard/projects_spec.rb'
- 'spec/features/error_tracking/user_sees_error_index_spec.rb'
- 'spec/features/groups/members/request_access_spec.rb'
- 'spec/features/issuables/close_reopen_report_toggle_spec.rb'
- 'spec/features/issues/bulk_assignment_labels_spec.rb'
- 'spec/features/issues/gfm_autocomplete_spec.rb'
- 'spec/features/issues/issue_sidebar_spec.rb'
@ -217,9 +209,6 @@ Rails/SaveBang:
- 'spec/features/issues/user_filters_issues_spec.rb'
- 'spec/features/issues/user_sees_live_update_spec.rb'
- 'spec/features/issues/user_sorts_issues_spec.rb'
- 'spec/features/profiles/emails_spec.rb'
- 'spec/features/profiles/password_spec.rb'
- 'spec/features/profiles/personal_access_tokens_spec.rb'
- 'spec/features/projects/features_visibility_spec.rb'
- 'spec/features/projects/fork_spec.rb'
- 'spec/features/projects/jobs_spec.rb'
@ -236,12 +225,6 @@ Rails/SaveBang:
- 'spec/features/projects/wiki/user_updates_wiki_page_spec.rb'
- 'spec/features/projects/wiki/user_views_wiki_page_spec.rb'
- 'spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb'
- 'spec/features/runners_spec.rb'
- 'spec/features/security/project/internal_access_spec.rb'
- 'spec/features/security/project/private_access_spec.rb'
- 'spec/features/security/project/public_access_spec.rb'
- 'spec/features/users/login_spec.rb'
- 'spec/features/users/show_spec.rb'
- 'spec/frontend/fixtures/issues.rb'
- 'spec/frontend/fixtures/merge_requests.rb'
- 'spec/graphql/mutations/merge_requests/set_locked_spec.rb'
@ -369,9 +352,6 @@ Rails/SaveBang:
- 'spec/models/user_status_spec.rb'
- 'spec/models/wiki_page/meta_spec.rb'
- 'spec/models/wiki_page_spec.rb'
- 'spec/presenters/ci/build_runner_presenter_spec.rb'
- 'spec/presenters/ci/trigger_presenter_spec.rb'
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
- 'spec/requests/api/ci/runner_spec.rb'
- 'spec/requests/api/commit_statuses_spec.rb'
- 'spec/requests/api/conan_packages_spec.rb'

View File

@ -1 +1 @@
79003389aa5098a6ef37e73298cafbad4d9e6b79
67a362bf7aaab3aae021d19fda728c24b7723d7a

View File

@ -3,7 +3,7 @@ import IntegrationForm from '../components/integration_form.vue';
import { createStore } from '../stores';
export default () => {
const entryPoint = document.querySelector('#js-cluster-integration-form');
const entryPoint = document.querySelector('#js-cluster-details-form');
if (!entryPoint) {
return;

View File

@ -1,5 +1,6 @@
<script>
import { GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
/* eslint-disable vue/no-v-html */
import { GlTooltipDirective } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@ -21,7 +22,6 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
SafeHtml,
},
mixins: [glFeatureFlagsMixin()],
props: {
@ -256,7 +256,7 @@ export default {
@mousedown="handleParallelLineMouseDown"
>
<strong v-if="isLeftConflictMarker">{{ conflictText(line.left) }}</strong>
<span v-else v-safe-html="line.left.rich_text"></span>
<span v-else v-html="line.left.rich_text"></span>
</div>
</template>
<template v-else-if="!inline || (line.left && line.left.type === $options.CONFLICT_MARKER)">
@ -345,7 +345,6 @@ export default {
<div
:id="line.right.line_code"
:key="line.right.rich_text"
v-safe-html="line.right.rich_text"
:class="[
line.right.type,
{
@ -360,7 +359,7 @@ export default {
<strong v-if="line.right.type === $options.CONFLICT_MARKER_THEIR">{{
conflictText(line.right)
}}</strong>
<span v-else v-safe-html="line.right.rich_text"></span>
<span v-else v-html="line.right.rich_text"></span>
</div>
</template>
<template v-else>

View File

@ -77,15 +77,10 @@ export default {
},
[types.SET_DIFF_DATA_BATCH](state, data) {
const files = prepareDiffData({
state.diffFiles = prepareDiffData({
diff: data,
priorFiles: state.diffFiles,
});
Object.assign(state, {
...convertObjectPropsToCamelCase(data),
});
updateDiffFilesInState(state, files);
},
[types.SET_COVERAGE_DATA](state, coverageFiles) {

View File

@ -1,10 +1,12 @@
<script>
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlDropdownSectionHeader } from '@gitlab/ui';
import { debounce } from 'lodash';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
const emptyDropdownText = s__('CompareRevisions|Select branch/tag');
const EMPTY_DROPDOWN_TEXT = s__('CompareRevisions|Select branch/tag');
const SEARCH_DEBOUNCE_MS = 300;
export default {
components: {
@ -38,19 +40,11 @@ export default {
};
},
computed: {
filteredBranches() {
return this.branches.filter((branch) =>
branch.toLowerCase().includes(this.searchTerm.toLowerCase()),
);
hasBranches() {
return Boolean(this.branches?.length);
},
hasFilteredBranches() {
return this.filteredBranches.length;
},
filteredTags() {
return this.tags.filter((tag) => tag.toLowerCase().includes(this.searchTerm.toLowerCase()));
},
hasFilteredTags() {
return this.filteredTags.length;
hasTags() {
return Boolean(this.tags?.length);
},
},
watch: {
@ -59,13 +53,34 @@ export default {
this.fetchBranchesAndTags(true);
}
},
searchTerm: debounce(function debounceSearch() {
this.searchBranchesAndTags();
}, SEARCH_DEBOUNCE_MS),
},
mounted() {
this.fetchBranchesAndTags();
},
methods: {
searchBranchesAndTags() {
return axios
.get(this.refsProjectPath, {
params: {
search: this.searchTerm,
},
})
.then(({ data }) => {
this.branches = data.Branches || [];
this.tags = data.Tags || [];
})
.catch(() => {
createFlash({
message: s__(
'CompareRevisions|There was an error while searching the branch/tag list. Please try again.',
),
});
});
},
fetchBranchesAndTags(reset = false) {
const endpoint = this.refsProjectPath;
this.loading = true;
if (reset) {
@ -73,7 +88,7 @@ export default {
}
return axios
.get(endpoint)
.get(this.refsProjectPath)
.then(({ data }) => {
this.branches = data.Branches || [];
this.tags = data.Tags || [];
@ -90,7 +105,7 @@ export default {
});
},
getDefaultBranch() {
return this.paramsBranch || emptyDropdownText;
return this.paramsBranch || EMPTY_DROPDOWN_TEXT;
},
onClick(revision) {
this.selectedRevision = revision;
@ -119,24 +134,24 @@ export default {
@keyup.enter="onSearchEnter"
/>
</template>
<gl-dropdown-section-header v-if="hasFilteredBranches">
<gl-dropdown-section-header v-if="hasBranches">
{{ s__('CompareRevisions|Branches') }}
</gl-dropdown-section-header>
<gl-dropdown-item
v-for="(branch, index) in filteredBranches"
:key="`branch${index}`"
v-for="branch in branches"
:key="branch"
is-check-item
:is-checked="selectedRevision === branch"
@click="onClick(branch)"
>
{{ branch }}
</gl-dropdown-item>
<gl-dropdown-section-header v-if="hasFilteredTags">
<gl-dropdown-section-header v-if="hasTags">
{{ s__('CompareRevisions|Tags') }}
</gl-dropdown-section-header>
<gl-dropdown-item
v-for="(tag, index) in filteredTags"
:key="`tag${index}`"
v-for="tag in tags"
:key="tag"
is-check-item
:is-checked="selectedRevision === tag"
@click="onClick(tag)"

View File

@ -1,13 +1,11 @@
<script>
import { GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ApplySuggestion from './apply_suggestion.vue';
export default {
components: { GlIcon, GlButton, GlLoadingIcon, ApplySuggestion },
directives: { 'gl-tooltip': GlTooltipDirective },
mixins: [glFeatureFlagsMixin()],
props: {
batchSuggestionsCount: {
type: Number,
@ -59,9 +57,6 @@ export default {
};
},
computed: {
canBeBatched() {
return Boolean(this.glFeatures.batchSuggestions);
},
isApplying() {
return this.isApplyingSingle || this.isApplyingBatch;
},
@ -118,7 +113,7 @@ export default {
<gl-loading-icon class="d-flex-center mr-2" />
<span>{{ applyingSuggestionsMessage }}</span>
</div>
<div v-else-if="canApply && canBeBatched && isBatched" class="d-flex align-items-center">
<div v-else-if="canApply && isBatched" class="d-flex align-items-center">
<gl-button
class="btn-inverted js-remove-from-batch-btn btn-grouped"
:disabled="isApplying"
@ -142,7 +137,7 @@ export default {
</div>
<div v-else class="d-flex align-items-center">
<gl-button
v-if="suggestionsCount > 1 && canBeBatched && !isDisableButton"
v-if="suggestionsCount > 1 && !isDisableButton"
class="btn-inverted js-add-to-batch-btn btn-grouped"
data-qa-selector="add_suggestion_batch_button"
:disabled="isDisableButton"

View File

@ -5,8 +5,8 @@ module RunnerSetupScripts
private
def private_runner_setup_scripts(**kwargs)
instructions = Gitlab::Ci::RunnerInstructions.new(current_user: current_user, os: script_params[:os], arch: script_params[:arch], **kwargs)
def private_runner_setup_scripts
instructions = Gitlab::Ci::RunnerInstructions.new(os: script_params[:os], arch: script_params[:arch])
output = {
install: instructions.install_script,
register: instructions.register_command

View File

@ -52,7 +52,7 @@ module Groups
end
def runner_setup_scripts
private_runner_setup_scripts(group: group)
private_runner_setup_scripts
end
private

View File

@ -30,7 +30,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
before_action only: [:show] do
push_frontend_feature_flag(:file_identifier_hash)
push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true)
push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true)
push_frontend_feature_flag(:merge_request_widget_graphql, @project, default_enabled: :yaml)
push_frontend_feature_flag(:drag_comment_selection, @project, default_enabled: true)

View File

@ -62,7 +62,7 @@ module Projects
end
def runner_setup_scripts
private_runner_setup_scripts(project: @project)
private_runner_setup_scripts
end
private

View File

@ -21,19 +21,19 @@ module Resolvers
argument :project_id,
type: ::Types::GlobalIDType[::Project],
required: false,
deprecated: { reason: 'No longer used', milestone: '13.11' },
description: 'Project to register the runner for.'
argument :group_id,
type: ::Types::GlobalIDType[::Group],
required: false,
deprecated: { reason: 'No longer used', milestone: '13.11' },
description: 'Group to register the runner for.'
def resolve(platform:, architecture:, **args)
instructions = Gitlab::Ci::RunnerInstructions.new(
current_user: current_user,
os: platform,
arch: architecture,
**target_param(args)
arch: architecture
)
{

View File

@ -29,7 +29,6 @@ class JenkinsService < CiService
end
def execute(data)
return if project.disabled_services.include?(to_param)
return unless supported_events.include?(data[:object_kind])
service_hook.execute(data, "#{data[:object_kind]}_hook")

View File

@ -1,3 +1,3 @@
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-integration-form' } do |field|
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-details-form' } do |field|
= form_errors(@cluster)
#js-cluster-integration-form{ data: js_cluster_form_data(@cluster, can?(current_user, :update_cluster, @cluster)) }
#js-cluster-details-form{ data: js_cluster_form_data(@cluster, can?(current_user, :update_cluster, @cluster)) }

View File

@ -0,0 +1,5 @@
---
title: Fix issue where merge description not showing when merged with merge train
merge_request: 57787
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Remove batch_suggestions feature flag
merge_request: 57745
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Use search param in refs call to filter revisions
merge_request: 57442
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Remove groupId and projectId arguments to Runner install instructions
merge_request: 57720
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Fix Rails/SaveBang Rubocop offenses for presenters
merge_request: 57888
author: Huzaifa Iftikhar @huzaifaiftikhar
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix Rails/SaveBang rubocop offenses in auth controllers
merge_request: 57886
author: Abdul Wadood @abdulwd
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix Rails/SaveBang rubocop offenses in spec/features/
merge_request: 57907
author: Abdul Wadood @abdulwd
type: fixed

View File

@ -1,8 +0,0 @@
---
name: batch_suggestions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34782
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320755
milestone: '13.1'
type: development
group: group::code review
default_enabled: true

View File

@ -0,0 +1,8 @@
---
name: sentry_processors_before_send
introduced_by_url:
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/849#processors
milestone: '13.11'
type: development
group: team::Scalability
default_enabled: false

View File

@ -281,9 +281,9 @@ Returns [`RunnerSetup`](#runnersetup).
| Name | Type | Description |
| ---- | ---- | ----------- |
| `architecture` | [`String!`](#string) | Architecture to generate the instructions for. |
| `groupId` | [`GroupID`](#groupid) | Group to register the runner for. |
| `groupId` | [`GroupID`](#groupid) | Group to register the runner for. Deprecated in 13.11: No longer used. |
| `platform` | [`String!`](#string) | Platform to generate the instructions for. |
| `projectId` | [`ProjectID`](#projectid) | Project to register the runner for. |
| `projectId` | [`ProjectID`](#projectid) | Project to register the runner for. Deprecated in 13.11: No longer used. |
### `snippets`

View File

@ -6,14 +6,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Monthly release process
When a new GitLab version is released on the 22nd, we need to release the published documentation
for the new version.
When a new GitLab version is released on the 22nd, we release version-specific published
documentation for the new version.
This should be done as soon as possible after the GitLab version is announced, so that:
We complete the process as soon as possible after the GitLab version is announced. The result is:
- The published documentation includes the three most recent minor releases of the current major
version, and the most recent minor releases of the last two major versions. For example 13.9,
13.8, 13.7, 12.10, and 11.11.
- The [online published documentation](https://docs.gitlab.com) includes:
- The three most recent minor releases of the current major version. For example 13.9, 13.8, and
13.7.
- The most recent minor releases of the last two major versions. For example 12.10, and 11.11.
- Documentation updates after the 22nd are for the next release. The versions drop down
should have the current milestone with `-pre` appended to it, for example `13.10-pre`.
@ -31,23 +32,30 @@ For example:
[stable branch](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/13.8) and Docker image:
[`registry.gitlab.com/gitlab-org/gitlab-docs:13.8`](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635).
To set up a documentation release, follow these steps:
## Recommended timeline
1. [Add the charts version](#add-chart-version), so that the documentation is built using the
[version of the charts project that maps to](https://docs.gitlab.com/charts/installation/version_mappings.html)
the GitLab release. This step may have been completed already.
1. [Create a stable branch and Docker image](#create-stable-branch-and-docker-image-for-release) for
the new version.
1. [Create a release merge request](#create-release-merge-request) for the new version, which
updates the version dropdown menu for the current documentation and adds the release to the
Docker configuration. For example, the
[release merge request for 13.9](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1555).
1. [Update the three online versions](#update-dropdown-for-online-versions), so that they display the new release on their
version dropdown menus. For example:
- The merge request to [update the 13.9 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1556).
- The merge request to [update the 13.8 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1557).
- The merge request to [update the 13.7 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1558).
1. [Merge the release merge request and run the necessary Docker image builds](#merge-release-merge-request-and-run-docker-image-builds).
To minimize problems during the documentation release process, use the following timeline:
- Before the 20nd of the month:
[Add the charts version](#add-chart-version), so that the documentation is built using the
[version of the charts project that maps to](https://docs.gitlab.com/charts/installation/version_mappings.html)
the GitLab release. This step may have been completed already.
- On or near the 20th of the month:
1. [Create a stable branch and Docker image](#create-stable-branch-and-docker-image-for-release) for
the new version.
1. [Create a release merge request](#create-release-merge-request) for the new version, which
updates the version dropdown menu for the current documentation and adds the release to the
Docker configuration. For example, the
[release merge request for 13.9](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1555).
1. [Update the three online versions](#update-dropdown-for-online-versions), so that they display the new release on their
version dropdown menus.
- On the 22nd of the month:
[Merge the release merge requests and run the necessary Docker image builds](#merge-merge-requests-and-run-docker-image-builds).
## Add chart version
@ -135,8 +143,12 @@ Do not merge the release merge request yet.
## Update dropdown for online versions
To update`content/_data/versions.yaml` for all online versions (stable branches `X.Y` of the
`gitlab-docs` project):
To update `content/_data/versions.yaml` for all online versions (stable branches `X.Y` of the
`gitlab-docs` project). For example:
- The merge request to [update the 13.9 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1556).
- The merge request to [update the 13.8 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1557).
- The merge request to [update the 13.7 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1558).
1. Run the Rake task that creates all of the necessary merge requests to update the dropdowns. For
example, for the 13.9 release:
@ -146,13 +158,12 @@ To update`content/_data/versions.yaml` for all online versions (stable branches
./bin/rake release:dropdowns
```
These merge requests are set to automatically merge.
1. [Visit the merge requests page](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests?label_name%5B%5D=release)
to check that their pipelines pass. After all MRs are merged, proceed to the following and final
step.
to check that their pipelines pass.
## Merge release merge request and run Docker image builds
Do not merge these merge requests yet.
## Merge merge requests and run Docker image builds
The merge requests for the dropdowns should now all be merged into their respective stable branches.
Each merge triggers a new pipeline for each stable branch. Wait for the stable branch pipelines to
@ -160,7 +171,9 @@ complete, then:
1. Check the [pipelines page](https://gitlab.com/gitlab-org/gitlab-docs/pipelines)
and make sure all stable branches have green pipelines.
1. After all the pipelines succeed, merge the [release merge request](#create-release-merge-request).
1. After all the pipelines succeed:
1. Merge all of the [dropdown merge requests](#update-dropdown-for-online-versions).
1. Merge the [release merge request](#create-release-merge-request).
1. Finally, run the
[`Build docker images weekly` pipeline](https://gitlab.com/gitlab-org/gitlab-docs/pipeline_schedules)
that builds the `:latest` and `:archives` Docker images.

View File

@ -625,7 +625,7 @@ This also applies when using links in between translated sentences, otherwise th
```haml
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- zones_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: zones_link_url }
= s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}').html_safe % { zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe }
= html_escape(s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}')) % { zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe }
```
- In Vue, instead of:

View File

@ -10124,6 +10124,54 @@ Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_due_date_monthly`
Counts of MAU manually updating fixed due date
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210329043548_g_project_management_users_updating_fixed_epic_due_date_monthly.yml)
Group: `group::product planning`
Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_due_date_weekly`
Counts of WAU manually updating fixed due date
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210329042536_g_project_management_users_updating_fixed_epic_due_date_weekly.yml)
Group: `group::product planning`
Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_start_date_monthly`
Counts of MAU manually updating fixed start date
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210329043509_g_project_management_users_updating_fixed_epic_start_date_monthly.yml)
Group: `group::product planning`
Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_start_date_weekly`
Counts of WAU manually updating fixed start date
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210329043402_g_project_management_users_updating_fixed_epic_start_date_weekly.yml)
Group: `group::product planning`
Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.ide_edit.g_edit_by_sfe_monthly`
Missing description

View File

@ -486,11 +486,9 @@ introduced by [#25381](https://gitlab.com/gitlab-org/gitlab/-/issues/25381).
### Batch Suggestions
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
> - Deployed behind a feature flag, disabled by default.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha) behind a feature flag, disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/227799) in GitLab 13.2.
> - Enabled on GitLab.com.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-batch-suggestions).
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/320755) in GitLab 13.11.
You can apply multiple suggestions at once to reduce the number of commits added
to your branch to address your reviewers' requests.
@ -540,7 +538,7 @@ You can assign an issue to a user who made a comment.
In the comment, click the **More Actions** menu and click **Assign to commenting user**.
Click the button again to unassign the commenter.
Click the button again to unassign the commenter.
![Assign to commenting user](img/quickly_assign_commenter_v13_1.png)
@ -562,24 +560,3 @@ To disable it:
```ruby
Feature.disable(:confidential_notes)
```
## Enable or disable Batch Suggestions **(FREE SELF)**
Batch Suggestions is
deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
can opt to disable it for your instance.
To enable it:
```ruby
# Instance-wide
Feature.enable(:batch_suggestions)
```
To disable it:
```ruby
# Instance-wide
Feature.disable(:batch_suggestions)
```

View File

@ -18,38 +18,39 @@ and is automatically configured on [GitHub import](../../../integration/github.m
## Configuration
### Complete these steps on GitHub
This integration requires a [GitHub API token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
with `repo:status` access granted:
with `repo:status` access granted.
1. Go to your "Personal access tokens" page at <https://github.com/settings/tokens>
1. Click "Generate New Token"
1. Ensure that `repo:status` is checked and click "Generate token"
1. Copy the generated token to use on GitLab
Complete these steps on GitHub:
### Complete these steps on GitLab
1. Go to your **Personal access tokens** page at <https://github.com/settings/tokens>.
1. Select **Generate new token**.
1. Under **Note**, enter a name for the new token.
1. Ensure that `repo:status` is checked and select **Generate token**.
1. Copy the generated token to use in GitLab.
1. Navigate to the project you want to configure.
1. Navigate to the [Integrations page](overview.md#accessing-integrations)
1. Click "GitHub".
Complete these steps in GitLab:
1. Go to the project you want to configure.
1. Go to the [Integrations page](overview.md#accessing-integrations)
1. Select **GitHub**.
1. Ensure that the **Active** toggle is enabled.
1. Paste the token you've generated on GitHub
1. Enter the path to your project on GitHub, such as `https://github.com/username/repository`
1. Optionally uncheck **Static status check names** checkbox to disable static status check names.
1. Save or optionally click "Test Settings".
1. Paste the token you generated on GitHub.
1. Enter the path to your project on GitHub, such as `https://github.com/username/repository`.
1. (Optional) To disable static status check names, clear the **Static status check names** checkbox.
1. Select **Save changes** or optionally select **Test settings**.
Once the integration is configured, see [Pipelines for external pull requests](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests)
After configuring the integration, see [Pipelines for external pull requests](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests)
to configure pipelines to run for open pull requests.
#### Static / dynamic status check names
### Static / dynamic status check names
> - Introduced in GitLab 11.5: using static status check names as opt-in option.
> - [In GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/9931), static status check names is default behavior for new projects.
This makes it possible to mark these status checks as _Required_ on GitHub.
With **Static status check names** enabled on the integration page, your
GitLab instance host name is appended to a status check name,
whereas in case of dynamic status check names, a branch name is appended.
This makes it possible to mark these status checks as **Required** on GitHub.
![Configure GitHub Project Integration](img/github_configuration.png)
When **Static status check names** is enabled on the integration page, your
GitLab instance host name is appended to a status check name.
When disabled, it uses dynamic status check names and appends the branch name.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -127,7 +127,7 @@ module API
# as `:tags` are defined as: `has_many :tags, through: :taggings`
# N+1 is solved then by using `subject.tags.map(&:name)`
# MR describing the solution: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/20555
super(projects_relation).preload(:group)
super(projects_relation).preload(group: :namespace_settings)
.preload(:ci_cd_settings)
.preload(:project_setting)
.preload(:container_expiration_policy)

View File

@ -13,7 +13,7 @@ module API
helpers do
def authenticate_gitlab_kas_request!
unauthorized! unless Gitlab::Kas.verify_api_request(headers)
render_api_error!('KAS JWT authentication invalid', 401) unless Gitlab::Kas.verify_api_request(headers)
end
def agent_token
@ -51,7 +51,7 @@ module API
end
def check_agent_token
forbidden! unless agent_token
unauthorized! unless agent_token
forbidden! unless Gitlab::Kas.included_in_gitlab_com_rollout?(agent.project)

View File

@ -51,10 +51,7 @@ module Gitlab
attr_reader :errors
def initialize(current_user:, group: nil, project: nil, os:, arch:)
@current_user = current_user
@group = group
@project = project
def initialize(os:, arch:)
@os = os
@arch = arch
@errors = []
@ -77,7 +74,7 @@ module Gitlab
server_url = Gitlab::Routing.url_helpers.root_url(only_path: false)
runner_executable = environment[:runner_executable]
"#{runner_executable} register --url #{server_url} --registration-token #{registration_token}"
"#{runner_executable} register --url #{server_url} --registration-token $REGISTRATION_TOKEN"
end
end
@ -108,30 +105,6 @@ module Gitlab
def get_file(path)
File.read(Rails.root.join(path).to_s)
end
def registration_token
project_token || group_token || instance_token
end
def project_token
return unless @project
raise Gitlab::Access::AccessDeniedError unless can?(@current_user, :admin_pipeline, @project)
'$REGISTRATION_TOKEN'
end
def group_token
return unless @group
raise Gitlab::Access::AccessDeniedError unless can?(@current_user, :admin_group, @group)
'$REGISTRATION_TOKEN'
end
def instance_token
raise Gitlab::Access::AccessDeniedError unless @current_user&.admin?
'$REGISTRATION_TOKEN'
end
end
end
end

View File

@ -16,6 +16,12 @@ module Gitlab
Rack::Timeout::RequestTimeoutException
].freeze
PROCESSORS = [
::Gitlab::ErrorTracking::Processor::SidekiqProcessor,
::Gitlab::ErrorTracking::Processor::GrpcErrorProcessor,
::Gitlab::ErrorTracking::Processor::ContextPayloadProcessor
].freeze
class << self
def configure
Raven.configure do |config|
@ -97,7 +103,9 @@ module Gitlab
inject_context_for_exception(event, hint[:exception])
custom_fingerprinting(event, hint[:exception])
event
PROCESSORS.reduce(event) do |processed_event, processor|
processor.call(processed_event)
end
end
def process_exception(exception, sentry: false, logging: true, extra:)

View File

@ -9,9 +9,21 @@ module Gitlab
# integrations are re-implemented and use Gitlab::ErrorTracking, this
# processor should be removed.
def process(payload)
return payload if ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
context_payload = Gitlab::ErrorTracking::ContextPayloadGenerator.generate(nil, {})
payload.deep_merge!(context_payload)
end
def self.call(event)
return event unless ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
Gitlab::ErrorTracking::ContextPayloadGenerator.generate(nil, {}).each do |key, value|
event.public_send(key).deep_merge!(value) # rubocop:disable GitlabSecurity/PublicSend
end
event
end
end
end
end

View File

@ -6,60 +6,126 @@ module Gitlab
class GrpcErrorProcessor < ::Raven::Processor
DEBUG_ERROR_STRING_REGEX = RE2('(.*) debug_error_string:(.*)')
def process(value)
process_first_exception_value(value)
process_custom_fingerprint(value)
def process(payload)
return payload if ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
value
self.class.process_first_exception_value(payload)
self.class.process_custom_fingerprint(payload)
payload
end
# Sentry can report multiple exceptions in an event. Sanitize
# only the first one since that's what is used for grouping.
def process_first_exception_value(value)
exceptions = value.dig(:exception, :values)
class << self
def call(event)
return event unless ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
return unless exceptions.is_a?(Array)
process_first_exception_value(event)
process_custom_fingerprint(event)
entry = exceptions.first
event
end
return unless entry.is_a?(Hash)
# Sentry can report multiple exceptions in an event. Sanitize
# only the first one since that's what is used for grouping.
def process_first_exception_value(event_or_payload)
exceptions = exceptions(event_or_payload)
exception_type = entry[:type]
raw_message = entry[:value]
return unless exceptions.is_a?(Array)
return unless exception_type&.start_with?('GRPC::')
return unless raw_message.present?
exception = exceptions.first
message, debug_str = split_debug_error_string(raw_message)
return unless valid_exception?(exception)
entry[:value] = message if message
extra = value[:extra] || {}
extra[:grpc_debug_error_string] = debug_str if debug_str
end
exception_type, raw_message = type_and_value(exception)
def process_custom_fingerprint(value)
fingerprint = value[:fingerprint]
return unless exception_type&.start_with?('GRPC::')
return unless raw_message.present?
return value unless custom_grpc_fingerprint?(fingerprint)
message, debug_str = split_debug_error_string(raw_message)
message, _ = split_debug_error_string(fingerprint[1])
fingerprint[1] = message if message
end
set_new_values!(event_or_payload, exception, message, debug_str)
end
private
def process_custom_fingerprint(event)
fingerprint = fingerprint(event)
def custom_grpc_fingerprint?(fingerprint)
fingerprint.is_a?(Array) && fingerprint.length == 2 && fingerprint[0].start_with?('GRPC::')
end
return event unless custom_grpc_fingerprint?(fingerprint)
def split_debug_error_string(message)
return unless message
message, _ = split_debug_error_string(fingerprint[1])
fingerprint[1] = message if message
end
match = DEBUG_ERROR_STRING_REGEX.match(message)
private
return unless match
def custom_grpc_fingerprint?(fingerprint)
fingerprint.is_a?(Array) && fingerprint.length == 2 && fingerprint[0].start_with?('GRPC::')
end
[match[1], match[2]]
def split_debug_error_string(message)
return unless message
match = DEBUG_ERROR_STRING_REGEX.match(message)
return unless match
[match[1], match[2]]
end
# The below methods can be removed once we remove the
# sentry_processors_before_send feature flag, and we can
# assume we always have an Event object
def exceptions(event_or_payload)
case event_or_payload
when Raven::Event
# Better in new version, will be event_or_payload.exception.values
event_or_payload.instance_variable_get(:@interfaces)[:exception]&.values
when Hash
event_or_payload.dig(:exception, :values)
end
end
def valid_exception?(exception)
case exception
when Raven::SingleExceptionInterface
exception&.value
when Hash
true
else
false
end
end
def type_and_value(exception)
case exception
when Raven::SingleExceptionInterface
[exception.type, exception.value]
when Hash
exception.values_at(:type, :value)
end
end
def set_new_values!(event_or_payload, exception, message, debug_str)
case event_or_payload
when Raven::Event
# Worse in new version, no setter! Have to poke at the
# instance variable
exception.value = message if message
event_or_payload.extra[:grpc_debug_error_string] = debug_str if debug_str
when Hash
exception[:value] = message if message
extra = event_or_payload[:extra] || {}
extra[:grpc_debug_error_string] = debug_str if debug_str
end
end
def fingerprint(event_or_payload)
case event_or_payload
when Raven::Event
event_or_payload.fingerprint
when Hash
event_or_payload[:fingerprint]
end
end
end
end
end

View File

@ -8,39 +8,66 @@ module Gitlab
class SidekiqProcessor < ::Raven::Processor
FILTERED_STRING = '[FILTERED]'
def self.filter_arguments(args, klass)
args.lazy.with_index.map do |arg, i|
case arg
when Numeric
arg
else
if permitted_arguments_for_worker(klass).include?(i)
class << self
def filter_arguments(args, klass)
args.lazy.with_index.map do |arg, i|
case arg
when Numeric
arg
else
FILTERED_STRING
if permitted_arguments_for_worker(klass).include?(i)
arg
else
FILTERED_STRING
end
end
end
end
end
def self.permitted_arguments_for_worker(klass)
@permitted_arguments_for_worker ||= {}
@permitted_arguments_for_worker[klass] ||=
begin
klass.constantize&.loggable_arguments&.to_set
rescue
Set.new
def permitted_arguments_for_worker(klass)
@permitted_arguments_for_worker ||= {}
@permitted_arguments_for_worker[klass] ||=
begin
klass.constantize&.loggable_arguments&.to_set
rescue
Set.new
end
end
def loggable_arguments(args, klass)
Gitlab::Utils::LogLimitedArray
.log_limited_array(filter_arguments(args, klass))
.map(&:to_s)
.to_a
end
def call(event)
return event unless ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
sidekiq = event&.extra&.dig(:sidekiq)
return event unless sidekiq
sidekiq = sidekiq.deep_dup
sidekiq.delete(:jobstr)
# 'args' in this hash => from Gitlab::ErrorTracking.track_*
# 'args' in :job => from default error handler
job_holder = sidekiq.key?('args') ? sidekiq : sidekiq[:job]
if job_holder['args']
job_holder['args'] = filter_arguments(job_holder['args'], job_holder['class']).to_a
end
end
def self.loggable_arguments(args, klass)
Gitlab::Utils::LogLimitedArray
.log_limited_array(filter_arguments(args, klass))
.map(&:to_s)
.to_a
event.extra[:sidekiq] = sidekiq
event
end
end
def process(value, key = nil)
return value if ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
sidekiq = value.dig(:extra, :sidekiq)
return value unless sidekiq

View File

@ -21,6 +21,8 @@
aggregation: daily
feature_flag: track_epics_activity
# epic notes
- name: g_project_management_users_creating_epic_notes
category: epics_usage
redis_slot: project_management
@ -39,24 +41,40 @@
aggregation: daily
feature_flag: track_epics_activity
# start date events
- name: g_project_management_users_setting_epic_start_date_as_fixed
category: epics_usage
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
- name: g_project_management_users_updating_fixed_epic_start_date
category: epics_usage
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
- name: g_project_management_users_setting_epic_start_date_as_inherited
category: epics_usage
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
# due date events
- name: g_project_management_users_setting_epic_due_date_as_fixed
category: epics_usage
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
- name: g_project_management_users_updating_fixed_epic_due_date
category: epics_usage
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
- name: g_project_management_users_setting_epic_due_date_as_inherited
category: epics_usage
redis_slot: project_management

View File

@ -7832,6 +7832,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
msgstr ""
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@ -14447,6 +14450,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
msgstr ""
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
msgid "GithubIntegration|Repository URL"
msgstr ""
msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
msgstr ""
msgid "GithubIntegration|Static status check names (optional)"
msgstr ""
msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
msgstr ""
msgid "Gitlab Pages"
msgstr ""
@ -16706,9 +16727,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
msgstr ""
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@ -34336,6 +34354,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
msgid "What is repository mirroring?"
msgstr ""
msgid "What is squashing?"
msgstr ""

View File

@ -136,11 +136,9 @@ postgresql:
metrics:
enabled: false
resources:
requests:
cpu: 550m
cpu: 600m
memory: 1000M
limits:
cpu: 825m
cpu: 1300m
memory: 1500M
prometheus:
install: false

View File

@ -54,7 +54,7 @@ RSpec.describe Oauth::AuthorizationsController do
shared_examples "Implicit grant can't be used in confidential application" do
context 'when application is confidential' do
before do
application.update(confidential: true)
application.update!(confidential: true)
params[:response_type] = 'token'
end
@ -96,7 +96,7 @@ RSpec.describe Oauth::AuthorizationsController do
end
it 'deletes session.user_return_to and redirects when skip authorization' do
application.update(trusted: true)
application.update!(trusted: true)
request.session['user_return_to'] = 'http://example.com'
subject

View File

@ -60,7 +60,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
let(:extern_uid) { 'my-uid' }
before do
user.update(failed_attempts: User.maximum_attempts.pred)
user.update!(failed_attempts: User.maximum_attempts.pred)
subject.response = ActionDispatch::Response.new
end
@ -233,7 +233,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
settings = Gitlab::CurrentSettings.current_application_settings
settings.update(disabled_oauth_sign_in_sources: [provider.to_s])
settings.update!(disabled_oauth_sign_in_sources: [provider.to_s])
end
it 'prevents login via POST' do
@ -299,7 +299,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
before do
stub_omniauth_setting(enabled: true, auto_link_user: true, allow_single_sign_on: ['atlassian_oauth2'])
user.destroy
user.destroy!
end
it 'denies sign-in if sign-up is enabled, but block_auto_created_users is set' do
@ -381,7 +381,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
context 'sign up' do
before do
user.destroy
user.destroy!
end
it 'denies login if sign up is enabled, but block_auto_created_users is set' do

View File

@ -64,7 +64,7 @@ RSpec.describe 'Contributions Calendar', :js do
author_id: user.id
}
Event.create(note_comment_params)
Event.create!(note_comment_params)
end
def selected_day_activities(visible: true)

View File

@ -23,7 +23,7 @@ RSpec.describe 'Clusterable > Show page' do
it 'allow the user to set domain', :js do
visit cluster_path
within '.js-cluster-integration-form' do
within '.js-cluster-details-form' do
fill_in('cluster_base_domain', with: 'test.com')
click_on 'Save changes'
end
@ -39,7 +39,7 @@ RSpec.describe 'Clusterable > Show page' do
end
it 'shows help text with the domain as an alternative to custom domain', :js do
within '.js-cluster-integration-form' do
within '.js-cluster-details-form' do
expect(find(cluster_ingress_help_text_selector).text).to include('192.168.1.100')
end
end
@ -49,7 +49,7 @@ RSpec.describe 'Clusterable > Show page' do
it 'alternative to custom domain is not shown' do
visit cluster_path
within '.js-cluster-integration-form' do
within '.js-cluster-details-form' do
expect(page).not_to have_selector(cluster_ingress_help_text_selector)
end
end

View File

@ -140,7 +140,7 @@ RSpec.describe 'Commits' do
context 'when accessing internal project with disallowed access', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/299575' do
before do
project.update(
project.update!(
visibility_level: Gitlab::VisibilityLevel::INTERNAL,
public_builds: false)
create(:ci_job_artifact, :archive, file: artifacts_file, job: build)

View File

@ -41,7 +41,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
context 'with error tracking settings disabled' do
before do
project_error_tracking_settings.update(enabled: false)
project_error_tracking_settings.update!(enabled: false)
sign_in(project.owner)
visit project_error_tracking_index_path(project)

View File

@ -97,7 +97,7 @@ RSpec.describe 'User Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
page.within('.js-cluster-integration-form') { click_button 'Save changes' }
page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do

View File

@ -15,7 +15,7 @@ RSpec.describe 'Groups > Members > Request access' do
end
it 'request access feature is disabled' do
group.update(request_access_enabled: false)
group.update!(request_access_enabled: false)
visit group_path(group)
expect(page).not_to have_content 'Request Access'

View File

@ -43,7 +43,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user removes email' do
user.emails.create(email: 'my@email.com')
user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect(page).to have_content("my@email.com")
@ -52,7 +52,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user confirms email' do
email = user.emails.create(email: 'my@email.com')
email = user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect(page).to have_content("#{email.email} Unverified")
@ -64,7 +64,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user re-sends confirmation email' do
email = user.emails.create(email: 'my@email.com')
email = user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect { click_link("Resend confirmation email") }.to have_enqueued_job.on_queue('mailers')
@ -72,7 +72,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'old unconfirmed emails show Send Confirmation button' do
email = user.emails.create(email: 'my@email.com')
email = user.emails.create!(email: 'my@email.com')
email.update_attribute(:confirmation_sent_at, nil)
visit profile_emails_path

View File

@ -119,7 +119,7 @@ RSpec.describe 'Profile > Password' do
before do
sign_in(user)
user.update(password_expires_at: 1.hour.ago)
user.update!(password_expires_at: 1.hour.ago)
user.identities.delete
expect(user.ldap_user?).to eq false
end

View File

@ -95,7 +95,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
end
it "removes expired tokens from 'active' section" do
personal_access_token.update(expires_at: 5.days.ago)
personal_access_token.update!(expires_at: 5.days.ago)
visit profile_personal_access_tokens_path
expect(page).to have_selector(".settings-message")

View File

@ -119,7 +119,7 @@ RSpec.describe 'Gcp Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
page.within('.js-cluster-integration-form') { click_button 'Save changes' }
page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do

View File

@ -84,7 +84,7 @@ RSpec.describe 'User Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
page.within('.js-cluster-integration-form') { click_button 'Save changes' }
page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do

View File

@ -58,7 +58,7 @@ RSpec.describe 'Clusters', :js do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
within '.js-cluster-integration-form' do
within '.js-cluster-details-form' do
click_button 'Save changes'
end
end
@ -149,7 +149,7 @@ RSpec.describe 'Clusters', :js do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
within ".js-cluster-integration-form" do
within ".js-cluster-details-form" do
click_button 'Save changes'
end
end

View File

@ -92,7 +92,7 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
specific_runner.update(tag_list: ['tag'])
specific_runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
@ -370,7 +370,7 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
runner.update(tag_list: ['tag'])
runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
@ -450,7 +450,7 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
runner.update(tag_list: ['tag'])
runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do

View File

@ -356,7 +356,7 @@ RSpec.describe "Internal Project Access" do
context "when allowed for public and internal" do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@ -372,7 +372,7 @@ RSpec.describe "Internal Project Access" do
context "when disallowed for public and internal" do
before do
project.update(public_builds: false)
project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@ -396,7 +396,7 @@ RSpec.describe "Internal Project Access" do
context "when allowed for public and internal" do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@ -412,7 +412,7 @@ RSpec.describe "Internal Project Access" do
context "when disallowed for public and internal" do
before do
project.update(public_builds: false)
project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@ -436,7 +436,7 @@ RSpec.describe "Internal Project Access" do
context 'when allowed for public and internal' do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@ -452,7 +452,7 @@ RSpec.describe "Internal Project Access" do
context 'when disallowed for public and internal' do
before do
project.update(public_builds: false)
project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }

View File

@ -319,7 +319,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@ -348,7 +348,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@ -375,7 +375,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@ -405,7 +405,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@ -414,7 +414,7 @@ RSpec.describe "Private Project Access" do
context 'when public buils are disabled' do
before do
project.public_builds = false
project.save
project.save!
end
it { is_expected.to be_denied_for(:guest).of(project) }
@ -440,7 +440,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@ -448,7 +448,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is disabled' do
before do
project.update(public_builds: false)
project.update!(public_builds: false)
end
it { is_expected.to be_denied_for(:guest).of(project) }

View File

@ -164,7 +164,7 @@ RSpec.describe "Public Project Access" do
context "when allowed for public" do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@ -180,7 +180,7 @@ RSpec.describe "Public Project Access" do
context "when disallowed for public" do
before do
project.update(public_builds: false)
project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@ -204,7 +204,7 @@ RSpec.describe "Public Project Access" do
context "when allowed for public" do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@ -220,7 +220,7 @@ RSpec.describe "Public Project Access" do
context "when disallowed for public" do
before do
project.update(public_builds: false)
project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@ -244,7 +244,7 @@ RSpec.describe "Public Project Access" do
context 'when allowed for public' do
before do
project.update(public_builds: true)
project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@ -260,7 +260,7 @@ RSpec.describe "Public Project Access" do
context 'when disallowed for public' do
before do
project.update(public_builds: false)
project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }

View File

@ -239,7 +239,7 @@ RSpec.describe 'Login' do
expect(codes.size).to eq 10
# Ensure the generated codes get saved
user.save(touch: false)
user.save!(touch: false)
end
context 'with valid code' do

View File

@ -33,7 +33,7 @@ RSpec.describe 'User page' do
context 'work information' do
it 'shows job title and organization details' do
user.update(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
user.update!(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
subject
@ -41,7 +41,7 @@ RSpec.describe 'User page' do
end
it 'shows job title' do
user.update(organization: nil, job_title: 'Frontend Engineer - work info test')
user.update!(organization: nil, job_title: 'Frontend Engineer - work info test')
subject
@ -49,7 +49,7 @@ RSpec.describe 'User page' do
end
it 'shows organization details' do
user.update(organization: 'GitLab - work info test', job_title: '')
user.update!(organization: 'GitLab - work info test', job_title: '')
subject

View File

@ -1,4 +1,4 @@
import { GlDropdown } from '@gitlab/ui';
import { GlDropdown, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import createFlash from '~/flash';
@ -23,6 +23,10 @@ describe('RevisionDropdown component', () => {
...defaultProps,
...props,
},
stubs: {
GlDropdown,
GlSearchBoxByType,
},
});
};
@ -36,6 +40,7 @@ describe('RevisionDropdown component', () => {
});
const findGlDropdown = () => wrapper.find(GlDropdown);
const findSearchBox = () => wrapper.find(GlSearchBoxByType);
it('sets hidden input', () => {
createComponent();
@ -85,6 +90,40 @@ describe('RevisionDropdown component', () => {
expect(axios.get).toHaveBeenLastCalledWith(newRefsProjectPath);
});
describe('search', () => {
it('shows flash message on error', async () => {
axiosMock.onGet('some/invalid/path').replyOnce(404);
createComponent();
await wrapper.vm.searchBranchesAndTags();
expect(createFlash).toHaveBeenCalled();
});
it('makes request with search param', async () => {
jest.spyOn(axios, 'get').mockResolvedValue({
data: {
Branches: [],
Tags: [],
},
});
const mockSearchTerm = 'foobar';
createComponent();
findSearchBox().vm.$emit('input', mockSearchTerm);
await axios.waitForAll();
expect(axios.get).toHaveBeenCalledWith(
defaultProps.refsProjectPath,
expect.objectContaining({
params: {
search: mockSearchTerm,
},
}),
);
});
});
describe('GlDropdown component', () => {
it('renders props', () => {
createComponent();

View File

@ -16,18 +16,12 @@ const DEFAULT_PROPS = {
describe('Suggestion Diff component', () => {
let wrapper;
const createComponent = (props, glFeatures = {}) => {
const createComponent = (props) => {
wrapper = shallowMount(SuggestionDiffHeader, {
propsData: {
...DEFAULT_PROPS,
...props,
},
provide: {
glFeatures: {
batchSuggestions: true,
...glFeatures,
},
},
});
};
@ -211,18 +205,6 @@ describe('Suggestion Diff component', () => {
});
});
describe('batchSuggestions feature flag is set to false', () => {
beforeEach(() => {
createComponent({}, { batchSuggestions: false });
});
it('disables add to batch buttons but keeps apply suggestion enabled', () => {
expect(findApplyButton().exists()).toBe(true);
expect(findAddToBatchButton().exists()).toBe(false);
expect(findApplyButton().attributes('disabled')).not.toBe('true');
});
});
describe('canApply is set to false', () => {
beforeEach(() => {
createComponent({ canApply: false });

View File

@ -8,12 +8,11 @@ RSpec.describe Resolvers::Ci::RunnerSetupResolver do
describe '#resolve' do
let(:user) { create(:user) }
subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, args: { platform: platform, architecture: 'amd64' }.merge(target_param)) }
subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, args: { platform: platform, architecture: 'amd64' }) }
context 'with container platforms' do
let(:platform) { 'docker' }
let(:project) { create(:project) }
let(:target_param) { { project_id: project.to_global_id } }
it 'returns install instructions' do
expect(resolve_subject[:install_instructions]).not_to eq(nil)
@ -27,77 +26,9 @@ RSpec.describe Resolvers::Ci::RunnerSetupResolver do
context 'with regular platforms' do
let(:platform) { 'linux' }
context 'without target parameter' do
let(:target_param) { {} }
context 'when user is not admin' do
it 'returns access error' do
expect { resolve_subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when user is admin' do
before do
user.update!(admin: true)
end
it 'returns install and register instructions' do
expect(resolve_subject.keys).to contain_exactly(:install_instructions, :register_instructions)
expect(resolve_subject.values).not_to include(nil)
end
end
end
context 'with project target parameter' do
let(:project) { create(:project) }
let(:target_param) { { project_id: project.to_global_id } }
context 'when user has access to admin builds on project' do
before do
project.add_maintainer(user)
end
it 'returns install and register instructions' do
expect(resolve_subject.keys).to contain_exactly(:install_instructions, :register_instructions)
expect(resolve_subject.values).not_to include(nil)
end
end
context 'when user does not have access to admin builds on project' do
before do
project.add_developer(user)
end
it 'returns access error' do
expect { resolve_subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
context 'with group target parameter' do
let(:group) { create(:group) }
let(:target_param) { { group_id: group.to_global_id } }
context 'when user has access to admin builds on group' do
before do
group.add_owner(user)
end
it 'returns install and register instructions' do
expect(resolve_subject.keys).to contain_exactly(:install_instructions, :register_instructions)
expect(resolve_subject.values).not_to include(nil)
end
end
context 'when user does not have access to admin builds on group' do
before do
group.add_developer(user)
end
it 'returns access error' do
expect { resolve_subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
it 'returns install and register instructions' do
expect(resolve_subject.keys).to contain_exactly(:install_instructions, :register_instructions)
expect(resolve_subject.values).not_to include(nil)
end
end
end

View File

@ -6,7 +6,6 @@ RSpec.describe Gitlab::Ci::RunnerInstructions do
using RSpec::Parameterized::TableSyntax
let(:params) { {} }
let(:user) { create(:user) }
describe 'OS' do
Gitlab::Ci::RunnerInstructions::OS.each do |name, subject|
@ -37,7 +36,7 @@ RSpec.describe Gitlab::Ci::RunnerInstructions do
end
describe '#install_script' do
subject { described_class.new(current_user: user, **params) }
subject { described_class.new(**params) }
context 'invalid params' do
where(:current_params, :expected_error_message) do
@ -106,117 +105,18 @@ RSpec.describe Gitlab::Ci::RunnerInstructions do
end
end
context 'group' do
let(:group) { create(:group) }
subject { described_class.new(current_user: user, group: group, **params) }
context 'user is owner' do
before do
group.add_owner(user)
end
with_them do
let(:params) { { os: commands.each_key.first, arch: 'foo' } }
it 'have correct configurations' do
result = subject.register_command
expect(result).to include("#{commands[commands.each_key.first]} register")
expect(result).to include("--registration-token $REGISTRATION_TOKEN")
expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
end
end
end
context 'user is not owner' do
where(:user_permission) do
[:maintainer, :developer, :reporter, :guest]
end
with_them do
before do
create(:group_member, user_permission, group: group, user: user)
end
it 'raises error' do
result = subject.register_command
expect(result).to be_nil
expect(subject.errors).to include("Gitlab::Access::AccessDeniedError")
end
end
end
end
context 'project' do
let(:project) { create(:project) }
subject { described_class.new(current_user: user, project: project, **params) }
context 'user is maintainer' do
before do
project.add_maintainer(user)
end
with_them do
let(:params) { { os: commands.each_key.first, arch: 'foo' } }
it 'have correct configurations' do
result = subject.register_command
expect(result).to include("#{commands[commands.each_key.first]} register")
expect(result).to include("--registration-token $REGISTRATION_TOKEN")
expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
end
end
end
context 'user is not maintainer' do
where(:user_permission) do
[:developer, :reporter, :guest]
end
with_them do
before do
create(:project_member, user_permission, project: project, user: user)
end
it 'raises error' do
result = subject.register_command
expect(result).to be_nil
expect(subject.errors).to include("Gitlab::Access::AccessDeniedError")
end
end
end
end
context 'instance' do
subject { described_class.new(current_user: user, **params) }
subject { described_class.new(**params) }
context 'user is admin' do
let(:user) { create(:user, :admin) }
with_them do
let(:params) { { os: commands.each_key.first, arch: 'foo' } }
with_them do
let(:params) { { os: commands.each_key.first, arch: 'foo' } }
it 'have correct configurations' do
result = subject.register_command
expect(result).to include("#{commands[commands.each_key.first]} register")
expect(result).to include("--registration-token $REGISTRATION_TOKEN")
expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
end
end
end
context 'user is not admin' do
it 'raises error' do
it 'have correct configurations' do
result = subject.register_command
expect(result).to be_nil
expect(subject.errors).to include("Gitlab::Access::AccessDeniedError")
expect(result).to include("#{commands[commands.each_key.first]} register")
expect(result).to include("--registration-token $REGISTRATION_TOKEN")
expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
end
end
end

View File

@ -1,45 +1,66 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::ContextPayloadProcessor do
subject(:processor) { described_class.new }
shared_examples 'processing an exception' do
before do
allow_next_instance_of(Gitlab::ErrorTracking::ContextPayloadGenerator) do |generator|
allow(generator).to receive(:generate).and_return(
user: { username: 'root' },
tags: { locale: 'en', program: 'test', feature_category: 'feature_a', correlation_id: 'cid' },
extra: { some_info: 'info' }
)
end
end
before do
allow_next_instance_of(Gitlab::ErrorTracking::ContextPayloadGenerator) do |generator|
allow(generator).to receive(:generate).and_return(
user: { username: 'root' },
tags: { locale: 'en', program: 'test', feature_category: 'feature_a', correlation_id: 'cid' },
extra: { some_info: 'info' }
)
let(:payload) do
{
user: { ip_address: '127.0.0.1' },
tags: { priority: 'high' },
extra: { sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] } }
}
end
it 'merges the context payload into event payload', :aggregate_failures do
expect(result_hash[:user]).to eq(ip_address: '127.0.0.1', username: 'root')
expect(result_hash[:tags])
.to eq(priority: 'high',
locale: 'en',
program: 'test',
feature_category: 'feature_a',
correlation_id: 'cid')
expect(result_hash[:extra])
.to include(some_info: 'info',
sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] })
end
end
it 'merges the context payload into event payload' do
payload = {
user: { ip_address: '127.0.0.1' },
tags: { priority: 'high' },
extra: { sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] } }
}
describe '.call' do
let(:event) { Raven::Event.new(payload) }
let(:result_hash) { described_class.call(event).to_hash }
processor.process(payload)
it_behaves_like 'processing an exception'
expect(payload).to eql(
user: {
ip_address: '127.0.0.1',
username: 'root'
},
tags: {
priority: 'high',
locale: 'en',
program: 'test',
feature_category: 'feature_a',
correlation_id: 'cid'
},
extra: {
some_info: 'info',
sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] }
}
)
context 'when followed by #process' do
let(:result_hash) { described_class.new.process(described_class.call(event).to_hash) }
it_behaves_like 'processing an exception'
end
end
describe '#process' do
let(:event) { Raven::Event.new(payload) }
let(:result_hash) { described_class.new.process(event.to_hash) }
context 'with sentry_processors_before_send disabled' do
before do
stub_feature_flags(sentry_processors_before_send: false)
end
it_behaves_like 'processing an exception'
end
end
end

View File

@ -3,73 +3,83 @@
require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
describe '#process' do
subject { described_class.new }
shared_examples 'processing an exception' do
context 'when there is no GRPC exception' do
let(:exception) { RuntimeError.new }
let(:data) { { fingerprint: ['ArgumentError', 'Missing arguments'] } }
it 'leaves data unchanged' do
expect(subject.process(data)).to eq(data)
expect(result_hash).to include(data)
end
end
context 'when there is a GPRC exception with a debug string' do
let(:exception) { GRPC::DeadlineExceeded.new('Deadline Exceeded', {}, '{"hello":1}') }
let(:data) do
{
exception: {
values: [
{
type: "GRPC::DeadlineExceeded",
value: "4:DeadlineExceeded. debug_error_string:{\"hello\":1}"
}
]
},
extra: {
caller: 'test'
},
fingerprint: [
"GRPC::DeadlineExceeded",
"4:Deadline Exceeded. debug_error_string:{\"created\":\"@1598938192.005782000\",\"description\":\"Error received from peer unix:/home/git/gitalypraefect.socket\",\"file\":\"src/core/lib/surface/call.cc\",\"file_line\":1055,\"grpc_message\":\"Deadline Exceeded\",\"grpc_status\":4}"
'GRPC::DeadlineExceeded',
'4:Deadline Exceeded. debug_error_string:{"created":"@1598938192.005782000","description":"Error received from peer unix:/home/git/gitalypraefect.socket","file":"src/core/lib/surface/call.cc","file_line":1055,"grpc_message":"Deadline Exceeded","grpc_status":4}'
]
}
end
let(:expected) do
{
fingerprint: [
"GRPC::DeadlineExceeded",
"4:Deadline Exceeded."
],
exception: {
values: [
{
type: "GRPC::DeadlineExceeded",
value: "4:DeadlineExceeded."
}
]
},
extra: {
caller: 'test',
grpc_debug_error_string: "{\"hello\":1}"
}
}
end
it 'removes the debug error string and stores it as an extra field' do
expect(subject.process(data)).to eq(expected)
expect(result_hash[:fingerprint])
.to eq(['GRPC::DeadlineExceeded', '4:Deadline Exceeded.'])
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
context 'with no custom fingerprint' do
before do
data.delete(:fingerprint)
expected.delete(:fingerprint)
let(:data) do
{ extra: { caller: 'test' } }
end
it 'removes the debug error string and stores it as an extra field' do
expect(subject.process(data)).to eq(expected)
expect(result_hash).not_to include(:fingerprint)
expect(result_hash[:exception][:values].first)
.to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
expect(result_hash[:extra])
.to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
end
end
end
describe '.call' do
let(:event) { Raven::Event.from_exception(exception, data) }
let(:result_hash) { described_class.call(event).to_hash }
it_behaves_like 'processing an exception'
context 'when followed by #process' do
let(:result_hash) { described_class.new.process(described_class.call(event).to_hash) }
it_behaves_like 'processing an exception'
end
end
describe '#process' do
let(:event) { Raven::Event.from_exception(exception, data) }
let(:result_hash) { described_class.new.process(event.to_hash) }
context 'with sentry_processors_before_send disabled' do
before do
stub_feature_flags(sentry_processors_before_send: false)
end
it_behaves_like 'processing an exception'
end
end
end

View File

@ -94,28 +94,37 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
end
end
describe '#process' do
shared_examples 'processing an exception' do
context 'when there is Sidekiq data' do
let(:wrapped_value) { { extra: { sidekiq: value } } }
shared_examples 'Sidekiq arguments' do |args_in_job_hash: true|
let(:path) { [:extra, :sidekiq, args_in_job_hash ? :job : nil, 'args'].compact }
let(:args) { [1, 'string', { a: 1 }, [1, 2]] }
it 'only allows numeric arguments for an unknown worker' do
value = { 'args' => args, 'class' => 'UnknownWorker' }
context 'for an unknown worker' do
let(:value) do
hash = { 'args' => args, 'class' => 'UnknownWorker' }
value = { job: value } if args_in_job_hash
args_in_job_hash ? { job: hash } : hash
end
expect(subject.process(extra_sidekiq(value)).dig(*path))
.to eq([1, described_class::FILTERED_STRING, described_class::FILTERED_STRING, described_class::FILTERED_STRING])
it 'only allows numeric arguments for an unknown worker' do
expect(result_hash.dig(*path))
.to eq([1, described_class::FILTERED_STRING, described_class::FILTERED_STRING, described_class::FILTERED_STRING])
end
end
it 'allows all argument types for a permitted worker' do
value = { 'args' => args, 'class' => 'PostReceive' }
context 'for a permitted worker' do
let(:value) do
hash = { 'args' => args, 'class' => 'PostReceive' }
value = { job: value } if args_in_job_hash
args_in_job_hash ? { job: hash } : hash
end
expect(subject.process(extra_sidekiq(value)).dig(*path))
.to eq(args)
it 'allows all argument types for a permitted worker' do
expect(result_hash.dig(*path)).to eq(args)
end
end
end
@ -127,39 +136,62 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
it 'removes a jobstr field if present' do
value = {
job: { 'args' => [1] },
jobstr: { 'args' => [1] }.to_json
}
context 'when a jobstr field is present' do
let(:value) do
{
job: { 'args' => [1] },
jobstr: { 'args' => [1] }.to_json
}
end
expect(subject.process(extra_sidekiq(value)))
.to eq(extra_sidekiq(value.except(:jobstr)))
it 'removes the jobstr' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value.except(:jobstr))
end
end
it 'does nothing with no jobstr' do
value = { job: { 'args' => [1] } }
context 'when no jobstr value is present' do
let(:value) { { job: { 'args' => [1] } } }
expect(subject.process(extra_sidekiq(value)))
.to eq(extra_sidekiq(value))
it 'does nothing' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value)
end
end
end
context 'when there is no Sidekiq data' do
it 'does nothing' do
value = {
request: {
method: 'POST',
data: { 'key' => 'value' }
}
}
let(:value) { { tags: { foo: 'bar', baz: 'quux' } } }
let(:wrapped_value) { value }
expect(subject.process(value)).to eq(value)
it 'does nothing' do
expect(result_hash).to include(value)
expect(result_hash.dig(:extra, :sidekiq)).to be_nil
end
end
end
def extra_sidekiq(hash)
{ extra: { sidekiq: hash } }
describe '.call' do
let(:event) { Raven::Event.new(wrapped_value) }
let(:result_hash) { described_class.call(event).to_hash }
it_behaves_like 'processing an exception'
context 'when followed by #process' do
let(:result_hash) { described_class.new.process(described_class.call(event).to_hash) }
it_behaves_like 'processing an exception'
end
end
describe '#process' do
let(:event) { Raven::Event.new(wrapped_value) }
let(:result_hash) { described_class.new.process(event.to_hash) }
context 'with sentry_processors_before_send disabled' do
before do
stub_feature_flags(sentry_processors_before_send: false)
end
it_behaves_like 'processing an exception'
end
end
end

View File

@ -7,6 +7,7 @@ require 'raven/transports/dummy'
RSpec.describe Gitlab::ErrorTracking do
let(:exception) { RuntimeError.new('boom') }
let(:issue_url) { 'http://gitlab.com/gitlab-org/gitlab-foss/issues/1' }
let(:extra) { { issue_url: issue_url, some_other_info: 'info' } }
let(:user) { create(:user) }
@ -42,6 +43,8 @@ RSpec.describe Gitlab::ErrorTracking do
}
end
let(:sentry_event) { Gitlab::Json.parse(Raven.client.transport.events.last[1]) }
before do
stub_sentry_settings
@ -133,8 +136,6 @@ RSpec.describe Gitlab::ErrorTracking do
end
describe '.track_exception' do
let(:extra) { { issue_url: issue_url, some_other_info: 'info' } }
subject(:track_exception) { described_class.track_exception(exception, extra) }
before do
@ -195,6 +196,55 @@ RSpec.describe Gitlab::ErrorTracking do
end
end
context 'when the error is kind of an `ActiveRecord::StatementInvalid`' do
let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') }
it 'injects the normalized sql query into extra' do
track_exception
expect(sentry_event.dig('extra', 'sql')).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
end
end
context 'when the `ActiveRecord::StatementInvalid` is wrapped in another exception' do
it 'injects the normalized sql query into extra' do
allow(exception).to receive(:cause).and_return(ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1'))
track_exception
expect(sentry_event.dig('extra', 'sql')).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
end
end
end
shared_examples 'event processors' do
subject(:track_exception) { described_class.track_exception(exception, extra) }
before do
allow(Raven).to receive(:capture_exception).and_call_original
allow(Gitlab::ErrorTracking::Logger).to receive(:error)
end
context 'custom GitLab context when using Raven.capture_exception directly' do
subject(:raven_capture_exception) { Raven.capture_exception(exception) }
it 'merges a default set of tags into the existing tags' do
allow(Raven.context).to receive(:tags).and_return(foo: 'bar')
raven_capture_exception
expect(sentry_event['tags']).to include('correlation_id', 'feature_category', 'foo', 'locale', 'program')
end
it 'merges the current user information into the existing user information' do
Raven.user_context(id: -1)
raven_capture_exception
expect(sentry_event['user']).to eq('id' => -1, 'username' => user.username)
end
end
context 'with sidekiq args' do
context 'when the args does not have anything sensitive' do
let(:extra) { { sidekiq: { 'class' => 'PostReceive', 'args' => [1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value'] } } }
@ -211,16 +261,20 @@ RSpec.describe Gitlab::ErrorTracking do
)
)
end
it 'does not filter parameters when sending to Sentry' do
track_exception
expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq([1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value'])
end
end
context 'when the args has sensitive information' do
let(:extra) { { sidekiq: { 'class' => 'UnknownWorker', 'args' => ['sensitive string', 1, 2] } } }
it 'filters sensitive arguments before sending' do
it 'filters sensitive arguments before sending and logging' do
track_exception
sentry_event = Gitlab::Json.parse(Raven.client.transport.events.last[1])
expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq(['[FILTERED]', 1, 2])
expect(Gitlab::ErrorTracking::Logger).to have_received(:error).with(
hash_including(
@ -234,28 +288,44 @@ RSpec.describe Gitlab::ErrorTracking do
end
end
context 'when the error is kind of an `ActiveRecord::StatementInvalid`' do
let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') }
context 'when the error is a GRPC error' do
context 'when the GRPC error contains a debug_error_string value' do
let(:exception) { GRPC::DeadlineExceeded.new('unknown cause', {}, '{"hello":1}') }
it 'injects the normalized sql query into extra' do
allow(Raven.client.transport).to receive(:send_event) do |event|
expect(event.extra).to include(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
it 'sets the GRPC debug error string in the Sentry event and adds a custom fingerprint' do
track_exception
expect(sentry_event.dig('extra', 'grpc_debug_error_string')).to eq('{"hello":1}')
expect(sentry_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause.'])
end
track_exception
end
end
context 'when the `ActiveRecord::StatementInvalid` is wrapped in another exception' do
let(:exception) { RuntimeError.new(cause: ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1')) }
context 'when the GRPC error does not contain a debug_error_string value' do
let(:exception) { GRPC::DeadlineExceeded.new }
it 'injects the normalized sql query into extra' do
allow(Raven.client.transport).to receive(:send_event) do |event|
expect(event.extra).to include(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
it 'does not do any processing on the event' do
track_exception
expect(sentry_event['extra']).not_to include('grpc_debug_error_string')
expect(sentry_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause'])
end
track_exception
end
end
end
context 'with sentry_processors_before_send enabled' do
before do
stub_feature_flags(sentry_processors_before_send: true)
end
include_examples 'event processors'
end
context 'with sentry_processors_before_send disabled' do
before do
stub_feature_flags(sentry_processors_before_send: false)
end
include_examples 'event processors'
end
end

View File

@ -223,7 +223,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) }
before do
pipeline.persistent_ref.create
pipeline.persistent_ref.create # rubocop:disable Rails/SaveBang
end
it 'returns the correct refspecs' do
@ -261,7 +261,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
let(:build) { create(:ci_build, pipeline: pipeline) }
before do
pipeline.persistent_ref.create
pipeline.persistent_ref.create # rubocop:disable Rails/SaveBang
end
it 'exposes the persistent pipeline ref' do

View File

@ -35,7 +35,7 @@ RSpec.describe Ci::TriggerPresenter do
context 'when user is a trigger owner and builds admin' do
before do
trigger.update(owner: user)
trigger.update!(owner: user)
end
describe '#token' do

View File

@ -146,7 +146,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
before do
[info_file, manifest_file, package_file].each do |file|
file.conan_file_metadatum.conan_package_reference = alternative_reference
file.save
file.save!
end
end

View File

@ -38,16 +38,16 @@ RSpec.describe API::Internal::Kubernetes do
end
shared_examples 'agent authentication' do
it 'returns 403 if Authorization header not sent' do
it 'returns 401 if Authorization header not sent' do
send_request
expect(response).to have_gitlab_http_status(:forbidden)
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'returns 403 if Authorization is for non-existent agent' do
it 'returns 401 if Authorization is for non-existent agent' do
send_request(headers: { 'Authorization' => 'Bearer NONEXISTENT' })
expect(response).to have_gitlab_http_status(:forbidden)
expect(response).to have_gitlab_http_status(:unauthorized)
end
end

View File

@ -85,7 +85,7 @@ func TestConfigDefaults(t *testing.T) {
DocumentRoot: "public",
ProxyHeadersTimeout: 5 * time.Minute,
APIQueueTimeout: queueing.DefaultTimeout,
APICILongPollingDuration: 50 * time.Second,
APICILongPollingDuration: 50 * time.Nanosecond, // TODO this is meant to be 50*time.Second but it has been wrong for ages
ImageResizerConfig: config.DefaultImageResizerConfig,
}

View File

@ -102,7 +102,7 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error
fset.UintVar(&cfg.APILimit, "apiLimit", 0, "Number of API requests allowed at single time")
fset.UintVar(&cfg.APIQueueLimit, "apiQueueLimit", 0, "Number of API requests allowed to be queued")
fset.DurationVar(&cfg.APIQueueTimeout, "apiQueueDuration", queueing.DefaultTimeout, "Maximum queueing duration of requests")
fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50*time.Second, "Long polling duration for job requesting for runners (default 50s - enabled)")
fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50, "Long polling duration for job requesting for runners (default 50s - enabled)")
fset.BoolVar(&cfg.PropagateCorrelationID, "propagateCorrelationID", false, "Reuse existing Correlation-ID from the incoming request header `X-Request-ID` if present")
if err := fset.Parse(args); err != nil {