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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-14 00:10:04 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-14 00:10:04 +0300
commit3825437c53474e3d6f3a7d82ef4f26583212531e (patch)
tree1bb207713ff4e28c10a9a9e3f7c9d3e509001733
parentc787c1559e9e558b83e78354823eb54b9fe8c718 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/layout_nav.js2
-rw-r--r--app/assets/javascripts/whats_new/components/app.vue29
-rw-r--r--app/assets/javascripts/whats_new/components/trigger.vue19
-rw-r--r--app/assets/javascripts/whats_new/index.js32
-rw-r--r--app/assets/javascripts/whats_new/store/actions.js10
-rw-r--r--app/assets/javascripts/whats_new/store/index.js13
-rw-r--r--app/assets/javascripts/whats_new/store/mutation_types.js2
-rw-r--r--app/assets/javascripts/whats_new/store/mutations.js10
-rw-r--r--app/assets/javascripts/whats_new/store/state.js3
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss1
-rw-r--r--app/graphql/mutations/boards/lists/update.rb52
-rw-r--r--app/graphql/resolvers/ci_configuration/sast_resolver.rb17
-rw-r--r--app/graphql/types/board_list_type.rb23
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/graphql/types/project_type.rb4
-rw-r--r--app/models/project_services/prometheus_service.rb8
-rw-r--r--app/services/projects/update_pages_configuration_service.rb5
-rw-r--r--app/services/projects/update_service.rb2
-rw-r--r--app/services/web_hook_service.rb5
-rw-r--r--app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json76
-rw-r--r--app/views/layouts/header/_default.html.haml3
-rw-r--r--app/views/shared/web_hooks/_form.html.haml6
-rw-r--r--changelogs/unreleased/229764-graphql-reorder-lists-within-a-board.yml5
-rw-r--r--changelogs/unreleased/233109-http-timeout-handling-improvements.yml5
-rw-r--r--changelogs/unreleased/235106-board-list-graphql.yml5
-rw-r--r--changelogs/unreleased/25344-fire-webhook-on-new-deployment-2.yml5
-rw-r--r--changelogs/unreleased/ajk-enable-design_management_reference_filter_gfm_pipeline.yml5
-rw-r--r--changelogs/unreleased/coverage_fuzzing_usage_ping.yml5
-rw-r--r--changelogs/unreleased/jarv-env-for-disabling-unstructured-log.yml5
-rw-r--r--changelogs/unreleased/update-ado-image-to-v1-0-0.yml5
-rw-r--r--config/initializers/lograge.rb2
-rw-r--r--db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb38
-rw-r--r--db/schema_migrations/202007211405071
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/environment_variables.md1
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql69
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json207
-rw-r--r--doc/api/graphql/reference/index.md17
-rw-r--r--doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.pngbin0 -> 298542 bytes
-rw-r--r--doc/user/compliance/compliance_dashboard/index.md14
-rw-r--r--doc/user/project/issues/design_management.md14
-rw-r--r--lib/banzai/filter/design_reference_filter.rb2
-rw-r--r--lib/gitlab/app_logger.rb6
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml2
-rw-r--r--lib/gitlab/prometheus_client.rb2
-rw-r--r--locale/gitlab.pot27
-rw-r--r--spec/controllers/projects/hooks_controller_spec.rb3
-rw-r--r--spec/features/registrations/experience_level_spec.rb35
-rw-r--r--spec/frontend/whats_new/components/app_spec.js57
-rw-r--r--spec/frontend/whats_new/components/trigger_spec.js43
-rw-r--r--spec/frontend/whats_new/store/actions_spec.js17
-rw-r--r--spec/frontend/whats_new/store/mutations_spec.js25
-rw-r--r--spec/graphql/mutations/boards/lists/update_spec.rb56
-rw-r--r--spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb28
-rw-r--r--spec/graphql/types/board_list_type_spec.rb2
-rw-r--r--spec/graphql/types/project_type_spec.rb90
-rw-r--r--spec/lib/gitlab/app_logger_spec.rb8
-rw-r--r--spec/requests/api/graphql/mutations/boards/lists/update_spec.rb57
-rw-r--r--spec/services/projects/update_pages_configuration_service_spec.rb79
-rw-r--r--spec/services/projects/update_service_spec.rb25
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast.yml13
-rw-r--r--spec/support/shared_contexts/read_ci_configuration_shared_context.rb9
64 files changed, 1050 insertions, 268 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index a78697498ca..c415db06b25 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-187f550dce577f1fb39503976a30a73a58b2b8e1
+1fc116768ec27739965f6394d2fd2eddea22f621
diff --git a/app/assets/javascripts/layout_nav.js b/app/assets/javascripts/layout_nav.js
index 4314e5e1afb..0ecf3301250 100644
--- a/app/assets/javascripts/layout_nav.js
+++ b/app/assets/javascripts/layout_nav.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import ContextualSidebar from './contextual_sidebar';
import initFlyOutNav from './fly_out_nav';
+import initWhatsNew from '~/whats_new';
function hideEndFade($scrollingTabs) {
$scrollingTabs.each(function scrollTabsLoop() {
@@ -20,6 +21,7 @@ export default function initLayoutNav() {
contextualSidebar.bindEvents();
initFlyOutNav();
+ initWhatsNew();
// We need to init it on DomContentLoaded as others could also call it
$(document).on('init.scrolling-tabs', () => {
diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue
new file mode 100644
index 00000000000..d974556cb9e
--- /dev/null
+++ b/app/assets/javascripts/whats_new/components/app.vue
@@ -0,0 +1,29 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { GlDrawer } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDrawer,
+ },
+ computed: {
+ ...mapState(['open']),
+ },
+ methods: {
+ ...mapActions(['closeDrawer']),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-drawer class="mt-6" :open="open" @close="closeDrawer">
+ <template #header>
+ <h4>{{ __("What's new at GitLab") }}</h4>
+ </template>
+ <template>
+ <div></div>
+ </template>
+ </gl-drawer>
+ </div>
+</template>
diff --git a/app/assets/javascripts/whats_new/components/trigger.vue b/app/assets/javascripts/whats_new/components/trigger.vue
new file mode 100644
index 00000000000..e6c48e92888
--- /dev/null
+++ b/app/assets/javascripts/whats_new/components/trigger.vue
@@ -0,0 +1,19 @@
+<script>
+import { mapActions } from 'vuex';
+import { GlButton } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlButton,
+ },
+ methods: {
+ ...mapActions(['openDrawer']),
+ },
+};
+</script>
+
+<template>
+ <li>
+ <gl-button variant="link" @click="openDrawer">{{ __("See what's new at GitLab") }}</gl-button>
+ </li>
+</template>
diff --git a/app/assets/javascripts/whats_new/index.js b/app/assets/javascripts/whats_new/index.js
new file mode 100644
index 00000000000..c9ee3404d2a
--- /dev/null
+++ b/app/assets/javascripts/whats_new/index.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import App from './components/app.vue';
+import Trigger from './components/trigger.vue';
+import store from './store';
+
+export default () => {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: document.getElementById('whats-new-app'),
+ store,
+ components: {
+ App,
+ },
+
+ render(createElement) {
+ return createElement('app');
+ },
+ });
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: document.getElementById('whats-new-trigger'),
+ store,
+ components: {
+ Trigger,
+ },
+
+ render(createElement) {
+ return createElement('trigger');
+ },
+ });
+};
diff --git a/app/assets/javascripts/whats_new/store/actions.js b/app/assets/javascripts/whats_new/store/actions.js
new file mode 100644
index 00000000000..53488413d9e
--- /dev/null
+++ b/app/assets/javascripts/whats_new/store/actions.js
@@ -0,0 +1,10 @@
+import * as types from './mutation_types';
+
+export default {
+ closeDrawer({ commit }) {
+ commit(types.CLOSE_DRAWER);
+ },
+ openDrawer({ commit }) {
+ commit(types.OPEN_DRAWER);
+ },
+};
diff --git a/app/assets/javascripts/whats_new/store/index.js b/app/assets/javascripts/whats_new/store/index.js
new file mode 100644
index 00000000000..aea980060aa
--- /dev/null
+++ b/app/assets/javascripts/whats_new/store/index.js
@@ -0,0 +1,13 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import actions from './actions';
+import mutations from './mutations';
+import state from './state';
+
+Vue.use(Vuex);
+
+export default new Vuex.Store({
+ actions,
+ mutations,
+ state,
+});
diff --git a/app/assets/javascripts/whats_new/store/mutation_types.js b/app/assets/javascripts/whats_new/store/mutation_types.js
new file mode 100644
index 00000000000..daa65230101
--- /dev/null
+++ b/app/assets/javascripts/whats_new/store/mutation_types.js
@@ -0,0 +1,2 @@
+export const CLOSE_DRAWER = 'CLOSE_DRAWER';
+export const OPEN_DRAWER = 'OPEN_DRAWER';
diff --git a/app/assets/javascripts/whats_new/store/mutations.js b/app/assets/javascripts/whats_new/store/mutations.js
new file mode 100644
index 00000000000..f7e84ee81a9
--- /dev/null
+++ b/app/assets/javascripts/whats_new/store/mutations.js
@@ -0,0 +1,10 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.CLOSE_DRAWER](state) {
+ state.open = false;
+ },
+ [types.OPEN_DRAWER](state) {
+ state.open = true;
+ },
+};
diff --git a/app/assets/javascripts/whats_new/store/state.js b/app/assets/javascripts/whats_new/store/state.js
new file mode 100644
index 00000000000..97089a095f1
--- /dev/null
+++ b/app/assets/javascripts/whats_new/store/state.js
@@ -0,0 +1,3 @@
+export default {
+ open: false,
+};
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 32c276ea6d2..6b742853f8f 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -312,6 +312,7 @@
> a,
button,
+ .gl-button.btn-link,
.menu-item {
@include dropdown-link;
}
diff --git a/app/graphql/mutations/boards/lists/update.rb b/app/graphql/mutations/boards/lists/update.rb
new file mode 100644
index 00000000000..7efed3058b3
--- /dev/null
+++ b/app/graphql/mutations/boards/lists/update.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Boards
+ module Lists
+ class Update < BaseMutation
+ graphql_name 'UpdateBoardList'
+
+ argument :list_id, GraphQL::ID_TYPE,
+ required: true,
+ loads: Types::BoardListType,
+ description: 'Global ID of the list.'
+
+ argument :position, GraphQL::INT_TYPE,
+ required: false,
+ description: 'Position of list within the board'
+
+ argument :collapsed, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Indicates if list is collapsed for this user'
+
+ field :list,
+ Types::BoardListType,
+ null: true,
+ description: 'Mutated list'
+
+ def resolve(list: nil, **args)
+ raise_resource_not_available_error! unless can_read_list?(list)
+ update_result = update_list(list, args)
+
+ {
+ list: update_result[:list],
+ errors: list.errors.full_messages
+ }
+ end
+
+ private
+
+ def update_list(list, args)
+ service = ::Boards::Lists::UpdateService.new(list.board, current_user, args)
+ service.execute(list)
+ end
+
+ def can_read_list?(list)
+ return false unless list.present?
+
+ Ability.allowed?(current_user, :read_list, list.board)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci_configuration/sast_resolver.rb b/app/graphql/resolvers/ci_configuration/sast_resolver.rb
deleted file mode 100644
index e8c42076ea2..00000000000
--- a/app/graphql/resolvers/ci_configuration/sast_resolver.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require "json"
-
-module Resolvers
- module CiConfiguration
- class SastResolver < BaseResolver
- SAST_UI_SCHEMA_PATH = 'app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json'
-
- type ::Types::CiConfiguration::Sast::Type, null: true
-
- def resolve(**args)
- Gitlab::Json.parse(File.read(Rails.root.join(SAST_UI_SCHEMA_PATH)))
- end
- end
- end
-end
diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb
index 781fd55c41e..70c0794fc90 100644
--- a/app/graphql/types/board_list_type.rb
+++ b/app/graphql/types/board_list_type.rb
@@ -3,6 +3,8 @@
module Types
# rubocop: disable Graphql/AuthorizeTypes
class BoardListType < BaseObject
+ include Gitlab::Utils::StrongMemoize
+
graphql_name 'BoardList'
description 'Represents a list for an issue board'
@@ -19,10 +21,31 @@ module Types
field :collapsed, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if list is collapsed for this user',
resolve: -> (list, _args, ctx) { list.collapsed?(ctx[:current_user]) }
+ field :issues_count, GraphQL::INT_TYPE, null: true,
+ description: 'Count of issues in the list'
field :issues, ::Types::IssueType.connection_type, null: true,
description: 'Board issues',
resolver: ::Resolvers::BoardListIssuesResolver
+
+ def issues_count
+ metadata[:size]
+ end
+
+ def total_weight
+ metadata[:total_weight]
+ end
+
+ def metadata
+ strong_memoize(:metadata) do
+ list = self.object
+ user = context[:current_user]
+
+ Boards::Issues::ListService
+ .new(list.board.resource_parent, user, board_id: list.board_id, id: list.id)
+ .metadata
+ end
+ end
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index ea0e3a8adb7..e143d14676e 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -16,6 +16,7 @@ module Types
mount_mutation Mutations::AwardEmojis::Toggle
mount_mutation Mutations::Boards::Issues::IssueMoveList
mount_mutation Mutations::Boards::Lists::Create
+ mount_mutation Mutations::Boards::Lists::Update
mount_mutation Mutations::Branches::Create, calls_gitaly: true
mount_mutation Mutations::Commits::Create, calls_gitaly: true
mount_mutation Mutations::Discussions::ToggleResolve
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 523e019b955..5562db69de6 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -175,10 +175,6 @@ module Types
description: 'A single environment of the project',
resolver: Resolvers::EnvironmentsResolver.single
- field :sast_ci_configuration, ::Types::CiConfiguration::Sast::Type, null: true,
- description: 'SAST CI configuration for the project',
- resolver: ::Resolvers::CiConfiguration::SastResolver
-
field :issue,
Types::IssueType,
null: true,
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index 997c6eba91a..950cd4f6859 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -97,7 +97,13 @@ class PrometheusService < MonitoringService
def prometheus_client
return unless should_return_client?
- options = { allow_local_requests: allow_local_api_url? }
+ options = {
+ allow_local_requests: allow_local_api_url?,
+ # We should choose more conservative timeouts, but some queries we run are now busting our
+ # default timeouts, which are stricter. We should make those queries faster instead.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/233109
+ timeout: 60
+ }
if behind_iap?
# Adds the Authorization header
diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb
index 1f07d52ed4e..88c17d502df 100644
--- a/app/services/projects/update_pages_configuration_service.rb
+++ b/app/services/projects/update_pages_configuration_service.rb
@@ -11,6 +11,11 @@ module Projects
end
def execute
+ # If the pages were never deployed, we can't write out the config, as the
+ # directory would not exist.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/235139
+ return success unless project.pages_deployed?
+
unless file_equals?(pages_config_file, pages_config_json)
update_file(pages_config_file, pages_config_json)
reload_daemon
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 53c8489474b..c9ba7cde199 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -142,6 +142,8 @@ module Projects
end
def update_pages_config
+ return unless project.pages_deployed?
+
if Feature.enabled?(:async_update_pages_config, project)
PagesUpdateConfigurationWorker.perform_async(project.id)
else
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 792b71b577f..d6cb0729d6f 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -55,16 +55,17 @@ class WebHookService
message: response.to_s
}
rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep, Gitlab::Json::LimitedEncoder::LimitExceeded => e
+ execution_duration = Gitlab::Metrics::System.monotonic_time - start_time
log_execution(
trigger: hook_name,
url: hook.url,
request_data: data,
response: InternalErrorResponse.new,
- execution_duration: Gitlab::Metrics::System.monotonic_time - start_time,
+ execution_duration: execution_duration,
error_message: e.to_s
)
- Gitlab::AppLogger.error("WebHook Error => #{e}")
+ Gitlab::AppLogger.error("WebHook Error after #{execution_duration.to_i.seconds}s => #{e}")
{
status: :error,
diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
index cce2b28529f..aa4dd60a9fb 100644
--- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
+++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
@@ -4,83 +4,43 @@
"field" : "SECURE_ANALYZERS_PREFIX",
"label" : "Image prefix",
"type": "string",
- "default_value": "registry.gitlab.com/gitlab-org/security-products/analyzers",
- "value": ""
+ "default_value": "",
+ "value": "",
+ "description": "Analyzer image's registry prefix (or Name of the registry providing the analyzers' image)"
},
{
"field" : "SAST_EXCLUDED_PATHS",
"label" : "Excluded Paths",
"type": "string",
- "default_value": "spec, test, tests, tmp",
- "value": ""
+ "default_value": "",
+ "value": "",
+ "description": "Comma-separated list of paths to be excluded from analyzer output. Patterns can be globs, file paths, or folder paths."
},
{
"field" : "SAST_ANALYZER_IMAGE_TAG",
"label" : "Image tag",
"type": "string",
- "options": [],
- "default_value": "2",
- "value": ""
- },
- {
- "field" : "SAST_DISABLED",
- "label" : "Disable SAST",
- "type": "options",
- "options": [
- {
- "value" :"true",
- "label" : "true (disables SAST)"
- },
- {
- "value":"false",
- "label":"false (enables SAST)"
- }
- ],
- "default_value": "false",
- "value": ""
+ "default_value": "",
+ "value": "",
+ "description": "Analyzer image's tag"
}
],
"pipeline": [
{
"field" : "stage",
"label" : "Stage",
- "type": "dropdown",
- "options": [
- {
- "value" :"test",
- "label" : "test"
- },
- {
- "value":"build",
- "label":"build"
- }
- ],
- "default_value": "test",
- "value": ""
- },
- {
- "field" : "allow_failure",
- "label" : "Allow Failure",
- "type": "options",
- "options": [
- {
- "value" :"true",
- "label" : "Allows pipeline failure"
- },
- {
- "value": "false",
- "label": "Does not allow pipeline failure"
- }
- ],
- "default_value": "true",
- "value": ""
+ "type": "string",
+ "default_value": "",
+ "value": "",
+ "description": "Pipeline stage in which the scan jobs run"
},
{
- "field" : "rules",
- "label" : "Rules",
- "type": "multiline",
+ "field" : "SEARCH_MAX_DEPTH",
+ "label" : "Search maximum depth",
+ "type": "string",
"default_value": "",
- "value": ""
+ "value": "",
+ "description": "Maximum depth of language and framework detection"
}
],
"analyzers": [
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index a191eb8cbdb..ea5a663a654 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -84,5 +84,8 @@
= sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
= sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
+- if ::Feature.enabled?(:whats_new_drawer)
+ #whats-new-app
+
- if can?(current_user, :update_user_status, current_user)
.js-set-status-modal-wrapper{ data: { current_emoji: current_user.status.present? ? current_user.status.emoji : '', current_message: current_user.status.present? ? current_user.status.message : '' } }
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index ce85cbd7f07..0f6188fa334 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -72,6 +72,12 @@
%strong Wiki Page events
%p.text-muted.ml-1
This URL will be triggered when a wiki page is created/updated
+ %li
+ = form.check_box :deployment_events, class: 'form-check-input'
+ = form.label :deployment_events, class: 'list-label form-check-label ml-1' do
+ %strong= s_('Webhooks|Deployment events')
+ %p.text-muted.ml-1
+ = s_('Webhooks|This URL will be triggered when a deployment is finished/failed/canceled')
.form-group
= form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox'
.form-check
diff --git a/changelogs/unreleased/229764-graphql-reorder-lists-within-a-board.yml b/changelogs/unreleased/229764-graphql-reorder-lists-within-a-board.yml
new file mode 100644
index 00000000000..8b0276614fa
--- /dev/null
+++ b/changelogs/unreleased/229764-graphql-reorder-lists-within-a-board.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL mutation for updating board list position and collapsed/expanded state.
+merge_request: 38942
+author:
+type: added
diff --git a/changelogs/unreleased/233109-http-timeout-handling-improvements.yml b/changelogs/unreleased/233109-http-timeout-handling-improvements.yml
new file mode 100644
index 00000000000..253f6eb4514
--- /dev/null
+++ b/changelogs/unreleased/233109-http-timeout-handling-improvements.yml
@@ -0,0 +1,5 @@
+---
+title: Set longer Prometheus timeouts in PrometheusService
+merge_request: 39318
+author:
+type: other
diff --git a/changelogs/unreleased/235106-board-list-graphql.yml b/changelogs/unreleased/235106-board-list-graphql.yml
new file mode 100644
index 00000000000..a9f758e9f52
--- /dev/null
+++ b/changelogs/unreleased/235106-board-list-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add total_weight and issues_count fields to the board list graphQL endpoint
+merge_request: 39110
+author:
+type: added
diff --git a/changelogs/unreleased/25344-fire-webhook-on-new-deployment-2.yml b/changelogs/unreleased/25344-fire-webhook-on-new-deployment-2.yml
new file mode 100644
index 00000000000..a50b2fcc0ce
--- /dev/null
+++ b/changelogs/unreleased/25344-fire-webhook-on-new-deployment-2.yml
@@ -0,0 +1,5 @@
+---
+title: Add webhooks for deployments
+merge_request: 38902
+author:
+type: added
diff --git a/changelogs/unreleased/ajk-enable-design_management_reference_filter_gfm_pipeline.yml b/changelogs/unreleased/ajk-enable-design_management_reference_filter_gfm_pipeline.yml
new file mode 100644
index 00000000000..2e2af0e9713
--- /dev/null
+++ b/changelogs/unreleased/ajk-enable-design_management_reference_filter_gfm_pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Enable design management reference filter by default
+merge_request: 39113
+author:
+type: changed
diff --git a/changelogs/unreleased/coverage_fuzzing_usage_ping.yml b/changelogs/unreleased/coverage_fuzzing_usage_ping.yml
new file mode 100644
index 00000000000..d93ac51cfc9
--- /dev/null
+++ b/changelogs/unreleased/coverage_fuzzing_usage_ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add usage ping for coverage_fuzzing
+merge_request: 36960
+author:
+type: added
diff --git a/changelogs/unreleased/jarv-env-for-disabling-unstructured-log.yml b/changelogs/unreleased/jarv-env-for-disabling-unstructured-log.yml
new file mode 100644
index 00000000000..f1b68a90e78
--- /dev/null
+++ b/changelogs/unreleased/jarv-env-for-disabling-unstructured-log.yml
@@ -0,0 +1,5 @@
+---
+title: Adds an environment variable override to disable unstructured logs
+merge_request: 39109
+author:
+type: other
diff --git a/changelogs/unreleased/update-ado-image-to-v1-0-0.yml b/changelogs/unreleased/update-ado-image-to-v1-0-0.yml
new file mode 100644
index 00000000000..41cff3e6d8b
--- /dev/null
+++ b/changelogs/unreleased/update-ado-image-to-v1-0-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update auto-deploy-image to v1.0.0, including a locally vendored auto-deploy-app chart instead of charts.gitlab.io
+merge_request: 39272
+author:
+type: changed
diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb
index 42c97e4aebd..e3601a9538e 100644
--- a/config/initializers/lograge.rb
+++ b/config/initializers/lograge.rb
@@ -5,7 +5,7 @@ unless Gitlab::Runtime.sidekiq?
Rails.application.configure do
config.lograge.enabled = true
# Store the lograge JSON files in a separate file
- config.lograge.keep_original_rails_log = true
+ config.lograge.keep_original_rails_log = Gitlab::Utils.to_boolean(ENV.fetch('UNSTRUCTURED_RAILS_LOG', 'true'))
# Don't use the Logstash formatter since this requires logstash-event, an
# unmaintained gem that monkey patches `Time`
config.lograge.formatter = Lograge::Formatters::Json.new
diff --git a/db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb b/db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb
new file mode 100644
index 00000000000..4f884319125
--- /dev/null
+++ b/db/post_migrate/20200721140507_update_index_for_coverage_fuzzing_telemetry.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class UpdateIndexForCoverageFuzzingTelemetry < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ disable_ddl_transaction!
+
+ OLD_INDEX_NAME = 'index_security_ci_builds_on_name_and_id'
+ NEW_INDEX_NAME = 'index_security_ci_builds_on_name_and_id_parser_features'
+
+ OLD_CLAUSE = "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text,
+ ('dast'::character varying)::text,
+ ('dependency_scanning'::character varying)::text,
+ ('license_management'::character varying)::text,
+ ('sast'::character varying)::text,
+ ('secret_detection'::character varying)::text,
+ ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text)"
+
+ NEW_CLAUSE = "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text,
+ ('dast'::character varying)::text,
+ ('dependency_scanning'::character varying)::text,
+ ('license_management'::character varying)::text,
+ ('sast'::character varying)::text,
+ ('secret_detection'::character varying)::text,
+ ('coverage_fuzzing'::character varying)::text,
+ ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text)"
+
+ def up
+ add_concurrent_index :ci_builds, [:name, :id], name: NEW_INDEX_NAME, where: NEW_CLAUSE
+ remove_concurrent_index_by_name :ci_builds, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :ci_builds, [:name, :id], name: OLD_INDEX_NAME, where: OLD_CLAUSE
+ remove_concurrent_index_by_name :ci_builds, NEW_INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20200721140507 b/db/schema_migrations/20200721140507
new file mode 100644
index 00000000000..3fbd67734c7
--- /dev/null
+++ b/db/schema_migrations/20200721140507
@@ -0,0 +1 @@
+9a395ab591542ec49fc17c22747d9bbf085fd5f61ae71f49493dfe34f0389059 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 50e6e4d9dd4..853c686ccd5 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -20634,7 +20634,7 @@ CREATE UNIQUE INDEX index_scim_oauth_access_tokens_on_group_id_and_token_encrypt
CREATE INDEX index_secure_ci_builds_on_user_id_created_at ON public.ci_builds USING btree (user_id, created_at) WHERE (((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text])));
-CREATE INDEX index_security_ci_builds_on_name_and_id ON public.ci_builds USING btree (name, id) WHERE (((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text));
+CREATE INDEX index_security_ci_builds_on_name_and_id_parser_features ON public.ci_builds USING btree (name, id) WHERE (((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text));
CREATE INDEX index_self_managed_prometheus_alert_events_on_environment_id ON public.self_managed_prometheus_alert_events USING btree (environment_id);
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index ecf9464eb91..ebc3848017f 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -33,6 +33,7 @@ Variable | Type | Description
`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer
`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer
`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` | string | Sets the initial registration token used for GitLab Runners
+`UNSTRUCTURED_RAILS_LOG` | string | Enables the unstructured log in addition to JSON logs (defaults to `true`)
## Complete database variables
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 92766ab68e4..78026a82a36 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -1225,6 +1225,11 @@ type BoardList {
): IssueConnection
"""
+ Count of issues in the list
+ """
+ issuesCount: Int
+
+ """
Label of the list
"""
label: Label
@@ -1263,6 +1268,11 @@ type BoardList {
Title of the list
"""
title: String!
+
+ """
+ Total weight of all issues in the list
+ """
+ totalWeight: Int
}
"""
@@ -4961,7 +4971,7 @@ Counts of descendent epics.
"""
type EpicDescendantCount {
"""
- Number of closed sub-epics
+ Number of closed child epics
"""
closedEpics: Int
@@ -4971,7 +4981,7 @@ type EpicDescendantCount {
closedIssues: Int
"""
- Number of opened sub-epics
+ Number of opened child epics
"""
openedEpics: Int
@@ -7355,9 +7365,9 @@ input IssueSetEpicInput {
clientMutationId: String
"""
- Global ID of the epic to be assigned to the issue
+ Global ID of the epic to be assigned to the issue, epic will be removed if absent or set to null
"""
- epicId: ID!
+ epicId: ID
"""
The IID of the issue to mutate
@@ -7710,6 +7720,11 @@ type Iteration {
description: String
"""
+ The GitLab Flavored Markdown rendering of `description`
+ """
+ descriptionHtml: String
+
+ """
Timestamp of the iteration due date
"""
dueDate: Time
@@ -9561,6 +9576,7 @@ type Mutation {
toggleAwardEmoji(input: ToggleAwardEmojiInput!): ToggleAwardEmojiPayload @deprecated(reason: "Use awardEmojiToggle. Deprecated in 13.2")
updateAlertStatus(input: UpdateAlertStatusInput!): UpdateAlertStatusPayload
updateBoard(input: UpdateBoardInput!): UpdateBoardPayload
+ updateBoardList(input: UpdateBoardListInput!): UpdateBoardListPayload
updateContainerExpirationPolicy(input: UpdateContainerExpirationPolicyInput!): UpdateContainerExpirationPolicyPayload
updateEpic(input: UpdateEpicInput!): UpdateEpicPayload
@@ -15574,6 +15590,51 @@ input UpdateBoardInput {
}
"""
+Autogenerated input type of UpdateBoardList
+"""
+input UpdateBoardListInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Indicates if list is collapsed for this user
+ """
+ collapsed: Boolean
+
+ """
+ Global ID of the list.
+ """
+ listId: ID!
+
+ """
+ Position of list within the board
+ """
+ position: Int
+}
+
+"""
+Autogenerated return type of UpdateBoardList
+"""
+type UpdateBoardListPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ Mutated list
+ """
+ list: BoardList
+}
+
+"""
Autogenerated return type of UpdateBoard
"""
type UpdateBoardPayload {
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 719d448b5f4..2a05368e331 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -3255,6 +3255,20 @@
"deprecationReason": null
},
{
+ "name": "issuesCount",
+ "description": "Count of issues in the list",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "label",
"description": "Label of the list",
"args": [
@@ -3373,6 +3387,20 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "totalWeight",
+ "description": "Total weight of all issues in the list",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -13827,7 +13855,7 @@
"fields": [
{
"name": "closedEpics",
- "description": "Number of closed sub-epics",
+ "description": "Number of closed child epics",
"args": [
],
@@ -13855,7 +13883,7 @@
},
{
"name": "openedEpics",
- "description": "Number of opened sub-epics",
+ "description": "Number of opened child epics",
"args": [
],
@@ -20359,15 +20387,11 @@
},
{
"name": "epicId",
- "description": "Global ID of the epic to be assigned to the issue",
+ "description": "Global ID of the epic to be assigned to the issue, epic will be removed if absent or set to null",
"type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- }
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
},
"defaultValue": null
},
@@ -21221,6 +21245,20 @@
"deprecationReason": null
},
{
+ "name": "descriptionHtml",
+ "description": "The GitLab Flavored Markdown rendering of `description`",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "dueDate",
"description": "Timestamp of the iteration due date",
"args": [
@@ -28404,6 +28442,33 @@
"deprecationReason": null
},
{
+ "name": "updateBoardList",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "UpdateBoardListInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "UpdateBoardListPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "updateContainerExpirationPolicy",
"description": null,
"args": [
@@ -45858,6 +45923,128 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "UpdateBoardListInput",
+ "description": "Autogenerated input type of UpdateBoardList",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "listId",
+ "description": "Global ID of the list.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "position",
+ "description": "Position of list within the board",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "collapsed",
+ "description": "Indicates if list is collapsed for this user",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "UpdateBoardListPayload",
+ "description": "Autogenerated return type of UpdateBoardList",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "list",
+ "description": "Mutated list",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "BoardList",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "UpdateBoardPayload",
"description": "Autogenerated return type of UpdateBoard",
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index cadcacb7f48..fac5357dc78 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -207,6 +207,7 @@ Represents a list for an issue board
| `assignee` | User | Assignee in the list |
| `collapsed` | Boolean | Indicates if list is collapsed for this user |
| `id` | ID! | ID (global ID) of the list |
+| `issuesCount` | Int | Count of issues in the list |
| `label` | Label | Label of the list |
| `limitMetric` | ListLimitMetric | The current limit metric for the list |
| `listType` | String! | Type of the list |
@@ -215,6 +216,7 @@ Represents a list for an issue board
| `milestone` | Milestone | Milestone of the list |
| `position` | Int | Position of list within the board |
| `title` | String! | Title of the list |
+| `totalWeight` | Int | Total weight of all issues in the list |
## BoardListCreatePayload
@@ -805,9 +807,9 @@ Counts of descendent epics.
| Name | Type | Description |
| --- | ---- | ---------- |
-| `closedEpics` | Int | Number of closed sub-epics |
+| `closedEpics` | Int | Number of closed child epics |
| `closedIssues` | Int | Number of closed epic issues |
-| `openedEpics` | Int | Number of opened sub-epics |
+| `openedEpics` | Int | Number of opened child epics |
| `openedIssues` | Int | Number of opened epic issues |
## EpicDescendantWeights
@@ -1165,6 +1167,7 @@ Represents an iteration object.
| --- | ---- | ---------- |
| `createdAt` | Time! | Timestamp of iteration creation |
| `description` | String | Description of the iteration |
+| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `dueDate` | Time | Timestamp of the iteration due date |
| `id` | ID! | ID of the iteration |
| `iid` | ID! | Internal ID of the iteration |
@@ -2305,6 +2308,16 @@ Autogenerated return type of UpdateAlertStatus
| `issue` | Issue | The issue created after mutation |
| `todo` | Todo | The todo after mutation |
+## UpdateBoardListPayload
+
+Autogenerated return type of UpdateBoardList
+
+| Name | Type | Description |
+| --- | ---- | ---------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `list` | BoardList | Mutated list |
+
## UpdateBoardPayload
Autogenerated return type of UpdateBoard
diff --git a/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.png b/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.png
new file mode 100644
index 00000000000..a06f8812b41
--- /dev/null
+++ b/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.png
Binary files differ
diff --git a/doc/user/compliance/compliance_dashboard/index.md b/doc/user/compliance/compliance_dashboard/index.md
index e26a223e47a..5c05725d95b 100644
--- a/doc/user/compliance/compliance_dashboard/index.md
+++ b/doc/user/compliance/compliance_dashboard/index.md
@@ -17,7 +17,7 @@ for merging into production.
To access the Compliance Dashboard for a group, navigate to **{shield}** **Security & Compliance > Compliance** on the group's menu.
-![Compliance Dashboard](img/compliance_dashboard_v13_3.png)
+![Compliance Dashboard](img/compliance_dashboard_v13_3_1.png)
NOTE: **Note:**
The Compliance Dashboard shows only the latest MR on each project.
@@ -62,3 +62,15 @@ This column has four states:
If you do not see the success icon in your Compliance dashboard; please review the above criteria for the Merge Requests
project to make sure it complies with the separation of duties described above.
+
+## Chain of Custody report
+
+The Chain of Custody report allows customers to export a list of merge commits within the group.
+The data provides a comprehensive view with respect to merge commits. It includes the merge commit SHA,
+merge request author, merge request ID, merge user, pipeline ID, group name, project name, and merge request approvers.
+
+To download the Chain of Custody report, navigate to **{shield}** **Security & Compliance > Compliance** on the group's menu and click **List of all merge commits**
+
+NOTE: **Note:**
+The Chain of Custody report download is a CSV file, with a maximum size of 15 MB.
+The remaining records are truncated when this limit is reached.
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 371469a6ed6..5e456c7986c 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -276,21 +276,21 @@ This will be rendered as:
### Enable or disable design references **(CORE ONLY)**
-Design reference parsing is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
+Design reference parsing 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 for your instance.
+can disable it for your instance.
-To enable it:
+To disable it:
```ruby
-Feature.enable(:design_management_reference_filter_gfm_pipeline)
+Feature.disable(:design_management_reference_filter_gfm_pipeline)
```
-To disable it:
+To re-enable it:
```ruby
-Feature.disable(:design_management_reference_filter_gfm_pipeline)
+Feature.enable(:design_management_reference_filter_gfm_pipeline)
```
## Design activity records
diff --git a/lib/banzai/filter/design_reference_filter.rb b/lib/banzai/filter/design_reference_filter.rb
index 7455dfe00ef..2ab47c5c6db 100644
--- a/lib/banzai/filter/design_reference_filter.rb
+++ b/lib/banzai/filter/design_reference_filter.rb
@@ -114,7 +114,7 @@ module Banzai
end
def enabled?
- Feature.enabled?(FEATURE_FLAG, parent)
+ Feature.enabled?(FEATURE_FLAG, parent, default_enabled: true)
end
end
end
diff --git a/lib/gitlab/app_logger.rb b/lib/gitlab/app_logger.rb
index 3f5e9adf925..a39e7f31886 100644
--- a/lib/gitlab/app_logger.rb
+++ b/lib/gitlab/app_logger.rb
@@ -5,7 +5,11 @@ module Gitlab
LOGGERS = [Gitlab::AppTextLogger, Gitlab::AppJsonLogger].freeze
def self.loggers
- LOGGERS
+ if Gitlab::Utils.to_boolean(ENV.fetch('UNSTRUCTURED_RAILS_LOG', 'true'))
+ LOGGERS
+ else
+ [Gitlab::AppJsonLogger]
+ end
end
def self.primary_logger
diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
index 39e27ed14e3..f234008dad4 100644
--- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
.dast-auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.17.2"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.0"
dast_environment_deploy:
extends: .dast-auto-deploy
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 66c60e85892..76fb2948144 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,5 +1,5 @@
.auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.17.2"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.0"
dependencies: []
include:
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index e2a13610dc0..56e1154a672 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -132,7 +132,7 @@ module Gitlab
def http_options
strong_memoize(:http_options) do
- { follow_redirects: false, open_timeout: 5, read_timeout: 10 }.merge(mapped_options)
+ { follow_redirects: false }.merge(mapped_options)
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 38120b51b0f..299c5cc1008 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -868,6 +868,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1156,6 +1159,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -4343,10 +4349,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4367,7 +4373,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -14387,6 +14393,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -16499,9 +16508,6 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
@@ -27373,6 +27379,12 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27418,6 +27430,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
diff --git a/spec/controllers/projects/hooks_controller_spec.rb b/spec/controllers/projects/hooks_controller_spec.rb
index 440e6b2a74c..85d036486ee 100644
--- a/spec/controllers/projects/hooks_controller_spec.rb
+++ b/spec/controllers/projects/hooks_controller_spec.rb
@@ -36,7 +36,8 @@ RSpec.describe Projects::HooksController do
note_events: true,
job_events: true,
pipeline_events: true,
- wiki_page_events: true
+ wiki_page_events: true,
+ deployment_events: true
}
post :create, params: { namespace_id: project.namespace, project_id: project, hook: hook_params }
diff --git a/spec/features/registrations/experience_level_spec.rb b/spec/features/registrations/experience_level_spec.rb
new file mode 100644
index 00000000000..d08bcc76ac8
--- /dev/null
+++ b/spec/features/registrations/experience_level_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Experience level screen' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ before do
+ group.add_owner(user)
+ gitlab_sign_in(user)
+ stub_experiment_for_user(onboarding_issues: true)
+ visit users_sign_up_experience_level_path(namespace_path: group.to_param)
+ end
+
+ subject { page }
+
+ it 'shows the intro content' do
+ is_expected.to have_content('Hello there')
+ is_expected.to have_content('Welcome to the guided GitLab tour')
+ is_expected.to have_content('What describes you best?')
+ end
+
+ it 'shows the option for novice' do
+ is_expected.to have_content('Novice')
+ is_expected.to have_content('I’m not very familiar with the basics of project management and DevOps')
+ is_expected.to have_content('Show me everything')
+ end
+
+ it 'shows the option for experienced' do
+ is_expected.to have_content('Experienced')
+ is_expected.to have_content('I’m familiar with the basics of project management and DevOps')
+ is_expected.to have_content('Show me more advanced stuff')
+ end
+end
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
new file mode 100644
index 00000000000..a349aad9f1c
--- /dev/null
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -0,0 +1,57 @@
+import { createLocalVue, mount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { GlDrawer } from '@gitlab/ui';
+import App from '~/whats_new/components/app.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('App', () => {
+ let wrapper;
+ let store;
+ let actions;
+ let state;
+
+ beforeEach(() => {
+ actions = {
+ closeDrawer: jest.fn(),
+ };
+
+ state = {
+ open: true,
+ };
+
+ store = new Vuex.Store({
+ actions,
+ state,
+ });
+
+ wrapper = mount(App, {
+ localVue,
+ store,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const getDrawer = () => wrapper.find(GlDrawer);
+
+ it('contains a drawer', () => {
+ expect(getDrawer().exists()).toBe(true);
+ });
+
+ it('dispatches closeDrawer when clicking close', () => {
+ getDrawer().vm.$emit('close');
+ expect(actions.closeDrawer).toHaveBeenCalled();
+ });
+
+ it.each([true, false])('passes open property', async openState => {
+ wrapper.vm.$store.state.open = openState;
+
+ await wrapper.vm.$nextTick();
+
+ expect(getDrawer().props('open')).toBe(openState);
+ });
+});
diff --git a/spec/frontend/whats_new/components/trigger_spec.js b/spec/frontend/whats_new/components/trigger_spec.js
new file mode 100644
index 00000000000..7961957e077
--- /dev/null
+++ b/spec/frontend/whats_new/components/trigger_spec.js
@@ -0,0 +1,43 @@
+import { createLocalVue, mount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { GlButton } from '@gitlab/ui';
+import Trigger from '~/whats_new/components/trigger.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Trigger', () => {
+ let wrapper;
+ let store;
+ let actions;
+ let state;
+
+ beforeEach(() => {
+ actions = {
+ openDrawer: jest.fn(),
+ };
+
+ state = {
+ open: true,
+ };
+
+ store = new Vuex.Store({
+ actions,
+ state,
+ });
+
+ wrapper = mount(Trigger, {
+ localVue,
+ store,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('dispatches openDrawer when clicking close', () => {
+ wrapper.find(GlButton).vm.$emit('click');
+ expect(actions.openDrawer).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/whats_new/store/actions_spec.js b/spec/frontend/whats_new/store/actions_spec.js
new file mode 100644
index 00000000000..d95453c9175
--- /dev/null
+++ b/spec/frontend/whats_new/store/actions_spec.js
@@ -0,0 +1,17 @@
+import testAction from 'helpers/vuex_action_helper';
+import actions from '~/whats_new/store/actions';
+import * as types from '~/whats_new/store/mutation_types';
+
+describe('whats new actions', () => {
+ describe('openDrawer', () => {
+ it('should commit openDrawer', () => {
+ testAction(actions.openDrawer, {}, {}, [{ type: types.OPEN_DRAWER }]);
+ });
+ });
+
+ describe('closeDrawer', () => {
+ it('should commit closeDrawer', () => {
+ testAction(actions.closeDrawer, {}, {}, [{ type: types.CLOSE_DRAWER }]);
+ });
+ });
+});
diff --git a/spec/frontend/whats_new/store/mutations_spec.js b/spec/frontend/whats_new/store/mutations_spec.js
new file mode 100644
index 00000000000..3c33364fed3
--- /dev/null
+++ b/spec/frontend/whats_new/store/mutations_spec.js
@@ -0,0 +1,25 @@
+import mutations from '~/whats_new/store/mutations';
+import createState from '~/whats_new/store/state';
+import * as types from '~/whats_new/store/mutation_types';
+
+describe('whats new mutations', () => {
+ let state;
+
+ beforeEach(() => {
+ state = createState;
+ });
+
+ describe('openDrawer', () => {
+ it('sets open to true', () => {
+ mutations[types.OPEN_DRAWER](state);
+ expect(state.open).toBe(true);
+ });
+ });
+
+ describe('closeDrawer', () => {
+ it('sets open to false', () => {
+ mutations[types.CLOSE_DRAWER](state);
+ expect(state.open).toBe(false);
+ });
+ });
+});
diff --git a/spec/graphql/mutations/boards/lists/update_spec.rb b/spec/graphql/mutations/boards/lists/update_spec.rb
new file mode 100644
index 00000000000..d5d8a2af6bf
--- /dev/null
+++ b/spec/graphql/mutations/boards/lists/update_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Boards::Lists::Update do
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:board) { create(:board, group: group) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
+ let_it_be(:list2) { create(:list, board: board) }
+ let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+ let(:list_update_params) { { position: 1, collapsed: true } }
+
+ before_all do
+ group.add_reporter(reporter)
+ group.add_guest(guest)
+ list.update_preferences_for(reporter, collapsed: false)
+ end
+
+ subject { mutation.resolve(list: list, **list_update_params) }
+
+ describe '#resolve' do
+ context 'with permission to admin board lists' do
+ let(:current_user) { reporter }
+
+ it 'updates the list position and collapsed state as expected' do
+ subject
+
+ reloaded_list = list.reload
+ expect(reloaded_list.position).to eq(1)
+ expect(reloaded_list.collapsed?(current_user)).to eq(true)
+ end
+ end
+
+ context 'with permission to read board lists' do
+ let(:current_user) { guest }
+
+ it 'updates the list collapsed state but not the list position' do
+ subject
+
+ reloaded_list = list.reload
+ expect(reloaded_list.position).to eq(0)
+ expect(reloaded_list.collapsed?(current_user)).to eq(true)
+ end
+ end
+
+ context 'without permission to read board lists' do
+ let(:current_user) { create(:user) }
+
+ it 'raises Resource Not Found error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb b/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb
deleted file mode 100644
index de69ad5d450..00000000000
--- a/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Resolvers::CiConfiguration::SastResolver do
- include GraphqlHelpers
-
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
-
- describe '#resolve' do
- subject(:sast_config) { resolve(described_class, ctx: { current_user: user }, obj: project) }
-
- it 'returns global variable informations related to SAST' do
- expect(sast_config['global'].first['field']).to eql("SECURE_ANALYZERS_PREFIX")
- expect(sast_config['global'].first['label']).to eql("Image prefix")
- expect(sast_config['global'].first['type']).to eql("string")
-
- expect(sast_config['pipeline'].first['field']).to eql("stage")
- expect(sast_config['pipeline'].first['label']).to eql("Stage")
- expect(sast_config['pipeline'].first['type']).to eql("dropdown")
-
- expect(sast_config['analyzers'].first['name']).to eql("brakeman")
- expect(sast_config['analyzers'].first['label']).to eql("Brakeman")
- expect(sast_config['analyzers'].first['enabled']).to be true
- end
- end
-end
diff --git a/spec/graphql/types/board_list_type_spec.rb b/spec/graphql/types/board_list_type_spec.rb
index 66ea003d175..7976936fc1f 100644
--- a/spec/graphql/types/board_list_type_spec.rb
+++ b/spec/graphql/types/board_list_type_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['BoardList'] do
specify { expect(described_class.graphql_name).to eq('BoardList') }
it 'has specific fields' do
- expected_fields = %w[id list_type position label issues]
+ expected_fields = %w[id list_type position label issues_count issues]
expect(described_class).to include_graphql_fields(*expected_fields)
end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index a0b6858fc99..8a5d0cdf12d 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe GitlabSchema.types['Project'] do
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
environment boards jira_import_status jira_imports services releases release
alert_management_alerts alert_management_alert alert_management_alert_status_counts
- container_expiration_policy sast_ci_configuration service_desk_enabled service_desk_address
+ container_expiration_policy service_desk_enabled service_desk_address
issue_status_counts
]
@@ -150,93 +150,5 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::ContainerExpirationPolicyType) }
end
- describe 'sast_ci_configuration' do
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
- let_it_be(:query) do
- %(
- query {
- project(fullPath: "#{project.full_path}") {
- sastCiConfiguration {
- global {
- nodes {
- type
- options {
- nodes {
- label
- value
- }
- }
- field
- label
- defaultValue
- value
- }
- }
- pipeline {
- nodes {
- type
- options {
- nodes {
- label
- value
- }
- }
- field
- label
- defaultValue
- value
- }
- }
- analyzers {
- nodes {
- name
- label
- enabled
- }
- }
- }
- }
- }
- )
- end
-
- subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
-
- before do
- project.add_developer(user)
- end
-
- it "returns the project's sast configuration for global variables" do
- query_result = subject.dig('data', 'project', 'sastCiConfiguration', 'global', 'nodes')
- first_config = query_result.first
- fourth_config = query_result[3]
- expect(first_config['type']).to eq('string')
- expect(first_config['field']).to eq('SECURE_ANALYZERS_PREFIX')
- expect(first_config['label']).to eq('Image prefix')
- expect(first_config['defaultValue']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
- expect(first_config['value']).to eq('')
- expect(first_config['options']).to be_nil
- expect(fourth_config['options']['nodes']).to match([{ "value" => "true", "label" => "true (disables SAST)" },
- { "value" => "false", "label" => "false (enables SAST)" }])
- end
-
- it "returns the project's sast configuration for pipeline variables" do
- configuration = subject.dig('data', 'project', 'sastCiConfiguration', 'pipeline', 'nodes').first
- expect(configuration['type']).to eq('dropdown')
- expect(configuration['field']).to eq('stage')
- expect(configuration['label']).to eq('Stage')
- expect(configuration['defaultValue']).to eq('test')
- expect(configuration['value']).to eq('')
- end
-
- it "returns the project's sast configuration for analyzer variables" do
- configuration = subject.dig('data', 'project', 'sastCiConfiguration', 'analyzers', 'nodes').first
- expect(configuration['name']).to eq('brakeman')
- expect(configuration['label']).to eq('Brakeman')
- expect(configuration['enabled']).to eq(true)
- end
- end
-
it_behaves_like 'a GraphQL type with labels'
end
diff --git a/spec/lib/gitlab/app_logger_spec.rb b/spec/lib/gitlab/app_logger_spec.rb
index 166b1fda268..23bac444dbe 100644
--- a/spec/lib/gitlab/app_logger_spec.rb
+++ b/spec/lib/gitlab/app_logger_spec.rb
@@ -19,4 +19,12 @@ RSpec.describe Gitlab::AppLogger do
subject.info('Hello World!')
end
+
+ it 'logs info to only the AppJsonLogger when unstructured logs are disabled' do
+ stub_env('UNSTRUCTURED_RAILS_LOG', 'false')
+ expect_any_instance_of(Gitlab::AppTextLogger).not_to receive(:info).and_call_original
+ expect_any_instance_of(Gitlab::AppJsonLogger).to receive(:info).and_call_original
+
+ subject.info('Hello World!')
+ end
end
diff --git a/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb b/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb
new file mode 100644
index 00000000000..8a6d2cb3994
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Update of an existing board list' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:board) { create(:board, group: group) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
+ let_it_be(:list2) { create(:list, board: board) }
+ let_it_be(:input) { { list_id: list.to_global_id.to_s, position: 1, collapsed: true } }
+ let(:mutation) { graphql_mutation(:update_board_list, input) }
+ let(:mutation_response) { graphql_mutation_response(:update_board_list) }
+
+ context 'the user is not allowed to read board lists' do
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ end
+
+ before do
+ list.update_preferences_for(current_user, collapsed: false)
+ end
+
+ context 'when user has permissions to admin board lists' do
+ before do
+ group.add_reporter(current_user)
+ end
+
+ it 'updates the list position and collapsed state' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['list']).to include(
+ 'position' => 1,
+ 'collapsed' => true
+ )
+ end
+ end
+
+ context 'when user has permissions to read board lists' do
+ before do
+ group.add_guest(current_user)
+ end
+
+ it 'updates the list collapsed state but not the list position' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['list']).to include(
+ 'position' => 0,
+ 'collapsed' => true
+ )
+ end
+ end
+end
diff --git a/spec/services/projects/update_pages_configuration_service_spec.rb b/spec/services/projects/update_pages_configuration_service_spec.rb
index 479653304a0..9f7ebd40df6 100644
--- a/spec/services/projects/update_pages_configuration_service_spec.rb
+++ b/spec/services/projects/update_pages_configuration_service_spec.rb
@@ -3,50 +3,75 @@
require 'spec_helper'
RSpec.describe Projects::UpdatePagesConfigurationService do
- let(:project) { create(:project) }
let(:service) { described_class.new(project) }
describe "#execute" do
- let(:file) { Tempfile.new('pages-test') }
-
subject { service.execute }
- after do
- file.close
- file.unlink
- end
+ context 'when pages are deployed' do
+ let_it_be(:project) do
+ create(:project).tap(&:mark_pages_as_deployed)
+ end
- before do
- allow(service).to receive(:pages_config_file).and_return(file.path)
- end
+ let(:file) { Tempfile.new('pages-test') }
- context 'when configuration changes' do
- it 'updates the .update file' do
- expect(service).to receive(:reload_daemon).and_call_original
+ before do
+ allow(service).to receive(:pages_config_file).and_return(file.path)
+ end
- expect(subject).to include(status: :success)
+ after do
+ file.close
+ file.unlink
end
- end
- context 'when configuration does not change' do
- before do
- # we set the configuration
- service.execute
+ context 'when configuration changes' do
+ it 'updates the config and reloads the daemon' do
+ allow(service).to receive(:update_file).and_call_original
+
+ expect(service).to receive(:update_file).with(file.path, an_instance_of(String))
+ .and_call_original
+ expect(service).to receive(:reload_daemon).and_call_original
+
+ expect(subject).to include(status: :success)
+ end
+ end
+
+ context 'when configuration does not change' do
+ before do
+ # we set the configuration
+ service.execute
+ end
+
+ it 'does not update the .update file' do
+ expect(service).not_to receive(:reload_daemon)
+
+ expect(subject).to include(status: :success)
+ end
end
- it 'does not update the .update file' do
- expect(service).not_to receive(:reload_daemon)
+ context 'when an error occurs' do
+ it 'returns an error object' do
+ e = StandardError.new("Failure")
+ allow(service).to receive(:reload_daemon).and_raise(e)
- expect(subject).to include(status: :success)
+ expect(subject).to eq(status: :error, message: "Failure", exception: e)
+ end
end
end
- context 'when an error occurs' do
- it 'returns an error object' do
- e = StandardError.new("Failure")
- allow(service).to receive(:reload_daemon).and_raise(e)
+ context 'when pages are not deployed' do
+ let_it_be(:project) do
+ create(:project).tap(&:mark_pages_as_not_deployed)
+ end
+
+ it 'returns successfully' do
+ expect(subject).to eq(status: :success)
+ end
+
+ it 'does not update the config' do
+ expect(service).not_to receive(:update_file)
- expect(subject).to eq(status: :error, message: "Failure", exception: e)
+ subject
end
end
end
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 48bbed40f29..4a613f42556 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -397,18 +397,30 @@ RSpec.describe Projects::UpdateService do
end
shared_examples 'updating pages configuration' do
- it 'schedules the `PagesUpdateConfigurationWorker`' do
+ it 'schedules the `PagesUpdateConfigurationWorker` when pages are deployed' do
+ project.mark_pages_as_deployed
+
expect(PagesUpdateConfigurationWorker).to receive(:perform_async).with(project.id)
subject
end
+ it "does not schedule a job when pages aren't deployed" do
+ project.mark_pages_as_not_deployed
+
+ expect(PagesUpdateConfigurationWorker).not_to receive(:perform_async).with(project.id)
+
+ subject
+ end
+
context 'when `async_update_pages_config` is disabled' do
before do
stub_feature_flags(async_update_pages_config: false)
end
- it 'calls Projects::UpdatePagesConfigurationService' do
+ it 'calls Projects::UpdatePagesConfigurationService when pages are deployed' do
+ project.mark_pages_as_deployed
+
expect(Projects::UpdatePagesConfigurationService)
.to receive(:new)
.with(project)
@@ -416,6 +428,15 @@ RSpec.describe Projects::UpdateService do
subject
end
+
+ it "does not update pages config when pages aren't deployed" do
+ project.mark_pages_as_not_deployed
+
+ expect(Projects::UpdatePagesConfigurationService)
+ .not_to receive(:new)
+
+ subject
+ end
end
end
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
new file mode 100644
index 00000000000..4134660e4b9
--- /dev/null
+++ b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
@@ -0,0 +1,13 @@
+include:
+ - template: SAST.gitlab-ci.yml
+
+variables:
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
+ SAST_EXCLUDED_PATHS: "spec, executables"
+
+stages:
+ - our_custom_security_stage
+sast:
+ stage: our_custom_security_stage
+ variables:
+ SEARCH_MAX_DEPTH: 8
diff --git a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
new file mode 100644
index 00000000000..f8f33e2a745
--- /dev/null
+++ b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'read ci configuration for sast enabled project' do
+ let_it_be(:gitlab_ci_yml_content) do
+ File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast.yml'))
+ end
+
+ let_it_be(:project) { create(:project, :repository) }
+end