提交 39a4ea61 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 9b141607
<script>
import { uniqueId } from 'lodash';
import { mapActions } from 'vuex';
import { GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { GlButton } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
export default {
name: 'ManualVariablesForm',
components: {
GlDeprecatedButton,
GlIcon,
GlButton,
},
props: {
action: {
......@@ -136,12 +135,12 @@ export default {
<div class="table-section section-10">
<div class="table-mobile-header" role="rowheader"></div>
<div class="table-mobile-content justify-content-end">
<gl-deprecated-button
class="btn-transparent btn-blank w-25"
<gl-button
category="tertiary"
icon="clear"
:aria-label="__('Delete variable')"
@click="deleteVariable(variable.id)"
>
<gl-icon name="clear" />
</gl-deprecated-button>
/>
</div>
</div>
</div>
......@@ -175,9 +174,14 @@ export default {
<p class="text-muted" v-html="helpText"></p>
</div>
<div class="d-flex justify-content-center">
<gl-deprecated-button variant="primary" @click="triggerManualJob(variables)">
<gl-button
variant="info"
category="primary"
:aria-label="__('Trigger manual job')"
@click="triggerManualJob(variables)"
>
{{ action.button_title }}
</gl-deprecated-button>
</gl-button>
</div>
</div>
</template>
......@@ -3,7 +3,7 @@
module Types
module Ci
class PipelineConfigSourceEnum < BaseEnum
::Ci::PipelineEnums.config_sources.keys.each do |state_symbol|
::Enums::Ci::Pipeline.config_sources.keys.each do |state_symbol|
value state_symbol.to_s.upcase, value: state_symbol.to_s
end
end
......
......@@ -26,7 +26,7 @@ module Types
description: 'Detailed status of the pipeline',
resolve: -> (obj, _args, ctx) { obj.detailed_status(ctx[:current_user]) }
field :config_source, PipelineConfigSourceEnum, null: true,
description: "Config source of the pipeline (#{::Ci::PipelineEnums.config_sources.keys.join(', ').upcase})"
description: "Config source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})"
field :duration, GraphQL::INT_TYPE, null: true,
description: 'Duration of the pipeline in seconds'
field :coverage, GraphQL::FLOAT_TYPE, null: true,
......
......@@ -104,15 +104,15 @@ module Ci
after_create :keep_around_commits, unless: :importing?
# We use `Ci::PipelineEnums.sources` here so that EE can more easily extend
# We use `Enums::Ci::Pipeline.sources` here so that EE can more easily extend
# this `Hash` with new values.
enum_with_nil source: ::Ci::PipelineEnums.sources
enum_with_nil source: Enums::Ci::Pipeline.sources
enum_with_nil config_source: ::Ci::PipelineEnums.config_sources
enum_with_nil config_source: Enums::Ci::Pipeline.config_sources
# We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily
# We use `Enums::Ci::Pipeline.failure_reasons` here so that EE can more easily
# extend this `Hash` with new values.
enum failure_reason: ::Ci::PipelineEnums.failure_reasons
enum failure_reason: Enums::Ci::Pipeline.failure_reasons
enum locked: { unlocked: 0, artifacts_locked: 1 }
......@@ -260,7 +260,7 @@ module Ci
scope :internal, -> { where(source: internal_sources) }
scope :no_child, -> { where.not(source: :parent_pipeline) }
scope :ci_sources, -> { where(config_source: ::Ci::PipelineEnums.ci_config_sources_values) }
scope :ci_sources, -> { where(config_source: Enums::Ci::Pipeline.ci_config_sources_values) }
scope :for_user, -> (user) { where(user: user) }
scope :for_sha, -> (sha) { where(sha: sha) }
scope :for_source_sha, -> (source_sha) { where(source_sha: source_sha) }
......@@ -1012,7 +1012,7 @@ module Ci
end
def cacheable?
Ci::PipelineEnums.ci_config_sources.key?(config_source.to_sym)
Enums::Ci::Pipeline.ci_config_sources.key?(config_source.to_sym)
end
def source_ref_path
......
# frozen_string_literal: true
module Ci
module PipelineEnums
# Returns the `Hash` to use for creating the `failure_reason` enum for
# `Ci::Pipeline`.
def self.failure_reasons
{
unknown_failure: 0,
config_error: 1,
external_validation_failure: 2
}
end
# Returns the `Hash` to use for creating the `sources` enum for
# `Ci::Pipeline`.
def self.sources
{
unknown: nil,
push: 1,
web: 2,
trigger: 3,
schedule: 4,
api: 5,
external: 6,
# TODO: Rename `pipeline` to `cross_project_pipeline` in 13.0
# https://gitlab.com/gitlab-org/gitlab/issues/195991
pipeline: 7,
chat: 8,
webide: 9,
merge_request_event: 10,
external_pull_request_event: 11,
parent_pipeline: 12,
ondemand_dast_scan: 13
}
end
# Returns the `Hash` to use for creating the `config_sources` enum for
# `Ci::Pipeline`.
def self.config_sources
{
unknown_source: nil,
repository_source: 1,
auto_devops_source: 2,
webide_source: 3,
remote_source: 4,
external_project_source: 5,
bridge_source: 6,
parameter_source: 7
}
end
def self.ci_config_sources
config_sources.slice(
:unknown_source,
:repository_source,
:auto_devops_source,
:remote_source,
:external_project_source
)
end
def self.ci_config_sources_values
ci_config_sources.values
end
def self.non_ci_config_source_values
config_sources.values - ci_config_sources.values
end
end
end
Ci::PipelineEnums.prepend_if_ee('EE::Ci::PipelineEnums')
......@@ -77,9 +77,9 @@ class CommitStatus < ApplicationRecord
merge(or_conditions)
end
# We use `CommitStatusEnums.failure_reasons` here so that EE can more easily
# We use `Enums::CommitStatus.failure_reasons` here so that EE can more easily
# extend this `Hash` with new values.
enum_with_nil failure_reason: ::CommitStatusEnums.failure_reasons
enum_with_nil failure_reason: Enums::CommitStatus.failure_reasons
##
# We still create some CommitStatuses outside of CreatePipelineService.
......
# frozen_string_literal: true
module CommitStatusEnums
# Returns the Hash to use for creating the `failure_reason` enum for
# `CommitStatus`.
def self.failure_reasons
{
unknown_failure: nil,
script_failure: 1,
api_failure: 2,
stuck_or_timeout_failure: 3,
runner_system_failure: 4,
missing_dependency_failure: 5,
runner_unsupported: 6,
stale_schedule: 7,
job_execution_timeout: 8,
archived_failure: 9,
unmet_prerequisites: 10,
scheduler_failure: 11,
data_integrity_failure: 12,
forward_deployment_failure: 13,
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
bridge_pipeline_is_child_pipeline: 1_006,
downstream_pipeline_creation_failed: 1_007,
secrets_provider_not_found: 1_008
}
end
end
CommitStatusEnums.prepend_if_ee('EE::CommitStatusEnums')
# frozen_string_literal: true
module Enums
module Ci
module Pipeline
# Returns the `Hash` to use for creating the `failure_reason` enum for
# `Ci::Pipeline`.
def self.failure_reasons
{
unknown_failure: 0,
config_error: 1,
external_validation_failure: 2
}
end
# Returns the `Hash` to use for creating the `sources` enum for
# `Ci::Pipeline`.
def self.sources
{
unknown: nil,
push: 1,
web: 2,
trigger: 3,
schedule: 4,
api: 5,
external: 6,
# TODO: Rename `pipeline` to `cross_project_pipeline` in 13.0
# https://gitlab.com/gitlab-org/gitlab/issues/195991
pipeline: 7,
chat: 8,
webide: 9,
merge_request_event: 10,
external_pull_request_event: 11,
parent_pipeline: 12,
ondemand_dast_scan: 13
}
end
# Returns the `Hash` to use for creating the `config_sources` enum for
# `Ci::Pipeline`.
def self.config_sources
{
unknown_source: nil,
repository_source: 1,
auto_devops_source: 2,
webide_source: 3,
remote_source: 4,
external_project_source: 5,
bridge_source: 6,
parameter_source: 7
}
end
def self.ci_config_sources
config_sources.slice(
:unknown_source,
:repository_source,
:auto_devops_source,
:remote_source,
:external_project_source
)
end
def self.ci_config_sources_values
ci_config_sources.values
end
def self.non_ci_config_source_values
config_sources.values - ci_config_sources.values
end
end
end
end
Enums::Ci::Pipeline.prepend_if_ee('EE::Enums::Ci::Pipeline')
# frozen_string_literal: true
module Enums
module CommitStatus
# Returns the Hash to use for creating the `failure_reason` enum for
# `CommitStatus`.
def self.failure_reasons
{
unknown_failure: nil,
script_failure: 1,
api_failure: 2,
stuck_or_timeout_failure: 3,
runner_system_failure: 4,
missing_dependency_failure: 5,
runner_unsupported: 6,
stale_schedule: 7,
job_execution_timeout: 8,
archived_failure: 9,
unmet_prerequisites: 10,
scheduler_failure: 11,
data_integrity_failure: 12,
forward_deployment_failure: 13,
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
bridge_pipeline_is_child_pipeline: 1_006,
downstream_pipeline_creation_failed: 1_007,
secrets_provider_not_found: 1_008
}
end
end
end
Enums::CommitStatus.prepend_if_ee('EE::Enums::CommitStatus')
# frozen_string_literal: true
module InternalIdEnums
def self.usage_resources
# when adding new resource, make sure it doesn't conflict with EE usage_resources
{
module Enums
module InternalId
def self.usage_resources
# when adding new resource, make sure it doesn't conflict with EE usage_resources
{
issues: 0,
merge_requests: 1,
deployments: 2,
......@@ -14,8 +15,9 @@ module InternalIdEnums
operations_user_lists: 7,
alert_management_alerts: 8,
sprints: 9 # iterations
}
}
end
end
end
InternalIdEnums.prepend_if_ee('EE::InternalIdEnums')
Enums::InternalId.prepend_if_ee('EE::Enums::InternalId')
# frozen_string_literal: true
module Enums
module PrometheusMetric
def self.groups
{
# built-in groups
nginx_ingress_vts: -1,
ha_proxy: -2,
aws_elb: -3,
nginx: -4,
kubernetes: -5,
nginx_ingress: -6,
cluster_health: -100
}.merge(custom_groups).freeze
end
# custom/user groups
def self.custom_groups
{
business: 0,
response: 1,
system: 2
}.freeze
end
def self.group_details
{
# built-in groups
nginx_ingress_vts: {
group_title: _('Response metrics (NGINX Ingress VTS)'),
required_metrics: %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg),
priority: 10
}.freeze,
nginx_ingress: {
group_title: _('Response metrics (NGINX Ingress)'),
required_metrics: %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum),
priority: 10
}.freeze,
ha_proxy: {
group_title: _('Response metrics (HA Proxy)'),
required_metrics: %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total),
priority: 10
}.freeze,
aws_elb: {
group_title: _('Response metrics (AWS ELB)'),
required_metrics: %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum),
priority: 10
}.freeze,
nginx: {
group_title: _('Response metrics (NGINX)'),
required_metrics: %w(nginx_server_requests nginx_server_requestMsec),
priority: 10
}.freeze,
kubernetes: {
group_title: _('System metrics (Kubernetes)'),
required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
priority: 5
}.freeze,
cluster_health: {
group_title: _('Cluster Health'),
required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
priority: 10
}.freeze
}.merge(custom_group_details).freeze
end
# custom/user groups
def self.custom_group_details
{
business: {
group_title: _('Business metrics (Custom)'),
priority: 0
}.freeze,
response: {
group_title: _('Response metrics (Custom)'),
priority: -5
}.freeze,
system: {
group_title: _('System metrics (Custom)'),
priority: -10
}.freeze
}.freeze
end
end
end
# frozen_string_literal: true
module Enums
module UserCallout
# Returns the `Hash` to use for the `feature_name` enum in the `UserCallout`
# model.
#
# This method is separate from the `UserCallout` model so that it can be
# extended by EE.
#
# If you are going to add new items to this hash, check that you're not going
# to conflict with EE-only values: https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/models/concerns/ee/enums/user_callout.rb
def self.feature_names
{
gke_cluster_integration: 1,
gcp_signup_offer: 2,
cluster_security_warning: 3,
suggest_popover_dismissed: 9,
tabs_position_highlight: 10,
webhooks_moved: 13,
service_templates_deprecated: 14,
admin_integrations_moved: 15,
personal_access_token_expiry: 21, # EE-only
suggest_pipeline: 22,
customize_homepage: 23
}
end
end
end
Enums::UserCallout.prepend_if_ee('EE::Enums::UserCallout')
......@@ -21,7 +21,7 @@ class InternalId < ApplicationRecord
belongs_to :project
belongs_to :namespace
enum usage: ::InternalIdEnums.usage_resources
enum usage: Enums::InternalId.usage_resources
validates :usage, presence: true
......
......@@ -37,6 +37,7 @@ class Packages::Package < ApplicationRecord
validates :name, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan?
validates :version, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan?
validates :version, format: { with: Gitlab::Regex.maven_version_regex }, if: -> { version? && maven? }
validates :version, format: { with: Gitlab::Regex.pypi_version_regex }, if: :pypi?
enum package_type: { maven: 1, npm: 2, conan: 3, nuget: 4, pypi: 5, composer: 6 }
......
......@@ -4,7 +4,7 @@ class PrometheusMetric < ApplicationRecord
belongs_to :project, validate: true, inverse_of: :prometheus_metrics
has_many :prometheus_alerts, inverse_of: :prometheus_metric
enum group: PrometheusMetricEnums.groups
enum group: Enums::PrometheusMetric.groups
validates :title, presence: true
validates :query, presence: true
......@@ -72,6 +72,6 @@ class PrometheusMetric < ApplicationRecord
private
def group_details(group)
PrometheusMetricEnums.group_details.fetch(group.to_sym)
Enums::PrometheusMetric.group_details.fetch(group.to_sym)
end
end
# frozen_string_literal: true
module PrometheusMetricEnums
def self.groups
{
# built-in groups
nginx_ingress_vts: -1,
ha_proxy: -2,
aws_elb: -3,
nginx: -4,
kubernetes: -5,
nginx_ingress: -6,
cluster_health: -100
}.merge(custom_groups).freeze
end
# custom/user groups
def self.custom_groups
{
business: 0,
response: 1,
system: 2
}.freeze
end
def self.group_details
{
# built-in groups
nginx_ingress_vts: {
group_title: _('Response metrics (NGINX Ingress VTS)'),
required_metrics: %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg),
priority: 10
}.freeze,
nginx_ingress: {
group_title: _('Response metrics (NGINX Ingress)'),
required_metrics: %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum),
priority: 10
}.freeze,
ha_proxy: {
group_title: _('Response metrics (HA Proxy)'),
required_metrics: %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total),
priority: 10
}.freeze,
aws_elb: {
group_title: _('Response metrics (AWS ELB)'),
required_metrics: %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum),
priority: 10
}.freeze,
nginx: {
group_title: _('Response metrics (NGINX)'),
required_metrics: %w(nginx_server_requests nginx_server_requestMsec),
priority: 10
}.freeze,
kubernetes: {
group_title: _('System metrics (Kubernetes)'),
required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
priority: 5
}.freeze,
cluster_health: {
group_title: _('Cluster Health'),
required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
priority: 10
}.freeze
}.merge(custom_group_details).freeze
end
# custom/user groups
def self.custom_group_details
{
business: {
group_title: _('Business metrics (Custom)'),
priority: 0
}.freeze,
response: {
group_title: _('Response metrics (Custom)'),
priority: -5
}.freeze,
system: {
group_title: _('System metrics (Custom)'),
priority: -10
}.freeze
}.freeze
end
end
......@@ -9,7 +9,6 @@ class Service < ApplicationRecord
include DataFields
include IgnorableColumns
ignore_columns %i[title description], remove_with: '13.4', remove_after: '2020-09-22'
ignore_columns %i[default], remove_with: '13.5', remove_after: '2020-10-22'
SERVICE_NAMES = %w[
......
......@@ -3,9 +3,9 @@
class UserCallout < ApplicationRecord
belongs_to :user
# We use `UserCalloutEnums.feature_names` here so that EE can more easily
# We use `Enums::UserCallout.feature_names` here so that EE can more easily
# extend this `Hash` with new values.
enum feature_name: ::UserCalloutEnums.feature_names
enum feature_name: Enums::UserCallout.feature_names
validates :user, presence: true
validates :feature_name,
......
# frozen_string_literal: true
module UserCalloutEnums
# Returns the `Hash` to use for the `feature_name` enum in the `UserCallout`
# model.
#
# This method is separate from the `UserCallout` model so that it can be
# extended by EE.
#
# If you are going to add new items to this hash, check that you're not going
# to conflict with EE-only values: https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/models/ee/user_callout_enums.rb
def self.feature_names
{
gke_cluster_integration: 1,
gcp_signup_offer: 2,
cluster_security_warning: 3,
suggest_popover_dismissed: 9,
tabs_position_highlight: 10,
webhooks_moved: 13,
service_templates_deprecated: 14,
admin_integrations_moved: 15,
personal_access_token_expiry: 21, # EE-only
suggest_pipeline: 22,
customize_homepage: 23
}
end
end
UserCalloutEnums.prepend_if_ee('EE::UserCalloutEnums')
......@@ -24,5 +24,6 @@ class IssuablePolicy < BasePolicy
prevent :create_note
prevent :admin_note
prevent :resolve_note
prevent :award_emoji
end
end
......@@ -31,7 +31,7 @@ module Metrics
# A group title is valid if it is one of the limited
# options the user can select in the UI.
def valid_group_title?(group)
PrometheusMetricEnums
Enums::PrometheusMetric
.custom_group_details
.map { |_, details| details[:group_title] }
.include?(group)
......@@ -99,12 +99,12 @@ module Metrics
# Returns a symbol representing the group that
# the dashboard's group title belongs to.
# It will be one of the keys found under
# PrometheusMetricEnums.custom_groups.
# Enums::PrometheusMetric.custom_groups.
#
# @return [String]
def group_key
strong_memoize(:group_key) do
PrometheusMetricEnums
Enums::PrometheusMetric
.group_details
.find { |_, details| details[:group_title] == group }
.first
......
---
title: Disallow awarding emojis to locked Issuables for users that are not member
of the project
merge_request: 40150
author:
type: changed
---
title: Add validation to pypi package version
merge_request: 35080
author: Bola Ahmed Buari
type: added
---
title: Update spec to glbutton
merge_request: 39311
author:
type: other
......@@ -13,7 +13,7 @@ class DeleteUserCalloutAlertsMoved < ActiveRecord::Migration[6.0]
BATCH_SIZE = 1_000
# Inlined from UserCalloutEnums.feature_names
# Inlined from Enums::UserCallout.feature_names
FEATURE_NAME_ALERTS_MOVED = 20
def up
......
......@@ -33,28 +33,32 @@ tempted to organize the `enum` as the following:
```ruby
# Define `failure_reason` enum in `Pipeline` model:
class Pipeline < ApplicationRecord
enum failure_reason: ::PipelineEnums.failure_reasons
enum failure_reason: Enums::Pipeline.failure_reasons
end
```
```ruby
# Define key/value pairs that used in FOSS and EE:
module PipelineEnums
def self.failure_reasons
{ unknown_failure: 0, config_error: 1 }
module Enums
module Pipeline
def self.failure_reasons
{ unknown_failure: 0, config_error: 1 }
end
end
end
PipelineEnums.prepend_if_ee('EE::PipelineEnums')
Enums::Pipeline.prepend_if_ee('EE::Enums::Pipeline')
```
```ruby
# Define key/value pairs that used in EE only:
module EE
module PipelineEnums
override :failure_reasons
def failure_reasons
super.merge(activity_limit_exceeded: 2)
module Enums
module Pipeline
override :failure_reasons
def failure_reasons
super.merge(activity_limit_exceeded: 2)
end
end
end
end
......@@ -63,7 +67,7 @@ end
This works as-is, however, it has a couple of downside that:
- Someone could define a key/value pair in EE that is **conflicted** with a value defined in FOSS.
e.g. Define `activity_limit_exceeded: 1` in `EE::PipelineEnums`.
e.g. Define `activity_limit_exceeded: 1` in `EE::Enums::Pipeline`.
- When it happens, the feature works totally different.
e.g. We cannot figure out `failure_reason` is either `config_error` or `activity_limit_exceeded`.
- When it happens, we have to ship a database migration to fix the data integrity,
......@@ -74,10 +78,12 @@ For example, this example sets `1000` as the offset:
```ruby
module EE
module PipelineEnums
override :failure_reasons
def failure_reasons
super.merge(activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
module Enums
module Pipeline
override :failure_reasons
def failure_reasons
super.merge(activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
end
end
end
end
......
......@@ -206,6 +206,26 @@ When uploading packages, note that:
- The maximum allowed size is 50 Megabytes.
- You cannot upload the same version of a package multiple times. If you try, you receive the error `Validation failed: File name has already been taken`.
### Ensure your version string is valid
If your version string (for example, `0.0.1`) is invalid, it will be rejected. GitLab uses the following regex to validate the version string.
```ruby
\A(?:
v?
(?:([0-9]+)!)? (?# epoch)
([0-9]+(?:\.[0-9]+)*) (?# release segment)
([-_\.]?((a|b|c|rc|alpha|beta|pre|preview))[-_\.]?([0-9]+)?)? (?# pre-release)
((?:-([0-9]+))|(?:[-_\.]?(post|rev|r)[-_\.]?([0-9]+)?))? (?# post release)
([-_\.]?(dev)[-_\.]?([0-9]+)?)? (?# dev release)
(?:\+([a-z0-9]+(?:[-_\.][a-z0-9]+)*))? (?# local version)
)\z}xi
```
You can play around with the regex and try your version strings on [this regular expression editor](https://rubular.com/r/FKM6d07ouoDaFV).
For more details about the regex used, please check the [documentation here](https://www.python.org/dev/peps/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions))
### Upload packages with Twine
If you were following the guide above, then the `MyPyPiPackage` package should
......
......@@ -83,4 +83,9 @@ namespace that started the import process.
## Troubleshooting
If the GUI-based import tool does not work, you can try to:
- Use the [GitLab Import API](../../../api/import.md#import-repository-from-bitbucket-server) Bitbucket server endpoint.
- Set up [Repository Mirroring](../repository/repository_mirroring.md), which provides verbose error output.
See the [troubleshooting](bitbucket.md#troubleshooting) section for [Bitbucket](bitbucket.md).
......@@ -27,7 +27,7 @@ module Gitlab
private
def custom_group_titles
@custom_group_titles ||= PrometheusMetricEnums.custom_group_details.values.map { |group_details| group_details[:group_title] }
@custom_group_titles ||= Enums::PrometheusMetric.custom_group_details.values.map { |group_details| group_details[:group_title] }
end
def edit_path(metric)
......
......@@ -51,6 +51,21 @@ module Gitlab
maven_app_name_regex
end
def pypi_version_regex
# See the official regex: https://github.com/pypa/packaging/blob/16.7/packaging/version.py#L159
@pypi_version_regex ||= %r{
\A(?:
v?
(?:([0-9]+)!)? (?# epoch)
([0-9]+(?:\.[0-9]+)*) (?# release segment)
([-_\.]?((a|b|c|rc|alpha|beta|pre|preview))[-_\.]?([0-9]+)?)? (?# pre-release)
((?:-([0-9]+))|(?:[-_\.]?(post|rev|r)[-_\.]?([0-9]+)?))? (?# post release)
([-_\.]?(dev)[-_\.]?([0-9]+)?)? (?# dev release)
(?:\+([a-z0-9]+(?:[-_\.][a-z0-9]+)*))? (?# local version)
)\z}xi.freeze
end
def unbounded_semver_regex
# See the official regex: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
......
......@@ -26049,6 +26049,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
msgid "Trigger manual job"
msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
......
......@@ -56,14 +56,20 @@ FactoryBot.define do
end
factory :pypi_package do
pypi_metadatum
sequence(:name) { |n| "pypi-package-#{n}"}
sequence(:version) { |n| "1.0.#{n}" }
package_type { :pypi }
after :create do |package|
transient do
without_loaded_metadatum { false }
end
after :create do |package, evaluator|
create :package_file, :pypi, package: package, file_name: "#{package.name}-#{package.version}.tar.gz"
unless evaluator.without_loaded_metadatum
create :pypi_metadatum, package: package
end
end
end
......@@ -297,7 +303,7 @@ FactoryBot.define do
end
factory :pypi_metadatum, class: 'Packages::Pypi::Metadatum' do
association :package, package_type: :pypi
package { create(:pypi_package, without_loaded_metadatum: true) }
required_python { '>=2.7' }
end
......
......@@ -184,6 +184,31 @@ RSpec.describe 'User interacts with awards' do
wait_for_requests
end
context 'when the issue is locked' do
before do
create(:award_emoji, awardable: issue, name: '100')
issue.update!(discussion_locked: true)
visit project_issue_path(project, issue)
wait_for_requests
end
it 'hides the add award button' do
page.within('.awards') do
expect(page).not_to have_css('.js-add-award')
end
end
it 'does not allow toggling existing emoji' do
page.within('.awards') do
find('gl-emoji[data-name="100"]').click
end
wait_for_requests
expect(issue.reload.award_emoji.size).to eq(1)
end
end
it 'adds award to issue' do
first('.js-emoji-btn').click
......
......@@ -52,7 +52,6 @@ describe('Issuable component', () => {
},
stubs: {
'gl-sprintf': GlSprintf,
'gl-link': '<a><slot></slot></a>',
},
});
};
......
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlDeprecatedButton } from '@gitlab/ui';
import { GlButton } from '@gitlab/ui';
import Form from '~/jobs/components/manual_variables_form.vue';
const localVue = createLocalVue();
......@@ -95,7 +95,7 @@ describe('Manual Variables Form', () => {
});
it('removes the variable row', () => {
wrapper.find(GlDeprecatedButton).vm.$emit('click');
wrapper.find(GlButton).vm.$emit('click');
expect(wrapper.vm.variables.length).toBe(0);
});
......
......@@ -18,7 +18,6 @@ describe('packages_list', () => {
let wrapper;
let store;
const GlSortingItem = { name: 'sorting-item-stub', template: '<div><slot></slot></div>' };
const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>bar</div>' };
const findPackagesListLoader = () => wrapper.find(PackagesListLoader);
......@@ -67,7 +66,6 @@ describe('packages_list', () => {
stubs: {
...stubChildren(PackagesList),
GlTable,
GlSortingItem,
GlModal,
},
...options,
......
import Vuex from 'vuex';
import { GlSorting } from '@gitlab/ui';
import { GlSorting, GlSortingItem } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import stubChildren from 'helpers/stub_children';
import PackagesSort from '~/packages/list/components/packages_sort.vue';
......@@ -13,8 +13,6 @@ describe('packages_sort', () => {
let sorting;
let sortingItems;
const GlSortingItem = { name: 'sorting-item-stub', template: '<div><slot></slot></div>' };
const findPackageListSorting = () => wrapper.find(GlSorting);
const findSortingItems = () => wrapper.findAll(GlSortingItem);
......
......@@ -23,9 +23,7 @@ const createComponent = ({ config = mockAuthorToken, value = { data: '' }, activ
alignSuggestions: function fakeAlignSuggestions() {},
},
stubs: {
Portal: {
template: '<div><slot></slot></div>',
},
Portal: true,
GlFilteredSearchSuggestionList: {
template: '<div></div>',
methods: {
......
......@@ -27,9 +27,7 @@ const createComponent = ({ config = mockLabelToken, value = { data: '' }, active
alignSuggestions: function fakeAlignSuggestions() {},
},
stubs: {
Portal: {
template: '<div><slot></slot></div>',
},
Portal: true,
GlFilteredSearchSuggestionList: {
template: '<div></div>',
methods: {
......
......@@ -32,9 +32,7 @@ const createComponent = ({
alignSuggestions: function fakeAlignSuggestions() {},
},
stubs: {
Portal: {
template: '<div><slot></slot></div>',
},
Portal: true,
GlFilteredSearchSuggestionList: {
template: '<div></div>',
methods: {
......
......@@ -36,8 +36,8 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
context 'when the pipeline is not a ci_config_source' do
let(:pipeline) do
config_source_value = Ci::PipelineEnums.non_ci_config_source_values.first
config_source = Ci::PipelineEnums.config_sources.key(config_source_value)
config_source_value = ::Enums::Ci::Pipeline.non_ci_config_source_values.first
config_source = ::Enums::Ci::Pipeline.config_sources.key(config_source_value)
create(:ci_pipeline, config_source: config_source, project: project)
end
......
......@@ -8,7 +8,7 @@ RSpec.describe Gitlab::DatabaseImporters::CommonMetrics::PrometheusMetric do
end
it '.group_titles equals ::PrometheusMetric' do
existing_group_titles = ::PrometheusMetricEnums.group_details.transform_values do |value|
existing_group_titles = Enums::PrometheusMetric.group_details.transform_values do |value|
value[:group_title]
end
expect(Gitlab::DatabaseImporters::CommonMetrics::PrometheusMetricEnums.group_titles).to eq(existing_group_titles)
......
......@@ -311,6 +311,73 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('%2e%2e%2f1.2.3') }
end
describe '.pypi_version_regex' do
subject { described_class.pypi_version_regex }
it { is_expected.to match('0.1') }
it { is_expected.to match('2.0') }
it { is_expected.to match('1.2.0')}
it { is_expected.to match('0100!0.0') }
it { is_expected.to match('00!1.2') }
it { is_expected.to match('1.0a') }
it { is_expected.to match('1.0-a') }
it { is_expected.to match('1.0.a1') }
it { is_expected.to match('1.0a1') }
it { is_expected.to match('1.0-a1') }
it { is_expected.to match('1.0alpha1') }
it { is_expected.to match('1.0b1') }
it { is_expected.to match('1.0beta1') }
it { is_expected.to match('1.0rc1') }
it { is_expected.to match('1.0pre1') }
it { is_expected.to match('1.0preview1') }
it { is_expected.to match('1.0.dev1') }
it { is_expected.to match('1.0.DEV1') }
it { is_expected.to match('1.0.post1') }
it { is_expected.to match('1.0.rev1') }
it { is_expected.to match('1.0.r1') }
it { is_expected.to match('1.0c2') }
it { is_expected.to match('2012.15') }
it { is_expected.to match('1.0+5') }
it { is_expected.to match('1.0+abc.5') }
it { is_expected.to match('1!1.1') }
it { is_expected.to match('1.0c3') }
it { is_expected.to match('1.0rc2') }
it { is_expected.to match('1.0c1') }
it { is_expected.to match('1.0b2-346') }
it { is_expected.to match('1.0b2.post345') }
it { is_expected.to match('1.0b2.post345.dev456') }
it { is_expected.to match('1.2.rev33+123456') }
it { is_expected.to match('1.1.dev1') }
it { is_expected.to match('1.0b1.dev456') }
it { is_expected.to match('1.0a12.dev456') }
it { is_expected.to match('1.0b2') }
it { is_expected.to match('1.0.dev456') }
it { is_expected.to match('1.0c1.dev456') }
it { is_expected.to match('1.0.post456') }
it { is_expected.to match('1.0.post456.dev34') }
it { is_expected.to match('1.2+123abc') }
it { is_expected.to match('1.2+abc') }
it { is_expected.to match('1.2+abc123') }
it { is_expected.to match('1.2+abc123def') }
it { is_expected.to match('1.2+1234.abc') }
it { is_expected.to match('1.2+123456') }
it { is_expected.to match('1.2.r32+123456') }
it { is_expected.to match('1!1.2.rev33+123456') }
it { is_expected.to match('1.0a12') }
it { is_expected.to match('1.2.3-45+abcdefgh') }
it { is_expected.to match('v1.2.3') }
it { is_expected.not_to match('1.2.3-45-abcdefgh') }
it { is_expected.not_to match('..1.2.3') }
it { is_expected.not_to match(' 1.2.3') }
it { is_expected.not_to match("1.2.3 \r\t") }
it { is_expected.not_to match("\r\t 1.2.3") }
it { is_expected.not_to match('1./2.3') }
it { is_expected.not_to match('1.2.3-4/../../') }
it { is_expected.not_to match('1.2.3-4%2e%2e%') }
it { is_expected.not_to match('../../../../../1.2.3') }
it { is_expected.not_to match('%2e%2e%2f1.2.3') }
end
describe '.semver_regex' do
subject { described_class.semver_regex }
......
......@@ -1965,7 +1965,7 @@ RSpec.describe Ci::Pipeline, :mailer do
let(:project) { create(:project, :repository) }
let(:branch) { project.default_branch }
let(:ref) { project.ci_refs.take }
let(:config_source) { Ci::PipelineEnums.config_sources[:parameter_source] }
let(:config_source) { Enums::Ci::Pipeline.config_sources[:parameter_source] }
let!(:pipeline1) { create(:ci_pipeline, :success, project: project, ref: branch) }
let!(:pipeline2) { create(:ci_pipeline, :success, project: project, ref: branch) }
let!(:pipeline3) { create(:ci_pipeline, :failed, project: project, ref: branch) }
......
......@@ -125,7 +125,7 @@ RSpec.describe Ci::Ref do
describe '#last_finished_pipeline_id' do
let(:pipeline_status) { :running }
let(:config_source) { Ci::PipelineEnums.config_sources[:repository_source] }
let(:config_source) { Enums::Ci::Pipeline.config_sources[:repository_source] }
let(:pipeline) { create(:ci_pipeline, pipeline_status, config_source: config_source) }
let(:ci_ref) { pipeline.ci_ref }
......@@ -143,7 +143,7 @@ RSpec.describe Ci::Ref do
end
context 'when the pipeline is not a ci_source' do
let(:config_source) { Ci::PipelineEnums.config_sources[:parameter_source] }
let(:config_source) { Enums::Ci::Pipeline.config_sources[:parameter_source] }
it 'returns nil' do
expect(ci_ref.last_finished_pipeline_id).to be_nil
......
......@@ -169,6 +169,73 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
end
context 'pypi package' do
subject { create(:pypi_package) }
it { is_expected.to allow_value('0.1').for(:version) }
it { is_expected.to allow_value('2.0').for(:version) }
it { is_expected.to allow_value('1.2.0').for(:version) }
it { is_expected.to allow_value('0100!0.0').for(:version) }
it { is_expected.to allow_value('00!1.2').for(:version) }
it { is_expected.to allow_value('1.0a').for(:version) }
it { is_expected.to allow_value('1.0-a').for(:version) }
it { is_expected.to allow_value('1.0.a1').for(:version) }
it { is_expected.to allow_value('1.0a1').for(:version) }
it { is_expected.to allow_value('1.0-a1').for(:version) }
it { is_expected.to allow_value('1.0alpha1').for(:version) }
it { is_expected.to allow_value('1.0b1').for(:version) }
it { is_expected.to allow_value('1.0beta1').for(:version) }
it { is_expected.to allow_value('1.0rc1').for(:version) }
it { is_expected.to allow_value('1.0pre1').for(:version) }
it { is_expected.to allow_value('1.0preview1').for(:version) }
it { is_expected.to allow_value('1.0.dev1').for(:version) }
it { is_expected.to allow_value('1.0.DEV1').for(:version) }
it { is_expected.to allow_value('1.0.post1').for(:version) }
it { is_expected.to allow_value('1.0.rev1').for(:version) }
it { is_expected.to allow_value('1.0.r1').for(:version) }
it { is_expected.to allow_value('1.0c2').for(:version) }
it { is_expected.to allow_value('2012.15').for(:version) }
it { is_expected.to allow_value('1.0+5').for(:version) }
it { is_expected.to allow_value('1.0+abc.5').for(:version) }
it { is_expected.to allow_value('1!1.1').for(:version) }
it { is_expected.to allow_value('1.0c3').for(:version) }
it { is_expected.to allow_value('1.0rc2').for(:version) }
it { is_expected.to allow_value('1.0c1').for(:version) }
it { is_expected.to allow_value('1.0b2-346').for(:version) }
it { is_expected.to allow_value('1.0b2.post345').for(:version) }
it { is_expected.to allow_value('1.0b2.post345.dev456').for(:version) }
it { is_expected.to allow_value('1.2.rev33+123456').for(:version) }
it { is_expected.to allow_value('1.1.dev1').for(:version) }
it { is_expected.to allow_value('1.0b1.dev456').for(:version) }
it { is_expected.to allow_value('1.0a12.dev456').for(:version) }
it { is_expected.to allow_value('1.0b2').for(:version) }
it { is_expected.to allow_value('1.0.dev456').for(:version) }
it { is_expected.to allow_value('1.0c1.dev456').for(:version) }
it { is_expected.to allow_value('1.0.post456').for(:version) }
it { is_expected.to allow_value('1.0.post456.dev34').for(:version) }
it { is_expected.to allow_value('1.2+123abc').for(:version) }
it { is_expected.to allow_value('1.2+abc').for(:version) }
it { is_expected.to allow_value('1.2+abc123').for(:version) }
it { is_expected.to allow_value('1.2+abc123def').for(:version) }
it { is_expected.to allow_value('1.2+1234.abc').for(:version) }
it { is_expected.to allow_value('1.2+123456').for(:version) }
it { is_expected.to allow_value('1.2.r32+123456').for(:version) }
it { is_expected.to allow_value('1!1.2.rev33+123456').for(:version) }
it { is_expected.to allow_value('1.0a12').for(:version) }
it { is_expected.to allow_value('1.2.3-45+abcdefgh').for(:version) }
it { is_expected.to allow_value('v1.2.3').for(:version) }
it { is_expected.not_to allow_value('1.2.3-45-abcdefgh').for(:version) }
it { is_expected.not_to allow_value('..1.2.3').for(:version) }
it { is_expected.not_to allow_value(' 1.2.3').for(:version) }
it { is_expected.not_to allow_value("1.2.3 \r\t").for(:version) }
it { is_expected.not_to allow_value("\r\t 1.2.3").for(:version) }
it { is_expected.not_to allow_value('1./2.3').for(:version) }
it { is_expected.not_to allow_value('1.2.3-4/../../').for(:version) }
it { is_expected.not_to allow_value('1.2.3-4%2e%2e%').for(:version) }
it { is_expected.not_to allow_value('../../../../../1.2.3').for(:version) }
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
end
it_behaves_like 'validating version to be SemVer compliant for', :npm_package
it_behaves_like 'validating version to be SemVer compliant for', :nuget_package
end
......
......@@ -40,8 +40,8 @@ RSpec.describe IssuablePolicy, models: true do
let(:issue) { create(:issue, project: project, discussion_locked: true) }
context 'when the user is not a project member' do
it 'can not create a note' do
expect(policies).to be_disallowed(:create_note)
it 'can not create a note nor award emojis' do
expect(policies).to be_disallowed(:create_note, :award_emoji)
end
end
......@@ -50,8 +50,8 @@ RSpec.describe IssuablePolicy, models: true do
project.add_guest(user)
end
it 'can create a note' do
expect(policies).to be_allowed(:create_note)
it 'can create a note and award emojis' do
expect(policies).to be_allowed(:create_note, :award_emoji)
end
end
end
......
......@@ -65,7 +65,7 @@ RSpec.describe Ci::PipelinePresenter do
describe '#failure_reason' do
context 'when pipeline has a failure reason' do
::Ci::PipelineEnums.failure_reasons.keys.each do |failure_reason|
Enums::Ci::Pipeline.failure_reasons.keys.each do |failure_reason|
context "when failure reason is #{failure_reason}" do
before do
pipeline.failure_reason = failure_reason
......
......@@ -477,7 +477,7 @@ RSpec.describe API::Ci::Pipelines do
end
context 'when config source is not ci' do
let(:non_ci_config_source) { ::Ci::PipelineEnums.non_ci_config_source_values.first }
let(:non_ci_config_source) { Enums::Ci::Pipeline.non_ci_config_source_values.first }
let(:pipeline_not_ci) do
create(:ci_pipeline, config_source: non_ci_config_source, project: project)
end
......
......@@ -240,7 +240,7 @@ RSpec.describe API::Jobs do
end
context 'when config source not ci' do
let(:non_ci_config_source) { ::Ci::PipelineEnums.non_ci_config_source_values.first }
let(:non_ci_config_source) { Enums::Ci::Pipeline.non_ci_config_source_values.first }
let(:pipeline) do
create(:ci_pipeline, config_source: non_ci_config_source, project: project)
end
......
......@@ -47,7 +47,7 @@ module MetricsDashboardHelpers
end
def business_metric_title
PrometheusMetricEnums.group_details[:business][:group_title]
Enums::PrometheusMetric.group_details[:business][:group_title]
end
def self_monitoring_dashboard_path
......
......@@ -843,15 +843,15 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
"@gitlab/svgs@1.158.0":
version "1.158.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.158.0.tgz#300d416184a2b0e05f15a96547f726e1825b08a1"
integrity sha512-5OJl+7TsXN9PJhY6/uwi+mTwmDZa9n/6119rf77orQ/joFYUypaYhBmy/1TcKVPsy5Zs6KCxE1kmGsfoXc1TYA==
"@gitlab/svgs@1.160.0":
version "1.160.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.160.0.tgz#1f6b3c9f587b7847be32b5a4ddc397fa5add8829"
integrity sha512-oBGeuQAdgd0UAha+YweeHiBsiukKX1fatzPFxD2f2UJodMJXZh/I8e+1yL68cLT/Sn0pmZBiYF2dzaDQHBbWkg==
"@gitlab/ui@20.5.0":
version "20.5.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-20.5.0.tgz#b2b366544f72f020eeb34a9a1c59f56dfadfa7e4"
integrity sha512-+0bumPvD9FdZR2dWd54qvETJXDc5vQTl71q2PugFwlYPd/00fqvqahpHInYzobjVu9+MM9KOUFhkZApT/4ZZXw==
"@gitlab/ui@20.6.0":
version "20.6.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-20.6.0.tgz#54ca0dd156d807564fcefd5583cb730fde09b3c9"
integrity sha512-1QW9nXAD6HXCH/a+mj3qdiLX8sHtD5tOTqJeCluqL0b0y6pPs9uXkQv0AV0zvruggQ36tHQeer8SiU2Op+EOtQ==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
......@@ -1140,10 +1140,10 @@
dependencies:
type-detect "4.0.8"
"@sourcegraph/code-host-integration@0.0.49":
version "0.0.49"
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.49.tgz#d0d1e61fd058d63a2798d5131d05738aa0ac4765"
integrity sha512-aMSTy+JqVaJ6E8zpQUU1bH5kwGvpt1pWPkT5/o/HnN113ZLlBfvPpNdiXDiTUYcc3zHAtFa49VD34AgxglXG9w==
"@sourcegraph/code-host-integration@0.0.50":
version "0.0.50"
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.50.tgz#3f91be4c1b117efbf3d49c73033a6b1880db1c70"
integrity sha512-Hf4JeXDnqxOpW8lrkmgzKCYKklQhS6f87j4EPxK//UdjV7W7rtBhsxr6RQqdV2VdVaVCLQW2tfA/tkm0zDk8CQ==
"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册