Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock6
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js4
-rw-r--r--app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js (renamed from app/assets/javascripts/editor/editor_ci_schema_ext.js)2
-rw-r--r--app/assets/javascripts/editor/extensions/editor_file_template_ext.js (renamed from app/assets/javascripts/editor/editor_file_template_ext.js)0
-rw-r--r--app/assets/javascripts/editor/extensions/editor_lite_extension_base.js (renamed from app/assets/javascripts/editor/editor_lite_extension_base.js)2
-rw-r--r--app/assets/javascripts/editor/extensions/editor_markdown_ext.js (renamed from app/assets/javascripts/editor/editor_markdown_ext.js)0
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js1
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js6
-rw-r--r--app/assets/javascripts/pipeline_editor/components/text_editor.vue2
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue29
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue33
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue (renamed from app/assets/javascripts/projects/pipelines/charts/components/pipelines_area_chart.vue)15
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js10
-rw-r--r--app/assets/javascripts/user_lists/components/user_list_form.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue3
-rw-r--r--app/controllers/concerns/invisible_captcha_on_signup.rb4
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/helpers/application_settings_helper.rb1
-rw-r--r--app/helpers/graph_helper.rb6
-rw-r--r--app/helpers/preferences_helper.rb2
-rw-r--r--app/helpers/web_ide_button_helper.rb4
-rw-r--r--app/models/application_setting.rb7
-rw-r--r--app/models/application_setting_implementation.rb1
-rw-r--r--app/models/concerns/boards/listable.rb46
-rw-r--r--app/models/list.rb36
-rw-r--r--app/presenters/packages/composer/packages_presenter.rb30
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml1
-rw-r--r--app/views/admin/application_settings/_spam.html.haml8
-rw-r--r--app/views/admin/application_settings/reporting.html.haml2
-rw-r--r--app/views/devise/shared/_signup_box.html.haml2
-rw-r--r--app/views/projects/pipelines/charts.html.haml7
-rw-r--r--changelogs/unreleased/258206-remove-gitpod-feature-flag.yml5
-rw-r--r--changelogs/unreleased/290288-composer-cache-prep.yml5
-rw-r--r--changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml5
-rw-r--r--changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml5
-rw-r--r--changelogs/unreleased/feat-flag-copy-change.yml5
-rw-r--r--changelogs/unreleased/invisible-captcha-as-application-setting.yml5
-rw-r--r--changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml5
-rw-r--r--config/feature_flags/development/ci_allow_failure_with_exit_codes.yml2
-rw-r--r--config/feature_flags/development/gitpod.yml8
-rw-r--r--config/feature_flags/development/invisible_captcha.yml8
-rw-r--r--config/feature_flags/development/widget_visibility_polling.yml8
-rw-r--r--db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb19
-rw-r--r--db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb9
-rw-r--r--db/schema_migrations/202012091935511
-rw-r--r--db/schema_migrations/202012291059481
-rw-r--r--db/structure.sql4
-rw-r--r--doc/api/settings.md1
-rw-r--r--doc/ci/yaml/README.md22
-rw-r--r--doc/integration/gitpod.md35
-rw-r--r--doc/user/project/quick_actions.md4
-rw-r--r--lib/api/settings.rb1
-rw-r--r--lib/gitlab/ci/features.rb2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/composer/version_index.rb47
-rw-r--r--lib/gitlab/gitpod.rb26
-rw-r--r--locale/gitlab.pot49
-rw-r--r--package.json2
-rw-r--r--qa/qa/flow/sign_up.rb8
-rw-r--r--spec/controllers/registrations_controller_spec.rb8
-rw-r--r--spec/features/admin/admin_settings_spec.rb31
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb9
-rw-r--r--spec/features/users/signup_spec.rb6
-rw-r--r--spec/frontend/blob_edit/edit_blob_spec.js8
-rw-r--r--spec/frontend/editor/editor_ci_schema_ext_spec.js2
-rw-r--r--spec/frontend/editor/editor_lite_extension_base_spec.js2
-rw-r--r--spec/frontend/editor/editor_lite_spec.js2
-rw-r--r--spec/frontend/editor/editor_markdown_ext_spec.js2
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap (renamed from spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap)2
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js13
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js63
-rw-r--r--spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js (renamed from spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js)15
-rw-r--r--spec/helpers/graph_helper_spec.rb12
-rw-r--r--spec/helpers/tree_helper_spec.rb3
-rw-r--r--spec/lib/gitlab/composer/version_index_spec.rb49
-rw-r--r--spec/lib/gitlab/gitpod_spec.rb73
-rw-r--r--spec/models/list_spec.rb67
-rw-r--r--spec/spec_helper.rb3
-rw-r--r--spec/support/shared_examples/models/boards/listable_shared_examples.rb91
-rw-r--r--yarn.lock8
82 files changed, 613 insertions, 427 deletions
diff --git a/Gemfile b/Gemfile
index 37964d454fa..5b75a346649 100644
--- a/Gemfile
+++ b/Gemfile
@@ -57,7 +57,7 @@ gem 'gssapi', group: :kerberos
# Spam and anti-bot protection
gem 'recaptcha', '~> 4.11', require: 'recaptcha/rails'
gem 'akismet', '~> 3.0'
-gem 'invisible_captcha', '~> 0.12.1'
+gem 'invisible_captcha', '~> 1.1.0'
# Two-factor authentication
gem 'devise-two-factor', '~> 3.1.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 47538b82386..61583a27c72 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -598,8 +598,8 @@ GEM
i18n_data (0.8.0)
icalendar (2.4.1)
ice_nine (0.11.2)
- invisible_captcha (0.12.1)
- rails (>= 3.2.0)
+ invisible_captcha (1.1.0)
+ rails (>= 4.2)
ipaddress (0.8.3)
jaeger-client (1.1.0)
opentracing (~> 0.3)
@@ -1395,7 +1395,7 @@ DEPENDENCIES
html2text
httparty (~> 0.16.4)
icalendar
- invisible_captcha (~> 0.12.1)
+ invisible_captcha (~> 1.1.0)
ipaddress (~> 0.8.3)
jira-ruby (~> 2.1.4)
js_regex (~> 3.4)
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index e73e368fe01..c7f66a357f3 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -5,7 +5,7 @@ import { BLOB_EDITOR_ERROR, BLOB_PREVIEW_ERROR } from './constants';
import TemplateSelectorMediator from '../blob/file_template_mediator';
import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
import EditorLite from '~/editor/editor_lite';
-import { FileTemplateExtension } from '~/editor/editor_file_template_ext';
+import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext';
import { insertFinalNewline } from '~/lib/utils/text_utility';
export default class EditBlob {
@@ -16,7 +16,7 @@ export default class EditBlob {
this.configureMonacoEditor();
if (this.options.isMarkdown) {
- import('~/editor/editor_markdown_ext')
+ import('~/editor/extensions/editor_markdown_ext')
.then(({ EditorMarkdownExtension: MarkdownExtension } = {}) => {
this.editor.use(new MarkdownExtension());
addEditorMarkdownListeners(this.editor);
diff --git a/app/assets/javascripts/editor/editor_ci_schema_ext.js b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
index 36e2fe22718..05d938c57ce 100644
--- a/app/assets/javascripts/editor/editor_ci_schema_ext.js
+++ b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
@@ -1,7 +1,7 @@
import Api from '~/api';
import { registerSchema } from '~/ide/utils';
import { EditorLiteExtension } from './editor_lite_extension_base';
-import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from './constants';
+import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '../constants';
export class CiSchemaExtension extends EditorLiteExtension {
/**
diff --git a/app/assets/javascripts/editor/editor_file_template_ext.js b/app/assets/javascripts/editor/extensions/editor_file_template_ext.js
index f5474318447..f5474318447 100644
--- a/app/assets/javascripts/editor/editor_file_template_ext.js
+++ b/app/assets/javascripts/editor/extensions/editor_file_template_ext.js
diff --git a/app/assets/javascripts/editor/editor_lite_extension_base.js b/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js
index b8d87fa4969..8d350068973 100644
--- a/app/assets/javascripts/editor/editor_lite_extension_base.js
+++ b/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js
@@ -1,4 +1,4 @@
-import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from './constants';
+import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from '../constants';
export class EditorLiteExtension {
constructor({ instance, ...options } = {}) {
diff --git a/app/assets/javascripts/editor/editor_markdown_ext.js b/app/assets/javascripts/editor/extensions/editor_markdown_ext.js
index 2ce003753f7..2ce003753f7 100644
--- a/app/assets/javascripts/editor/editor_markdown_ext.js
+++ b/app/assets/javascripts/editor/extensions/editor_markdown_ext.js
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 8a2b35752ae..cf9ff87f25e 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -103,6 +103,7 @@ class GfmAutoComplete {
at: '/',
alias: 'commands',
searchKey: 'search',
+ limit: 100,
skipSpecialCharacterTest: true,
skipMarkdownCharacterTest: true,
data: GfmAutoComplete.defaultLoadingData,
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index 6f8d954d798..bd283201eff 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -154,7 +154,7 @@ export default class Todos {
goToTodoUrl(e) {
const todoLink = this.dataset.url;
- if (!todoLink || e.target.tagName === 'A' || e.target.tagName === 'IMG') {
+ if (!todoLink || e.target.closest('a')) {
return;
}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
index 90d2df50d5a..40730ec7e60 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
@@ -13,12 +13,12 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line no-new
new Vue({
el,
- render(createElement) {
- return createElement(PipelineSchedulesCallout);
- },
provide: {
docsUrl,
illustrationUrl,
},
+ render(createElement) {
+ return createElement(PipelineSchedulesCallout);
+ },
});
});
diff --git a/app/assets/javascripts/pipeline_editor/components/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/text_editor.vue
index fae08ca89f4..b8d49d77ea9 100644
--- a/app/assets/javascripts/pipeline_editor/components/text_editor.vue
+++ b/app/assets/javascripts/pipeline_editor/components/text_editor.vue
@@ -1,6 +1,6 @@
<script>
import EditorLite from '~/vue_shared/components/editor_lite.vue';
-import { CiSchemaExtension } from '~/editor/editor_ci_schema_ext';
+import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
export default {
components: {
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 4d48468ce88..75f5edbfd2b 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -7,7 +7,8 @@ import { getDateInPast } from '~/lib/utils/datetime_utility';
import getPipelineCountByStatus from '../graphql/queries/get_pipeline_count_by_status.query.graphql';
import getProjectPipelineStatistics from '../graphql/queries/get_project_pipeline_statistics.query.graphql';
import StatisticsList from './statistics_list.vue';
-import PipelinesAreaChart from './pipelines_area_chart.vue';
+import CiCdAnalyticsAreaChart from './ci_cd_analytics_area_chart.vue';
+
import {
CHART_CONTAINER_HEIGHT,
CHART_DATE_FORMAT,
@@ -52,13 +53,19 @@ export default {
GlColumnChart,
GlSkeletonLoader,
StatisticsList,
- PipelinesAreaChart,
+ CiCdAnalyticsAreaChart,
+ DeploymentFrequencyCharts: () =>
+ import('ee_component/projects/pipelines/charts/components/deployment_frequency_charts.vue'),
},
inject: {
projectPath: {
type: String,
default: '',
},
+ shouldRenderDeploymentFrequencyCharts: {
+ type: Boolean,
+ default: false,
+ },
},
data() {
return {
@@ -260,6 +267,15 @@ export default {
lastYear: __('Pipelines for last year'),
};
},
+ areaChartOptions: {
+ xAxis: {
+ name: s__('Pipeline|Date'),
+ type: 'category',
+ },
+ yAxis: {
+ name: s__('Pipeline|Pipelines'),
+ },
+ },
};
</script>
<template>
@@ -292,12 +308,17 @@ export default {
</div>
<hr />
<h4 class="gl-my-4">{{ __('Pipelines charts') }}</h4>
- <pipelines-area-chart
+ <ci-cd-analytics-area-chart
v-for="(chart, index) in areaCharts"
:key="index"
:chart-data="chart.data"
+ :area-chart-options="$options.areaChartOptions"
>
{{ chart.title }}
- </pipelines-area-chart>
+ </ci-cd-analytics-area-chart>
+ <template v-if="shouldRenderDeploymentFrequencyCharts">
+ <hr />
+ <deployment-frequency-charts />
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue b/app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue
index 1a102815e97..915d334f949 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app_legacy.vue
@@ -1,10 +1,11 @@
<script>
import dateFormat from 'dateformat';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import { __, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import { getDateInPast } from '~/lib/utils/datetime_utility';
import StatisticsList from './statistics_list.vue';
-import PipelinesAreaChart from './pipelines_area_chart.vue';
+import CiCdAnalyticsAreaChart from './ci_cd_analytics_area_chart.vue';
+
import {
CHART_CONTAINER_HEIGHT,
INNER_CHART_HEIGHT,
@@ -19,7 +20,15 @@ export default {
components: {
StatisticsList,
GlColumnChart,
- PipelinesAreaChart,
+ CiCdAnalyticsAreaChart,
+ DeploymentFrequencyCharts: () =>
+ import('ee_component/projects/pipelines/charts/components/deployment_frequency_charts.vue'),
+ },
+ inject: {
+ shouldRenderDeploymentFrequencyCharts: {
+ type: Boolean,
+ default: false,
+ },
},
props: {
counts: {
@@ -112,6 +121,15 @@ export default {
lastYear: __('Pipelines for last year'),
};
},
+ areaChartOptions: {
+ xAxis: {
+ name: s__('Pipeline|Date'),
+ type: 'category',
+ },
+ yAxis: {
+ name: s__('Pipeline|Pipelines'),
+ },
+ },
};
</script>
<template>
@@ -140,12 +158,17 @@ export default {
</div>
<hr />
<h4 class="my-4">{{ __('Pipelines charts') }}</h4>
- <pipelines-area-chart
+ <ci-cd-analytics-area-chart
v-for="(chart, index) in areaCharts"
:key="index"
:chart-data="chart.data"
+ :area-chart-options="$options.areaChartOptions"
>
{{ chart.title }}
- </pipelines-area-chart>
+ </ci-cd-analytics-area-chart>
+ <template v-if="shouldRenderDeploymentFrequencyCharts">
+ <hr />
+ <deployment-frequency-charts />
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/pipelines_area_chart.vue b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
index d726196aadf..3590e2c4632 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/pipelines_area_chart.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
@@ -1,10 +1,10 @@
<script>
import { GlAreaChart } from '@gitlab/ui/dist/charts';
-import { s__ } from '~/locale';
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
import { CHART_CONTAINER_HEIGHT } from '../constants';
export default {
+ name: 'CiCdAnalyticsAreaChart',
components: {
GlAreaChart,
ResizableChartContainer,
@@ -14,14 +14,9 @@ export default {
type: Array,
required: true,
},
- },
- areaChartOptions: {
- xAxis: {
- name: s__('Pipeline|Date'),
- type: 'category',
- },
- yAxis: {
- name: s__('Pipeline|Pipelines'),
+ areaChartOptions: {
+ type: Object,
+ required: true,
},
},
chartContainerHeight: CHART_CONTAINER_HEIGHT,
@@ -39,7 +34,7 @@ export default {
:height="$options.chartContainerHeight"
:data="chartData"
:include-legend-avg-max="false"
- :option="$options.areaChartOptions"
+ :option="areaChartOptions"
/>
</resizable-chart-container>
</div>
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index c94a4e6af99..12943e1c3c7 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import { parseBoolean } from '~/lib/utils/common_utils';
import ProjectPipelinesChartsLegacy from './components/app_legacy.vue';
import ProjectPipelinesCharts from './components/app.vue';
@@ -35,6 +36,10 @@ const mountPipelineChartsApp = (el) => {
projectPath,
} = el.dataset;
+ const shouldRenderDeploymentFrequencyCharts = parseBoolean(
+ el.dataset.shouldRenderDeploymentFrequencyCharts,
+ );
+
const parseAreaChartData = (labels, totals, success) => {
let parsedData = {};
@@ -61,6 +66,7 @@ const mountPipelineChartsApp = (el) => {
apolloProvider,
provide: {
projectPath,
+ shouldRenderDeploymentFrequencyCharts,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
@@ -72,6 +78,10 @@ const mountPipelineChartsApp = (el) => {
components: {
ProjectPipelinesChartsLegacy,
},
+ provide: {
+ projectPath,
+ shouldRenderDeploymentFrequencyCharts,
+ },
render: (createElement) =>
createElement(ProjectPipelinesChartsLegacy, {
props: {
diff --git a/app/assets/javascripts/user_lists/components/user_list_form.vue b/app/assets/javascripts/user_lists/components/user_list_form.vue
index 657acb51fee..a0364089d68 100644
--- a/app/assets/javascripts/user_lists/components/user_list_form.vue
+++ b/app/assets/javascripts/user_lists/components/user_list_form.vue
@@ -41,7 +41,7 @@ export default {
],
},
translations: {
- formLabel: s__('UserLists|Feature flag list'),
+ formLabel: s__('UserLists|Feature flag user list'),
formSubtitle: s__(
'UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}',
),
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index cebbc7f2466..4beaa2509d9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -307,8 +307,7 @@ export default {
callback: this.checkStatus,
startingInterval: this.startingPollInterval,
maxInterval: this.startingPollInterval + secondsToMilliseconds(4 * 60),
- hiddenInterval:
- window.gon?.features?.widgetVisibilityPolling && secondsToMilliseconds(6 * 60),
+ hiddenInterval: secondsToMilliseconds(6 * 60),
incrementByFactorOf: 2,
});
},
diff --git a/app/controllers/concerns/invisible_captcha_on_signup.rb b/app/controllers/concerns/invisible_captcha_on_signup.rb
index 9bea6145ff3..c7fd6d08744 100644
--- a/app/controllers/concerns/invisible_captcha_on_signup.rb
+++ b/app/controllers/concerns/invisible_captcha_on_signup.rb
@@ -8,7 +8,7 @@ module InvisibleCaptchaOnSignup
end
def on_honeypot_spam_callback
- return unless Feature.enabled?(:invisible_captcha)
+ return unless Gitlab::CurrentSettings.invisible_captcha_enabled
invisible_captcha_honeypot_counter.increment
log_request('Invisible_Captcha_Honeypot_Request')
@@ -17,7 +17,7 @@ module InvisibleCaptchaOnSignup
end
def on_timestamp_spam_callback
- return unless Feature.enabled?(:invisible_captcha)
+ return unless Gitlab::CurrentSettings.invisible_captcha_enabled
invisible_captcha_timestamp_counter.increment
log_request('Invisible_Captcha_Timestamp_Request')
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 1318c61509d..2a4e382e27a 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -28,7 +28,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
before_action only: [:show] do
- push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true)
push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true)
push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true)
push_frontend_feature_flag(:file_identifier_hash)
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index cc91e2cf809..ed30adfabf0 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -242,6 +242,7 @@ module ApplicationSettingsHelper
:housekeeping_incremental_repack_period,
:html_emails_enabled,
:import_sources,
+ :invisible_captcha_enabled,
:max_artifacts_size,
:max_attachment_size,
:max_import_size,
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index 24072d1ab46..abb3c5a7af8 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -22,4 +22,10 @@ module GraphHelper
ratio = (counts[:success].to_f / (counts[:success] + counts[:failed])) * 100
ratio.to_i
end
+
+ def should_render_deployment_frequency_charts
+ false
+ end
end
+
+GraphHelper.prepend_if_ee('EE::GraphHelper')
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 5310aef5bad..c2a77abb9c9 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -82,7 +82,7 @@ module PreferencesHelper
def integration_views
[].tap do |views|
- views << { name: 'gitpod', message: gitpod_enable_description, message_url: 'https://gitpod.io/', help_link: help_page_path('integration/gitpod.md') } if Gitlab::Gitpod.feature_and_settings_enabled?
+ views << { name: 'gitpod', message: gitpod_enable_description, message_url: 'https://gitpod.io/', help_link: help_page_path('integration/gitpod.md') } if Gitlab::CurrentSettings.gitpod_enabled
views << { name: 'sourcegraph', message: sourcegraph_url_message, message_url: Gitlab::CurrentSettings.sourcegraph_url, help_link: help_page_path('user/profile/preferences.md', anchor: 'sourcegraph') } if Gitlab::Sourcegraph.feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
end
end
diff --git a/app/helpers/web_ide_button_helper.rb b/app/helpers/web_ide_button_helper.rb
index 7aa0adc31bd..6c73d365e8e 100644
--- a/app/helpers/web_ide_button_helper.rb
+++ b/app/helpers/web_ide_button_helper.rb
@@ -26,7 +26,7 @@ module WebIdeButtonHelper
end
def show_gitpod_button?
- show_web_ide_button? && Gitlab::Gitpod.feature_and_settings_enabled?(@project)
+ show_web_ide_button? && Gitlab::CurrentSettings.gitpod_enabled
end
def can_push_code?
@@ -54,7 +54,7 @@ module WebIdeButtonHelper
end
def gitpod_url
- return "" unless Gitlab::Gitpod.feature_and_settings_enabled?(@project)
+ return "" unless Gitlab::CurrentSettings.gitpod_enabled
"#{Gitlab::CurrentSettings.gitpod_url}##{project_tree_url(@project, tree_join(@ref, @path || ''))}"
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index fe4d9776ccb..5655ea4d4bf 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -171,7 +171,7 @@ class ApplicationSetting < ApplicationRecord
validates :default_artifacts_expire_in, presence: true, duration: true
validates :container_expiration_policies_enable_historic_entries,
- inclusion: { in: [true, false], message: 'must be a boolean value' }
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
validates :container_registry_token_expire_delay,
presence: true,
@@ -309,6 +309,9 @@ class ApplicationSetting < ApplicationRecord
validates :container_registry_expiration_policies_worker_capacity,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validates :invisible_captcha_enabled,
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
+
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
@@ -469,7 +472,7 @@ class ApplicationSetting < ApplicationRecord
attr_encrypted :cloud_license_auth_token, encryption_options_base_truncated_aes_256_gcm
validates :disable_feed_token,
- inclusion: { in: [true, false], message: 'must be a boolean value' }
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
before_validation :ensure_uuid!
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index b68125d529a..191f3e3ffa6 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -91,6 +91,7 @@ module ApplicationSettingImplementation
housekeeping_gc_period: 200,
housekeeping_incremental_repack_period: 10,
import_sources: Settings.gitlab['import_sources'],
+ invisible_captcha_enabled: false,
issues_create_limit: 300,
local_markdown_version: 0,
login_recaptcha_protection_enabled: false,
diff --git a/app/models/concerns/boards/listable.rb b/app/models/concerns/boards/listable.rb
new file mode 100644
index 00000000000..013669a1444
--- /dev/null
+++ b/app/models/concerns/boards/listable.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Boards
+ module Listable
+ extend ActiveSupport::Concern
+
+ included do
+ validates :label, :position, presence: true, if: :label?
+ validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :movable?
+
+ before_destroy :can_be_destroyed
+
+ scope :ordered, -> { order(:list_type, :position) }
+ scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
+ scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
+ end
+
+ class_methods do
+ def destroyable_types
+ [:label]
+ end
+
+ def movable_types
+ [:label]
+ end
+ end
+
+ def destroyable?
+ self.class.destroyable_types.include?(list_type&.to_sym)
+ end
+
+ def movable?
+ self.class.movable_types.include?(list_type&.to_sym)
+ end
+
+ def title
+ label? ? label.name : list_type.humanize
+ end
+
+ private
+
+ def can_be_destroyed
+ throw(:abort) unless destroyable? # rubocop:disable Cop/BanCatchThrow
+ end
+ end
+end
diff --git a/app/models/list.rb b/app/models/list.rb
index 1df565c83e6..49834af3dfb 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class List < ApplicationRecord
+ include Boards::Listable
include Importable
belongs_to :board
@@ -10,30 +11,13 @@ class List < ApplicationRecord
enum list_type: { backlog: 0, label: 1, closed: 2, assignee: 3, milestone: 4, iteration: 5 }
validates :board, :list_type, presence: true, unless: :importing?
- validates :label, :position, presence: true, if: :label?
validates :label_id, uniqueness: { scope: :board_id }, if: :label?
- validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :movable?
-
- before_destroy :can_be_destroyed
-
- scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
- scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
scope :preload_associated_models, -> { preload(:board, label: :priorities) }
- scope :ordered, -> { order(:list_type, :position) }
-
alias_method :preferences, :list_user_preferences
class << self
- def destroyable_types
- [:label]
- end
-
- def movable_types
- [:label]
- end
-
def preload_preferences_for_user(lists, user)
return unless user
@@ -60,18 +44,6 @@ class List < ApplicationRecord
preferences_for(user).update(preferences)
end
- def destroyable?
- self.class.destroyable_types.include?(list_type&.to_sym)
- end
-
- def movable?
- self.class.movable_types.include?(list_type&.to_sym)
- end
-
- def title
- label? ? label.name : list_type.humanize
- end
-
def collapsed?(user)
preferences = preferences_for(user)
@@ -95,12 +67,6 @@ class List < ApplicationRecord
end
end
end
-
- private
-
- def can_be_destroyed
- throw(:abort) unless destroyable? # rubocop:disable Cop/BanCatchThrow
- end
end
List.prepend_if_ee('::EE::List')
diff --git a/app/presenters/packages/composer/packages_presenter.rb b/app/presenters/packages/composer/packages_presenter.rb
index cce006cbb1a..ed0e9d3b731 100644
--- a/app/presenters/packages/composer/packages_presenter.rb
+++ b/app/presenters/packages/composer/packages_presenter.rb
@@ -20,33 +20,17 @@ module Packages
end
def package_versions(packages = @packages)
- { 'packages' => { packages.first.name => package_versions_map(packages) } }
+ package_versions_index(packages).as_json
end
private
- def package_versions_map(packages)
- packages.each_with_object({}) do |package, map|
- map[package.version] = package_metadata(package)
- end
+ def package_versions_sha(packages = @packages)
+ package_versions_index(packages).sha
end
- def package_metadata(package)
- json = package.composer_metadatum.composer_json
-
- json.merge('dist' => package_dist(package), 'uid' => package.id, 'version' => package.version)
- end
-
- def package_dist(package)
- sha = package.composer_metadatum.target_sha
- archive_api_path = api_v4_projects_packages_composer_archives_package_name_path({ id: package.project_id, package_name: package.name, format: '.zip' }, true)
-
- {
- 'type' => 'zip',
- 'url' => expose_url(archive_api_path) + "?sha=#{sha}",
- 'reference' => sha,
- 'shasum' => ''
- }
+ def package_versions_index(packages)
+ ::Gitlab::Composer::VersionIndex.new(packages)
end
def providers_map
@@ -59,10 +43,6 @@ module Packages
map
end
- def package_versions_sha(packages)
- Digest::SHA256.hexdigest(package_versions(packages).to_json)
- end
-
def provider_sha
Digest::SHA256.hexdigest(provider.to_json)
end
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index 1baec07fa25..7f78cce4575 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -1,4 +1,3 @@
-- return unless Gitlab::Gitpod.feature_available?
- expanded = integration_expanded?('gitpod_')
%section.settings.no-animate#js-gitpod-settings{ class: ('expanded' if expanded) }
diff --git a/app/views/admin/application_settings/_spam.html.haml b/app/views/admin/application_settings/_spam.html.haml
index b54f1d7c829..2b871d3693c 100644
--- a/app/views/admin/application_settings/_spam.html.haml
+++ b/app/views/admin/application_settings/_spam.html.haml
@@ -30,6 +30,14 @@
.form-group
.form-check
+ = f.check_box :invisible_captcha_enabled, class: 'form-check-input'
+ = f.label :invisible_captcha_enabled, class: 'form-check-label' do
+ = _('Enable Invisible Captcha during sign up')
+ %span.form-text.text-muted
+ = _('Helps prevent bots from creating accounts.')
+
+ .form-group
+ .form-check
= f.check_box :akismet_enabled, class: 'form-check-input'
= f.label :akismet_enabled, class: 'form-check-label' do
Enable Akismet
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index c60e44b3864..6ea139844d4 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -11,7 +11,7 @@
%p
- recaptcha_v2_link_url = 'https://developers.google.com/recaptcha/docs/versions'
- recaptcha_v2_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: recaptcha_v2_link_url }
- = _('Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}').html_safe % { recaptcha_v2_link_start: recaptcha_v2_link_start, recaptcha_v2_link_end: '</a>'.html_safe }
+ = _('Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}').html_safe % { recaptcha_v2_link_start: recaptcha_v2_link_start, recaptcha_v2_link_end: '</a>'.html_safe }
.settings-content
= render 'spam'
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 3c4cbbbc3bd..acbf3b398b0 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -10,7 +10,7 @@
= form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- - if Feature.enabled?(:invisible_captcha)
+ - if Gitlab::CurrentSettings.invisible_captcha_enabled
= invisible_captcha
.name.form-row
.col.form-group
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index f3360e150ad..711928c963b 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,10 +1,13 @@
- page_title _('CI / CD Analytics')
- if Feature.enabled?(:graphql_pipeline_analytics)
- #js-project-pipelines-charts-app{ data: { project_path: @project.full_path } }
+ #js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
+ should_render_deployment_frequency_charts: should_render_deployment_frequency_charts.to_s } }
- else
#js-project-pipelines-charts-app{ data: { counts: @counts, success_ratio: success_ratio(@counts),
times_chart: { labels: @charts[:pipeline_times].labels, values: @charts[:pipeline_times].pipeline_times },
last_week_chart: { labels: @charts[:week].labels, totals: @charts[:week].total, success: @charts[:week].success },
last_month_chart: { labels: @charts[:month].labels, totals: @charts[:month].total, success: @charts[:month].success },
- last_year_chart: { labels: @charts[:year].labels, totals: @charts[:year].total, success: @charts[:year].success } } }
+ last_year_chart: { labels: @charts[:year].labels, totals: @charts[:year].total, success: @charts[:year].success },
+ project_path: @project.full_path,
+ should_render_deployment_frequency_charts: should_render_deployment_frequency_charts.to_s } }
diff --git a/changelogs/unreleased/258206-remove-gitpod-feature-flag.yml b/changelogs/unreleased/258206-remove-gitpod-feature-flag.yml
new file mode 100644
index 00000000000..1ca19a5431f
--- /dev/null
+++ b/changelogs/unreleased/258206-remove-gitpod-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Add configurable Gitpod button within projcet repository page
+merge_request: 51197
+author:
+type: added
diff --git a/changelogs/unreleased/290288-composer-cache-prep.yml b/changelogs/unreleased/290288-composer-cache-prep.yml
new file mode 100644
index 00000000000..c6925a60910
--- /dev/null
+++ b/changelogs/unreleased/290288-composer-cache-prep.yml
@@ -0,0 +1,5 @@
+---
+title: Add version cache field to composer metadata
+merge_request: 50906
+author:
+type: other
diff --git a/changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml b/changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml
new file mode 100644
index 00000000000..a7e1f625817
--- /dev/null
+++ b/changelogs/unreleased/292393-include-all-available-quick-actions-in-autocomplete.yml
@@ -0,0 +1,5 @@
+---
+title: Show all quick actions in `/` autocomplete
+merge_request: 51239
+author:
+type: added
diff --git a/changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml b/changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml
new file mode 100644
index 00000000000..44e439b80d7
--- /dev/null
+++ b/changelogs/unreleased/ci-enable-allow-failure-exit-codes.yml
@@ -0,0 +1,5 @@
+---
+title: Control job status using exit codes
+merge_request: 51439
+author:
+type: added
diff --git a/changelogs/unreleased/feat-flag-copy-change.yml b/changelogs/unreleased/feat-flag-copy-change.yml
new file mode 100644
index 00000000000..48994845ee1
--- /dev/null
+++ b/changelogs/unreleased/feat-flag-copy-change.yml
@@ -0,0 +1,5 @@
+---
+title: Update copy on Feature Flags List view to be more descriptive for users
+merge_request: 50813
+author: Sarah Rosenshine
+type: other
diff --git a/changelogs/unreleased/invisible-captcha-as-application-setting.yml b/changelogs/unreleased/invisible-captcha-as-application-setting.yml
new file mode 100644
index 00000000000..4d9153cfb8a
--- /dev/null
+++ b/changelogs/unreleased/invisible-captcha-as-application-setting.yml
@@ -0,0 +1,5 @@
+---
+title: Add setting to enable Invisible Captcha
+merge_request: 50650
+author:
+type: added
diff --git a/changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml b/changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml
new file mode 100644
index 00000000000..7878397fff9
--- /dev/null
+++ b/changelogs/unreleased/run_dast_job_even_if_the_user_isnt_licensed_290958.yml
@@ -0,0 +1,5 @@
+---
+title: Update the DAST latest template to run when configured even if the user doesn't have sufficient permission
+merge_request: 51279
+author:
+type: changed
diff --git a/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml b/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml
index c2701705616..1d33a162445 100644
--- a/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml
+++ b/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292024
milestone: '13.7'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/gitpod.yml b/config/feature_flags/development/gitpod.yml
deleted file mode 100644
index 616aae4be45..00000000000
--- a/config/feature_flags/development/gitpod.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitpod
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37985
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258206
-milestone: '13.4'
-type: development
-group: group::editor
-default_enabled: true
diff --git a/config/feature_flags/development/invisible_captcha.yml b/config/feature_flags/development/invisible_captcha.yml
deleted file mode 100644
index bfe118c1826..00000000000
--- a/config/feature_flags/development/invisible_captcha.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invisible_captcha
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31625
-rollout_issue_url:
-milestone: '12.2'
-type: development
-group: group::acquisition
-default_enabled: false
diff --git a/config/feature_flags/development/widget_visibility_polling.yml b/config/feature_flags/development/widget_visibility_polling.yml
deleted file mode 100644
index 3021388b17f..00000000000
--- a/config/feature_flags/development/widget_visibility_polling.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: widget_visibility_polling
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29318
-rollout_issue_url:
-milestone: '12.10'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb b/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb
new file mode 100644
index 00000000000..62d0cdae8bc
--- /dev/null
+++ b/db/migrate/20201209193551_add_version_sha_cache_to_composer_metadata.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddVersionShaCacheToComposerMetadata < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :packages_composer_metadata, :version_cache_sha, :binary, null: true
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :packages_composer_metadata, :version_cache_sha, :binary
+ end
+ end
+end
diff --git a/db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb b/db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb
new file mode 100644
index 00000000000..025fcba0729
--- /dev/null
+++ b/db/migrate/20201229105948_add_invisible_captcha_enabled_to_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddInvisibleCaptchaEnabledToSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :invisible_captcha_enabled, :boolean, null: false, default: false
+ end
+end
diff --git a/db/schema_migrations/20201209193551 b/db/schema_migrations/20201209193551
new file mode 100644
index 00000000000..2eb96840500
--- /dev/null
+++ b/db/schema_migrations/20201209193551
@@ -0,0 +1 @@
+2278b1e4e19b5306e4b616eb87b622427ef2dcf73dae761739cb3106d5e64718 \ No newline at end of file
diff --git a/db/schema_migrations/20201229105948 b/db/schema_migrations/20201229105948
new file mode 100644
index 00000000000..73da30d5392
--- /dev/null
+++ b/db/schema_migrations/20201229105948
@@ -0,0 +1 @@
+cf391e617ef16f70c0daa4584959d36eda4b29c7e211f3f90ad74b4ebbc7ebbd \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 4d1c265a05f..1fe523e5138 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -9388,6 +9388,7 @@ CREATE TABLE application_settings (
disable_feed_token boolean DEFAULT false NOT NULL,
personal_access_token_prefix text,
rate_limiting_response_text text,
+ invisible_captcha_enabled boolean DEFAULT false NOT NULL,
container_registry_cleanup_tags_service_max_list_size integer DEFAULT 200 NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
@@ -14711,7 +14712,8 @@ ALTER SEQUENCE packages_build_infos_id_seq OWNED BY packages_build_infos.id;
CREATE TABLE packages_composer_metadata (
package_id bigint NOT NULL,
target_sha bytea NOT NULL,
- composer_json jsonb DEFAULT '{}'::jsonb NOT NULL
+ composer_json jsonb DEFAULT '{}'::jsonb NOT NULL,
+ version_cache_sha bytea
);
CREATE TABLE packages_conan_file_metadata (
diff --git a/doc/api/settings.md b/doc/api/settings.md
index a71f49e724e..253381b3d50 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -300,6 +300,7 @@ listed in the descriptions of the relevant settings.
| `housekeeping_incremental_repack_period` | integer | required by: `housekeeping_enabled` | Number of Git pushes after which an incremental `git repack` is run. |
| `html_emails_enabled` | boolean | no | Enable HTML emails. |
| `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `bitbucket_server`, `gitlab`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. |
+| `invisible_captcha_enabled` | boolean | no | Enable Invisible Captcha spam detection during signup. Disabled by default. |
| `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.|
| `local_markdown_version` | integer | no | Increase this value when any cached Markdown should be invalidated. |
| `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode |
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 20c6941686a..f47124d3c07 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -2278,10 +2278,10 @@ job3:
#### `allow_failure:exit_codes`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273157) in GitLab 13.8.
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-allow_failureexit_codes). **(CORE ONLY)**
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-allow_failureexit_codes). **(CORE ONLY)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -2310,21 +2310,21 @@ test_job_2:
##### Enable or disable `allow_failure:exit_codes` **(CORE ONLY)**
-`allow_failure:exit_codes` is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
+`allow_failure:exit_codes` is under development but ready for production use. It 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 enable it.
+can disable it.
-To enable it:
+To disable it:
```ruby
-Feature.enable(:ci_allow_failure_with_exit_codes)
+Feature.disable(:ci_allow_failure_with_exit_codes)
```
-To disable it:
+To enable it:
```ruby
-Feature.disable(:ci_allow_failure_with_exit_codes)
+Feature.enable(:ci_allow_failure_with_exit_codes)
```
### `when`
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index 04274c1c015..05f129e6049 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -8,14 +8,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
# Gitpod Integration
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228893) in GitLab 13.4.
-> - It was [deployed behind a feature flag](#enable-or-disable-the-gitpod-integration), disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/258206) in GitLab 13.5.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#configure-your-gitlab-instance-with-gitpod). **(CORE ONLY)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/258206) in GitLab 13.8
With [Gitpod](https://gitpod.io/) you can describe your dev environment as code to get fully set
up, compiled, and tested dev environments for any GitLab project. The dev environments are not only
@@ -48,28 +41,14 @@ can follow the same steps once the integration has been enabled and configured b
## Configure your GitLab instance with Gitpod **(CORE ONLY)**
-If you are new to Gitpod, head over to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/)
-and get your instance up and running.
+The integration of Gitpod with GitLab is enabled on GitLab.com and available to all users.
+For GitLab self-managed instances, a GitLab administrator needs to enable it through the admin settings.
+
+First, you (GitLab admin) need to set up a Gitpod instance to integrate with GitLab.
+Head over to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/) to
+get your instance up and running. Once done:
1. In GitLab, go to **Admin Area > Settings > General**.
1. Expand the **Gitpod** configuration section.
1. Check **Enable Gitpod**.
1. Add your Gitpod instance URL (for example, `https://gitpod.example.com`).
-
-## Enable or disable the Gitpod integration **(CORE ONLY)**
-
-The Gitpod integration 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 enable or disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:gitpod)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:gitpod)
-```
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 56299f80ef0..a8cbc5a5aff 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -9,8 +9,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Introduced in [GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26672):
> once an action is executed, an alert appears when a quick action is successfully applied.
-> - In [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877) and later, you can use
+> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877): you can use
> quick actions when updating the description of issues, epics, and merge requests.
+> - Introduced in [GitLab 13.8](https://gitlab.com/gitlab-org/gitlab/-/issues/292393): when you enter
+> `/` into a description or comment field, all available quick actions are displayed in a scrollable list.
Quick actions are textual shortcuts for common actions on issues, epics, merge requests,
and commits that are usually done by clicking buttons or dropdowns in the GitLab UI.
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index b3f09b431b0..f329a94adf2 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -91,6 +91,7 @@ module API
optional :import_sources, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce,
values: %w[github bitbucket bitbucket_server gitlab google_code fogbugz git gitlab_project gitea manifest phabricator],
desc: 'Enabled sources for code import during project creation. OmniAuth must be configured for GitHub, Bitbucket, and GitLab.com'
+ optional :invisible_captcha_enabled, type: Boolean, desc: 'Enable Invisible Captcha spam detection during signup.'
optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size for each job's artifacts"
optional :max_attachment_size, type: Integer, desc: 'Maximum attachment size in MB'
optional :max_import_size, type: Integer, desc: 'Maximum import size in MB'
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index c96bc435957..e78e29422ea 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -64,7 +64,7 @@ module Gitlab
end
def self.allow_failure_with_exit_codes_enabled?
- ::Feature.enabled?(:ci_allow_failure_with_exit_codes)
+ ::Feature.enabled?(:ci_allow_failure_with_exit_codes, default_enabled: :yaml)
end
def self.rules_variables_enabled?(project)
diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
index dc3e1ab5ef8..fc1acd09714 100644
--- a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -38,8 +38,6 @@ dast:
$CI_KUBERNETES_ACTIVE &&
$GITLAB_FEATURES =~ /\bdast\b/
- if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdast\b/ &&
$DAST_WEBSITE
- if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdast\b/ &&
$DAST_API_SPECIFICATION
diff --git a/lib/gitlab/composer/version_index.rb b/lib/gitlab/composer/version_index.rb
new file mode 100644
index 00000000000..de9a17a453f
--- /dev/null
+++ b/lib/gitlab/composer/version_index.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Composer
+ class VersionIndex
+ include API::Helpers::RelatedResourcesHelpers
+
+ def initialize(packages)
+ @packages = packages
+ end
+
+ def as_json(_options = nil)
+ { 'packages' => { @packages.first.name => package_versions_map } }
+ end
+
+ def sha
+ Digest::SHA256.hexdigest(to_json)
+ end
+
+ private
+
+ def package_versions_map
+ @packages.each_with_object({}) do |package, map|
+ map[package.version] = package_metadata(package)
+ end
+ end
+
+ def package_metadata(package)
+ json = package.composer_metadatum.composer_json
+
+ json.merge('dist' => package_dist(package), 'uid' => package.id, 'version' => package.version)
+ end
+
+ def package_dist(package)
+ sha = package.composer_metadatum.target_sha
+ archive_api_path = api_v4_projects_packages_composer_archives_package_name_path({ id: package.project_id, package_name: package.name, format: '.zip' }, true)
+
+ {
+ 'type' => 'zip',
+ 'url' => expose_url(archive_api_path) + "?sha=#{sha}",
+ 'reference' => sha,
+ 'shasum' => ''
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/gitpod.rb b/lib/gitlab/gitpod.rb
deleted file mode 100644
index e35fb8fed02..00000000000
--- a/lib/gitlab/gitpod.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class Gitpod
- class << self
- def feature_available?
- # The gitpod_bundle feature could be conditionally applied, so check if `!off?`
- !feature.off? || feature_enabled?
- end
-
- def feature_enabled?(actor = nil)
- Feature.enabled?(:gitpod, actor, default_enabled: true)
- end
-
- def feature_and_settings_enabled?(actor = nil)
- feature_enabled?(actor) && Gitlab::CurrentSettings.gitpod_enabled
- end
-
- private
-
- def feature
- Feature.get(:gitpod) # rubocop:disable Gitlab/AvoidFeatureGet
- end
- end
- end
-end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 34530f07f9e..7e3c89201bf 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8827,6 +8827,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8914,6 +8917,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8923,6 +8929,9 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
@@ -8941,6 +8950,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8950,6 +8962,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8962,6 +8977,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9604,6 +9622,27 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10605,6 +10644,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10692,7 +10734,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -30677,7 +30719,7 @@ msgstr ""
msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
msgstr ""
-msgid "UserLists|Feature flag list"
+msgid "UserLists|Feature flag user list"
msgstr ""
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
@@ -33849,6 +33891,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
diff --git a/package.json b/package.json
index 47669e7ed8d..14cb6d04d8f 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.178.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "25.7.3",
+ "@gitlab/ui": "25.8.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-4",
"@rails/ujs": "^6.0.3-4",
diff --git a/qa/qa/flow/sign_up.rb b/qa/qa/flow/sign_up.rb
index 2fd42e8345a..b367b7976e8 100644
--- a/qa/qa/flow/sign_up.rb
+++ b/qa/qa/flow/sign_up.rb
@@ -14,14 +14,6 @@ module QA
sign_up.fill_new_user_username_field(user.username)
sign_up.fill_new_user_email_field(user.email)
sign_up.fill_new_user_password_field(user.password)
-
- # Because invisible_captcha would prevent submitting this form
- # within 4 seconds, sleep here. This can be removed once we
- # implement invisible_captcha as an application setting instead
- # of a feature flag, so we can turn it off while testing.
- # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/284113
- sleep 5
-
sign_up.click_new_user_register_button
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 2fb17e56f37..737ec4f95c5 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -6,7 +6,6 @@ RSpec.describe RegistrationsController do
include TermsHelper
before do
- stub_feature_flags(invisible_captcha: false)
stub_application_setting(require_admin_approval_after_user_signup: false)
end
@@ -193,15 +192,10 @@ RSpec.describe RegistrationsController do
context 'when invisible captcha is enabled' do
before do
- stub_feature_flags(invisible_captcha: true)
- InvisibleCaptcha.timestamp_enabled = true
+ stub_application_setting(invisible_captcha_enabled: true)
InvisibleCaptcha.timestamp_threshold = treshold
end
- after do
- InvisibleCaptcha.timestamp_enabled = false
- end
-
let(:treshold) { 4 }
let(:session_params) { { invisible_captcha_timestamp: form_rendered_time.iso8601 } }
let(:form_rendered_time) { Time.current }
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 06d31b544ea..0c66775c323 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -17,10 +17,7 @@ RSpec.describe 'Admin updates settings' do
end
context 'General page' do
- let(:gitpod_feature_enabled) { true }
-
before do
- stub_feature_flags(gitpod: gitpod_feature_enabled)
visit general_admin_application_settings_path
end
@@ -224,28 +221,16 @@ RSpec.describe 'Admin updates settings' do
end
context 'Configure Gitpod' do
- context 'with feature disabled' do
- let(:gitpod_feature_enabled) { false }
-
- it 'do not show settings' do
- expect(page).not_to have_selector('#js-gitpod-settings')
+ it 'changes gitpod settings' do
+ page.within('#js-gitpod-settings') do
+ check 'Enable Gitpod integration'
+ fill_in 'Gitpod URL', with: 'https://gitpod.test/'
+ click_button 'Save changes'
end
- end
-
- context 'with feature enabled' do
- let(:gitpod_feature_enabled) { true }
- it 'changes gitpod settings' do
- page.within('#js-gitpod-settings') do
- check 'Enable Gitpod integration'
- fill_in 'Gitpod URL', with: 'https://gitpod.test/'
- click_button 'Save changes'
- end
-
- expect(page).to have_content 'Application settings saved successfully'
- expect(current_settings.gitpod_url).to eq('https://gitpod.test/')
- expect(current_settings.gitpod_enabled).to be(true)
- end
+ expect(page).to have_content 'Application settings saved successfully'
+ expect(current_settings.gitpod_url).to eq('https://gitpod.test/')
+ expect(current_settings.gitpod_enabled).to be(true)
end
end
end
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 64c056deca5..9b2a11c4b0e 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -294,6 +294,15 @@ RSpec.describe 'GFM autocomplete', :js do
user_item = find('.atwho-view li', text: user.username)
expect(user_item).to have_content(user.username)
end
+
+ it 'does not limit quick actions autocomplete list to 5' do
+ note = find('#note-body')
+ page.within '.timeline-content-form' do
+ note.native.send_keys('/')
+ end
+
+ expect(page).to have_selector('.atwho-view li', minimum: 6, visible: true)
+ end
end
context 'assignees' do
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index bfdd1e1bdb7..5f70517224e 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -294,17 +294,13 @@ RSpec.describe 'Signup' do
context 'when reCAPTCHA and invisible captcha are enabled' do
before do
- InvisibleCaptcha.timestamp_enabled = true
+ stub_application_setting(invisible_captcha_enabled: true)
stub_application_setting(recaptcha_enabled: true)
allow_next_instance_of(RegistrationsController) do |instance|
allow(instance).to receive(:verify_recaptcha).and_return(true)
end
end
- after do
- InvisibleCaptcha.timestamp_enabled = false
- end
-
context 'when reCAPTCHA detects malicious behaviour' do
before do
allow_next_instance_of(RegistrationsController) do |instance|
diff --git a/spec/frontend/blob_edit/edit_blob_spec.js b/spec/frontend/blob_edit/edit_blob_spec.js
index f1f22010a2a..7927c14d2ac 100644
--- a/spec/frontend/blob_edit/edit_blob_spec.js
+++ b/spec/frontend/blob_edit/edit_blob_spec.js
@@ -1,12 +1,12 @@
import waitForPromises from 'helpers/wait_for_promises';
import EditBlob from '~/blob_edit/edit_blob';
import EditorLite from '~/editor/editor_lite';
-import { EditorMarkdownExtension } from '~/editor/editor_markdown_ext';
-import { FileTemplateExtension } from '~/editor/editor_file_template_ext';
+import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext';
+import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext';
jest.mock('~/editor/editor_lite');
-jest.mock('~/editor/editor_markdown_ext');
-jest.mock('~/editor/editor_file_template_ext');
+jest.mock('~/editor/extensions/editor_markdown_ext');
+jest.mock('~/editor/extensions/editor_file_template_ext');
describe('Blob Editing', () => {
const useMock = jest.fn();
diff --git a/spec/frontend/editor/editor_ci_schema_ext_spec.js b/spec/frontend/editor/editor_ci_schema_ext_spec.js
index f9a1070f601..4d65b77cdfc 100644
--- a/spec/frontend/editor/editor_ci_schema_ext_spec.js
+++ b/spec/frontend/editor/editor_ci_schema_ext_spec.js
@@ -1,6 +1,6 @@
import { languages } from 'monaco-editor';
import EditorLite from '~/editor/editor_lite';
-import { CiSchemaExtension } from '~/editor/editor_ci_schema_ext';
+import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants';
describe('~/editor/editor_ci_config_ext', () => {
diff --git a/spec/frontend/editor/editor_lite_extension_base_spec.js b/spec/frontend/editor/editor_lite_extension_base_spec.js
index 8261864b7a2..5490e9dc7b5 100644
--- a/spec/frontend/editor/editor_lite_extension_base_spec.js
+++ b/spec/frontend/editor/editor_lite_extension_base_spec.js
@@ -1,5 +1,5 @@
import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from '~/editor/constants';
-import { EditorLiteExtension } from '~/editor/editor_lite_extension_base';
+import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base';
describe('The basis for an Editor Lite extension', () => {
let ext;
diff --git a/spec/frontend/editor/editor_lite_spec.js b/spec/frontend/editor/editor_lite_spec.js
index 7d8acd8599a..c3099997287 100644
--- a/spec/frontend/editor/editor_lite_spec.js
+++ b/spec/frontend/editor/editor_lite_spec.js
@@ -2,7 +2,7 @@
import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
import waitForPromises from 'helpers/wait_for_promises';
import Editor from '~/editor/editor_lite';
-import { EditorLiteExtension } from '~/editor/editor_lite_extension_base';
+import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
import { EDITOR_LITE_INSTANCE_ERROR_NO_EL, URI_PREFIX } from '~/editor/constants';
diff --git a/spec/frontend/editor/editor_markdown_ext_spec.js b/spec/frontend/editor/editor_markdown_ext_spec.js
index f3b5add0b70..3f64dcfd7a0 100644
--- a/spec/frontend/editor/editor_markdown_ext_spec.js
+++ b/spec/frontend/editor/editor_markdown_ext_spec.js
@@ -1,6 +1,6 @@
import { Range, Position } from 'monaco-editor';
import EditorLite from '~/editor/editor_lite';
-import { EditorMarkdownExtension } from '~/editor/editor_markdown_ext';
+import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext';
describe('Markdown Extension for Editor Lite', () => {
let editor;
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
index d68e009f46e..fc51825f15b 100644
--- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap
+++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`PipelinesAreaChart matches the snapshot 1`] = `
+exports[`CiCdAnalyticsAreaChart matches the snapshot 1`] = `
<div
class="gl-mt-3"
>
diff --git a/spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js b/spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js
index c03b571eb26..99d0e910485 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_legacy_spec.js
@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
import Component from '~/projects/pipelines/charts/components/app_legacy.vue';
import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
-import PipelinesAreaChart from '~/projects/pipelines/charts/components/pipelines_area_chart.vue';
+import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
import {
counts,
timesChartData,
@@ -23,6 +23,13 @@ describe('ProjectsPipelinesChartsApp', () => {
lastMonthChartData,
lastYearChartData,
},
+ provide: {
+ projectPath: 'test/project',
+ shouldRenderDeploymentFrequencyCharts: true,
+ },
+ stubs: {
+ DeploymentFrequencyCharts: true,
+ },
});
});
@@ -52,12 +59,12 @@ describe('ProjectsPipelinesChartsApp', () => {
describe('pipelines charts', () => {
it('displays 3 area charts', () => {
- expect(wrapper.findAll(PipelinesAreaChart).length).toBe(3);
+ expect(wrapper.findAll(CiCdAnalyticsAreaChart).length).toBe(3);
});
describe('displays individual correctly', () => {
it('renders with the correct data', () => {
- const charts = wrapper.findAll(PipelinesAreaChart);
+ const charts = wrapper.findAll(CiCdAnalyticsAreaChart);
for (let i = 0; i < charts.length; i += 1) {
const chart = charts.at(i);
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 977d1caa2b6..1313a549f02 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -1,10 +1,11 @@
+import { merge } from 'lodash';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
import Component from '~/projects/pipelines/charts/components/app.vue';
import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
-import PipelinesAreaChart from '~/projects/pipelines/charts/components/pipelines_area_chart.vue';
+import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
import getPipelineCountByStatus from '~/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql';
import getProjectPipelineStatistics from '~/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql';
import { mockPipelineCount, mockPipelineStatistics } from '../mock_data';
@@ -13,6 +14,8 @@ const projectPath = 'gitlab-org/gitlab';
const localVue = createLocalVue();
localVue.use(VueApollo);
+const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
+
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
@@ -25,21 +28,29 @@ describe('ProjectsPipelinesChartsApp', () => {
return createMockApollo(requestHandlers);
}
- function createComponent(options = {}) {
- const { fakeApollo } = options;
-
- return shallowMount(Component, {
- provide: {
- projectPath,
- },
- localVue,
- apolloProvider: fakeApollo,
- });
+ function createComponent(mountOptions = {}) {
+ wrapper = shallowMount(
+ Component,
+ merge(
+ {},
+ {
+ provide: {
+ projectPath,
+ shouldRenderDeploymentFrequencyCharts: false,
+ },
+ localVue,
+ apolloProvider: createMockApolloProvider(),
+ stubs: {
+ DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
+ },
+ },
+ mountOptions,
+ ),
+ );
}
beforeEach(() => {
- const fakeApollo = createMockApolloProvider();
- wrapper = createComponent({ fakeApollo });
+ createComponent();
});
afterEach(() => {
@@ -73,12 +84,12 @@ describe('ProjectsPipelinesChartsApp', () => {
describe('pipelines charts', () => {
it('displays 3 area charts', () => {
- expect(wrapper.findAll(PipelinesAreaChart)).toHaveLength(3);
+ expect(wrapper.findAll(CiCdAnalyticsAreaChart)).toHaveLength(3);
});
describe('displays individual correctly', () => {
it('renders with the correct data', () => {
- const charts = wrapper.findAll(PipelinesAreaChart);
+ const charts = wrapper.findAll(CiCdAnalyticsAreaChart);
for (let i = 0; i < charts.length; i += 1) {
const chart = charts.at(i);
@@ -92,4 +103,26 @@ describe('ProjectsPipelinesChartsApp', () => {
});
});
});
+
+ const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
+
+ describe('when shouldRenderDeploymentFrequencyCharts is true', () => {
+ beforeEach(() => {
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ });
+
+ it('renders the deployment frequency charts', () => {
+ expect(findDeploymentFrequencyCharts().exists()).toBe(true);
+ });
+ });
+
+ describe('when shouldRenderDeploymentFrequencyCharts is false', () => {
+ beforeEach(() => {
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: false } });
+ });
+
+ it('does not render the deployment frequency charts', () => {
+ expect(findDeploymentFrequencyCharts().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js
index aea25903023..64f80300237 100644
--- a/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js
@@ -1,14 +1,23 @@
import { mount } from '@vue/test-utils';
-import Component from '~/projects/pipelines/charts/components/pipelines_area_chart.vue';
+import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
import { transformedAreaChartData } from '../mock_data';
-describe('PipelinesAreaChart', () => {
+describe('CiCdAnalyticsAreaChart', () => {
let wrapper;
beforeEach(() => {
- wrapper = mount(Component, {
+ wrapper = mount(CiCdAnalyticsAreaChart, {
propsData: {
chartData: transformedAreaChartData,
+ areaChartOptions: {
+ xAxis: {
+ name: 'X axis title',
+ type: 'category',
+ },
+ yAxis: {
+ name: 'Y axis title',
+ },
+ },
},
slots: {
default: 'Some title',
diff --git a/spec/helpers/graph_helper_spec.rb b/spec/helpers/graph_helper_spec.rb
index 3c7e4f970c3..682f6365481 100644
--- a/spec/helpers/graph_helper_spec.rb
+++ b/spec/helpers/graph_helper_spec.rb
@@ -15,4 +15,16 @@ RSpec.describe GraphHelper do
expect(refs).to match('master')
end
end
+
+ describe '#should_render_deployment_frequency_charts' do
+ let(:project) { create(:project, :private) }
+
+ before do
+ self.instance_variable_set(:@project, project)
+ end
+
+ it 'always returns false' do
+ expect(should_render_deployment_frequency_charts).to be(false)
+ end
+ end
end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index 136ec07e73d..6cb9894e306 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -330,9 +330,8 @@ RSpec.describe TreeHelper do
end
end
- context 'gitpod feature is enabled' do
+ context 'gitpod settings is enabled' do
before do
- stub_feature_flags(gitpod: true)
allow(Gitlab::CurrentSettings)
.to receive(:gitpod_enabled)
.and_return(true)
diff --git a/spec/lib/gitlab/composer/version_index_spec.rb b/spec/lib/gitlab/composer/version_index_spec.rb
new file mode 100644
index 00000000000..4c4742d9f59
--- /dev/null
+++ b/spec/lib/gitlab/composer/version_index_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Composer::VersionIndex do
+ let_it_be(:package_name) { 'sample-project' }
+ let_it_be(:json) { { 'name' => package_name } }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :custom_repo, files: { 'composer.json' => json.to_json }, group: group) }
+ let_it_be(:package1) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let_it_be(:package2) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '2.0.0', json: json) }
+
+ let(:branch) { project.repository.find_branch('master') }
+
+ let(:packages) { [package1, package2] }
+
+ describe '#as_json' do
+ subject(:index) { described_class.new(packages).as_json }
+
+ def expected_json(package)
+ {
+ 'dist' => {
+ 'reference' => branch.target,
+ 'shasum' => '',
+ 'type' => 'zip',
+ 'url' => "http://localhost/api/v4/projects/#{project.id}/packages/composer/archives/#{package.name}.zip?sha=#{branch.target}"
+ },
+ 'name' => package.name,
+ 'uid' => package.id,
+ 'version' => package.version
+ }
+ end
+
+ it 'returns the packages json' do
+ packages = index['packages'][package_name]
+
+ expect(packages['1.0.0']).to eq(expected_json(package1))
+ expect(packages['2.0.0']).to eq(expected_json(package2))
+ end
+ end
+
+ describe '#sha' do
+ subject(:sha) { described_class.new(packages).sha }
+
+ it 'returns the json SHA' do
+ expect(sha).to match /^[A-Fa-f0-9]{64}$/
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gitpod_spec.rb b/spec/lib/gitlab/gitpod_spec.rb
deleted file mode 100644
index 717e396f942..00000000000
--- a/spec/lib/gitlab/gitpod_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Gitpod do
- let_it_be(:user) { create(:user) }
-
- before do
- stub_feature_flags(gitpod: feature_scope)
- end
-
- describe '.feature_available?' do
- subject { described_class.feature_available? }
-
- context 'when feature has not been set' do
- let(:feature_scope) { nil }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is disabled' do
- let(:feature_scope) { false }
-
- it { is_expected.to be_falsey }
- end
-
- context 'when feature is enabled globally' do
- let(:feature_scope) { true }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is enabled only to a resource' do
- let(:feature_scope) { user }
-
- it { is_expected.to be_truthy }
- end
- end
-
- describe '.feature_enabled?' do
- let(:current_user) { nil }
-
- subject { described_class.feature_enabled?(current_user) }
-
- context 'when feature has not been set' do
- let(:feature_scope) { nil }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is enabled globally' do
- let(:feature_scope) { true }
-
- it { is_expected.to be_truthy }
- end
-
- context 'when feature is enabled only to a resource' do
- let(:feature_scope) { user }
-
- context 'for the same resource' do
- let(:current_user) { user }
-
- it { is_expected.to be_truthy }
- end
-
- context 'for a different resource' do
- let(:current_user) { create(:user) }
-
- it { is_expected.to be_falsey }
- end
- end
- end
-end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
index 37158584062..f0b1bc33e84 100644
--- a/spec/models/list_spec.rb
+++ b/spec/models/list_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe List do
it_behaves_like 'having unique enum values'
+ it_behaves_like 'boards listable model', :list
describe 'relationships' do
it { is_expected.to belong_to(:board) }
@@ -14,72 +15,6 @@ RSpec.describe List do
it { is_expected.to validate_presence_of(:board) }
it { is_expected.to validate_presence_of(:label) }
it { is_expected.to validate_presence_of(:list_type) }
- it { is_expected.to validate_presence_of(:position) }
- it { is_expected.to validate_numericality_of(:position).only_integer.is_greater_than_or_equal_to(0) }
-
- context 'when list_type is set to closed' do
- subject { described_class.new(list_type: :closed) }
-
- it { is_expected.not_to validate_presence_of(:label) }
- it { is_expected.not_to validate_presence_of(:position) }
- end
- end
-
- describe '#destroy' do
- it 'can be destroyed when list_type is set to label' do
- subject = create(:list)
-
- expect(subject.destroy).to be_truthy
- end
-
- it 'can not be destroyed when list_type is set to closed' do
- subject = create(:closed_list)
-
- expect(subject.destroy).to be_falsey
- end
- end
-
- describe '#destroyable?' do
- it 'returns true when list_type is set to label' do
- subject.list_type = :label
-
- expect(subject).to be_destroyable
- end
-
- it 'returns false when list_type is set to closed' do
- subject.list_type = :closed
-
- expect(subject).not_to be_destroyable
- end
- end
-
- describe '#movable?' do
- it 'returns true when list_type is set to label' do
- subject.list_type = :label
-
- expect(subject).to be_movable
- end
-
- it 'returns false when list_type is set to closed' do
- subject.list_type = :closed
-
- expect(subject).not_to be_movable
- end
- end
-
- describe '#title' do
- it 'returns label name when list_type is set to label' do
- subject.list_type = :label
- subject.label = Label.new(name: 'Development')
-
- expect(subject.title).to eq 'Development'
- end
-
- it 'returns Closed when list_type is set to closed' do
- subject.list_type = :closed
-
- expect(subject.title).to eq 'Closed'
- end
end
describe '#update_preferences_for' do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c5560ea462f..9fac6c8e192 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -369,8 +369,5 @@ end
# Prevent Rugged from picking up local developer gitconfig.
Rugged::Settings['search_path_global'] = Rails.root.join('tmp/tests').to_s
-# Disable timestamp checks for invisible_captcha
-InvisibleCaptcha.timestamp_enabled = false
-
# Initialize FactoryDefault to use create_default helper
TestProf::FactoryDefault.init
diff --git a/spec/support/shared_examples/models/boards/listable_shared_examples.rb b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
new file mode 100644
index 00000000000..49b00076a46
--- /dev/null
+++ b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'boards listable model' do |list_factory|
+ subject { build(list_factory) }
+
+ describe 'associations' do
+ it { is_expected.to validate_presence_of(:position) }
+ it { is_expected.to validate_numericality_of(:position).only_integer.is_greater_than_or_equal_to(0) }
+
+ context 'when list_type is set to closed' do
+ subject { build(list_factory, list_type: :closed) }
+
+ it { is_expected.not_to validate_presence_of(:label) }
+ it { is_expected.not_to validate_presence_of(:position) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.ordered' do
+ it 'returns lists ordered by type and position' do
+ # rubocop:disable Rails/SaveBang
+ lists = [
+ create(list_factory, list_type: :backlog),
+ create(list_factory, list_type: :closed),
+ create(list_factory, position: 1),
+ create(list_factory, position: 2)
+ ]
+ # rubocop:enable Rails/SaveBang
+
+ expect(described_class.where(id: lists).ordered).to eq([lists[0], lists[2], lists[3], lists[1]])
+ end
+ end
+ end
+
+ describe '#destroyable?' do
+ it 'returns true when list_type is set to label' do
+ subject.list_type = :label
+
+ expect(subject).to be_destroyable
+ end
+
+ it 'returns false when list_type is set to closed' do
+ subject.list_type = :closed
+
+ expect(subject).not_to be_destroyable
+ end
+ end
+
+ describe '#movable?' do
+ it 'returns true when list_type is set to label' do
+ subject.list_type = :label
+
+ expect(subject).to be_movable
+ end
+
+ it 'returns false when list_type is set to closed' do
+ subject.list_type = :closed
+
+ expect(subject).not_to be_movable
+ end
+ end
+
+ describe '#title' do
+ it 'returns label name when list_type is set to label' do
+ subject.list_type = :label
+ subject.label = Label.new(name: 'Development')
+
+ expect(subject.title).to eq 'Development'
+ end
+
+ it 'returns Closed when list_type is set to closed' do
+ subject.list_type = :closed
+
+ expect(subject.title).to eq 'Closed'
+ end
+ end
+
+ describe '#destroy' do
+ it 'can be destroyed when list_type is set to label' do
+ subject = create(list_factory) # rubocop:disable Rails/SaveBang
+
+ expect(subject.destroy).to be_truthy
+ end
+
+ it 'can not be destroyed when list_type is set to closed' do
+ subject = create(list_factory, list_type: :closed) # rubocop:disable Rails/SaveBang
+
+ expect(subject.destroy).to be_falsey
+ end
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index 9e2fbe129f3..21d2280c7da 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -876,10 +876,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@25.7.3":
- version "25.7.3"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.7.3.tgz#abc5caa585c307f38e01a7f061d9da0bc238acd0"
- integrity sha512-Ia+Pqmy4tQ5oztxXSjViM6YMt13MGyrQ6dqOn3zsiKG9RLh9kSBMtCif9jA0dDT17P+HMIdBYxYc6rTRjbfC0w==
+"@gitlab/ui@25.8.0":
+ version "25.8.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.8.0.tgz#038090bc56215d2b0e5526097e1a16b0089ba5f4"
+ integrity sha512-h84StVkrviIm1cMDmGb2+Q8R+U6wCjddz7IXKpgkTNitxYzAcwPSIp7cS1FkZ6eWEG9dVeB6uj7JpUhGqAzvfw==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"