Skip to content

Commit

Permalink
Add latest changes from gitlab-org/gitlab@master
Browse files Browse the repository at this point in the history
  • Loading branch information
GitLab Bot committed Apr 2, 2024
1 parent cadb3f1 commit a4105ae
Show file tree
Hide file tree
Showing 21 changed files with 235 additions and 44 deletions.
13 changes: 13 additions & 0 deletions .gitlab/ci/package-and-test/main.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,19 @@ ai-gateway-no-seat-assigned:
- if: $QA_SUITES =~ /Test::Integration::AiGatewayNoSeatAssigned/
- !reference [.rules:test:manual, rules]

ai-gateway-no-add-on:
extends:
- .ai-gateway-base
variables:
QA_SCENARIO: Test::Integration::AiGatewayNoAddOn
before_script:
- export QA_EE_ACTIVATION_CODE=$QA_EE_ACTIVATION_CODE_NO_ADD_ON
- !reference [.ai-gateway-base, before_script]
rules:
- !reference [.rules:test:qa, rules]
- if: $QA_SUITES =~ /Test::Integration::AiGatewayNoAddOn/
- !reference [.rules:test:manual, rules]

ai-gateway-no-license:
extends:
- .ai-gateway-base
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/settings_panels.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function expandSection(sectionArg) {
.one('animationend.animateSection', () => $section.removeClass('animating'));
}

InternalEvents.trackEvent('click_expand_panel_on_settings', undefined, {
InternalEvents.trackEvent('click_expand_panel_on_settings', {
label: $section.find('.settings-title').text(),
});
}
Expand Down
10 changes: 5 additions & 5 deletions app/assets/javascripts/tracking/internal_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ const InternalEvents = {
/**
*
* @param {string} event
* @param {Object} additionalProperties - Object containing additional data for the event tracking.
* Supports `value`(number), `property`(string), and `label`(string) as keys.
* @param {string} category - The category of the event. This is optional and
* defaults to the page name where the event was triggered. It's advised not to use
* this parameter for new events unless absolutely necessary.
* @param {Object} additionalProperties - Object containing additional data for the event tracking.
* Supports `value`(number), `property`(string), and `label`(string) as keys.
*
*/
trackEvent(event, category = undefined, additionalProperties = {}) {
trackEvent(event, additionalProperties = {}, category = undefined) {
validateAdditionalProperties(additionalProperties);

API.trackInternalEvent(event, additionalProperties);
Expand All @@ -43,8 +43,8 @@ const InternalEvents = {
mixin() {
return {
methods: {
trackEvent(event, category = undefined, additionalProperties = {}) {
InternalEvents.trackEvent(event, category, additionalProperties);
trackEvent(event, additionalProperties = {}, category = undefined) {
InternalEvents.trackEvent(event, additionalProperties, category);
},
},
};
Expand Down
2 changes: 1 addition & 1 deletion app/models/ci/pipeline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ def triggered_pipelines_with_preloads

def valid_commit_sha
if Gitlab::Git.blank_ref?(self.sha)
self.errors.add(:sha, " cant be 00000000 (branch removal)")
self.errors.add(:sha, "can't be 00000000 (branch removal)")
end
end

Expand Down
6 changes: 3 additions & 3 deletions app/validators/cluster_name_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
class ClusterNameValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if record.provided_by_user?
record.errors.add(attribute, " has to be present") unless value.present?
record.errors.add(attribute, 'has to be present') unless value.present?
else
if record.persisted? && record.name_changed?
record.errors.add(attribute, " can not be changed because it's synchronized with provider")
record.errors.add(attribute, "can not be changed because it's synchronized with provider")
end

unless value.length >= 1 && value.length <= 63
record.errors.add(attribute, " is invalid syntax")
record.errors.add(attribute, 'syntax is invalid')
end

unless Gitlab::Regex.kubernetes_namespace_regex.match(value)
Expand Down
2 changes: 1 addition & 1 deletion app/validators/cron_freeze_period_timezone_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ def validate_each(record, attribute, value)
freeze_start_parser = Gitlab::Ci::CronParser.new(record.freeze_start, record.cron_timezone)
freeze_end_parser = Gitlab::Ci::CronParser.new(record.freeze_end, record.cron_timezone)

record.errors.add(attribute, " is invalid syntax") unless freeze_start_parser.cron_timezone_valid? && freeze_end_parser.cron_timezone_valid?
record.errors.add(attribute, 'syntax is invalid') unless freeze_start_parser.cron_timezone_valid? && freeze_end_parser.cron_timezone_valid?
end
end
2 changes: 1 addition & 1 deletion app/validators/cron_timezone_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
class CronTimezoneValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
cron_parser = Gitlab::Ci::CronParser.new(record.cron, record.cron_timezone)
record.errors.add(attribute, " is invalid syntax") unless cron_parser.cron_timezone_valid?
record.errors.add(attribute, 'syntax is invalid') unless cron_parser.cron_timezone_valid?
end
end
2 changes: 1 addition & 1 deletion app/validators/cron_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class CronValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if ATTRIBUTE_ALLOWLIST.include?(attribute)
cron_parser = Gitlab::Ci::CronParser.new(record.public_send(attribute), record.cron_timezone) # rubocop:disable GitlabSecurity/PublicSend
record.errors.add(attribute, " is invalid syntax") unless cron_parser.cron_valid?
record.errors.add(attribute, 'syntax is invalid') unless cron_parser.cron_valid?
else
raise NonAllowlistedAttributeError, "Non-allowlisted attribute"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329780
milestone: '13.12'
type: development
group: group::threat insights
default_enabled: false
default_enabled: true
16 changes: 13 additions & 3 deletions doc/development/api_graphql_styleguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -1461,9 +1461,19 @@ issues(labelName: "bug", not: {labelName: "bug2"}) {
}
```

To avoid duplicated argument definitions, you can place these arguments in a reusable module (or
class, if the arguments are nested). Alternatively, you can consider to add a
[helper resolver method](https://gitlab.com/gitlab-org/gitlab/-/issues/258969).
You can use the `negated` helper from `Gitlab::Graphql::NegatableArguments` in your type or resolver.
For example:

```ruby
extend ::Gitlab::Graphql::NegatableArguments

negated do
argument :labels, [GraphQL::STRING_TYPE],
required: false,
as: :label_name,
description: 'Array of label names. All resolved merge requests will not have these labels.'
end
```

### Metadata

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ import { InternalEvents } from '~/tracking';
mixins: [InternalEvents.mixin()]
...
...
this.trackEvent('action', 'category')
this.trackEvent('action', {}, 'category')
```

If you are currently passing `category` and need to keep it, it can be passed as the second argument in the `trackEvent` method, as illustrated in the previous example. Nonetheless, it is strongly advised against using the `category` parameter for new events. This is because, by default, the category field is populated with information about where the event was triggered.
If you are currently passing `category` and need to keep it, it can be passed as the third argument in the `trackEvent` method, as illustrated in the previous example. Nonetheless, it is strongly advised against using the `category` parameter for new events. This is because, by default, the category field is populated with information about where the event was triggered.

You can use [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123901/diffs) as an example. It migrates the `devops_adoption_app` component to use Internal Events Tracking.

Expand All @@ -88,7 +88,7 @@ If you are using `label`, `value`, and `property` in Snowplow tracking, you can
For Vue Mixin:

```javascript
this.trackEvent('i_code_review_user_apply_suggestion', undefined, {
this.trackEvent('i_code_review_user_apply_suggestion', {
label: 'push_event',
property: 'golang',
value: 20
Expand All @@ -98,7 +98,7 @@ For Vue Mixin:
For raw JavaScript:

```javascript
InternalEvents.trackEvent('i_code_review_user_apply_suggestion', undefined, {
InternalEvents.trackEvent('i_code_review_user_apply_suggestion', {
label: 'admin',
property: 'system',
value: 20
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ Additional properties can be passed when tracking events. They can be used to sa
For Vue Mixin:

```javascript
this.trackEvent('i_code_review_user_apply_suggestion', undefined, {
this.trackEvent('i_code_review_user_apply_suggestion', {
label: 'push_event',
property: 'golang',
value: 20
Expand All @@ -206,7 +206,7 @@ For Vue Mixin:
For raw JavaScript:

```javascript
InternalEvents.trackEvent('i_code_review_user_apply_suggestion', undefined, {
InternalEvents.trackEvent('i_code_review_user_apply_suggestion', {
label: 'admin',
property: 'system',
value: 20
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,11 +475,12 @@ Note the following:
- `custom` scans are being executed for triggered rules only.
- Jobs variables from `custom` scans take precedence over the project's CI/CD configuration.
- Users triggering a pipeline must have at least read access to CI files specified in the `ci_configuration_path` or included in the CI/CD configuration.
- It is not possible to define custom stages using the `stages` keyword in a custom scan action. Instead three default stages will be added to the pipeline:
- It is not possible to define custom stages using the `stages` keyword in a custom scan action. Instead three reserved stages will be added to the pipeline:
- `.pipeline-policy-pre`at the beginning of the pipeline, before the `.pre` stage.
- `.pipeline-policy-test` after the `test` stage. If the `test` stage does not exist, it will be injected after the `build` stage. If the `build` stage does not exist, it will be injected at the beginning of the pipeline after the `.pre` stage.
- `.pipeline-policy-post` at the very end of the pipeline, after the .post stage.
- Jobs without a stage are assigned to the `.pipeline-policy-test` stage by default.
- It is not possible to assign jobs to reserved stages outside of a custom scan action.

#### Example security policies project

Expand Down
45 changes: 45 additions & 0 deletions doc/user/group/value_stream_analytics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,51 @@ With cumulative label event duration calculation enabled, the duration is three
NOTE:
When you upgrade your GitLab version to 16.10 (or to a higher version), existing label-based value stream analytics stages are automatically reaggregated using the background aggregation process.

##### Reaggregate data after upgrade

DETAILS:
**Offering:** Self-managed

On large self-managed GitLab instances, when you upgrade the GitLab version and especially if several minor versions are skipped, the background aggregation processes might last longer. This delay can result in outdated data on the Value Stream Analytics page.
To speed up the aggregation process and avoid outdated data, in the [rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session) you can invoke the synchronous aggregation snippet for a given group:

```ruby
group = Group.find(-1) # put your group id here
group_to_aggregate = group.root_ancestor

loop do
cursor = {}
context = Analytics::CycleAnalytics::AggregationContext.new(cursor: cursor)
service_response = Analytics::CycleAnalytics::DataLoaderService.new(group: group_to_aggregate, model: Issue, context: context).execute

if service_response.success? && service_response.payload[:reason] == :limit_reached
cursor = service_response.payload[:context].cursor
elsif service_response.success?
puts "finished"
break
else
puts "failed"
break
end
end

loop do
cursor = {}
context = Analytics::CycleAnalytics::AggregationContext.new(cursor: cursor)
service_response = Analytics::CycleAnalytics::DataLoaderService.new(group: group_to_aggregate, model: MergeRequest, context: context).execute

if service_response.success? && service_response.payload[:reason] == :limit_reached
cursor = service_response.payload[:context].cursor
elsif service_response.success?
puts "finished"
break
else
puts "failed"
break
end
end
```

### How value stream analytics identifies the production environment

Value stream analytics identifies [production environments](../../../ci/environments/index.md#deployment-tier-of-environments) by looking for project
Expand Down
2 changes: 2 additions & 0 deletions keeps/helpers/groups.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ def group_for_group_label(group_label)
end

def pick_reviewer(group, identifiers)
return if group['backend_engineers'].empty?

random_engineer = Digest::SHA256.hexdigest(identifiers.join).to_i(16) % group['backend_engineers'].size

group['backend_engineers'][random_engineer]
Expand Down
113 changes: 113 additions & 0 deletions keeps/quarantine_flaky_tests.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# frozen_string_literal: true

require 'gitlab-http'

require_relative 'helpers/groups'

module Keeps
# This is an implementation of a ::Gitlab::Housekeeper::Keep. This keep will fetch any `failure::flaky-test` issues
# with more than 1000 reports and quarantine these tests.
#
# You can run it individually with:
#
# ```
# bundle exec gitlab-housekeeper -d \
# -k Keeps::QuarantineFlakyTests
# ```
class QuarantineFlakyTests < ::Gitlab::Housekeeper::Keep
MINIMUM_FLAKINESS_OCCURENCES = 1000
FLAKY_TEST_ISSUES_URL = "https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab/issues/?order_by=updated_at&state=opened&labels%5B%5D=test&labels%5B%5D=failure%3A%3Aflaky-test&not%5Blabels%5D%5B%5D=QA&not%5Blabel_name%5D%5B%5D=quarantine&per_page=10"
FLAKY_TEST_ISSUE_NOTES_URL = "https://gitlab.com/api/v4/projects/gitlab-org%%2Fgitlab/issues/%<issue_iid>s/notes"
EXAMPLE_LINE_REGEX = /([\w'",])? do$/

def each_change
each_very_flaky_issue do |flaky_issue|
change = prepare_change(flaky_issue)

yield(change) if change
end
end

private

def groups_helper
@groups_helper ||= ::Keeps::Helpers::Groups.new
end

def prepare_change(flaky_issue)
match = flaky_issue['description'].match(%r{\| File URL \| \[`(?<filename>[\w\/\.]+)#L(?<line_number>\d+)`\]})
return unless match

filename = match[:filename]
line_number = match[:line_number].to_i

match = flaky_issue['description'].match(%r{\| Description \| (?<description>.+) \|})
return unless match

description = match[:description]

file = File.expand_path("../#{filename}", __dir__)
full_file_content = File.read(file)
issue_url = flaky_issue['web_url']

file_lines = full_file_content.lines
return unless file_lines[line_number - 1].match?(EXAMPLE_LINE_REGEX)

file_lines[line_number - 1].sub!(EXAMPLE_LINE_REGEX, "\\1, quarantine: '#{issue_url}' do")
File.write(file, file_lines.join)

change = ::Gitlab::Housekeeper::Change.new
change.title = "Quarantine a flaky test"
change.identifiers = [self.class.name.demodulize, filename, line_number.to_s]
change.changed_files = [filename]
change.description = <<~MARKDOWN
The #{description} test has been reported as flaky more then #{MINIMUM_FLAKINESS_OCCURENCES} times.
This MR quarantines the test. This is a discussion starting point to let the responsible group know about the flakiness
so that they can take action:
- accept the merge request and schedule to improve the test
- close the merge request in favor of another merge request to delete the test
Relate to #{issue_url}.
MARKDOWN

group_label = flaky_issue['labels'].grep(/group::/).first
change.labels = [
'maintenance::refactor',
'test',
'failure::flaky-test',
'pipeline:expedite',
'quarantine',
'quarantine::flaky',
group_label
].compact

if change.reviewers.empty? && group_label
group_data = groups_helper.group_for_group_label(group_label)

change.reviewers = groups_helper.pick_reviewer(group_data, change.identifiers) if group_data
end

change
end

def each_very_flaky_issue
flaky_test_issues = Gitlab::HTTP.get(FLAKY_TEST_ISSUES_URL)

flaky_test_issues_above_threshold = flaky_test_issues.select do |flaky_test_issue|
Gitlab::HTTP.get(format(FLAKY_TEST_ISSUE_NOTES_URL, { issue_iid: flaky_test_issue['iid'] }),
headers: { 'PRIVATE-TOKEN': ENV['HOUSEKEEPER_GITLAB_API_TOKEN'] }).find do |note|
match = note['body'].match(/### Flakiness reports \((?<reports_count>\d+)\)/)
next unless match

match[:reports_count].to_i >= MINIMUM_FLAKINESS_OCCURENCES
end
end

flaky_test_issues_above_threshold.map do |issue|
yield(issue)
end
end
end
end
3 changes: 3 additions & 0 deletions locale/gitlab.pot
Original file line number Diff line number Diff line change
Expand Up @@ -31157,6 +31157,9 @@ msgstr ""
msgid "MemberRole|No custom roles found"
msgstr ""

msgid "MemberRole|No description"
msgstr ""

msgid "MemberRole|Permissions"
msgstr ""

Expand Down
Loading

0 comments on commit a4105ae

Please sign in to comment.