Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-08-01 15:11:13 +00:00
parent 9c5341dd08
commit faa19db44a
62 changed files with 542 additions and 413 deletions

View File

@ -402,12 +402,14 @@ Gitlab/NamespacedClass:
- 'app/policies/project_policy.rb'
- 'app/policies/project_snippet_policy.rb'
- 'app/policies/project_statistics_policy.rb'
- 'app/policies/project_hook_policy.rb'
- 'app/policies/prometheus_alert_policy.rb'
- 'app/policies/protected_branch_policy.rb'
- 'app/policies/release_policy.rb'
- 'app/policies/repository_policy.rb'
- 'app/policies/resource_label_event_policy.rb'
- 'app/policies/suggestion_policy.rb'
- 'app/policies/system_hook_policy.rb'
- 'app/policies/timebox_policy.rb'
- 'app/policies/timelog_policy.rb'
- 'app/policies/todo_policy.rb'
@ -968,6 +970,7 @@ Gitlab/NamespacedClass:
- 'ee/app/policies/push_rule_policy.rb'
- 'ee/app/policies/saml_provider_policy.rb'
- 'ee/app/policies/vulnerability_policy.rb'
- 'ee/app/policies/group_hook_policy.rb'
- 'ee/app/presenters/approval_rule_presenter.rb'
- 'ee/app/presenters/audit_event_presenter.rb'
- 'ee/app/presenters/epic_issue_presenter.rb'

View File

@ -141,8 +141,6 @@ Layout/HashAlignment:
- 'app/helpers/sorting_helper.rb'
- 'app/helpers/todos_helper.rb'
- 'app/helpers/wiki_helper.rb'
- 'app/mailers/abuse_report_mailer.rb'
- 'app/mailers/emails/projects.rb'
- 'app/models/bulk_imports/configuration.rb'
- 'app/models/ci/bridge.rb'
- 'app/models/ci/build_trace_metadata.rb'

View File

@ -2,6 +2,21 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 15.2.2 (2022-08-01)
### Fixed (6 changes)
- [Upgrade Oj to v3.13.19 to fix a seg fault](gitlab-org/gitlab@758dff584369303f4176a96ac130954724a0e9f5) ([merge request](gitlab-org/gitlab!93652))
- [Gracefully handle nil created_at values in CI pipelines](gitlab-org/gitlab@492a3dcf6c37f8968282a93cf485f2358ecd7943) ([merge request](gitlab-org/gitlab!93652))
- [Fix CI artifact sizes not logged for some runner endpoints](gitlab-org/gitlab@97ca5e38b1917239bb62cbd338eb689a0ff15fbb) ([merge request](gitlab-org/gitlab!93652))
- [Fix RescheduleBackfillImportedIssueSearchData migration](gitlab-org/gitlab@015e908479a44276833e5bb40d6bd613c394f460) ([merge request](gitlab-org/gitlab!93652))
- [Upgrade oj to v3.3.18 to fix illegal instruction errors](gitlab-org/gitlab@5caf005e1315f7acd145bcbb6d5ced5281a10e56) ([merge request](gitlab-org/gitlab!93652))
- [Use `CREATE OR REPLACE FUNCTION` to define vulnerability reads triggers](gitlab-org/gitlab@dbfa0d51a1851e940ad243f720cbfe1e25c76111) ([merge request](gitlab-org/gitlab!93652))
### Changed (1 change)
- [Fix ES client for nil password](gitlab-org/gitlab@9bd4fa109c06959f5e9b4668c85327e3503bf55a) ([merge request](gitlab-org/gitlab!93652)) **GitLab Enterprise Edition**
## 15.2.1 (2022-07-28)
### Security (18 changes)

View File

@ -1 +1 @@
2720ae51a9acae55951c54268649a5cd0e2fa5ba
3eac3e7f6535d6121cb7790870c169d4d3ed736e

View File

@ -984,7 +984,7 @@ module Ci
def collect_test_reports!(test_reports)
test_reports.get_suite(test_suite_name).tap do |test_suite|
each_report(Ci::JobArtifact::TEST_REPORT_FILE_TYPES) do |file_type, blob|
each_report(Ci::JobArtifact::REPORT_FILE_TYPES[:test]) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(
blob,
test_suite,
@ -995,7 +995,7 @@ module Ci
end
def collect_accessibility_reports!(accessibility_report)
each_report(Ci::JobArtifact::ACCESSIBILITY_REPORT_FILE_TYPES) do |file_type, blob|
each_report(Ci::JobArtifact::REPORT_FILE_TYPES[:accessibility]) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, accessibility_report)
end
@ -1003,7 +1003,7 @@ module Ci
end
def collect_codequality_reports!(codequality_report)
each_report(Ci::JobArtifact::CODEQUALITY_REPORT_FILE_TYPES) do |file_type, blob|
each_report(Ci::JobArtifact::REPORT_FILE_TYPES[:codequality]) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, codequality_report)
end
@ -1011,7 +1011,7 @@ module Ci
end
def collect_terraform_reports!(terraform_reports)
each_report(::Ci::JobArtifact::TERRAFORM_REPORT_FILE_TYPES) do |file_type, blob, report_artifact|
each_report(::Ci::JobArtifact::REPORT_FILE_TYPES[:terraform]) do |file_type, blob, report_artifact|
::Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, terraform_reports, artifact: report_artifact)
end

View File

@ -13,14 +13,18 @@ module Ci
include EachBatch
include Gitlab::Utils::StrongMemoize
TEST_REPORT_FILE_TYPES = %w[junit].freeze
COVERAGE_REPORT_FILE_TYPES = %w[cobertura].freeze
CODEQUALITY_REPORT_FILE_TYPES = %w[codequality].freeze
ACCESSIBILITY_REPORT_FILE_TYPES = %w[accessibility].freeze
NON_ERASABLE_FILE_TYPES = %w[trace].freeze
TERRAFORM_REPORT_FILE_TYPES = %w[terraform].freeze
SAST_REPORT_TYPES = %w[sast].freeze
SECRET_DETECTION_REPORT_TYPES = %w[secret_detection].freeze
REPORT_FILE_TYPES = {
sast: %w[sast],
secret_detection: %w[secret_detection],
test: %w[junit],
accessibility: %w[accessibility],
coverage: %w[cobertura],
codequality: %w[codequality],
terraform: %w[terraform]
}.freeze
DEFAULT_FILE_NAMES = {
archive: nil,
metadata: nil,
@ -152,38 +156,16 @@ module Ci
where(file_type: types)
end
REPORT_FILE_TYPES.each do |report_type, file_types|
scope "#{report_type}_reports", -> do
with_file_types(file_types)
end
end
scope :all_reports, -> do
with_file_types(REPORT_TYPES.keys.map(&:to_s))
end
scope :sast_reports, -> do
with_file_types(SAST_REPORT_TYPES)
end
scope :secret_detection_reports, -> do
with_file_types(SECRET_DETECTION_REPORT_TYPES)
end
scope :test_reports, -> do
with_file_types(TEST_REPORT_FILE_TYPES)
end
scope :accessibility_reports, -> do
with_file_types(ACCESSIBILITY_REPORT_FILE_TYPES)
end
scope :coverage_reports, -> do
with_file_types(COVERAGE_REPORT_FILE_TYPES)
end
scope :codequality_reports, -> do
with_file_types(CODEQUALITY_REPORT_FILE_TYPES)
end
scope :terraform_reports, -> do
with_file_types(TERRAFORM_REPORT_FILE_TYPES)
end
scope :erasable, -> do
where(file_type: self.erasable_file_types)
end

View File

@ -19,7 +19,8 @@ class LooseForeignKeys::DeletedRecord < Gitlab::Database::SharedModel
.limit(1)
.take
oldest_record_in_partition.present? && oldest_record_in_partition.created_at < PARTITION_DURATION.ago
oldest_record_in_partition.present? &&
oldest_record_in_partition.created_at < PARTITION_DURATION.ago
end,
detach_partition_if: -> (partition) do
return false if Feature.disabled?(:lfk_automatic_partition_dropping)

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
class ProjectHookPolicy < ::BasePolicy
delegate(:project)
rule { can?(:admin_project) }.policy do
enable :read_web_hook
enable :destroy_web_hook
end
end

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
class SystemHookPolicy < ::BasePolicy
rule { admin }.policy do
enable :read_web_hook
enable :destroy_web_hook
end
end

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
module WebHooks
# A variant of the destroy service that can only be used by an administrator
# from a rake task.
class AdminDestroyService < WebHooks::DestroyService
def initialize(rake_task:)
super(nil)
@rake_task = rake_task
end
def authorized?(web_hook)
@rake_task.present? # Not impossible to circumvent, but you need to provide something
end
def log_message(hook)
"An administrator scheduled a deletion of logs for hook ID #{hook.id} from #{@rake_task.name}"
end
end
end

View File

@ -1,25 +1,41 @@
# frozen_string_literal: true
module WebHooks
# Destroy a hook, and schedule the logs for deletion.
class DestroyService
include Services::ReturnServiceResponses
attr_accessor :current_user
DENIED = 'Insufficient permissions'
def initialize(current_user)
@current_user = current_user
end
# Destroy the hook immediately, schedule the logs for deletion
def execute(web_hook)
return error(DENIED, 401) unless authorized?(web_hook)
hook_id = web_hook.id
if web_hook.destroy
WebHooks::LogDestroyWorker.perform_async({ 'hook_id' => hook_id })
Gitlab::AppLogger.info("User #{current_user&.id} scheduled a deletion of logs for hook ID #{hook_id}")
Gitlab::AppLogger.info(log_message(web_hook))
ServiceResponse.success(payload: { async: false })
success({ async: false })
else
ServiceResponse.error(message: "Unable to destroy #{web_hook.model_name.human}")
end
error("Unable to destroy #{web_hook.model_name.human}", 500)
end
end
private
def log_message(hook)
"User #{current_user&.id} scheduled a deletion of logs for hook ID #{hook.id}"
end
def authorized?(web_hook)
Ability.allowed?(current_user, :destroy_web_hook, web_hook)
end
end
end

View File

@ -2,9 +2,10 @@
- hidden = @hidden_commit_count
- commits = Commit.decorate(commits, @project)
.card
.card-header
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}, body_options: { class: 'gl-py-0'}) do |c|
- c.header do
Commits (#{@total_commit_count})
- c.body do
- if hidden > 0
%ul.content-list
- commits.each do |commit|

View File

@ -1,8 +0,0 @@
---
name: fix_sliding_list_partitioning
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85222
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362246
milestone: '15.1'
type: development
group: group::sharding
default_enabled: true

View File

@ -144,4 +144,4 @@ methods: {
## Merge request widgets
Refer to the documentation specific to the [merge request widget extension framework](../merge_request_concepts/widget_extensions.md).
Refer to the documentation specific to the [merge request widget extension framework](../new_fe_guide/modules/widget_extensions.md).

View File

@ -5,13 +5,11 @@ group: Code Review
info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
---
# Merge Request Concepts
# Merge request concepts
**NOTE**:
NOTE:
The documentation below is the single source of truth for the merge request terminology and functionality.
## Overview
The merge request is made up of several different key components and ideas that encompass the overall merge request experience. These concepts sometimes have competing and confusing terminology or overlap with other concepts. The concepts this will cover are:
1. Merge widget
@ -19,9 +17,12 @@ The merge request is made up of several different key components and ideas that
1. Merge checks
1. Approval rules
When developing merge request widgets, refer to the documentation for the [merge request widget extension framework](widget_extensions.md).
When developing new merge request widgets, read the
[merge request widget extension framework](../new_fe_guide/modules/widget_extensions.md)
documentation. All new widgets should use this framework, and older widgets should
be ported to use it.
### Merge widget
## Merge widget
The merge widget is the component of the merge request where the `merge` button exists:
@ -29,7 +30,7 @@ The merge widget is the component of the merge request where the `merge` button
This area of the merge request is where all of the options and commit messages are defined prior to merging. It also contains information about what is in the merge request, what issues may be closed, and other important information to the merging process.
### Report widgets
## Report widgets
Reports are widgets within the merge request that report information about changes within the merge request. These widgets provide information to better help the author understand the changes and further improvements to the proposed changes.
@ -37,19 +38,19 @@ Reports are widgets within the merge request that report information about chang
![merge request reports](../img/merge_request_reports_v14_7.png)
### Merge checks
## Merge checks
Merge checks are statuses that can either pass or fail and conditionally control the availability of the merge button being available within a merge request. The key distinguishing factor in a merge check is that users **do not** interact with the merge checks inside of the merge request, but are able to influence whether or not the check passes or fails. Results from the check are processed as true/false to determine whether or not a merge request can be merged. Examples include:
1. merge conflicts
1. pipeline success
1. threads resolution
1. [external status checks](../../user/project/merge_requests/status_checks.md)
1. required approvals
- Merge conflicts.
- Pipeline success.
- Threads resolution.
- [External status checks](../../user/project/merge_requests/status_checks.md).
- Required approvals.
When all of the required merge checks are satisfied a merge request becomes mergeable.
### Approvals
## Approvals
Approval rules specify users that are required to or can optionally approve a merge request based on some kind of organizational policy. When approvals are required, they effectively become a required merge check. The key differentiator between merge checks and approval rules is that users **do** interact with approval rules, by deciding to approve the merge request.

View File

@ -1,93 +1,11 @@
---
stage: create
group: code review
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: '../new_fe_guide/modules/widget_extensions.md'
remove_date: '2022-10-27'
---
# Merge request widget extensions
This document was moved to [another location](../new_fe_guide/modules/widget_extensions.md).
The merge request **Overview** page has [a substantial widgets section](index.md#report-widgets)
that allows for other teams to provide content that enhances the Merge Request review experience
based on features and tools enabled on the instance has enabled.
To enable contributions from other teams, the Code Review team has created an extension
framework to create standardized widgets for display.
## Telemetry
The base implementation of the widget extension framework includes some telemetry events.
Each widget reports:
- `view`: When it is rendered to the screen.
- `expand`: When it is expanded.
- `full_report_clicked`: When an (optional) input is clicked to view the full report.
- Outcome (`expand_success`, `expand_warning`, or `expand_failed`): One of three
additional events relating to the status of the widget when it was expanded.
### Adding new widgets
When adding new widgets, the above events must be marked as `known`, and have metrics
created, to be reportable. To generate these known events for a single widget:
1. Widgets should be named `Widget${CamelName}`.
- For example: a widget for **Test Reports** should be `WidgetTestReports`.
1. Compute the widget name slug by converting the `${CamelName}` to lower-, snake-case.
- The previous example would be `test_reports`.
1. Add the new widget name slug to `lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb`
in the `WIDGETS` list.
1. Ensure the GDK is running (`gdk start`).
1. Generate known events on the command line with the following command.
Replace `test_reports` with your appropriate name slug:
```shell
bundle exec rails generate gitlab:usage_metric_definition \
counts.i_code_review_merge_request_widget_test_reports_count_view \
counts.i_code_review_merge_request_widget_test_reports_count_full_report_clicked \
counts.i_code_review_merge_request_widget_test_reports_count_expand \
counts.i_code_review_merge_request_widget_test_reports_count_expand_success \
counts.i_code_review_merge_request_widget_test_reports_count_expand_warning \
counts.i_code_review_merge_request_widget_test_reports_count_expand_failed \
--dir=all
```
1. Modify each newly generated file to match the existing files for the merge request widget extension telemetry.
- Find existing examples by doing a glob search, like: `metrics/**/*_i_code_review_merge_request_widget_*`
- Roughly speaking, each file should have these values:
1. `description` = A plain English description of this value. Please see existing widget extension telemetry files for examples.
1. `product_section` = `dev`
1. `product_stage` = `create`
1. `product_group` = `code_review`
1. `product_category` = `code_review`
1. `introduced_by_url` = `'[your MR]'`
1. `options.events` = (the event in the command from above that generated this file, like `i_code_review_merge_request_widget_test_reports_count_view`)
- This value is how the telemetry events are linked to "metrics" so this is probably one of the more important values.
1. `data_source` = `redis`
1. `data_category` = `optional`
1. Repeat steps 5 and 6 for the HLL metrics. Replace `test_reports` with your appropriate name slug.
```shell
bundle exec rails generate gitlab:usage_metric_definition:redis_hll code_review \
i_code_review_merge_request_widget_test_reports_view \
i_code_review_merge_request_widget_test_reports_full_report_clicked \
i_code_review_merge_request_widget_test_reports_expand \
i_code_review_merge_request_widget_test_reports_expand_success \
i_code_review_merge_request_widget_test_reports_expand_warning \
i_code_review_merge_request_widget_test_reports_expand_failed \
--class_name=RedisHLLMetric
```
- In step 6 for HLL, change the `data_source` to `redis_hll`.
1. Add each of the HLL metrics to `lib/gitlab/usage_data_counters/known_events/code_review_events.yml`:
1. `name` = (the event)
1. `redis_slot` = `code_review`
1. `category` = `code_review`
1. `aggregation` = `weekly`
1. Add each event to the appropriate aggregates in `config/metrics/aggregates/code_review.yml`
#### New events
If you are adding a new event to our known events:
1. Include it in
`lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb`.
1. Update the list of `KNOWN_EVENTS` with the new events.
<!-- This redirect file can be deleted after <2022-10-27>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -8,8 +8,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44616) in GitLab 13.6.
## Summary
Extensions in the merge request widget enable you to add new features
into the merge request widget that match the design framework.
With extensions we get a lot of benefits out of the box without much effort required, like:
@ -37,6 +35,7 @@ export default {
expandEvent: '', // Optional: RedisHLL event name to track expanding content
enablePolling: false, // Optional: Tells extension to poll for data
modalComponent: null, // Optional: The component to use for the modal
telemetry: true, // Optional: Reports basic telemetry for the extension. Set to false to disable telemetry
computed: {
summary(data) {}, // Required: Level 1 summary text
statusIcon(data) {}, // Required: Level 1 status icon
@ -77,7 +76,7 @@ data fetching methods to be used, such as GraphQL or REST API calls.
### API calls
For performance reasons, it is best if the collapsed state fetches only the data required to
render the collapsed state. This fetching happens within the `fetchCollapsedData` method.
render the collapsed state. This fetching happens in the `fetchCollapsedData` method.
This method is called with the props as an argument, so you can easily access
any paths set in the state.
@ -88,7 +87,7 @@ method.
When the user clicks **Expand**, the `fetchFullData` method is called. This method
also gets called with the props as an argument. This method **must** also return
the full data. However, this data needs to be correctly formatted to match the format
the full data. However, this data must be correctly formatted to match the format
mentioned in the data structure section.
#### Technical debt
@ -233,7 +232,7 @@ export default {
};
```
If the extension needs to poll multiple endpoints at the same time, then `fetchMultiData`
If the extension must poll multiple endpoints at the same time, then `fetchMultiData`
can be used to return an array of functions. A new `poll` object is created for each
endpoint and they are polled separately. After all endpoints are resolved, polling is
stopped and `setCollapsedData` is called with an array of `response.data`.
@ -253,7 +252,8 @@ export default {
};
```
**Important** The function needs to return a `Promise` that resolves the `response` object.
WARNING:
The function must return a `Promise` that resolves the `response` object.
The implementation relies on the `POLL-INTERVAL` header to keep polling, therefore it is
important not to alter the status code and headers.
@ -280,6 +280,87 @@ export default {
};
```
## Telemetry
The base implementation of the widget extension framework includes some telemetry events.
Each widget reports:
- `view`: When it is rendered to the screen.
- `expand`: When it is expanded.
- `full_report_clicked`: When an (optional) input is clicked to view the full report.
- Outcome (`expand_success`, `expand_warning`, or `expand_failed`): One of three
additional events relating to the status of the widget when it was expanded.
### Add new widgets
When adding new widgets, the above events must be marked as `known`, and have metrics
created, to be reportable.
NOTE:
Events that are only for EE should include `--ee` at the end of both shell commands below.
To generate these known events for a single widget:
1. Widgets should be named `Widget${CamelName}`.
- For example: a widget for **Test Reports** should be `WidgetTestReports`.
1. Compute the widget name slug by converting the `${CamelName}` to lower-, snake-case.
- The previous example would be `test_reports`.
1. Add the new widget name slug to `lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb`
in the `WIDGETS` list.
1. Ensure the GDK is running (`gdk start`).
1. Generate known events on the command line with the following command.
Replace `test_reports` with your appropriate name slug:
```shell
bundle exec rails generate gitlab:usage_metric_definition \
counts.i_code_review_merge_request_widget_test_reports_count_view \
counts.i_code_review_merge_request_widget_test_reports_count_full_report_clicked \
counts.i_code_review_merge_request_widget_test_reports_count_expand \
counts.i_code_review_merge_request_widget_test_reports_count_expand_success \
counts.i_code_review_merge_request_widget_test_reports_count_expand_warning \
counts.i_code_review_merge_request_widget_test_reports_count_expand_failed \
--dir=all
```
1. Modify each newly generated file to match the existing files for the merge request widget extension telemetry.
- Find existing examples by doing a glob search, like: `metrics/**/*_i_code_review_merge_request_widget_*`
- Roughly speaking, each file should have these values:
1. `description` = A plain English description of this value. Review existing widget extension telemetry files for examples.
1. `product_section` = `dev`
1. `product_stage` = `create`
1. `product_group` = `code_review`
1. `product_category` = `code_review`
1. `introduced_by_url` = `'[your MR]'`
1. `options.events` = (the event in the command from above that generated this file, like `i_code_review_merge_request_widget_test_reports_count_view`)
- This value is how the telemetry events are linked to "metrics" so this is probably one of the more important values.
1. `data_source` = `redis`
1. `data_category` = `optional`
1. Repeat steps 5 and 6 for the HLL metrics. Replace `test_reports` with your appropriate name slug.
```shell
bundle exec rails generate gitlab:usage_metric_definition:redis_hll code_review \
i_code_review_merge_request_widget_test_reports_view \
i_code_review_merge_request_widget_test_reports_full_report_clicked \
i_code_review_merge_request_widget_test_reports_expand \
i_code_review_merge_request_widget_test_reports_expand_success \
i_code_review_merge_request_widget_test_reports_expand_warning \
i_code_review_merge_request_widget_test_reports_expand_failed \
--class_name=RedisHLLMetric
```
- In step 6 for HLL, change the `data_source` to `redis_hll`.
1. Add each of the HLL metrics to `lib/gitlab/usage_data_counters/known_events/code_review_events.yml`:
1. `name` = (the event)
1. `redis_slot` = `code_review`
1. `category` = `code_review`
1. `aggregation` = `weekly`
1. Add each event to the appropriate aggregates in `config/metrics/aggregates/code_review.yml`
### Add new events
If you are adding a new event to our known events, include the new event in the
`KNOWN_EVENTS` list in `lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb`.
## Icons
Level 1 and all subsequent levels can have their own status icons. To keep with

View File

@ -20,7 +20,7 @@ module Gitlab
coverage_report.tap do |coverage_report|
report_builds.find_each do |build|
build.each_report(::Ci::JobArtifact::COVERAGE_REPORT_FILE_TYPES) do |file_type, blob|
build.each_report(::Ci::JobArtifact::REPORT_FILE_TYPES[:coverage]) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(
blob,
coverage_report,

View File

@ -77,7 +77,6 @@ module Gitlab
end
def validate_and_fix
return unless Feature.enabled?(:fix_sliding_list_partitioning)
return if no_partitions_exist?
old_default_value = current_default_value

View File

@ -5,6 +5,8 @@ module Gitlab
# Wrapper around ExclusiveLease that adds retry logic
class SleepingLock
delegate :cancel, to: :@lease
MAX_ATTEMPTS = 65
DEFAULT_ATTEMPTS = 10
def initialize(key, timeout:, delay:)
@lease = ::Gitlab::ExclusiveLease.new(key, timeout: timeout)
@ -12,9 +14,9 @@ module Gitlab
@attempts = 0
end
def obtain(max_attempts)
def obtain(max_attempts = DEFAULT_ATTEMPTS)
until held?
raise FailedToObtainLockError, 'Failed to obtain a lock' if attempts >= max_attempts
raise FailedToObtainLockError, 'Failed to obtain a lock' if attempts >= [max_attempts, MAX_ATTEMPTS].min
sleep(sleep_sec) unless first_attempt?
try_obtain

View File

@ -22,11 +22,13 @@ namespace :gitlab do
end
end
desc "GitLab | Webhook | Remove a webhook from the projects"
task rm: :environment do
desc "GitLab | Webhook | Remove a webhook from a namespace"
task rm: :environment do |task|
web_hook_url = ENV['URL']
namespace_path = ENV['NAMESPACE']
raise ArgumentError, 'URL is required' unless web_hook_url
web_hooks = find_web_hooks(namespace_path)
puts "Removing webhooks with the url '#{web_hook_url}' ... "
@ -36,11 +38,12 @@ namespace :gitlab do
# we could consider storing a hash of the URL alongside the encrypted
# value to speed up searches
count = 0
service = WebHooks::AdminDestroyService.new(rake_task: task)
web_hooks.find_each do |hook|
next unless hook.url == web_hook_url
user = hook.parent.owners.first
result = WebHooks::DestroyService.new(user).execute(hook)
result = service.execute(hook)
raise "Unable to destroy Web hook" unless result[:status] == :success

View File

@ -48,23 +48,6 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
end
describe '#validate_and_fix' do
context 'feature flag is disabled' do
before do
stub_feature_flags(fix_sliding_list_partitioning: false)
end
it 'does not try to fix the default partition value' do
connection.change_column_default(model.table_name, strategy.partitioning_key, 3)
expect(strategy.model.connection).not_to receive(:change_column_default)
strategy.validate_and_fix
end
end
context 'feature flag is enabled' do
before do
stub_feature_flags(fix_sliding_list_partitioning: true)
end
it 'does not call change_column_default if the partitioning in a valid state' do
expect(strategy.model.connection).not_to receive(:change_column_default)
@ -104,7 +87,6 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
strategy.validate_and_fix
end
end
end
describe '#active_partition' do
it 'is the partition with the largest value' do

View File

@ -52,6 +52,28 @@ RSpec.describe Gitlab::ExclusiveLeaseHelpers::SleepingLock, :clean_gitlab_redis_
end
end
context 'when the lease is obtained already' do
let!(:lease) { stub_exclusive_lease_taken(key) }
context 'when retries are not specified' do
it 'retries to obtain a lease and raises an error' do
expect(lease).to receive(:try_obtain).exactly(10).times
expect { subject.obtain }.to raise_error('Failed to obtain a lock')
end
end
context 'when specified retries are above the maximum attempts' do
let(:max_attempts) { 100 }
it 'retries to obtain a lease and raises an error' do
expect(lease).to receive(:try_obtain).exactly(65).times
expect { subject.obtain(max_attempts) }.to raise_error('Failed to obtain a lock')
end
end
end
context 'when the lease is held elsewhere' do
let!(:lease) { stub_exclusive_lease_taken(key) }
let(:max_attempts) { 7 }

View File

@ -4552,7 +4552,7 @@ RSpec.describe Ci::Build do
end
describe '#each_report' do
let(:report_types) { Ci::JobArtifact::COVERAGE_REPORT_FILE_TYPES }
let(:report_types) { Ci::JobArtifact::REPORT_FILE_TYPES[:coverage] }
let!(:codequality) { create(:ci_job_artifact, :codequality, job: build) }
let!(:coverage) { create(:ci_job_artifact, :coverage_gocov_xml, job: build) }

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ProjectHookPolicy do
let_it_be(:user) { create(:user) }
let(:hook) { create(:project_hook) }
subject(:policy) { described_class.new(user, hook) }
context 'when the user is not a maintainer' do
before do
hook.project.add_developer(user)
end
it "cannot read and destroy web-hooks" do
expect(policy).to be_disallowed(:read_web_hook, :destroy_web_hook)
end
end
context 'when the user is a maintainer' do
before do
hook.project.add_maintainer(user)
end
it "can read and destroy web-hooks" do
expect(policy).to be_allowed(:read_web_hook, :destroy_web_hook)
end
end
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe SystemHookPolicy do
let(:hook) { create(:system_hook) }
subject(:policy) { described_class.new(user, hook) }
context 'when the user is not an admin' do
let(:user) { create(:user) }
%i[read_web_hook destroy_web_hook].each do |thing|
it "cannot #{thing}" do
expect(policy).to be_disallowed(thing)
end
end
end
context 'when the user is an admin', :enable_admin_mode do
let(:user) { create(:admin) }
%i[read_web_hook destroy_web_hook].each do |thing|
it "can #{thing}" do
expect(policy).to be_allowed(thing)
end
end
end
end

View File

@ -8,11 +8,23 @@ RSpec.describe WebHooks::DestroyService do
subject { described_class.new(user) }
describe '#execute' do
%i[system_hook project_hook].each do |factory|
context "deleting a #{factory}" do
let!(:hook) { create(factory) } # rubocop: disable Rails/SaveBang (false-positive!)
# Testing with a project hook only - for permission tests, see policy specs.
let!(:hook) { create(:project_hook) }
let!(:log) { create_list(:web_hook_log, 3, web_hook: hook) }
context 'when the user does not have permission' do
it 'is an error' do
expect(subject.execute(hook))
.to be_error
.and have_attributes(message: described_class::DENIED)
end
end
context 'when the user does have permission' do
before do
hook.project.add_maintainer(user)
end
it 'is successful' do
expect(subject.execute(hook)).to be_success
end
@ -49,4 +61,3 @@ RSpec.describe WebHooks::DestroyService do
end
end
end
end

View File

@ -50,6 +50,10 @@ RSpec.describe 'gitlab:web_hook namespace rake tasks', :silence_stdout do
let(:other_url) { 'http://other.example.com' }
it 'complains if URL is not provided' do
expect { run_rake_task('gitlab:web_hook:rm') }.to raise_error(ArgumentError, 'URL is required')
end
it 'removes a web hook from all projects by URL' do
stub_env('URL' => url)
run_rake_task('gitlab:web_hook:rm')