Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c3fe9f5215
commit
5b9b518d9f
|
|
@ -1300,7 +1300,6 @@ lib/gitlab/checks/**
|
|||
/ee/app/views/ci_minutes_usage_mailer/
|
||||
/ee/app/views/projects/pipelines/
|
||||
/ee/app/views/projects/settings/ci_cd/
|
||||
/ee/app/workers/clear_shared_runners_minutes_worker.rb
|
||||
/ee/lib/api/merge_trains.rb
|
||||
/ee/lib/ee/api/entities/merge_train.rb
|
||||
|
||||
|
|
|
|||
|
|
@ -122,10 +122,6 @@ export-test-metrics:
|
|||
extends:
|
||||
- .export-test-metrics
|
||||
|
||||
relate-test-failures:
|
||||
extends:
|
||||
- .relate-test-failures
|
||||
|
||||
generate-test-session:
|
||||
extends:
|
||||
- .generate-test-session
|
||||
|
|
|
|||
|
|
@ -689,11 +689,6 @@ export-test-metrics:
|
|||
- .export-test-metrics
|
||||
- .rules:report:process-results
|
||||
|
||||
relate-test-failures:
|
||||
extends:
|
||||
- .relate-test-failures
|
||||
- .rules:report:process-results
|
||||
|
||||
generate-test-session:
|
||||
extends:
|
||||
- .generate-test-session
|
||||
|
|
|
|||
|
|
@ -205,27 +205,6 @@ stages:
|
|||
script:
|
||||
- bundle exec rake "ci:export_test_metrics[$QA_METRICS_REPORT_FILE_PATTERN]"
|
||||
|
||||
.relate-test-failures:
|
||||
extends:
|
||||
- .qa-install
|
||||
- .ruby-image
|
||||
stage: report
|
||||
when: always
|
||||
variables:
|
||||
QA_RSPEC_JSON_FILE_PATTERN: "${CI_PROJECT_DIR}/gitlab-qa-run-*/**/rspec-*.json"
|
||||
script:
|
||||
- |
|
||||
if [ "$SUITE_FAILED" != "true" ] && [ "$SUITE_RAN" == "true" ]; then
|
||||
echo "Test suite passed. Exiting..."
|
||||
exit 0
|
||||
fi
|
||||
- bundle exec update-screenshot-paths --input-files "${CI_PROJECT_DIR}/gitlab-qa-run-*/**/rspec-*.xml"
|
||||
- |
|
||||
bundle exec relate-failure-issue \
|
||||
--input-files "${QA_RSPEC_JSON_FILE_PATTERN}" \
|
||||
--project "gitlab-org/gitlab" \
|
||||
--token "${QA_RELATE_FAILURE_ISSUE_TOKEN}"
|
||||
|
||||
.generate-test-session:
|
||||
extends:
|
||||
- .qa-install
|
||||
|
|
|
|||
|
|
@ -70,15 +70,6 @@ qa:master-auto-quarantine-dequarantine:
|
|||
- bundle exec confiner -r .confiner/master.yml
|
||||
allow_failure: true
|
||||
|
||||
qa:nightly-auto-quarantine-dequarantine:
|
||||
extends:
|
||||
- .qa-job-base
|
||||
rules:
|
||||
- if: '$QA_TRIGGER_AUTO_QUARANTINE =~ /true|yes|1/i'
|
||||
script:
|
||||
- bundle exec confiner -r .confiner/nightly.yml
|
||||
allow_failure: true
|
||||
|
||||
qa:update-qa-cache:
|
||||
extends:
|
||||
- .qa-job-base
|
||||
|
|
|
|||
|
|
@ -149,12 +149,10 @@ export-test-metrics:
|
|||
variables:
|
||||
QA_METRICS_REPORT_FILE_PATTERN: $CI_PROJECT_DIR/qa/tmp/test-metrics-*.json
|
||||
|
||||
relate-test-failures:
|
||||
extends:
|
||||
- .relate-test-failures
|
||||
- .rules:report:process-results
|
||||
.gitlab-qa-report:
|
||||
variables:
|
||||
QA_RSPEC_JSON_FILE_PATTERN: $CI_PROJECT_DIR/qa/tmp/rspec-*.json
|
||||
QA_SYSTEM_LOG_FILE_PATTERN: $CI_PROJECT_DIR/test_output/logs
|
||||
|
||||
generate-test-session:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -1033,7 +1033,6 @@ Gitlab/NamespacedClass:
|
|||
- 'ee/app/workers/adjourned_project_deletion_worker.rb'
|
||||
- 'ee/app/workers/adjourned_projects_deletion_cron_worker.rb'
|
||||
- 'ee/app/workers/admin_emails_worker.rb'
|
||||
- 'ee/app/workers/clear_shared_runners_minutes_worker.rb'
|
||||
- 'ee/app/workers/create_github_webhook_worker.rb'
|
||||
- 'ee/app/workers/elastic_association_indexer_worker.rb'
|
||||
- 'ee/app/workers/elastic_cluster_reindexing_cron_worker.rb'
|
||||
|
|
|
|||
|
|
@ -325,12 +325,10 @@ SidekiqLoadBalancing/WorkerDataConsistency:
|
|||
- 'ee/app/workers/arkose/blocked_users_report_worker.rb'
|
||||
- 'ee/app/workers/auth/saml_group_sync_worker.rb'
|
||||
- 'ee/app/workers/automation/execute_rule_worker.rb'
|
||||
- 'ee/app/workers/ci/batch_reset_minutes_worker.rb'
|
||||
- 'ee/app/workers/ci/minutes/refresh_cached_data_worker.rb'
|
||||
- 'ee/app/workers/ci/minutes/update_project_and_namespace_usage_worker.rb'
|
||||
- 'ee/app/workers/ci/sync_reports_to_report_approval_rules_worker.rb'
|
||||
- 'ee/app/workers/ci/upstream_projects_subscriptions_cleanup_worker.rb'
|
||||
- 'ee/app/workers/clear_shared_runners_minutes_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/chain_of_custody_report_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/merge_requests/compliance_violations_consistency_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/merge_requests/compliance_violations_worker.rb'
|
||||
|
|
|
|||
|
|
@ -1,23 +1,67 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module SafeFormatHelper
|
||||
# Returns a HTML-safe string where
|
||||
# * +format+ is escaped via `html_escape_once`
|
||||
# * +args+ are escaped via `html_escape` if they are not marked as HTML-safe
|
||||
# Returns a HTML-safe String.
|
||||
#
|
||||
# Example:
|
||||
# safe_format('Some %{open}bold%{close} text.', open: '<strong>'.html_safe, close: '</strong>'.html_safe)
|
||||
# # => 'Some <strong>bold</strong>'
|
||||
# @param [String] format is escaped via `html_escape_once`
|
||||
# @param [Array<Hash>] args are escaped via `html_escape` if they are not marked as HTML-safe
|
||||
#
|
||||
# @example
|
||||
# safe_format('See %{user_input}', user_input: '<b>bold</b>')
|
||||
# # => 'See <b>bold</b>
|
||||
# safe_format('In < hour & more')
|
||||
# # => 'In < hour & more'
|
||||
# # => "See <b>bold</b>"
|
||||
#
|
||||
def safe_format(format, **args)
|
||||
# safe_format('In < hour & more')
|
||||
# # => "In < hour & more"
|
||||
#
|
||||
# @example With +tag_pair+ support
|
||||
# safe_format('Some %{open}bold%{close} text.', tag_pair(tag.strong, :open, :close))
|
||||
# # => "Some <strong>bold</strong> text."
|
||||
# safe_format('Some %{open}bold%{close} %{italicStart}text%{italicEnd}.',
|
||||
# tag_pair(tag.strong, :open, :close),
|
||||
# tag_pair(tag.i, :italicStart, :italicEnd))
|
||||
# # => "Some <strong>bold</strong> <i>text</i>.
|
||||
def safe_format(format, *args)
|
||||
args = args.inject({}, &:merge)
|
||||
|
||||
# Use `Kernel.format` to avoid conflicts with ViewComponent's `format`.
|
||||
Kernel.format(
|
||||
html_escape_once(format),
|
||||
args.transform_values { |value| html_escape(value) }
|
||||
).html_safe
|
||||
end
|
||||
|
||||
# Returns a Hash containing a pair of +open+ and +close+ tag parts extracted
|
||||
# from HTML-safe +tag+. The values are HTML-safe.
|
||||
#
|
||||
# Returns an empty Hash if +tag+ is not a valid paired tag (e.g. <p>foo</p>).
|
||||
# an empty Hash is returned.
|
||||
#
|
||||
# @param [String] tag is a HTML-safe output from tag helper
|
||||
# @param [Symbol,Object] open_name name of opening tag
|
||||
# @param [Symbol,Object] close_name name of closing tag
|
||||
# @raise [ArgumentError] if +tag+ is not HTML-safe
|
||||
#
|
||||
# @example
|
||||
# tag_pair(tag.strong, :open, :close)
|
||||
# # => { open: '<strong>', close: '</strong>' }
|
||||
# tag_pair(link_to('', '/'), :open, :close)
|
||||
# # => { open: '<a href="/">', close: '</a>' }
|
||||
def tag_pair(html_tag, open_name, close_name)
|
||||
raise ArgumentError, 'Argument `tag` must be `html_safe`!' unless html_tag.html_safe?
|
||||
return {} unless html_tag.start_with?('<')
|
||||
|
||||
# end of opening tag: <p>foo</p>
|
||||
# ^
|
||||
open_index = html_tag.index('>')
|
||||
# start of closing tag: <p>foo</p>
|
||||
# ^^
|
||||
close_index = html_tag.rindex('</')
|
||||
|
||||
return {} unless open_index && close_index
|
||||
|
||||
{
|
||||
open_name => html_tag[0, open_index + 1],
|
||||
close_name => html_tag[close_index, html_tag.size]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -702,9 +702,6 @@ Gitlab.ee do
|
|||
Settings.cron_jobs['adjourned_group_deletion_worker'] ||= {}
|
||||
Settings.cron_jobs['adjourned_group_deletion_worker']['cron'] ||= '0 2 * * *'
|
||||
Settings.cron_jobs['adjourned_group_deletion_worker']['job_class'] = 'AdjournedGroupDeletionWorker'
|
||||
Settings.cron_jobs['clear_shared_runners_minutes_worker'] ||= {}
|
||||
Settings.cron_jobs['clear_shared_runners_minutes_worker']['cron'] ||= '0 0 1 * *'
|
||||
Settings.cron_jobs['clear_shared_runners_minutes_worker']['job_class'] = 'ClearSharedRunnersMinutesWorker'
|
||||
Settings.cron_jobs['adjourned_projects_deletion_cron_worker'] ||= {}
|
||||
Settings.cron_jobs['adjourned_projects_deletion_cron_worker']['cron'] ||= '0 7 * * *'
|
||||
Settings.cron_jobs['adjourned_projects_deletion_cron_worker']['job_class'] = 'AdjournedProjectsDeletionCronWorker'
|
||||
|
|
|
|||
|
|
@ -113,8 +113,6 @@
|
|||
- 2
|
||||
- - chat_notification
|
||||
- 2
|
||||
- - ci_batch_reset_minutes
|
||||
- 1
|
||||
- - ci_cancel_pipeline
|
||||
- 1
|
||||
- - ci_cancel_redundant_pipelines
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveClearSharedRunnersMinutesWorkerJobInstances < Gitlab::Database::Migration[2.1]
|
||||
DEPRECATED_JOB_CLASSES = %w[
|
||||
ClearSharedRunnersMinutesWorker
|
||||
Ci::BatchResetMinutesWorker
|
||||
]
|
||||
disable_ddl_transaction!
|
||||
def up
|
||||
sidekiq_remove_jobs(job_klasses: DEPRECATED_JOB_CLASSES)
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
c312816ffabb9442b57d826a9e8c2214ae7672bf03938a911ddae490309fe87d
|
||||
|
|
@ -33,17 +33,17 @@ On self-managed GitLab instances:
|
|||
|
||||
- CI/CD minutes quotas are disabled by default.
|
||||
- When enabled, CI/CD minutes quotas apply to private projects only.
|
||||
- Administrators can [assign more CI/CD minutes](#set-the-quota-of-cicd-minutes-for-a-specific-namespace)
|
||||
- Administrators can [assign more CI/CD minutes](#set-the-compute-quota-for-a-specific-namespace)
|
||||
if a namespace uses all the CI/CD minutes in its monthly quota.
|
||||
|
||||
[Project runners](../runners/runners_scope.md#project-runners) are not subject to a quota of CI/CD minutes.
|
||||
|
||||
## Set the quota of CI/CD minutes for all namespaces
|
||||
## Set the compute quota for all namespaces
|
||||
|
||||
> [Moved](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) to GitLab Premium in 13.9.
|
||||
|
||||
By default, GitLab instances do not have a quota of CI/CD minutes.
|
||||
The default value for the quota is `0`, which grants unlimited CI/CD minutes.
|
||||
By default, GitLab instances do not have a compute quota.
|
||||
The default value for the quota is `0`, which is unlimited.
|
||||
However, you can change this default value.
|
||||
|
||||
Prerequisite:
|
||||
|
|
@ -55,35 +55,35 @@ To change the default quota that applies to all namespaces:
|
|||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > CI/CD**.
|
||||
1. Expand **Continuous Integration and Deployment**.
|
||||
1. In the **Quota of CI/CD minutes** box, enter the maximum number of CI/CD minutes.
|
||||
1. In the **Compute quota** box, enter a limit.
|
||||
1. Select **Save changes**.
|
||||
|
||||
If a quota is already defined for a specific namespace, this value does not change that quota.
|
||||
|
||||
## Set the quota of CI/CD minutes for a specific namespace
|
||||
## Set the compute quota for a specific namespace
|
||||
|
||||
> [Moved](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) to GitLab Premium in 13.9.
|
||||
|
||||
You can override the global value and set a quota of CI/CD minutes
|
||||
You can override the global value and set a compute quota
|
||||
for a specific namespace.
|
||||
|
||||
Prerequisite:
|
||||
|
||||
- You must be a GitLab administrator.
|
||||
|
||||
To set a quota of CI/CD minutes for a namespace:
|
||||
To set a compute quota for a namespace:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Overview > Groups**.
|
||||
1. For the group you want to update, select **Edit**.
|
||||
1. In the **Quota of CI/CD minutes** box, enter the maximum number of CI/CD minutes.
|
||||
1. In the **Compute quota** box, enter the maximum number of CI/CD minutes.
|
||||
1. Select **Save changes**.
|
||||
|
||||
You can also use the [update group API](../../api/groups.md#update-group) or the
|
||||
[update user API](../../api/users.md#user-modification) instead.
|
||||
|
||||
NOTE:
|
||||
You can set a quota of CI/CD minutes for only top-level groups or user namespaces.
|
||||
You can set a compute quota for only top-level groups or user namespaces.
|
||||
If you set a quota for a subgroup, it is not used.
|
||||
|
||||
## View CI/CD minutes
|
||||
|
|
@ -348,18 +348,18 @@ consumption for contributor fork projects, enabling more contributions.
|
|||
|
||||
See our [pipeline efficiency guide](pipeline_efficiency.md) for more details.
|
||||
|
||||
## Reset CI/CD minutes used **(PREMIUM SELF)**
|
||||
## Reset compute usage **(PREMIUM SELF)**
|
||||
|
||||
An administrator can reset the number of minutes used by a namespace for the current month.
|
||||
|
||||
### Reset minutes for a personal namespace
|
||||
### Reset usage for a personal namespace
|
||||
|
||||
1. Find the [user in the admin area](../../user/admin_area/index.md#administering-users).
|
||||
1. Select **Edit**.
|
||||
1. In **Limits**, select **Reset pipeline minutes**.
|
||||
1. In **Limits**, select **Reset compute usage**.
|
||||
|
||||
### Reset minutes for a group namespace
|
||||
### Reset usage for a group namespace
|
||||
|
||||
1. Find the [group in the admin area](../../user/admin_area/index.md#administering-groups).
|
||||
1. Select **Edit**.
|
||||
1. In **Permissions and group features**, select **Reset pipeline minutes**.
|
||||
1. In **Permissions and group features**, select **Reset compute usage**.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ If you are using a self-managed instance of GitLab:
|
|||
and selecting **Show runner installation instructions**.
|
||||
These instructions are also available [in the documentation](https://docs.gitlab.com/runner/install/index.html).
|
||||
- The administrator can also configure a maximum number of shared runner
|
||||
[CI/CD minutes for each group](../pipelines/cicd_minutes.md#set-the-quota-of-cicd-minutes-for-a-specific-namespace).
|
||||
[CI/CD minutes for each group](../pipelines/cicd_minutes.md#set-the-compute-quota-for-a-specific-namespace).
|
||||
|
||||
If you are using GitLab.com:
|
||||
|
||||
|
|
|
|||
|
|
@ -259,8 +259,8 @@ is inside `_()` so it can be translated:
|
|||
link:
|
||||
|
||||
```haml
|
||||
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/permissions') }
|
||||
%p= safe_format(_("This is a text describing the option/feature in a sentence. %{link_start}Learn more.%{link_end}"), link_start: link_start, link_end: '</a>'.html_safe)
|
||||
- link = link_to('', help_page_path('user/permissions'), target: '_blank', rel: 'noopener noreferrer')
|
||||
%p= safe_format(_("This is a text describing the option/feature in a sentence. %{link_start}Learn more.%{link_end}"), tag_pair(link, :link_start, :link_end))
|
||||
```
|
||||
|
||||
- Using a button link. Useful in places where text would be out of context with
|
||||
|
|
|
|||
|
|
@ -561,7 +561,7 @@ To include formatting in the translated string, you can do the following:
|
|||
- In Ruby/HAML:
|
||||
|
||||
```ruby
|
||||
safe_format(_('Some %{strongOpen}bold%{strongClose} text.'), strongOpen: '<strong>'.html_safe, strongClose: '</strong>'.html_safe)
|
||||
safe_format(_('Some %{strongOpen}bold%{strongClose} text.'), tag_pair(tag.strong, :strongOpen, :strongClose))
|
||||
# => 'Some <strong>bold</strong> text.'
|
||||
```
|
||||
|
||||
|
|
@ -800,8 +800,8 @@ translatable in certain languages.
|
|||
|
||||
```haml
|
||||
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
|
||||
- zones_link_start = safe_format('<a href="%{url}" target="_blank" rel="noopener noreferrer">', url: zones_link_url)
|
||||
= safe_format(s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}'), zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe)
|
||||
- zones_link = link_to('', zones_link_url, target: '_blank', rel: 'noopener noreferrer')
|
||||
= safe_format(s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}'), tag_pair(zones_link, :zones_link_start, :zones_link_end))
|
||||
```
|
||||
|
||||
- In Vue, instead of:
|
||||
|
|
|
|||
|
|
@ -130,8 +130,7 @@ module Gitlab
|
|||
strong_memoize_attr :content_hash
|
||||
|
||||
def interpolator
|
||||
External::Interpolator
|
||||
.new(content_result, content_inputs, context)
|
||||
Yaml::Interpolator.new(content_result, content_inputs, context)
|
||||
end
|
||||
strong_memoize_attr :interpolator
|
||||
|
||||
|
|
|
|||
|
|
@ -4,51 +4,6 @@ module Gitlab
|
|||
module Ci
|
||||
class Config
|
||||
module Yaml
|
||||
AVAILABLE_TAGS = [Config::Yaml::Tags::Reference].freeze
|
||||
MAX_DOCUMENTS = 2
|
||||
|
||||
class Loader
|
||||
def initialize(content, project: nil)
|
||||
@content = content
|
||||
@project = project
|
||||
end
|
||||
|
||||
def load!
|
||||
ensure_custom_tags
|
||||
|
||||
if project.present? && ::Feature.enabled?(:ci_multi_doc_yaml, project)
|
||||
::Gitlab::Config::Loader::MultiDocYaml.new(
|
||||
content,
|
||||
max_documents: MAX_DOCUMENTS,
|
||||
additional_permitted_classes: AVAILABLE_TAGS,
|
||||
reject_empty: true
|
||||
).load!
|
||||
else
|
||||
::Gitlab::Config::Loader::Yaml
|
||||
.new(content, additional_permitted_classes: AVAILABLE_TAGS)
|
||||
.load!
|
||||
end
|
||||
end
|
||||
|
||||
def to_result
|
||||
Yaml::Result.new(config: load!, error: nil)
|
||||
rescue ::Gitlab::Config::Loader::FormatError => e
|
||||
Yaml::Result.new(error: e)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :content, :project
|
||||
|
||||
def ensure_custom_tags
|
||||
@ensure_custom_tags ||= begin
|
||||
AVAILABLE_TAGS.each { |klass| Psych.add_tag(klass.tag, klass) }
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
def load!(content, project: nil)
|
||||
Loader.new(content, project: project).to_result.then do |result|
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
class Config
|
||||
module External
|
||||
module Yaml
|
||||
##
|
||||
# Config::External::Interpolation perform includable file interpolation, and surfaces all possible interpolation
|
||||
# Config::Yaml::Interpolation performs includable file interpolation, and surfaces all possible interpolation
|
||||
# errors. It is designed to provide an external file's validation context too.
|
||||
#
|
||||
class Interpolator
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Ci
|
||||
class Config
|
||||
module Yaml
|
||||
class Loader
|
||||
AVAILABLE_TAGS = [Config::Yaml::Tags::Reference].freeze
|
||||
MAX_DOCUMENTS = 2
|
||||
|
||||
def initialize(content, project: nil)
|
||||
@content = content
|
||||
@project = project
|
||||
end
|
||||
|
||||
def to_result
|
||||
Yaml::Result.new(config: load!, error: nil)
|
||||
rescue ::Gitlab::Config::Loader::FormatError => e
|
||||
Yaml::Result.new(error: e)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :content, :project
|
||||
|
||||
def ensure_custom_tags
|
||||
@ensure_custom_tags ||= begin
|
||||
AVAILABLE_TAGS.each { |klass| Psych.add_tag(klass.tag, klass) }
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def load!
|
||||
ensure_custom_tags
|
||||
|
||||
if project.present? && ::Feature.enabled?(:ci_multi_doc_yaml, project)
|
||||
::Gitlab::Config::Loader::MultiDocYaml.new(
|
||||
content,
|
||||
max_documents: MAX_DOCUMENTS,
|
||||
additional_permitted_classes: AVAILABLE_TAGS,
|
||||
reject_empty: true
|
||||
).load!
|
||||
else
|
||||
::Gitlab::Config::Loader::Yaml
|
||||
.new(content, additional_permitted_classes: AVAILABLE_TAGS)
|
||||
.load!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3725,6 +3725,9 @@ msgstr ""
|
|||
msgid "AdminUsers|Cohorts"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|Compute quota"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|Confirm user"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3830,9 +3833,6 @@ msgstr ""
|
|||
msgid "AdminUsers|Private profile"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|Quota of CI/CD minutes"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|Reactivating a user will:"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -3872,7 +3872,7 @@ msgstr ""
|
|||
msgid "AdminUsers|Sort by"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|The maximum number of CI/CD minutes on shared runners that a group can use each month. Set 0 for unlimited. Set empty to inherit the global setting of %{minutes}"
|
||||
msgid "AdminUsers|The maximum units of compute that jobs in this namespace can use on shared runners each month. Set 0 for unlimited. Set empty to inherit the global setting of %{minutes}"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminUsers|The user can't access git repositories."
|
||||
|
|
@ -5030,6 +5030,9 @@ msgstr ""
|
|||
msgid "An error occurred while reordering issues."
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred while resetting the compute usage."
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred while retrieving calendar activity"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -11614,6 +11617,9 @@ msgstr ""
|
|||
msgid "Components must have a 'name'"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compute quota"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confidence"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -37265,9 +37271,6 @@ msgstr ""
|
|||
msgid "Quick range"
|
||||
msgstr ""
|
||||
|
||||
msgid "Quota of CI/CD minutes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Quota of CI/CD minutes:"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42201,13 +42204,10 @@ msgstr ""
|
|||
msgid "Shared runners help link"
|
||||
msgstr ""
|
||||
|
||||
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
|
||||
msgid "SharedRunnersMinutesSettings|Reset compute usage"
|
||||
msgstr ""
|
||||
|
||||
msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
|
||||
msgstr ""
|
||||
|
||||
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
|
||||
msgid "SharedRunnersMinutesSettings|When you reset the compute usage for this namespace, the compute usage changes to zero."
|
||||
msgstr ""
|
||||
|
||||
msgid "Shimo|Go to Shimo Workspace"
|
||||
|
|
@ -44075,6 +44075,9 @@ msgstr ""
|
|||
msgid "Successfully removed email."
|
||||
msgstr ""
|
||||
|
||||
msgid "Successfully reset compute usage for namespace."
|
||||
msgstr ""
|
||||
|
||||
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -45524,10 +45527,10 @@ msgstr ""
|
|||
msgid "The maximum file size is %{size}."
|
||||
msgstr ""
|
||||
|
||||
msgid "The maximum number of CI/CD minutes on shared runners that a group can use each month. 0 for unlimited."
|
||||
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
|
||||
msgstr ""
|
||||
|
||||
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
|
||||
msgid "The maximum units of compute that jobs in a namespace can use on shared runners each month. 0 for unlimited."
|
||||
msgstr ""
|
||||
|
||||
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
|
||||
|
|
@ -46040,9 +46043,6 @@ msgstr ""
|
|||
msgid "There was an error removing the e-mail."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error resetting user pipeline minutes."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error retrieving LDAP groups. Please try again."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -50858,9 +50858,6 @@ msgstr ""
|
|||
msgid "Welcome, %{name}!"
|
||||
msgstr ""
|
||||
|
||||
msgid "What are CI/CD minutes?"
|
||||
msgstr ""
|
||||
|
||||
msgid "What are group audit events?"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -50885,6 +50882,9 @@ msgstr ""
|
|||
msgid "What is Markdown?"
|
||||
msgstr ""
|
||||
|
||||
msgid "What is a compute quota?"
|
||||
msgstr ""
|
||||
|
||||
msgid "What is listed here?"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -4,31 +4,73 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe SafeFormatHelper, feature_category: :shared do
|
||||
describe '#safe_format' do
|
||||
shared_examples 'safe formatting' do |format, args:, result:|
|
||||
subject { helper.safe_format(format, **args) }
|
||||
shared_examples 'safe formatting' do
|
||||
subject { helper.safe_format(format, args) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to be_html_safe }
|
||||
end
|
||||
|
||||
it_behaves_like 'safe formatting', '', args: {}, result: ''
|
||||
it_behaves_like 'safe formatting', 'Foo', args: {}, result: 'Foo'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { '' }
|
||||
let(:args) { {} }
|
||||
let(:result) { '' }
|
||||
end
|
||||
|
||||
it_behaves_like 'safe formatting', '<b>strong</b>', args: {},
|
||||
result: '<b>strong</b>'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { 'Foo' }
|
||||
let(:args) { {} }
|
||||
let(:result) { 'Foo' }
|
||||
end
|
||||
|
||||
it_behaves_like 'safe formatting', '%{open}strong%{close}',
|
||||
args: { open: '<b>'.html_safe, close: '</b>'.html_safe },
|
||||
result: '<b>strong</b>'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { '<b>strong</b>' }
|
||||
let(:args) { {} }
|
||||
let(:result) { '<b>strong</b>' }
|
||||
end
|
||||
|
||||
it_behaves_like 'safe formatting', '%{open}strong%{close} %{user_input}',
|
||||
args: { open: '<b>'.html_safe, close: '</b>'.html_safe,
|
||||
user_input: '<a href="">link</a>' },
|
||||
result: '<b>strong</b> <a href="">link</a>'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { '%{open}strong%{close}' }
|
||||
let(:args) { { open: '<b>'.html_safe, close: '</b>'.html_safe } }
|
||||
let(:result) { '<b>strong</b>' }
|
||||
end
|
||||
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { '%{open}strong%{close} %{user_input}' }
|
||||
|
||||
let(:args) do
|
||||
{ open: '<b>'.html_safe, close: '</b>'.html_safe,
|
||||
user_input: '<a href="">link</a>' }
|
||||
end
|
||||
|
||||
let(:result) { '<b>strong</b> <a href="">link</a>' }
|
||||
end
|
||||
|
||||
context 'when format is marked as html_safe' do
|
||||
it_behaves_like 'safe formatting', '<b>strong</b>'.html_safe, args: {},
|
||||
result: '<b>strong</b>'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { '<b>strong</b>'.html_safe }
|
||||
let(:args) { {} }
|
||||
let(:result) { '<b>strong</b>' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with multiple args' do
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { '%{a}c%{b} %{x}z%{y}' }
|
||||
|
||||
let(:args) do
|
||||
[
|
||||
{ a: '<a>'.html_safe, b: '</a>'.html_safe },
|
||||
# Demonstrate shadowing
|
||||
{ x: '<XX>'.html_safe, y: '</XX>'.html_safe },
|
||||
{ x: '<x>'.html_safe, y: '</x>'.html_safe }
|
||||
]
|
||||
end
|
||||
|
||||
let(:result) { '<a>c</a> <x>z</x>' }
|
||||
|
||||
subject { helper.safe_format(format, *args) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a view component' do
|
||||
|
|
@ -49,17 +91,62 @@ RSpec.describe SafeFormatHelper, feature_category: :shared do
|
|||
end
|
||||
|
||||
context 'with format containing escaped entities' do
|
||||
it_behaves_like 'safe formatting', 'In < hour',
|
||||
args: {},
|
||||
result: 'In < hour'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { 'In < hour' }
|
||||
let(:args) { {} }
|
||||
let(:result) { 'In < hour' }
|
||||
end
|
||||
|
||||
it_behaves_like 'safe formatting', '"air"',
|
||||
args: {},
|
||||
result: '"air"'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { '"air"' }
|
||||
let(:args) { {} }
|
||||
let(:result) { '"air"' }
|
||||
end
|
||||
|
||||
it_behaves_like 'safe formatting', 'Mix & match > all',
|
||||
args: {},
|
||||
result: 'Mix & match > all'
|
||||
it_behaves_like 'safe formatting' do
|
||||
let(:format) { 'Mix & match > all' }
|
||||
let(:args) { {} }
|
||||
let(:result) { 'Mix & match > all' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#tag_pair' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:tag) { plain_tag.html_safe }
|
||||
let(:open_name) { :tag_open }
|
||||
let(:close_name) { :tag_close }
|
||||
|
||||
subject(:result) { tag_pair(tag, open_name, close_name) }
|
||||
|
||||
where(:plain_tag, :open, :close) do
|
||||
'' | nil | nil
|
||||
'a' | nil | nil
|
||||
'<a' | nil | nil
|
||||
'<a>' | nil | nil
|
||||
'<a><a>' | nil | nil
|
||||
'<input/>' | nil | nil
|
||||
'<a></a>' | '<a>' | '</a>'
|
||||
'<a href="">x</a>' | '<a href="">' | '</a>'
|
||||
end
|
||||
|
||||
with_them do
|
||||
if params[:open] && params[:close]
|
||||
it { is_expected.to eq({ open_name => open, close_name => close }) }
|
||||
specify { expect(result.values).to be_all(&:html_safe?) }
|
||||
else
|
||||
it { is_expected.to eq({}) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when tag is not html_safe' do
|
||||
# `to_str` turns a html_safe string into a plain String.
|
||||
let(:tag) { helper.tag.strong.to_str }
|
||||
|
||||
it 'raises an ArgumentError' do
|
||||
expect { result }.to raise_error ArgumentError, 'Argument `tag` must be `html_safe`!'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Ci::Config::External::Interpolator, feature_category: :pipeline_composition do
|
||||
RSpec.describe Gitlab::Ci::Config::Yaml::Interpolator, feature_category: :pipeline_composition do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
let(:ctx) { instance_double(Gitlab::Ci::Config::External::Context, project: project, user: build(:user, id: 1234)) }
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Ci::Config::Yaml::Loader, feature_category: :pipeline_composition do
|
||||
describe '#to_result' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
subject(:result) { described_class.new(yaml, project: project).to_result }
|
||||
|
||||
context 'when syntax is invalid' do
|
||||
let(:yaml) { 'some: invalid: syntax' }
|
||||
|
||||
it 'returns an invalid result object' do
|
||||
expect(result).not_to be_valid
|
||||
expect(result.error).to be_a ::Gitlab::Config::Loader::FormatError
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the first document is a header' do
|
||||
context 'with explicit document start marker' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
---
|
||||
spec:
|
||||
---
|
||||
b: 2
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'considers the first document as header and the second as content' do
|
||||
expect(result).to be_valid
|
||||
expect(result.error).to be_nil
|
||||
expect(result.header).to eq({ spec: nil })
|
||||
expect(result.content).to eq({ b: 2 })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when first document is empty' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
---
|
||||
---
|
||||
b: 2
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'considers the first document as header and the second as content' do
|
||||
expect(result).not_to have_header
|
||||
end
|
||||
end
|
||||
|
||||
context 'when first document is an empty hash' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
{}
|
||||
---
|
||||
b: 2
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'returns second document as a content' do
|
||||
expect(result).not_to have_header
|
||||
expect(result.content).to eq({ b: 2 })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when first an array' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
---
|
||||
- a
|
||||
- b
|
||||
---
|
||||
b: 2
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'considers the first document as header and the second as content' do
|
||||
expect(result).not_to have_header
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the first document is not a header' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
a: 1
|
||||
---
|
||||
b: 2
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'considers the first document as content for backwards compatibility' do
|
||||
expect(result).to be_valid
|
||||
expect(result.error).to be_nil
|
||||
expect(result).not_to have_header
|
||||
expect(result.content).to eq({ a: 1 })
|
||||
end
|
||||
|
||||
context 'with explicit document start marker' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
---
|
||||
a: 1
|
||||
---
|
||||
b: 2
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'considers the first document as content for backwards compatibility' do
|
||||
expect(result).to be_valid
|
||||
expect(result.error).to be_nil
|
||||
expect(result).not_to have_header
|
||||
expect(result.content).to eq({ a: 1 })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the first document is not a header and second document is empty' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
a: 1
|
||||
---
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'considers the first document as content' do
|
||||
expect(result).to be_valid
|
||||
expect(result.error).to be_nil
|
||||
expect(result).not_to have_header
|
||||
expect(result.content).to eq({ a: 1 })
|
||||
end
|
||||
|
||||
context 'with explicit document start marker' do
|
||||
let(:yaml) do
|
||||
<<~YAML
|
||||
---
|
||||
a: 1
|
||||
---
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'considers the first document as content' do
|
||||
expect(result).to be_valid
|
||||
expect(result.error).to be_nil
|
||||
expect(result).not_to have_header
|
||||
expect(result.content).to eq({ a: 1 })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3125,7 +3125,6 @@
|
|||
- './ee/spec/workers/audit_events/audit_event_streaming_worker_spec.rb'
|
||||
- './ee/spec/workers/audit_events/user_impersonation_event_create_worker_spec.rb'
|
||||
- './ee/spec/workers/auth/saml_group_sync_worker_spec.rb'
|
||||
- './ee/spec/workers/ci/batch_reset_minutes_worker_spec.rb'
|
||||
- './ee/spec/workers/ci/initial_pipeline_process_worker_spec.rb'
|
||||
- './ee/spec/workers/ci/minutes/refresh_cached_data_worker_spec.rb'
|
||||
- './ee/spec/workers/ci/minutes/update_project_and_namespace_usage_worker_spec.rb'
|
||||
|
|
@ -3133,7 +3132,6 @@
|
|||
- './ee/spec/workers/ci/sync_reports_to_report_approval_rules_worker_spec.rb'
|
||||
- './ee/spec/workers/ci/trigger_downstream_subscriptions_worker_spec.rb'
|
||||
- './ee/spec/workers/ci/upstream_projects_subscriptions_cleanup_worker_spec.rb'
|
||||
- './ee/spec/workers/clear_shared_runners_minutes_worker_spec.rb'
|
||||
- './ee/spec/workers/compliance_management/chain_of_custody_report_worker_spec.rb'
|
||||
- './ee/spec/workers/compliance_management/merge_requests/compliance_violations_worker_spec.rb'
|
||||
- './ee/spec/workers/concerns/elastic/indexing_control_spec.rb'
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
|
|||
'Chaos::SleepWorker' => 3,
|
||||
'ChatNotificationWorker' => false,
|
||||
'Ci::ArchiveTraceWorker' => 3,
|
||||
'Ci::BatchResetMinutesWorker' => 10,
|
||||
'Ci::BuildFinishedWorker' => 3,
|
||||
'Ci::BuildPrepareWorker' => 3,
|
||||
'Ci::BuildScheduleWorker' => 3,
|
||||
|
|
|
|||
Loading…
Reference in New Issue