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>2021-06-09 12:10:18 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-09 12:10:18 +0300
commit82a546b14c7613fe355b3e68c425d5da8779641a (patch)
treeb7bce66a952a66375e0e4eeb8cbedc38c9479ebf
parenta5628d3b6d9b74f5902f790ceddd6374148c9d71 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml5
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue15
-rw-r--r--app/assets/javascripts/boards/components/board_list_deprecated.vue7
-rw-r--r--app/controllers/groups/group_links_controller.rb4
-rw-r--r--app/models/group.rb6
-rw-r--r--app/services/groups/group_links/create_service.rb34
-rw-r--r--app/services/web_hook_service.rb23
-rw-r--r--app/services/web_hooks/log_execution_service.rb35
-rw-r--r--app/workers/all_queues.yml9
-rw-r--r--app/workers/web_hook_worker.rb2
-rw-r--r--app/workers/web_hooks/log_execution_worker.rb24
-rw-r--r--config/feature_flags/development/disable_service_templates.yml2
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--doc/api/graphql/reference/index.md22
-rw-r--r--doc/development/usage_ping/dictionary.md4
-rw-r--r--doc/integration/external-issue-tracker.md7
-rw-r--r--doc/topics/autodevops/requirements.md7
-rw-r--r--doc/update/index.md2
-rw-r--r--doc/user/admin_area/index.md2
-rw-r--r--doc/user/project/integrations/overview.md13
-rw-r--r--doc/user/project/integrations/services_templates.md68
-rw-r--r--lib/api/groups.rb2
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml18
-rw-r--r--locale/gitlab.pot11
-rwxr-xr-xscripts/review_apps/review-apps.sh21
-rw-r--r--scripts/utils.sh12
-rw-r--r--spec/features/boards/new_issue_spec.rb26
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb2
-rw-r--r--spec/services/groups/group_links/create_service_spec.rb46
-rw-r--r--spec/services/web_hook_service_spec.rb44
-rw-r--r--spec/workers/web_hook_worker_spec.rb2
32 files changed, 309 insertions, 170 deletions
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 64d6f49576f..ac48f08435e 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -71,13 +71,16 @@ review-deploy:
- download_chart
- date
- deploy || (display_deployment_debug && exit 1)
+ - verify_deploy || exit 1
- disable_sign_ups || (delete_release && exit 1)
after_script:
# Run seed-dast-test-data.sh only when DAST_RUN is set to true. This is to pupulate review app with data for DAST scan.
# Set DAST_RUN to true when jobs are manually scheduled.
- if [ "$DAST_RUN" == "true" ]; then source scripts/review_apps/seed-dast-test-data.sh; TRACE=1 trigger_proj_user_creation; fi
artifacts:
- paths: [environment_url.txt]
+ paths:
+ - environment_url.txt
+ - curl_output.txt
expire_in: 7 days
when: always
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index d9dc0025658..b58600fa058 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -111,10 +111,17 @@ export default {
this.showCount = this.scrollHeight() > Math.ceil(this.listHeight());
});
},
- },
- created() {
- eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
- eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
+ 'list.id': {
+ handler(id, oldVal) {
+ if (id) {
+ eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
+ eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
+ eventHub.$off(`toggle-issue-form-${oldVal}`, this.toggleForm);
+ eventHub.$off(`scroll-board-list-${oldVal}`, this.scrollToTop);
+ }
+ },
+ immediate: true,
+ },
},
beforeDestroy() {
eventHub.$off(`toggle-issue-form-${this.list.id}`, this.toggleForm);
diff --git a/app/assets/javascripts/boards/components/board_list_deprecated.vue b/app/assets/javascripts/boards/components/board_list_deprecated.vue
index c9ced425c1d..9b3e7e1547d 100644
--- a/app/assets/javascripts/boards/components/board_list_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_list_deprecated.vue
@@ -91,6 +91,13 @@ export default {
}
});
},
+ 'list.id': {
+ handler(id) {
+ if (id) {
+ eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
+ }
+ },
+ },
},
created() {
eventHub.$on(`toggle-issue-form-${this.list.id}`, this.toggleForm);
diff --git a/app/controllers/groups/group_links_controller.rb b/app/controllers/groups/group_links_controller.rb
index 3b775af9722..0655d779a4e 100644
--- a/app/controllers/groups/group_links_controller.rb
+++ b/app/controllers/groups/group_links_controller.rb
@@ -11,8 +11,8 @@ class Groups::GroupLinksController < Groups::ApplicationController
if shared_with_group
result = Groups::GroupLinks::CreateService
- .new(shared_with_group, current_user, group_link_create_params)
- .execute(group)
+ .new(group, shared_with_group, current_user, group_link_create_params)
+ .execute
return render_404 if result[:http_status] == 404
diff --git a/app/models/group.rb b/app/models/group.rb
index bbae40f4442..41f8cfa8b26 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -442,6 +442,12 @@ class Group < Namespace
end
end
+ def self_and_descendants_ids
+ strong_memoize(:self_and_descendants_ids) do
+ self_and_descendants.pluck(:id)
+ end
+ end
+
def direct_members
GroupMember.active_without_invites_and_requests
.non_minimal_access
diff --git a/app/services/groups/group_links/create_service.rb b/app/services/groups/group_links/create_service.rb
index 0a60140d037..5f81e5972b0 100644
--- a/app/services/groups/group_links/create_service.rb
+++ b/app/services/groups/group_links/create_service.rb
@@ -3,27 +3,51 @@
module Groups
module GroupLinks
class CreateService < Groups::BaseService
- def execute(shared_group)
- unless group && shared_group &&
+ def initialize(shared_group, shared_with_group, user, params)
+ @shared_group = shared_group
+ super(shared_with_group, user, params)
+ end
+
+ def execute
+ unless shared_with_group && shared_group &&
can?(current_user, :admin_group_member, shared_group) &&
- can?(current_user, :read_group, group)
+ can?(current_user, :read_group, shared_with_group) &&
+ sharing_allowed?
return error('Not Found', 404)
end
link = GroupGroupLink.new(
shared_group: shared_group,
- shared_with_group: group,
+ shared_with_group: shared_with_group,
group_access: params[:shared_group_access],
expires_at: params[:expires_at]
)
if link.save
- group.refresh_members_authorized_projects(direct_members_only: true)
+ shared_with_group.refresh_members_authorized_projects(direct_members_only: true)
success(link: link)
else
error(link.errors.full_messages.to_sentence, 409)
end
end
+
+ private
+
+ attr_reader :shared_group
+
+ alias_method :shared_with_group, :group
+
+ def sharing_allowed?
+ sharing_outside_hierarchy_allowed? || within_hierarchy?
+ end
+
+ def sharing_outside_hierarchy_allowed?
+ !shared_group.root_ancestor.namespace_settings.prevent_sharing_groups_outside_hierarchy
+ end
+
+ def within_hierarchy?
+ shared_group.root_ancestor.self_and_descendants_ids.include?(shared_with_group.id)
+ end
end
end
end
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 1ffc51bec77..f258aa13376 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -29,15 +29,17 @@ class WebHookService
GITLAB_EVENT_HEADER = 'X-Gitlab-Event'
attr_accessor :hook, :data, :hook_name, :request_options
+ attr_reader :uniqueness_token
def self.hook_to_event(hook_name)
hook_name.to_s.singularize.titleize
end
- def initialize(hook, data, hook_name)
+ def initialize(hook, data, hook_name, uniqueness_token = nil)
@hook = hook
@data = data
@hook_name = hook_name.to_s
+ @uniqueness_token = uniqueness_token
@request_options = {
timeout: Gitlab.config.gitlab.webhook_timeout,
allow_local_requests: hook.allow_local_requests?
@@ -123,10 +125,8 @@ class WebHookService
end
def log_execution(trigger:, url:, request_data:, response:, execution_duration:, error_message: nil)
- handle_failure(response, hook)
-
- WebHookLog.create(
- web_hook: hook,
+ category = response_category(response)
+ log_data = {
trigger: trigger,
url: url,
execution_duration: execution_duration,
@@ -136,16 +136,19 @@ class WebHookService
response_body: safe_response_body(response),
response_status: response.code,
internal_error_message: error_message
- )
+ }
+
+ ::WebHooks::LogExecutionWorker
+ .perform_async(hook.id, log_data, category, uniqueness_token)
end
- def handle_failure(response, hook)
+ def response_category(response)
if response.success? || response.redirection?
- hook.enable!
+ :ok
elsif response.internal_server_error?
- hook.backoff!
+ :error
else
- hook.failed!
+ :failed
end
end
diff --git a/app/services/web_hooks/log_execution_service.rb b/app/services/web_hooks/log_execution_service.rb
new file mode 100644
index 00000000000..6e58e15f093
--- /dev/null
+++ b/app/services/web_hooks/log_execution_service.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module WebHooks
+ class LogExecutionService
+ attr_reader :hook, :log_data, :response_category
+
+ def initialize(hook:, log_data:, response_category:)
+ @hook = hook
+ @log_data = log_data
+ @response_category = response_category
+ end
+
+ def execute
+ update_hook_executability
+ log_execution
+ end
+
+ private
+
+ def log_execution
+ WebHookLog.create!(web_hook: hook, **log_data.transform_keys(&:to_sym))
+ end
+
+ def update_hook_executability
+ case response_category
+ when :ok
+ hook.enable!
+ when :error
+ hook.backoff!
+ when :failed
+ hook.failed!
+ end
+ end
+ end
+end
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index c9ed2e5fc84..985ca73d0d2 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -2828,6 +2828,15 @@
:idempotent: true
:tags:
- :exclude_from_kubernetes
+- :name: web_hooks_log_execution
+ :worker_name: WebHooks::LogExecutionWorker
+ :feature_category: :integrations
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: wikis_git_garbage_collect
:worker_name: Wikis::GitGarbageCollectWorker
:feature_category: :gitaly
diff --git a/app/workers/web_hook_worker.rb b/app/workers/web_hook_worker.rb
index ded14d6d314..3480f49d640 100644
--- a/app/workers/web_hook_worker.rb
+++ b/app/workers/web_hook_worker.rb
@@ -16,7 +16,7 @@ class WebHookWorker
hook = WebHook.find(hook_id)
data = data.with_indifferent_access
- WebHookService.new(hook, data, hook_name).execute
+ WebHookService.new(hook, data, hook_name, jid).execute
end
end
# rubocop:enable Scalability/IdempotentWorker
diff --git a/app/workers/web_hooks/log_execution_worker.rb b/app/workers/web_hooks/log_execution_worker.rb
new file mode 100644
index 00000000000..58059370200
--- /dev/null
+++ b/app/workers/web_hooks/log_execution_worker.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module WebHooks
+ class LogExecutionWorker
+ include ApplicationWorker
+
+ idempotent!
+ feature_category :integrations
+ urgency :low
+
+ # This worker accepts an extra argument. This enables us to
+ # treat this worker as idempotent. Currently this is set to
+ # the Job ID (jid) of the parent worker.
+ def perform(hook_id, log_data, response_category, _unique_by)
+ hook = WebHook.find_by_id(hook_id)
+
+ return unless hook # hook has been deleted before we could run.
+
+ ::WebHooks::LogExecutionService
+ .new(hook: hook, log_data: log_data, response_category: response_category.to_sym)
+ .execute
+ end
+ end
+end
diff --git a/config/feature_flags/development/disable_service_templates.yml b/config/feature_flags/development/disable_service_templates.yml
index 07e52224b98..5e9972a2171 100644
--- a/config/feature_flags/development/disable_service_templates.yml
+++ b/config/feature_flags/development/disable_service_templates.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327436
milestone: '13.12'
type: development
group: group::ecosystem
-default_enabled: false
+default_enabled: true
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 65c57753486..f315a8cb28e 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -400,6 +400,8 @@
- 1
- - web_hooks_destroy
- 1
+- - web_hooks_log_execution
+ - 1
- - wikis_git_garbage_collect
- 1
- - x509_certificate_revoke
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index e9df5857695..caa7429a964 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -713,6 +713,28 @@ Input type: `AwardEmojiToggleInput`
| <a id="mutationawardemojitoggleerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationawardemojitoggletoggledon"></a>`toggledOn` | [`Boolean!`](#boolean) | Indicates the status of the emoji. True if the toggle awarded the emoji, and false if the toggle removed the emoji. |
+### `Mutation.boardEpicCreate`
+
+Input type: `BoardEpicCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationboardepiccreateboardid"></a>`boardId` | [`BoardsEpicBoardID!`](#boardsepicboardid) | Global ID of the board that the epic is in. |
+| <a id="mutationboardepiccreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationboardepiccreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group the epic to create is in. |
+| <a id="mutationboardepiccreatelistid"></a>`listId` | [`BoardsEpicListID!`](#boardsepiclistid) | Global ID of the epic board list in which epic will be created. |
+| <a id="mutationboardepiccreatetitle"></a>`title` | [`String!`](#string) | Title of the epic. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationboardepiccreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationboardepiccreateepic"></a>`epic` | [`Epic`](#epic) | Epic after creation. |
+| <a id="mutationboardepiccreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.boardListCreate`
Input type: `BoardListCreateInput`
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
index 04f5ae3df7a..0133d36a28c 100644
--- a/doc/development/usage_ping/dictionary.md
+++ b/doc/development/usage_ping/dictionary.md
@@ -7262,9 +7262,9 @@ Tiers: `premium`, `ultimate`
Whether this is a trial license or not
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210204124851_license_trial.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124851_license_trial.yml)
-Group: `group::product intelligence`
+Group: `group::license`
Status: `data_available`
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index e82c21947e2..38bcc2b9932 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -34,10 +34,3 @@ Visit the links below for details:
- [Jira](../integration/jira/index.md)
- [Redmine](../user/project/integrations/redmine.md)
- [YouTrack](../user/project/integrations/youtrack.md)
-
-### Service Template
-
-To avoid configuring each project's service individually, GitLab provides the ability to set
-Service Templates. These can then be overridden in each project's settings.
-
-Read more on [Services Templates](../user/project/integrations/services_templates.md).
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index fe378122cb3..edcc662d8fd 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -77,10 +77,9 @@ To make full use of Auto DevOps with Kubernetes, you need:
instruct GitLab to query an in-cluster Prometheus by enabling
the [Prometheus cluster integration](../../user/clusters/integrations.md#prometheus-cluster-integration).
- The [Prometheus service](../../user/project/integrations/prometheus.md)
- integration must be enabled for the project, or enabled as a
- [default service template](../../user/project/integrations/services_templates.md)
- for the entire GitLab installation.
+ The [Prometheus integration](../../user/project/integrations/prometheus.md)
+ integration must be activated for the project, or activated at the group or instance level.
+ Learn more about [Project integration management](../../user/admin_area/settings/project_integration_management.md).
To get response metrics (in addition to system metrics), you must
[configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
diff --git a/doc/update/index.md b/doc/update/index.md
index d2ab0858edf..2ac22631289 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -194,7 +194,7 @@ Find where your version sits in the upgrade path below, and upgrade GitLab
accordingly, while also consulting the
[version-specific upgrade instructions](#version-specific-upgrading-instructions):
-`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> [latest `13.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
+`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> [latest `13.12.Z`](https://about.gitlab.com/releases/categories/releases/) -> [latest `14.0.Z`](https://about.gitlab.com/releases/categories/releases/)
The following table, while not exhaustive, shows some examples of the supported
upgrade paths.
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 6c7f985dce6..0da868b78ce 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -35,7 +35,7 @@ The Admin Area is made up of the following sections:
| **{location-dot}** Geo | Configure and maintain [Geo nodes](geo_nodes.md). |
| **{key}** Deploy keys | Create instance-wide [SSH deploy keys](../project/deploy_keys/index.md). |
| **{lock}** Credentials | View [credentials](credentials_inventory.md) that can be used to access your instance. |
-| **{template}** Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. |
+| **{template}** Integrations | Manage [instance-level default settings](settings/project_integration_management.md) for a project integration. |
| **{labels}** Labels | Create and maintain [labels](labels.md) for your GitLab instance. |
| **{appearance}** Appearance | Customize [GitLab appearance](appearance.md). |
| **{settings}** Settings | Modify the [settings](settings/index.md) for your GitLab instance. |
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
index e74800c176d..b0ae290e7cd 100644
--- a/doc/user/project/integrations/overview.md
+++ b/doc/user/project/integrations/overview.md
@@ -80,19 +80,6 @@ instance configuration or provide custom settings.
Read more about [Project integration management](../../admin_area/settings/project_integration_management.md).
-### Service templates
-
-[Service templates](services_templates.md) were a way to set predefined values for
-a project integration across all new projects on the instance. They are deprecated and
-[scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032)
-in GitLab 14.0.
-
-GitLab recommends you use [project integration management](../../admin_area/settings/project_integration_management.md)
-instead of service templates. GitLab versions 13.3 and later provide
-[instance-level integrations](../../admin_area/settings/project_integration_management.md#project-integration-management)
-you can use.
-instead.
-
## Troubleshooting integrations
Some integrations use service hooks for integration with external applications. To confirm which ones use service hooks, see the [integrations listing](#integrations-listing) above. GitLab stores details of service hook requests made within the last 2 days. To view details of the requests, go to that integration's configuration page.
diff --git a/doc/user/project/integrations/services_templates.md b/doc/user/project/integrations/services_templates.md
index 93ce74eb735..37df48c75f8 100644
--- a/doc/user/project/integrations/services_templates.md
+++ b/doc/user/project/integrations/services_templates.md
@@ -1,67 +1,9 @@
---
-stage: Create
-group: Ecosystem
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../admin_area/settings/project_integration_management.md'
+remove_date: '2021-09-09'
---
-# Service templates **(FREE)**
+This document was moved to [another location](../../admin_area/settings/project_integration_management.md).
-WARNING:
-Service templates are [deprecated and scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032)
-in GitLab 14.0. Use [project integration management](#central-administration-of-project-integrations) instead.
-
-Using a service template, GitLab administrators can:
-
-- Provide default values for configuring integrations when creating new projects.
-- Bulk configure all existing projects in one step.
-
-When you enable a service template:
-
-- The defaults are applied to **all** existing projects that either:
- - Don't already have the integration enabled.
- - Don't have custom values stored for already enabled integrations.
-- Values are populated on each project's configuration page for the applicable
- integration.
-- Settings are stored at the project level.
-
-If you disable the template:
-
-- GitLab default values again become the default values for integrations on
- new projects.
-- Projects previously configured using the template continue to use those settings.
-
-If you change the template, the revised values are applied to new projects. This feature
-does not provide central administration of integration settings.
-
-## Central administration of project integrations
-
-A new set of features is being introduced in GitLab to provide more control over
-how integrations are configured at the instance, group, and project level. For
-more information, read more about:
-
-- [Setting up project integration management](../../admin_area/settings/project_integration_management.md) (introduced in GitLab 13.3)
-- [Our plans for managing integrations](https://gitlab.com/groups/gitlab-org/-/epics/2137).
-
-## Enable a service template
-
-Navigate to the **Admin Area > Service Templates** and choose the service
-template you wish to create.
-
-Recommendation:
-
-- Test the settings on some projects individually before enabling a template.
-- Copy the working settings from a project to the template.
-
-There is no "Test settings" option when enabling templates. If the settings do not work,
-these incorrect settings are applied to all existing projects that do not already have
-the integration configured. Fixing the integration then needs to be done project-by-project.
-
-## Service for external issue trackers
-
-The following image shows an example service template for Redmine.
-
-![Redmine service template](img/services_templates_redmine_example.png)
-
-For each project, you still need to configure the issue tracking
-URLs by replacing `:issues_tracker_id` in the above screenshot with the ID used
-by your external issue tracker.
+<!-- This redirect file can be deleted after <2021-09-09>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 1a604e70bf1..0efb8b57885 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -372,7 +372,7 @@ module API
expires_at: params[:expires_at]
}
- result = ::Groups::GroupLinks::CreateService.new(shared_with_group, current_user, group_link_create_params).execute(shared_group)
+ result = ::Groups::GroupLinks::CreateService.new(shared_group, shared_with_group, current_user, group_link_create_params).execute
shared_group.preload_shared_group_links
if result[:status] == :success
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 5af270c4cff..5680950bba8 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -11,7 +11,7 @@
# * test: TEST_DISABLED
# * code_quality: CODE_QUALITY_DISABLED
# * license_management: LICENSE_MANAGEMENT_DISABLED
-# * browser_performance: PERFORMANCE_DISABLED
+# * browser_performance: BROWSER_PERFORMANCE_DISABLED
# * load_performance: LOAD_PERFORMANCE_DISABLED
# * sast: SAST_DISABLED
# * secret_detection: SECRET_DETECTION_DISABLED
diff --git a/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
index 657ac43b78e..d0595491400 100644
--- a/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
@@ -1,14 +1,14 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/secret_detection
#
-# Configure secret detection with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
-# List of available variables: https://docs.gitlab.com/ee/user/application_security/secret_detection/#available-variables
+# Configure the scanning tool through the environment variables.
+# List of the variables: https://docs.gitlab.com/ee/user/application_security/secret_detection/#available-variables
+# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
variables:
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
SECRETS_ANALYZER_VERSION: "3"
SECRET_DETECTION_EXCLUDED_PATHS: ""
-
.secret-analyzer:
stage: test
image: "$SECURE_ANALYZERS_PREFIX/secrets:$SECRETS_ANALYZER_VERSION"
@@ -20,23 +20,15 @@ variables:
reports:
secret_detection: gl-secret-detection-report.json
-secret_detection_default_branch:
- extends: .secret-analyzer
- rules:
- - if: $SECRET_DETECTION_DISABLED
- when: never
- - if: $CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH
- script:
- - /analyzer run
-
secret_detection:
extends: .secret-analyzer
rules:
- if: $SECRET_DETECTION_DISABLED
when: never
- - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
+ - if: $CI_COMMIT_BRANCH
script:
- if [[ $CI_COMMIT_TAG ]]; then echo "Skipping Secret Detection for tags. No code changes have occurred."; exit 0; fi
+ - if [[ $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH ]]; then echo "Running Secret Detection on default branch."; /analyzer run; exit 0; fi
- git fetch origin $CI_DEFAULT_BRANCH $CI_COMMIT_REF_NAME
- git log --left-right --cherry-pick --pretty=format:"%H" refs/remotes/origin/$CI_DEFAULT_BRANCH...refs/remotes/origin/$CI_COMMIT_REF_NAME > "$CI_COMMIT_SHA"_commit_list.txt
- export SECRET_DETECTION_COMMITS_FILE="$CI_COMMIT_SHA"_commit_list.txt
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 5daeb97fa0f..968eddfe3d9 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -960,9 +960,6 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
-msgid "%{type} License"
-msgstr ""
-
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -19599,6 +19596,9 @@ msgstr ""
msgid "License ID:"
msgstr ""
+msgid "License file"
+msgstr ""
+
msgid "License overview"
msgstr ""
@@ -31671,6 +31671,9 @@ msgstr ""
msgid "SuperSonics|Buy subscription"
msgstr ""
+msgid "SuperSonics|Cloud license"
+msgstr ""
+
msgid "SuperSonics|Enter activation code"
msgstr ""
@@ -31758,7 +31761,7 @@ msgstr ""
msgid "SuperSonics|Type"
msgstr ""
-msgid "SuperSonics|Upload a legacy license"
+msgid "SuperSonics|Upload a license file"
msgstr ""
msgid "SuperSonics|Users in subscription"
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index c1d274af56d..80b239b7e0d 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -127,13 +127,12 @@ function disable_sign_ups() {
fi
# Create the root token
- local ruby_cmd="token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups'); token.set_token('${REVIEW_APPS_ROOT_TOKEN}'); begin; token.save!; rescue(ActiveRecord::RecordNotUnique); end"
- retry "run_task \"${ruby_cmd}\""
+ local set_token_rb="token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups'); token.set_token('${REVIEW_APPS_ROOT_TOKEN}'); begin; token.save!; rescue(ActiveRecord::RecordNotUnique); end"
+ retry "run_task \"${set_token_rb}\""
# Disable sign-ups
- local signup_enabled=$(retry 'curl --silent --show-error --request PUT --header "PRIVATE-TOKEN: ${REVIEW_APPS_ROOT_TOKEN}" "${CI_ENVIRONMENT_URL}/api/v4/application/settings?signup_enabled=false" | jq ".signup_enabled"')
-
- if [[ "${signup_enabled}" == "false" ]]; then
+ local disable_signup_rb="Gitlab::CurrentSettings.current_application_settings.update!(signup_enabled: false)"
+ if (retry "run_task \"${disable_signup_rb}\""); then
echoinfo "Sign-ups have been disabled successfully."
else
echoerr "Sign-ups are still enabled!"
@@ -365,6 +364,18 @@ EOF
eval "${HELM_CMD}"
}
+function verify_deploy() {
+ echoinfo "Verifying deployment at ${CI_ENVIRONMENT_URL}"
+
+ if wait_for_url "${CI_ENVIRONMENT_URL}" curl_output.txt; then
+ echoinfo "Review app is deployed to ${CI_ENVIRONMENT_URL}"
+ return 0
+ else
+ echoerr "Review app is not available at ${CI_ENVIRONMENT_URL}. See curl_output.txt artifact for detail."
+ return 1
+ fi
+}
+
function display_deployment_debug() {
local namespace="${CI_ENVIRONMENT_SLUG}"
local release="${CI_ENVIRONMENT_SLUG}"
diff --git a/scripts/utils.sh b/scripts/utils.sh
index d4436e1171d..6486727c828 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -13,6 +13,18 @@ function retry() {
return 1
}
+function wait_for_url() {
+ local url="${1}"
+ local curl_output="${2}"
+
+ echo "Waiting for ${url}"
+
+ timeout -s 1 60 bash -c \
+ 'while [[ "$(curl -s -o ${1} -L -w ''%{http_code}'' ${0})" != "200" ]]; \
+ do echo "." && sleep 5; \
+ done' ${url} ${curl_output}
+}
+
function bundle_install_script() {
local extra_install_args="${1}"
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index 129d03d17f3..d423377886a 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -120,6 +120,32 @@ RSpec.describe 'Issue Boards new issue', :js do
expect(page).to have_content 'Label 1'
end
end
+
+ it 'allows creating an issue in newly created list' do
+ click_button 'Create list'
+ wait_for_all_requests
+
+ click_button 'Select a label'
+ find('label', text: label.title).click
+ click_button 'Add to board'
+
+ wait_for_all_requests
+
+ page.within('.board:nth-child(2)') do
+ click_button('New issue')
+
+ page.within(first('.board-new-issue-form')) do
+ find('.form-control').set('new issue')
+ click_button 'Create issue'
+ end
+
+ wait_for_all_requests
+
+ page.within('.board-card') do
+ expect(page).to have_content 'new issue'
+ end
+ end
+ end
end
context 'unauthorized user' do
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 33cf928c0cb..052727401dd 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -533,7 +533,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'pull it from Auto-DevOps' do
pipeline = execute_service
expect(pipeline).to be_auto_devops_source
- expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection_default_branch semgrep-sast test])
+ expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection semgrep-sast test])
end
end
diff --git a/spec/services/groups/group_links/create_service_spec.rb b/spec/services/groups/group_links/create_service_spec.rb
index df994b9f2a3..b1bb9a8de23 100644
--- a/spec/services/groups/group_links/create_service_spec.rb
+++ b/spec/services/groups/group_links/create_service_spec.rb
@@ -11,8 +11,8 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let_it_be(:group) { create(:group, :private, parent: group_parent) }
let_it_be(:group_child) { create(:group, :private, parent: group) }
- let_it_be(:shared_group_parent) { create(:group, :private) }
- let_it_be(:shared_group) { create(:group, :private, parent: shared_group_parent) }
+ let_it_be(:shared_group_parent, refind: true) { create(:group, :private) }
+ let_it_be(:shared_group, refind: true) { create(:group, :private, parent: shared_group_parent) }
let_it_be(:shared_group_child) { create(:group, :private, parent: shared_group) }
let_it_be(:project_parent) { create(:project, group: shared_group_parent) }
@@ -28,7 +28,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { group_user }
- subject { described_class.new(group, user, opts) }
+ subject { described_class.new(shared_group, group, user, opts) }
before do
group.add_guest(group_user)
@@ -36,11 +36,11 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
it 'adds group to another group' do
- expect { subject.execute(shared_group) }.to change { group.shared_group_links.count }.from(0).to(1)
+ expect { subject.execute }.to change { group.shared_group_links.count }.from(0).to(1)
end
it 'returns false if shared group is blank' do
- expect { subject.execute(nil) }.not_to change { group.shared_group_links.count }
+ expect { described_class.new(nil, group, user, opts) }.not_to change { group.shared_group_links.count }
end
context 'user does not have access to group' do
@@ -51,7 +51,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
it 'returns error' do
- result = subject.execute(shared_group)
+ result = subject.execute
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(404)
@@ -67,7 +67,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
it 'returns error' do
- result = subject.execute(shared_group)
+ result = subject.execute
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(404)
@@ -85,7 +85,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
it 'is executed only for the direct members of the group' do
expect(UserProjectAccessChangedService).to receive(:new).with(contain_exactly(group_user.id)).and_call_original
- subject.execute(shared_group)
+ subject.execute
end
end
@@ -94,7 +94,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { group_user }
it 'create proper authorizations' do
- subject.execute(shared_group)
+ subject.execute
expect(Ability.allowed?(user, :read_project, project_parent)).to be_falsey
expect(Ability.allowed?(user, :read_project, project)).to be_truthy
@@ -106,7 +106,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { parent_group_user }
it 'create proper authorizations' do
- subject.execute(shared_group)
+ subject.execute
expect(Ability.allowed?(user, :read_project, project_parent)).to be_falsey
expect(Ability.allowed?(user, :read_project, project)).to be_falsey
@@ -118,7 +118,7 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
let(:user) { child_group_user }
it 'create proper authorizations' do
- subject.execute(shared_group)
+ subject.execute
expect(Ability.allowed?(user, :read_project, project_parent)).to be_falsey
expect(Ability.allowed?(user, :read_project, project)).to be_falsey
@@ -127,4 +127,28 @@ RSpec.describe Groups::GroupLinks::CreateService, '#execute' do
end
end
end
+
+ context 'sharing outside the hierarchy is disabled' do
+ before do
+ shared_group_parent.namespace_settings.update!(prevent_sharing_groups_outside_hierarchy: true)
+ end
+
+ it 'prevents sharing with a group outside the hierarchy' do
+ result = subject.execute
+
+ expect(group.reload.shared_group_links.count).to eq(0)
+ expect(result[:status]).to eq(:error)
+ expect(result[:http_status]).to eq(404)
+ end
+
+ it 'allows sharing with a group within the hierarchy' do
+ sibling_group = create(:group, :private, parent: shared_group_parent)
+ sibling_group.add_guest(group_user)
+
+ result = described_class.new(shared_group, sibling_group, user, opts).execute
+
+ expect(sibling_group.reload.shared_group_links.count).to eq(1)
+ expect(result[:status]).to eq(:success)
+ end
+ end
end
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index d2e0399c6c4..9465fe7f0d6 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -174,13 +174,19 @@ RSpec.describe WebHookService do
context 'execution logging' do
let(:hook_log) { project_hook.web_hook_logs.last }
+ def run_service
+ service_instance.execute
+ ::WebHooks::LogExecutionWorker.drain
+ project_hook.reload
+ end
+
context 'with success' do
before do
stub_full_request(project_hook.url, method: :post).to_return(status: 200, body: 'Success')
end
it 'log successful execution' do
- service_instance.execute
+ run_service
expect(hook_log.trigger).to eq('push_hooks')
expect(hook_log.url).to eq(project_hook.url)
@@ -191,12 +197,16 @@ RSpec.describe WebHookService do
expect(hook_log.internal_error_message).to be_nil
end
+ it 'does not log in the service itself' do
+ expect { service_instance.execute }.not_to change(::WebHookLog, :count)
+ end
+
it 'does not increment the failure count' do
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
it 'does not change the disabled_until attribute' do
- expect { service_instance.execute }.not_to change(project_hook, :disabled_until)
+ expect { run_service }.not_to change(project_hook, :disabled_until)
end
context 'when the hook had previously failed' do
@@ -205,7 +215,7 @@ RSpec.describe WebHookService do
end
it 'resets the failure count' do
- expect { service_instance.execute }.to change(project_hook, :recent_failures).to(0)
+ expect { run_service }.to change(project_hook, :recent_failures).to(0)
end
end
end
@@ -216,7 +226,7 @@ RSpec.describe WebHookService do
end
it 'logs failed execution' do
- service_instance.execute
+ run_service
expect(hook_log).to have_attributes(
trigger: eq('push_hooks'),
@@ -230,17 +240,17 @@ RSpec.describe WebHookService do
end
it 'increments the failure count' do
- expect { service_instance.execute }.to change(project_hook, :recent_failures).by(1)
+ expect { run_service }.to change(project_hook, :recent_failures).by(1)
end
it 'does not change the disabled_until attribute' do
- expect { service_instance.execute }.not_to change(project_hook, :disabled_until)
+ expect { run_service }.not_to change(project_hook, :disabled_until)
end
it 'does not allow the failure count to overflow' do
project_hook.update!(recent_failures: 32767)
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
context 'when the web_hooks_disable_failed FF is disabled' do
@@ -252,7 +262,7 @@ RSpec.describe WebHookService do
it 'does not allow the failure count to overflow' do
project_hook.update!(recent_failures: 32767)
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
end
end
@@ -263,7 +273,7 @@ RSpec.describe WebHookService do
end
it 'log failed execution' do
- service_instance.execute
+ run_service
expect(hook_log.trigger).to eq('push_hooks')
expect(hook_log.url).to eq(project_hook.url)
@@ -275,17 +285,15 @@ RSpec.describe WebHookService do
end
it 'does not increment the failure count' do
- expect { service_instance.execute }.not_to change(project_hook, :recent_failures)
+ expect { run_service }.not_to change(project_hook, :recent_failures)
end
it 'backs off' do
- expect(project_hook).to receive(:backoff!).and_call_original
-
- expect { service_instance.execute }.to change(project_hook, :disabled_until)
+ expect { run_service }.to change(project_hook, :disabled_until)
end
it 'increases the backoff count' do
- expect { service_instance.execute }.to change(project_hook, :backoff_count).by(1)
+ expect { run_service }.to change(project_hook, :backoff_count).by(1)
end
context 'when the previous cool-off was near the maximum' do
@@ -294,7 +302,7 @@ RSpec.describe WebHookService do
end
it 'sets the disabled_until attribute' do
- expect { service_instance.execute }.to change(project_hook, :disabled_until).to(1.day.from_now)
+ expect { run_service }.to change(project_hook, :disabled_until).to(1.day.from_now)
end
end
@@ -304,7 +312,7 @@ RSpec.describe WebHookService do
end
it 'sets the disabled_until attribute' do
- expect { service_instance.execute }.to change(project_hook, :disabled_until).to(1.day.from_now)
+ expect { run_service }.to change(project_hook, :disabled_until).to(1.day.from_now)
end
end
end
@@ -312,7 +320,7 @@ RSpec.describe WebHookService do
context 'with unsafe response body' do
before do
stub_full_request(project_hook.url, method: :post).to_return(status: 200, body: "\xBB")
- service_instance.execute
+ run_service
end
it 'log successful execution' do
diff --git a/spec/workers/web_hook_worker_spec.rb b/spec/workers/web_hook_worker_spec.rb
index 066f4f67cb9..548cf4c717a 100644
--- a/spec/workers/web_hook_worker_spec.rb
+++ b/spec/workers/web_hook_worker_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe WebHookWorker do
describe '#perform' do
it 'delegates to WebHookService' do
- expect_next(WebHookService, project_hook, data.with_indifferent_access, hook_name).to receive(:execute)
+ expect_next(WebHookService, project_hook, data.with_indifferent_access, hook_name, anything).to receive(:execute)
subject.perform(project_hook.id, data, hook_name)
end