Commit 86f6c2a7 authored by Adam Hegyi's avatar Adam Hegyi

Merge branch '262395-devops-adoption-read-api' into 'master'

Expose Devops Adoption segments via GraphQL

See merge request gitlab-org/gitlab!46879
parents 93c1b5da 6f3125e0
......@@ -7,9 +7,11 @@ require:
- rubocop-rspec
inherit_from:
- .rubocop_manual_todo.yml
- .rubocop_todo.yml
- ./rubocop/rubocop-migrations.yml
- ./rubocop/rubocop-usage-data.yml
- ./rubocop/rubocop-code_reuse.yml
inherit_mode:
merge:
......
This diff is collapsed.
This diff is collapsed.
......@@ -370,11 +370,7 @@ group :development, :test do
gem 'spring', '~> 2.0.0'
gem 'spring-commands-rspec', '~> 1.0.4'
gem 'gitlab-styles', '~> 4.3.0', require: false
# Pin these dependencies, otherwise a new rule could break the CI pipelines
gem 'rubocop', '~> 0.82.0'
gem 'rubocop-performance', '~> 1.5.2'
gem 'rubocop-rspec', '~> 1.37.0'
gem 'gitlab-styles', '~> 5.0.0', require: false
gem 'scss_lint', '~> 0.56.0', require: false
gem 'haml_lint', '~> 0.36.0', require: false
......
......@@ -449,12 +449,12 @@ GEM
gitlab-puma (>= 2.7, < 5)
gitlab-sidekiq-fetcher (0.5.2)
sidekiq (~> 5)
gitlab-styles (4.3.0)
rubocop (~> 0.82.0)
gitlab-styles (5.0.0)
rubocop (~> 0.89.1)
rubocop-gitlab-security (~> 0.1.0)
rubocop-performance (~> 1.5.2)
rubocop-rails (~> 2.5)
rubocop-rspec (~> 1.36)
rubocop-performance (~> 1.8.1)
rubocop-rails (~> 2.8)
rubocop-rspec (~> 1.44)
gitlab_chronic_duration (0.10.6.2)
numerizer (~> 0.2)
gitlab_omniauth-ldap (2.1.1)
......@@ -602,7 +602,6 @@ GEM
jaeger-client (1.1.0)
opentracing (~> 0.3)
thrift
jaro_winkler (1.5.4)
jira-ruby (2.0.0)
activesupport
atlassian-jwt
......@@ -834,7 +833,7 @@ GEM
rubypants (~> 0.2)
orm_adapter (0.5.0)
os (1.0.0)
parallel (1.19.1)
parallel (1.19.2)
parser (2.7.2.0)
ast (~> 2.4.1)
parslet (1.8.2)
......@@ -958,7 +957,7 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.8.1)
redis (>= 4, < 5)
regexp_parser (1.5.1)
regexp_parser (1.8.2)
regexp_property_values (0.3.5)
representable (3.0.4)
declarative (< 0.1.0)
......@@ -1019,24 +1018,29 @@ GEM
pg
rails
sqlite3
rubocop (0.82.0)
jaro_winkler (~> 1.5.1)
rubocop (0.89.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
rubocop-ast (>= 0.3.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.8.0)
parser (>= 2.7.1.5)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
rubocop-performance (1.5.2)
rubocop (>= 0.71.0)
rubocop-rails (2.5.2)
activesupport
rubocop-performance (1.8.1)
rubocop (>= 0.87.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.8.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 0.72.0)
rubocop-rspec (1.37.0)
rubocop (>= 0.68.1)
rubocop (>= 0.87.0)
rubocop-rspec (1.44.1)
rubocop (~> 0.87)
rubocop-ast (>= 0.7.1)
ruby-enum (0.7.2)
i18n
ruby-fogbugz (0.2.1)
......@@ -1249,7 +1253,7 @@ GEM
xpath (3.2.0)
nokogiri (~> 1.8)
yajl-ruby (1.4.1)
zeitwerk (2.4.0)
zeitwerk (2.4.1)
PLATFORMS
ruby
......@@ -1353,7 +1357,7 @@ DEPENDENCIES
gitlab-puma (~> 4.3.3.gitlab.2)
gitlab-puma_worker_killer (~> 0.1.1.gitlab.1)
gitlab-sidekiq-fetcher (= 0.5.2)
gitlab-styles (~> 4.3.0)
gitlab-styles (~> 5.0.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.2)
......@@ -1473,9 +1477,6 @@ DEPENDENCIES
rspec-retry (~> 0.6.1)
rspec_junit_formatter
rspec_profiling (~> 0.0.6)
rubocop (~> 0.82.0)
rubocop-performance (~> 1.5.2)
rubocop-rspec (~> 1.37.0)
ruby-fogbugz (~> 0.2.1)
ruby-prof (~> 1.3.0)
ruby-progressbar
......
......@@ -52,7 +52,7 @@ export default {
<p class="gl-mb-0">
{{
s__(
'Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults.',
'Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults.',
)
}}
</p>
......
......@@ -38,8 +38,11 @@ export default {
isJira() {
return this.propsSource.type === 'jira';
},
isInstanceLevel() {
return this.propsSource.integrationLevel === integrationLevels.INSTANCE;
isInstanceOrGroupLevel() {
return (
this.propsSource.integrationLevel === integrationLevels.INSTANCE ||
this.propsSource.integrationLevel === integrationLevels.GROUP
);
},
showJiraIssuesFields() {
return this.isJira && this.glFeatures.jiraIssuesIntegration;
......@@ -91,7 +94,7 @@ export default {
v-bind="propsSource.jiraIssuesProps"
/>
<div v-if="isEditable" class="footer-block row-content-block">
<template v-if="isInstanceLevel">
<template v-if="isInstanceOrGroupLevel">
<gl-button
v-gl-modal.confirmSaveIntegration
category="primary"
......
......@@ -108,12 +108,7 @@ export default {
:label="s__('Integrations|Comment detail:')"
data-testid="comment-detail"
>
<input
v-if="isInheriting"
name="service[comment_detail]"
type="hidden"
:value="commentDetail"
/>
<input name="service[comment_detail]" type="hidden" :value="commentDetail" />
<gl-form-radio
v-for="commentDetailOption in commentDetailOptions"
:key="commentDetailOption.value"
......
globals:
AP: readonly
rules:
'@gitlab/require-i18n-strings': off
'@gitlab/vue-require-i18n-strings': off
<script>
export default {};
</script>
<template>
<div></div>
</template>
import Vue from 'vue';
import App from './components/app.vue';
function initJiraConnect() {
const el = document.querySelector('.js-jira-connect-app');
return new Vue({
el,
render(createElement) {
return createElement(App, {});
},
});
}
document.addEventListener('DOMContentLoaded', initJiraConnect);
@import 'framework/variables';
@import 'mixins_and_variables_and_functions';
// We should only import styles that we actually use.
// @import '@gitlab/ui/src/scss/gitlab_ui';
$atlaskit-border-color: #dfe1e6;
......
......@@ -150,6 +150,14 @@ module PageLayoutHelper
css_class.join(' ')
end
def page_itemtype(itemtype = nil)
if itemtype
@page_itemtype = { itemscope: true, itemtype: itemtype }
else
@page_itemtype || {}
end
end
private
def generic_canonical_url
......
......@@ -91,18 +91,18 @@ module UsersHelper
end
end
def work_information(user)
def work_information(user, with_schema_markup: false)
return unless user
organization = user.organization
job_title = user.job_title
if organization.present? && job_title.present?
s_('Profile|%{job_title} at %{organization}') % { job_title: job_title, organization: organization }
render_job_title_and_organization(job_title, organization, with_schema_markup: with_schema_markup)
elsif job_title.present?
job_title
render_job_title(job_title, with_schema_markup: with_schema_markup)
elsif organization.present?
organization
render_organization(organization, with_schema_markup: with_schema_markup)
end
end
......@@ -151,6 +151,35 @@ module UsersHelper
items
end
def render_job_title(job_title, with_schema_markup: false)
if with_schema_markup
content_tag :span, itemprop: 'jobTitle' do
job_title
end
else
job_title
end
end
def render_organization(organization, with_schema_markup: false)
if with_schema_markup
content_tag :span, itemprop: 'worksFor' do
organization
end
else
organization
end
end
def render_job_title_and_organization(job_title, organization, with_schema_markup: false)
if with_schema_markup
job_title = '<span itemprop="jobTitle">'.html_safe + job_title + "</span>".html_safe
organization = '<span itemprop="worksFor">'.html_safe + organization + "</span>".html_safe
end
html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization }
end
end
UsersHelper.prepend_if_ee('EE::UsersHelper')
......@@ -21,6 +21,8 @@
.gl-mt-5
%p Note: this integration only works with accounts on GitLab.com (SaaS).
- else
.js-jira-connect-app
%form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
.ak-field-group
%label
......@@ -57,5 +59,8 @@
or enable cross-site cookies in your browser when adding a namespace.
%a{ href: 'https://gitlab.com/gitlab-org/gitlab/-/issues/263509', target: '_blank', rel: 'noopener noreferrer' } Learn more
= webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
= webpack_bundle_tag 'jira_connect_app'
= page_specific_javascript_tag('jira_connect.js')
- add_page_specific_style 'page_bundles/jira_connect'
......@@ -20,6 +20,6 @@
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
.content{ id: "content-body" }
.content{ id: "content-body", **page_itemtype }
= render "layouts/flash", extra_flash_class: 'limit-container-width'
= yield
......@@ -4,6 +4,7 @@
- page_title @user.blocked? ? s_('UserProfile|Blocked user') : @user.name
- page_description @user.bio_html
- header_title @user.name, user_path(@user)
- page_itemtype 'http://schema.org/Person'
- link_classes = "flex-grow-1 mx-1 "
= content_for :meta_tags do
......@@ -35,7 +36,7 @@
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
.avatar-holder
= link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
= image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: ''
= image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: '', itemprop: 'image'
- if @user.blocked?
.user-info
......@@ -44,7 +45,7 @@
= render "users/profile_basic_info"
- else
.user-info
.cover-title
.cover-title{ itemprop: 'name' }
= @user.name
- if @user.status
......@@ -54,15 +55,15 @@
= render "users/profile_basic_info"
.cover-desc.cgray.mb-1.mb-sm-2
- unless @user.location.blank?
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mb-1.mb-sm-0
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mb-1.mb-sm-0{ itemprop: 'address', itemscope: true, itemtype: 'https://schema.org/PostalAddress' }
= sprite_icon('location', css_class: 'vertical-align-sub fgray')
%span.vertical-align-middle
%span.vertical-align-middle{ itemprop: 'addressLocality' }
= @user.location
- unless work_information(@user).blank?
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline
= sprite_icon('work', css_class: 'vertical-align-middle fgray')
%span.vertical-align-middle
= work_information(@user)
= work_information(@user, with_schema_markup: true)
.cover-desc.cgray.mb-1.mb-sm-2
- unless @user.skype.blank?
.profile-link-holder.middle-dot-divider
......@@ -80,10 +81,10 @@
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mt-1.mt-sm-0
- if Feature.enabled?(:security_auto_fix) && @user.bot?
= sprite_icon('question', css_class: 'gl-text-blue-600')
= link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow'
= link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow', itemprop: 'url'
- unless @user.public_email.blank?
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mt-1.mt-sm-0
= link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link'
= link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link', itemprop: 'email'
- if @user.bio.present?
.cover-desc.cgray
.profile-user-bio
......
---
title: Fix setting Comment detail for Jira and modal for groups
merge_request: 46945
author:
type: fixed
---
title: Add structured markup for users
merge_request: 46553
author:
type: added
---
name: security_on_demand_scans_http_header_validation
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42812
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276403
milestone: '13.6'
type: development
group: group::dynamic analysis
default_enabled: false
......@@ -82,6 +82,7 @@ function generateEntries() {
// sentry: './sentry/index.js', Temporarily commented out to investigate performance: https://gitlab.com/gitlab-org/gitlab/-/issues/251179
performance_bar: './performance_bar/index.js',
chrome_84_icon_fix: './lib/chrome_84_icon_fix.js',
jira_connect_app: './jira_connect/index.js',
};
return Object.assign(manualEntries, autoEntries);
......
---
stage: none
group: unassigned
stage: Enablement
group: Distribution
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/#designated-technical-writers
type: concepts
---
......@@ -57,21 +57,11 @@ one major version. For example, it is safe to:
- `12.7.5` -> `12.10.5`
- `11.3.4` -> `11.11.1`
- `10.6.6` -> `10.8.3`
- `11.3.4` -> `11.11.8`
- `10.6.6` -> `10.8.7`
- `9.2.3` -> `9.5.5`
- `8.9.4` -> `8.12.3`
- Upgrade the *patch* version. For example:
- `12.0.4` -> `12.0.12`
- `11.11.1` -> `11.11.8`
- `10.6.3` -> `10.6.6`
- `11.11.1` -> `11.11.8`
- `10.6.3` -> `10.6.6`
- `9.5.5` -> `9.5.9`
- `8.9.2` -> `8.9.6`
NOTE: **Note:**
Version specific changes in Omnibus GitLab Linux packages can be found in [the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes).
......@@ -82,87 +72,9 @@ Instructions are available for downloading an Omnibus GitLab Linux package local
NOTE: **Note:**
A step-by-step guide to [upgrading the Omnibus-bundled PostgreSQL is documented separately](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server).
### Upgrading major versions
Upgrading the *major* version requires more attention.
Backward-incompatible changes and migrations are reserved for major versions.
We cannot guarantee that upgrading between major versions will be seamless.
We suggest upgrading to the latest available *minor* version within
your major version before proceeding to the next major version.
Doing this will address any backward-incompatible changes or deprecations
to help ensure a successful upgrade to the next major release.
It's also important to ensure that any background migrations have been fully completed
before upgrading to a new major version. To see the current size of the `background_migration` queue,
[Check for background migrations before upgrading](../update/README.md#checking-for-background-migrations-before-upgrading).
If your GitLab instance has any runners associated with it, it is very
important to upgrade GitLab Runner to match the GitLab minor version that was
upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
### Version 12 onward: Extra step for major upgrades
From version 12 onward, an additional step is required. More significant migrations
may occur during major release upgrades.
NOTE: **Note:**
If you are planning to upgrade from `12.0.x` to `12.10.x`, it is necessary to perform an intermediary upgrade to `12.1.x`
before upgrading to `12.10.x` to avoid [#215141](https://gitlab.com/gitlab-org/gitlab/-/issues/215141).
To ensure these are successful:
1. Increment to the first minor version (`x.0.x`) during the major version jump.
1. Proceed with upgrading to a newer release.
**For example: `11.5.x` -> `11.11.x` -> `12.0.x` -> `12.1.x` -> `12.10.x` -> `13.0.x`**
### Example upgrade paths
Please see the table below for some examples:
## Upgrading major versions
| Target version | Your version | Recommended upgrade path | Note |
| --------------------- | ------------ | ------------------------ | ---- |
| `13.4.3` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.4.3` | Two intermediate versions are required: the final `12.10` release, plus `13.0`. |
| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.2.10` | Five intermediate versions are required: the final `11.11`, `12.0`, `12.1` and `12.10` releases, plus `13.0`. |
| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` | Three intermediate versions are required: the final `11.11` and `12.0` releases, plus `12.1` |
| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5` |
| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2`. |
| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
### Upgrades from versions earlier than 8.12
- `8.11.x` and earlier: you might have to upgrade to `8.12.0` specifically before you can upgrade to `8.17.7`. This was [reported in an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/207259).
- [CI changes prior to version 8.0](https://docs.gitlab.com/omnibus/update/README.html#updating-gitlab-ci-from-prior-540-to-version-714-via-omnibus-gitlab)
when it was merged into GitLab.
### Multi-step upgrade paths with GitLab all-in-one Linux package repository
Linux package managers default to installing the latest available version of a package for installation and upgrades.
Upgrading directly to the latest major version can be problematic for older GitLab versions that require a multi-stage upgrade path.
When following an upgrade path spanning multiple versions, for each upgrade, specify the intended GitLab version number in your package manager's install or upgrade command.
Examples:
```shell
# apt-get (Ubuntu/Debian)
sudo apt-get upgrade gitlab-ee=12.0.12-ee.0
# yum (RHEL/CentOS 6 and 7)
yum install gitlab-ee-12.0.12-ee.0.el7
# dnf (RHEL/CentOS 8)
dnf install gitlab-ee-12.0.12-ee.0.el8
# zypper (SUSE)
zypper install gitlab-ee=12.0.12-ee.0
```
To identify the GitLab version number in your package manager, run the following commands:
```shell
# apt-cache (Ubuntu/Debian)
sudo apt-cache madison gitlab-ee
# yum (RHEL/CentOS 6 and 7)
yum --showduplicates list gitlab-ee
```
Backward-incompatible changes and migrations are reserved for major versions. See the [upgrade guide](../update/README.md#upgrading-to-a-new-major-version).
## Patch releases
......@@ -237,19 +149,6 @@ This decision is made on a case-by-case basis.
## More information
Check [our release posts](https://about.gitlab.com/releases/categories/releases/).
Each month, we publish either a major or minor release of GitLab. At the end
of those release posts, there are three sections to look for: Deprecations, Removals, and Important notes on upgrading. These will include:
- Steps you need to perform as part of an upgrade.
For example [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)
required the Elasticsearch index to be recreated. Any older version of GitLab upgrading to 8.12 or higher would require this.
- Changes to the versions of software we support such as
[ceasing support for IE11 in GitLab 13](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11).
You should check all the major and minor versions you're passing over.
More information about the release procedures can be found in our
[release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our
[Responsible Disclosure Policy](https://about.gitlab.com/security/disclosure/).
This diff is collapsed.
......@@ -18,6 +18,12 @@ If you choose a size larger than what is currently configured for the web server
you will likely get errors. See the [troubleshooting section](#troubleshooting) for more
details.
## Max push size
You can change the maximum push size for your repository.
Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**.
From here, you can increase or decrease by changing the value in `Maximum push size (MB)`.
## Max import size
You can change the maximum file size for imports in GitLab.
......
......@@ -11,11 +11,16 @@ import {
GlInputGroupText,
GlLoadingIcon,
} from '@gitlab/ui';
import { omit } from 'lodash';
import * as Sentry from '~/sentry/wrapper';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import download from '~/lib/utils/downloader';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { cleanLeadingSeparator, joinPaths, stripPathTail } from '~/lib/utils/url_utility';
import { fetchPolicies } from '~/lib/graphql';
import {
DAST_SITE_VALIDATION_HTTP_HEADER_KEY,
DAST_SITE_VALIDATION_METHOD_HTTP_HEADER,
DAST_SITE_VALIDATION_METHOD_TEXT_FILE,
DAST_SITE_VALIDATION_METHODS,
DAST_SITE_VALIDATION_STATUS,
......@@ -27,6 +32,7 @@ import dastSiteValidationQuery from '../graphql/dast_site_validation.query.graph
export default {
name: 'DastSiteValidation',
components: {
ClipboardButton,
GlAlert,
GlButton,
GlCard,
......@@ -38,6 +44,7 @@ export default {
GlInputGroupText,
GlLoadingIcon,
},
mixins: [glFeatureFlagsMixin()],
apollo: {
dastSiteValidation: {
query: dastSiteValidationQuery,
......@@ -103,6 +110,16 @@ export default {
};
},
computed: {
validationMethodOptions() {
const isHttpHeaderValidationEnabled = this.glFeatures
.securityOnDemandScansHttpHeaderValidation;
const enabledValidationMethods = omit(DAST_SITE_VALIDATION_METHODS, [
!isHttpHeaderValidationEnabled ? DAST_SITE_VALIDATION_METHOD_HTTP_HEADER : '',
]);
return Object.values(enabledValidationMethods);
},
urlObject() {
try {
return new URL(this.targetUrl);
......@@ -119,12 +136,18 @@ export default {
isTextFileValidation() {
return this.validationMethod === DAST_SITE_VALIDATION_METHOD_TEXT_FILE;
},
isHttpHeaderValidation() {
return this.validationMethod === DAST_SITE_VALIDATION_METHOD_HTTP_HEADER;
},
textFileName() {
return `GitLab-DAST-Site-Validation-${this.token}.txt`;
},
locationStepLabel() {
return DAST_SITE_VALIDATION_METHODS[this.validationMethod].i18n.locationStepLabel;
},
httpHeader() {
return `${DAST_SITE_VALIDATION_HTTP_HEADER_KEY}: uuid-code-${this.token}`;
},
},
watch: {
targetUrl() {
......@@ -132,13 +155,22 @@ export default {
},
},
created() {
this.unsubscribe = this.$watch(() => this.token, this.updateValidationPath, {
immediate: true,
});
this.unsubscribe = this.$watch(
() => [this.token, this.validationMethod],
this.updateValidationPath,
{
immediate: true,
},
);
},
methods: {
updateValidationPath() {
this.validationPath = joinPaths(stripPathTail(this.path), this.textFileName);
this.validationPath = this.isTextFileValidation
? this.getTextFileValidationPath()
: this.path;
},
getTextFileValidationPath() {
return joinPaths(stripPathTail(this.path), this.textFileName);
},
onValidationPathInput() {
this.unsubscribe();
......@@ -189,7 +221,6 @@ export default {
this.hasValidationError = true;
},
},
validationMethodOptions: Object.values(DAST_SITE_VALIDATION_METHODS),
};
</script>
......@@ -199,7 +230,7 @@ export default {
{{ s__('DastProfiles|Site is not validated yet, please follow the steps.') }}
</gl-alert>
<gl-form-group :label="s__('DastProfiles|Step 1 - Choose site validation method')">
<gl-form-radio-group v-model="validationMethod" :options="$options.validationMethodOptions" />
<gl-form-radio-group v-model="validationMethod" :options="validationMethodOptions" />
</gl-form-group>
<gl-form-group
v-if="isTextFileValidation"
......@@ -217,6 +248,16 @@ export default {
{{ textFileName }}
</gl-button>
</gl-form-group>
<gl-form-group
v-else-if="isHttpHeaderValidation"
:label="s__('DastProfiles|Step 2 - Add following HTTP header to your site')"
>
<code class="gl-p-3 gl-bg-black gl-text-white">{{ httpHeader }}</code>
<clipboard-button
:text="httpHeader"
:title="s__('DastProfiles|Copy HTTP header to clipboard')"
/>
</gl-form-group>
<gl-form-group :label="locationStepLabel" class="mw-460">
<gl-form-input-group>
<template #prepend>
......@@ -255,7 +296,7 @@ export default {
<gl-icon name="status_failed" />
{{
s__(
'DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method.',
'DastProfiles|Validation failed, please make sure that you follow the steps above with the chosen method.',
)
}}
</template>
......
import { s__ } from '~/locale';
export const DAST_SITE_VALIDATION_METHOD_TEXT_FILE = 'TEXT_FILE';
export const DAST_SITE_VALIDATION_METHOD_HTTP_HEADER = 'HTTP_HEADER';
export const DAST_SITE_VALIDATION_METHODS = {
[DAST_SITE_VALIDATION_METHOD_TEXT_FILE]: {
value: DAST_SITE_VALIDATION_METHOD_TEXT_FILE,
......@@ -9,6 +11,13 @@ export const DAST_SITE_VALIDATION_METHODS = {
locationStepLabel: s__('DastProfiles|Step 3 - Confirm text file location and validate'),
},
},
[DAST_SITE_VALIDATION_METHOD_HTTP_HEADER]: {
value: DAST_SITE_VALIDATION_METHOD_HTTP_HEADER,
text: s__('DastProfiles|Header validation'),
i18n: {
locationStepLabel: s__('DastProfiles|Step 3 - Confirm header location and validate'),
},
},
};
export const DAST_SITE_VALIDATION_STATUS = {
......@@ -19,3 +28,4 @@ export const DAST_SITE_VALIDATION_STATUS = {
};
export const DAST_SITE_VALIDATION_POLL_INTERVAL = 1000;
export const DAST_SITE_VALIDATION_HTTP_HEADER_KEY = 'Gitlab-On-Demand-DAST';
......@@ -6,6 +6,7 @@ module Projects
before_action do
authorize_read_on_demand_scans!
push_frontend_feature_flag(:security_on_demand_scans_site_validation, @project)
push_frontend_feature_flag(:security_on_demand_scans_http_header_validation, @project)
end
feature_category :dynamic_application_security_testing
......
......@@ -3,8 +3,5 @@
---
inherit_from: ../../../../../lib/gitlab/background_migration/.rubocop.yml
CodeReuse/ActiveRecord:
Enabled: false
Style/Documentation:
Enabled: false
......@@ -14,7 +14,7 @@ export const dastSiteValidation = (status = DAST_SITE_VALIDATION_STATUS.PENDING)
export const dastSiteValidationCreate = (errors = []) => ({
data: {
dastSiteValidationCreate: { status: DAST_SITE_VALIDATION_STATUS.PASSED, id: '1', errors },
dastSiteValidationCreate: { status: DAST_SITE_VALIDATION_STATUS.PENDING, id: '1', errors },
},
});
......
......@@ -190,7 +190,7 @@ module Gitlab
%r{\A(ee/)?vendor/} => :backend,
%r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
%r{\A[A-Z_]+_VERSION\z} => :backend,
%r{\A\.rubocop(_todo)?\.yml\z} => :backend,
%r{\A\.rubocop((_manual)?_todo)?\.yml\z} => :backend,
%r{\Afile_hooks/} => :backend,
%r{\A(ee/)?qa/} => :qa,
......
......@@ -8319,6 +8319,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
msgid "DastProfiles|Copy HTTP header to clipboard"
msgstr ""
msgid "DastProfiles|Could not create site validation token. Please refresh the page, or try again later."
msgstr ""
......@@ -8385,6 +8388,9 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Header validation"
msgstr ""
msgid "DastProfiles|Hide debug messages"
msgstr ""
......@@ -8469,9 +8475,15 @@ msgstr ""
msgid "DastProfiles|Step 1 - Choose site validation method"
msgstr ""
msgid "DastProfiles|Step 2 - Add following HTTP header to your site"
msgstr ""
msgid "DastProfiles|Step 2 - Add following text to the target site"
msgstr ""
msgid "DastProfiles|Step 3 - Confirm header location and validate"
msgstr ""
msgid "DastProfiles|Step 3 - Confirm text file location and validate"
msgstr ""
......@@ -8508,7 +8520,7 @@ msgstr ""
msgid "DastProfiles|Validating..."
msgstr ""
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the chosen method."
msgstr ""
msgid "DastProfiles|Validation failed. Please try again."
......@@ -14507,7 +14519,7 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
msgstr ""
msgid "Integrations|Return to GitLab for Jira"
......
# frozen_string_literal: true
require_relative '../../code_reuse_helpers'
module RuboCop
module Cop
module CodeReuse
# Cop that denies the use of ActiveRecord methods outside of models.
class ActiveRecord < RuboCop::Cop::Cop
include CodeReuseHelpers
MSG = 'This method can only be used inside an ActiveRecord model: ' \
'https://gitlab.com/gitlab-org/gitlab-foss/issues/49653'
# Various methods from ActiveRecord::Querying that are denied. We
# exclude some generic ones such as `any?` and `first`, as these may
# lead to too many false positives, since `Array` also supports these
# methods.
#
# The keys of this Hash are the denied method names. The values are
# booleans that indicate if the method should only be denied if any
# arguments are provided.
NOT_ALLOWED = {
average: true,
calculate: true,
count_by_sql: true,
create_with: true,
distinct: false,
eager_load: true,
exists?: true,
find_by: true,
find_by!: true,
find_by_sql: true,
find_each: true,
find_in_batches: true,
find_or_create_by: true,
find_or_create_by!: true,
find_or_initialize_by: true,
first!: false,
first_or_create: true,
first_or_create!: true,
first_or_initialize: true,
from: true,
group: true,
having: true,
ids: false,
includes: true,
joins: true,
limit: true,
lock: false,
many?: false,
offset: true,
order: true,
pluck: true,
preload: true,
readonly: false,
references: true,
reorder: true,
rewhere: true,
take: false,
take!: false,
unscope: false,
where: false,
with: true
}.freeze
# Directories that allow the use of the denied methods. These
# directories are checked relative to both . and ee/
ALLOWED_DIRECTORIES = %w[
app/models
config
danger
db
lib/backup
lib/banzai
lib/gitlab/background_migration
lib/gitlab/cycle_analytics
lib/gitlab/database
lib/gitlab/import_export
lib/gitlab/project_authorizations
lib/gitlab/sql
lib/system_check
lib/tasks
qa
rubocop
spec
].freeze
def on_send(node)
return if in_allowed_directory?(node)
receiver = node.children[0]
send_name = node.children[1]
first_arg = node.children[2]
if receiver && NOT_ALLOWED.key?(send_name)
# If the rule requires an argument to be given, but none are
# provided, we won't register an offense. This prevents us from
# adding offenses for `project.group`, while still covering
# `Project.group(:name)`.
return if NOT_ALLOWED[send_name] && !first_arg
add_offense(node, location: :selector)
end
end
# Returns true if the node resides in one of the allowed
# directories.
def in_allowed_directory?(node)
path = file_path_for_node(node)
ALLOWED_DIRECTORIES.any? do |directory|
path.start_with?(
File.join(rails_root, directory),
File.join(rails_root, 'ee', directory)
)
end
end
# We can not auto correct code like this, as it requires manual
# refactoring. Instead, we'll just allow the surrounding scope.
#
# Despite this method's presence, you should not use it. This method
# exists to make it possible to allow large chunks of offenses we
# can't fix in the short term. If you are writing new code, follow the
# code reuse guidelines, instead of allowing any new offenses.
def autocorrect(node)
scope = surrounding_scope_of(node)
indent = indentation_of(scope)
lambda do |corrector|
# This prevents us from inserting the same enable/disable comment
# for a method or block that has multiple offenses.
next if allowed_scopes.include?(scope)
corrector.insert_before(
scope.source_range,
"# rubocop: disable #{cop_name}\n#{indent}"
)
corrector.insert_after(
scope.source_range,
"\n#{indent}# rubocop: enable #{cop_name}"
)
allowed_scopes << scope
end
end
def indentation_of(node)
' ' * node.loc.expression.source_line[/\A */].length
end
def surrounding_scope_of(node)
%i[def defs block begin].each do |type|
if (found = node.each_ancestor(type).first)
return found
end
end
end
def allowed_scopes
@allowed_scopes ||= Set.new
end
end
end
end
end
......@@ -5,7 +5,7 @@ module RuboCop
def in_qa_file?(node)
path = node.location.expression.source_buffer.name
path.start_with?(File.join(RuboCop::PathUtil.pwd, 'qa'))
path.start_with?(File.join(Dir.pwd, 'qa'))
end
end
end
# Denies the use of ActiveRecord methods outside of configured
# excluded directories
# Directories that allow the use of the denied methods.
# To start we provide a default configuration that matches
# a standard Rails app and enable.
# The default configuration can be overridden by
# providing your own Exclusion list as follows:
# CodeReuse/ActiveRecord:
# Enabled: true
# Exclude:
# - app/models/**/*.rb
# - config/**/*.rb
# - db/**/*.rb
# - lib/tasks/**/*.rb
# - spec/**/*.rb
# - lib/gitlab/**/*.rb
CodeReuse/ActiveRecord:
Exclude:
- app/models/**/*.rb
- config/**/*.rb
- db/**/*.rb
- lib/tasks/**/*.rake
- spec/**/*.rb
- danger/**/*.rb
- lib/backup/**/*.rb
- lib/banzai/**/*.rb
- lib/gitlab/background_migration/**/*.rb
- lib/gitlab/cycle_analytics/**/*.rb
- lib/gitlab/database/**/*.rb
- lib/gitlab/database_importers/common_metrics/importer.rb
- lib/gitlab/import_export/**/*.rb
- lib/gitlab/project_authorizations.rb
- lib/gitlab/sql/**/*.rb
- lib/system_check/**/*.rb
- qa/**/*.rb
- rubocop/**/*.rb
- ee/app/models/**/*.rb
- ee/spec/**/*.rb
- ee/db/fixtures/**/*.rb
- ee/lib/tasks/**/*.rake
- ee/lib/ee/gitlab/background_migration/**/*.rb
......@@ -5,11 +5,13 @@ require 'spec_helper'
RSpec.describe 'User page' do
include ExternalAuthorizationServiceHelpers
let(:user) { create(:user, bio: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') }
let_it_be(:user) { create(:user, bio: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') }
subject { visit(user_path(user)) }
context 'with public profile' do
it 'shows all the tabs' do
visit(user_path(user))
subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
......@@ -22,14 +24,12 @@ RSpec.describe 'User page' do
end
it 'does not show private profile message' do
visit(user_path(user))
subject
expect(page).not_to have_content("This user has a private profile")
end
context 'work information' do
subject { visit(user_path(user)) }
it 'shows job title and organization details' do
user.update(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
......@@ -57,24 +57,24 @@ RSpec.describe 'User page' do
end
context 'with private profile' do
let(:user) { create(:user, private_profile: true) }
let_it_be(:user) { create(:user, private_profile: true) }
it 'shows no tab' do
visit(user_path(user))
subject
expect(page).to have_css("div.profile-header")
expect(page).not_to have_css("ul.nav-links")
end
it 'shows private profile message' do
visit(user_path(user))
subject
expect(page).to have_content("This user has a private profile")
end
it 'shows own tabs' do
sign_in(user)
visit(user_path(user))
subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
......@@ -88,36 +88,36 @@ RSpec.describe 'User page' do
end
context 'with blocked profile' do
let(:user) { create(:user, state: :blocked) }
let_it_be(:user) { create(:user, state: :blocked) }
it 'shows no tab' do
visit(user_path(user))
subject
expect(page).to have_css("div.profile-header")
expect(page).not_to have_css("ul.nav-links")
end
it 'shows blocked message' do
visit(user_path(user))
subject
expect(page).to have_content("This user is blocked")
end
it 'shows user name as blocked' do
visit(user_path(user))
subject
expect(page).to have_css(".cover-title", text: 'Blocked user')
end
it 'shows no additional fields' do
visit(user_path(user))
subject
expect(page).not_to have_css(".profile-user-bio")
expect(page).not_to have_css(".profile-link-holder")
end
it 'shows username' do
visit(user_path(user))
subject
expect(page).to have_content("@#{user.username}")
end
......@@ -126,7 +126,7 @@ RSpec.describe 'User page' do
it 'shows the status if there was one' do
create(:user_status, user: user, message: "Working hard!")
visit(user_path(user))
subject
expect(page).to have_content("Working hard!")
end
......@@ -135,7 +135,7 @@ RSpec.describe 'User page' do
it 'shows the sign in link' do
stub_application_setting(signup_enabled: false)
visit(user_path(user))
subject
page.within '.navbar-nav' do
expect(page).to have_link('Sign in')
......@@ -147,7 +147,7 @@ RSpec.describe 'User page' do
it 'shows the sign in and register link' do
stub_application_setting(signup_enabled: true)
visit(user_path(user))
subject
page.within '.navbar-nav' do
expect(page).to have_link('Sign in / Register')
......@@ -157,7 +157,7 @@ RSpec.describe 'User page' do
context 'most recent activity' do
it 'shows the most recent activity' do
visit(user_path(user))
subject
expect(page).to have_content('Most Recent Activity')
end
......@@ -168,7 +168,7 @@ RSpec.describe 'User page' do
end
it 'hides the most recent activity' do
visit(user_path(user))
subject
expect(page).not_to have_content('Most Recent Activity')
end
......@@ -177,14 +177,14 @@ RSpec.describe 'User page' do
context 'page description' do
before do
visit(user_path(user))
subject
end
it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet'
end
context 'with a bot user' do
let(:user) { create(:user, user_type: :security_bot) }
let_it_be(:user) { create(:user, user_type: :security_bot) }
describe 'feature flag enabled' do
before do
......@@ -192,7 +192,7 @@ RSpec.describe 'User page' do
end
it 'only shows Overview and Activity tabs' do
visit(user_path(user))
subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
......@@ -211,7 +211,7 @@ RSpec.describe 'User page' do
end
it 'only shows Overview and Activity tabs' do
visit(user_path(user))
subject
page.within '.nav-links' do
expect(page).to have_link('Overview')
......@@ -224,4 +224,24 @@ RSpec.describe 'User page' do
end
end
end
context 'structured markup' do
let_it_be(:user) { create(:user, website_url: 'https://gitlab.com', organization: 'GitLab', job_title: 'Frontend Engineer', email: 'public@example.com', public_email: 'public@example.com', location: 'Country', created_at: Time.now, updated_at: Time.now) }
it 'shows Person structured markup' do
subject
aggregate_failures do
expect(page).to have_selector('[itemscope][itemtype="http://schema.org/Person"]')
expect(page).to have_selector('img[itemprop="image"]')
expect(page).to have_selector('[itemprop="name"]')
expect(page).to have_selector('[itemprop="address"][itemscope][itemtype="https://schema.org/PostalAddress"]')
expect(page).to have_selector('[itemprop="addressLocality"]')
expect(page).to have_selector('[itemprop="url"]')
expect(page).to have_selector('[itemprop="email"]')
expect(page).to have_selector('span[itemprop="jobTitle"]')
expect(page).to have_selector('span[itemprop="worksFor"]')
end
end
end
end
......@@ -34,7 +34,7 @@ describe('ConfirmationModal', () => {
'Saving will update the default settings for all projects that are not using custom settings.',
);
expect(findGlModal().text()).toContain(
'Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults.',
'Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults.',
);
});
......
......@@ -9,6 +9,7 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
import { integrationLevels } from '~/integrations/edit/constants';
describe('IntegrationForm', () => {
let wrapper;
......@@ -69,14 +70,24 @@ describe('IntegrationForm', () => {
describe('integrationLevel is instance', () => {
it('renders ConfirmationModal', () => {
createComponent({
integrationLevel: 'instance',
integrationLevel: integrationLevels.INSTANCE,
});
expect(findConfirmationModal().exists()).toBe(true);
});
});
describe('integrationLevel is not instance', () => {
describe('integrationLevel is group', () => {
it('renders ConfirmationModal', () => {
createComponent({
integrationLevel: integrationLevels.GROUP,
});
expect(findConfirmationModal().exists()).toBe(true);
});
});
describe('integrationLevel is project', () => {
it('does not render ConfirmationModal', () => {
createComponent({
integrationLevel: 'project',
......
......@@ -208,4 +208,27 @@ RSpec.describe PageLayoutHelper do
end
end
end
describe '#page_itemtype' do
subject { helper.page_itemtype(itemtype) }
context 'when itemtype is passed' do
let(:itemtype) { 'http://schema.org/Person' }
it 'stores and returns the itemtype value' do
attrs = { itemscope: true, itemtype: itemtype }
expect(subject).to eq attrs
expect(helper.page_itemtype(nil)).to eq attrs
end
end
context 'when no itemtype is provided' do
let(:itemtype) { nil }
it 'returns an empty hash' do
expect(subject).to eq({})
end
end
end
end
......@@ -204,40 +204,72 @@ RSpec.describe UsersHelper do
end
describe '#work_information' do
subject { helper.work_information(user) }
let(:with_schema_markup) { false }
context 'when both job_title and organization are present' do
let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
subject { helper.work_information(user, with_schema_markup: with_schema_markup) }
it 'returns job title concatenated with organization' do
is_expected.to eq('Frontend Engineer at GitLab')
end
context 'when neither organization nor job_title are present' do
it { is_expected.to be_nil }
end
context 'when only organization is present' do
let(:user) { build(:user, organization: 'GitLab') }
context 'when user parameter is nil' do
let(:user) { nil }
it "returns organization" do
is_expected.to eq('GitLab')
end
it { is_expected.to be_nil }
end
context 'when only job_title is present' do
let(:user) { build(:user, job_title: 'Frontend Engineer') }
context 'without schema markup' do
context 'when both job_title and organization are present' do
let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
it 'returns job title' do
is_expected.to eq('Frontend Engineer')
it 'returns job title concatenated with organization' do
is_expected.to eq('Frontend Engineer at GitLab')
end
end
end
context 'when neither organization nor job_title are present' do
it { is_expected.to be_nil }
context 'when only organization is present' do
let(:user) { build(:user, organization: 'GitLab') }
it "returns organization" do
is_expected.to eq('GitLab')
end
end
context 'when only job_title is present' do
let(:user) { build(:user, job_title: 'Frontend Engineer') }
it 'returns job title' do
is_expected.to eq('Frontend Engineer')
end
end
end
context 'when user parameter is nil' do
let(:user) { nil }
context 'with schema markup' do
let(:with_schema_markup) { true }
it { is_expected.to be_nil }
context 'when both job_title and organization are present' do
let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
it 'returns job title concatenated with organization' do
is_expected.to eq('<span itemprop="jobTitle">Frontend Engineer</span> at <span itemprop="worksFor">GitLab</span>')
end
end
context 'when only organization is present' do
let(:user) { build(:user, organization: 'GitLab') }
it "returns organization" do
is_expected.to eq('<span itemprop="worksFor">GitLab</span>')
end
end
context 'when only job_title is present' do
let(:user) { build(:user, job_title: 'Frontend Engineer') }
it 'returns job title' do
is_expected.to eq('<span itemprop="jobTitle">Frontend Engineer</span>')
end
end
end
end
end
......@@ -236,13 +236,16 @@ RSpec.describe Gitlab::Danger::Helper do
'.gitlab/ci/frontend.gitlab-ci.yml' | %i[frontend engineering_productivity]
'app/models/foo' | [:backend]
'bin/foo' | [:backend]
'config/foo' | [:backend]
'lib/foo' | [:backend]
'rubocop/foo' | [:backend]
'spec/foo' | [:backend]
'spec/foo/bar' | [:backend]
'app/models/foo' | [:backend]
'bin/foo' | [:backend]
'config/foo' | [:backend]
'lib/foo' | [:backend]
'rubocop/foo' | [:backend]
'.rubocop.yml' | [:backend]
'.rubocop_todo.yml' | [:backend]
'.rubocop_manual_todo.yml' | [:backend]
'spec/foo' | [:backend]
'spec/foo/bar' | [:backend]
'ee/app/foo' | [:backend]
'ee/bin/foo' | [:backend]
......
......@@ -108,7 +108,7 @@ RSpec.describe Key, :mailer do
expect(build(:key, key: 'ssh-rsa an-invalid-key==')).not_to be_valid
end
where(:factory, :chars, :expected_sections) do
where(:factory, :characters, :expected_sections) do
[
[:key, ["\n", "\r\n"], 3],
[:key, [' ', ' '], 3],
......@@ -122,7 +122,7 @@ RSpec.describe Key, :mailer do
let!(:original_fingerprint_sha256) { key.fingerprint_sha256 }
it 'accepts a key with blank space characters after stripping them' do
modified_key = key.key.insert(100, chars.first).insert(40, chars.last)
modified_key = key.key.insert(100, characters.first).insert(40, characters.last)
_, content = modified_key.split
key.update!(key: modified_key)
......
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/code_reuse/active_record'
RSpec.describe RuboCop::Cop::CodeReuse::ActiveRecord, type: :rubocop do
include CopHelper
subject(:cop) { described_class.new }
it 'flags the use of "where" without any arguments' do
expect_offense(<<~SOURCE)
def foo
User.where
^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
end
SOURCE
end
it 'flags the use of "where" with arguments' do
expect_offense(<<~SOURCE)
def foo
User.where(id: 10)
^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
end
SOURCE
end
it 'does not flag the use of "group" without any arguments' do
expect_no_offenses(<<~SOURCE)
def foo
project.group
end
SOURCE
end
it 'flags the use of "group" with arguments' do
expect_offense(<<~SOURCE)
def foo
project.group(:name)
^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
end
SOURCE
end
it 'does not flag the use of ActiveRecord models in a model' do
path = rails_root_join('app', 'models', 'foo.rb').to_s
expect_no_offenses(<<~SOURCE, path)
def foo
project.group(:name)
end
SOURCE
end
it 'does not flag the use of ActiveRecord models in a spec' do
path = rails_root_join('spec', 'foo_spec.rb').to_s
expect_no_offenses(<<~SOURCE, path)
def foo
project.group(:name)
end
SOURCE
end
it 'does not flag the use of ActiveRecord models in a background migration' do
path = rails_root_join('lib', 'gitlab', 'background_migration', 'foo.rb').to_s
expect_no_offenses(<<~SOURCE, path)
def foo
project.group(:name)
end
SOURCE
end
it 'does not flag the use of ActiveRecord models in lib/gitlab/database' do
path = rails_root_join('lib', 'gitlab', 'database', 'foo.rb').to_s
expect_no_offenses(<<~SOURCE, path)
def foo
project.group(:name)
end
SOURCE
end
it 'autocorrects offenses in instance methods by allowing them' do
corrected = autocorrect_source(<<~SOURCE)
def foo
User.where
end
SOURCE
expect(corrected).to eq(<<~SOURCE)
# rubocop: disable CodeReuse/ActiveRecord
def foo
User.where
end
# rubocop: enable CodeReuse/ActiveRecord
SOURCE
end
it 'autocorrects offenses in class methods by allowing them' do
corrected = autocorrect_source(<<~SOURCE)
def self.foo
User.where
end
SOURCE
expect(corrected).to eq(<<~SOURCE)
# rubocop: disable CodeReuse/ActiveRecord
def self.foo
User.where
end
# rubocop: enable CodeReuse/ActiveRecord
SOURCE
end
it 'autocorrects offenses in blocks by allowing them' do
corrected = autocorrect_source(<<~SOURCE)
get '/' do
User.where
end
SOURCE
expect(corrected).to eq(<<~SOURCE)
# rubocop: disable CodeReuse/ActiveRecord
get '/' do
User.where
end
# rubocop: enable CodeReuse/ActiveRecord
SOURCE
end
end
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/be_success_matcher'
RSpec.describe RuboCop::Cop::RSpec::BeSuccessMatcher, type: :rubocop do
......
# frozen_string_literal: true
require 'tempfile'
# This module provides methods that make it easier to test Cops.
module CopHelper
extend RSpec::SharedContext
let(:ruby_version) { 2.4 }
let(:rails_version) { false }
def inspect_source_file(source)
Tempfile.open('tmp') { |f| inspect_source(source, f) }
end
def inspect_source(source, file = nil)
RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
processed_source = parse_source(source, file)
raise 'Error parsing example code' unless processed_source.valid_syntax?
_investigate(cop, processed_source)
end
def parse_source(source, file = nil)
if file&.respond_to?(:write)
file.write(source)
file.rewind
file = file.path
end
RuboCop::ProcessedSource.new(source, ruby_version, file)
end
def autocorrect_source_file(source)
Tempfile.open('tmp') { |f| autocorrect_source(source, f) }
end
def autocorrect_source(source, file = nil)
RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
cop.instance_variable_get(:@options)[:auto_correct] = true
processed_source = parse_source(source, file)
_investigate(cop, processed_source)
@last_corrector.rewrite
end
def _investigate(cop, processed_source)
team = RuboCop::Cop::Team.new([cop], nil, raise_error: true)
report = team.investigate(processed_source)
@last_corrector = report.correctors.first || RuboCop::Cop::Corrector.new(processed_source)
report.offenses
end
end
module RuboCop
module Cop
# Monkey-patch Cop for tests to provide easy access to messages and
# highlights.
# this file is an exact copy of source except for this line
# where we change to the new Base class defined in rubocop and skirt around our superclass mismatch for class Cop
# when running a rubocop spec.
class Base
def messages
offenses.sort.map(&:message)
end
def highlights
offenses.sort.map { |o| o.location.source }
end
end
end
end
......@@ -5,7 +5,8 @@ require_relative "helpers/stub_metrics"
require_relative "helpers/stub_object_storage"
require_relative "helpers/stub_env"
require_relative "helpers/fast_rails_root"
require 'rubocop/rspec/support'
require_relative 'rubocop_patch'
RSpec.configure do |config|
config.mock_with :rspec
......
# frozen_string_literal: true
# There is an issue between rubocop versions 0.86 and 0.87 (verified by testing locally)
# where the monkey patching in cop_helper is referencing class Cop and should really be referencing class Base instead
# the gem's version of the cop_helper causes this issue when testing a rubocop cop locally and in CI
# The only difference in this file as compared to gem source file is that we include our own cop_helper instead
# which is a direct copy with a fix for the monkey patching part.
# Doing this, resolves the issue.
# Ideally we should move away from using the cop_helper at all as is the direction of rubocop as seen
# here - https://github.com/rubocop-hq/rubocop/issues/8003
# more info https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46477
require_relative 'helpers/cop_helper'
require 'rubocop/rspec/host_environment_simulation_helper'
require 'rubocop/rspec/shared_contexts'
require 'rubocop/rspec/expect_offense'
RSpec.configure do |config|
config.include CopHelper
config.include HostEnvironmentSimulatorHelper
end
......@@ -4,6 +4,6 @@
source 'https://rubygems.org'
gem 'overcommit'
gem 'gitlab-styles', '~> 4.3.0', require: false
gem 'gitlab-styles', '~> 5.0.0', require: false
gem 'scss_lint', '~> 0.56.0', require: false
gem 'haml_lint', '~> 0.34.0', require: false
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.3)
activesupport (6.0.3.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
ast (2.4.0)
ast (2.4.1)
childprocess (3.0.0)
concurrent-ruby (1.1.6)
concurrent-ruby (1.1.7)
ffi (1.12.2)
gitlab-styles (4.3.0)
rubocop (~> 0.82.0)
gitlab-styles (5.0.0)
rubocop (~> 0.89.1)
rubocop-gitlab-security (~> 0.1.0)
rubocop-performance (~> 1.5.2)
rubocop-rails (~> 2.5)
rubocop-rspec (~> 1.36)
rubocop-performance (~> 1.8.1)
rubocop-rails (~> 2.8)
rubocop-rspec (~> 1.44)
haml (5.1.2)
temple (>= 0.8.0)
tilt
......@@ -25,42 +25,47 @@ GEM
rainbow
rubocop (>= 0.50.0)
sysexits (~> 1.1)
i18n (1.8.2)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
iniparse (1.5.0)
jaro_winkler (1.5.4)
minitest (5.11.3)
minitest (5.14.2)
overcommit (0.53.0)
childprocess (>= 0.6.3, < 4)
iniparse (~> 1.4)
parallel (1.19.1)
parser (2.7.1.2)
ast (~> 2.4.0)
rack (2.0.9)
parallel (1.19.2)
parser (2.7.2.0)
ast (~> 2.4.1)
rack (2.2.3)
rainbow (3.0.0)
rake (12.3.3)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
regexp_parser (1.8.2)
rexml (3.2.4)
rubocop (0.82.0)
jaro_winkler (~> 1.5.1)
rubocop (0.89.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
parser (>= 2.7.1.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
rubocop-ast (>= 0.3.0, < 1.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.8.0)
parser (>= 2.7.1.5)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
rubocop-performance (1.5.2)
rubocop (>= 0.71.0)
rubocop-rails (2.5.2)
activesupport
rubocop-performance (1.8.1)
rubocop (>= 0.87.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.8.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 0.72.0)
rubocop-rspec (1.37.0)
rubocop (>= 0.68.1)
rubocop (>= 0.87.0)
rubocop-rspec (1.44.1)
rubocop (~> 0.87)
rubocop-ast (>= 0.7.1)
ruby-progressbar (1.10.1)
sass (3.5.5)
sass-listen (~> 4.0.0)
......@@ -77,13 +82,13 @@ GEM
tzinfo (1.2.7)
thread_safe (~> 0.1)
unicode-display_width (1.7.0)
zeitwerk (2.3.0)
zeitwerk (2.4.1)
PLATFORMS
ruby
DEPENDENCIES
gitlab-styles (~> 4.3.0)
gitlab-styles (~> 5.0.0)
haml_lint (~> 0.34.0)
overcommit
scss_lint (~> 0.56.0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment