summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop_todo/layout/argument_alignment.yml10
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/finders/serverless_domain_finder.rb35
-rw-r--r--app/models/clusters/applications/knative.rb4
-rw-r--r--app/models/clusters/cluster.rb6
-rw-r--r--app/models/pages_domain.rb1
-rw-r--r--app/models/serverless/domain.rb44
-rw-r--r--app/models/serverless/domain_cluster.rb39
-rw-r--r--app/models/serverless/function.rb26
-rw-r--r--app/models/serverless/lookup_path.rb30
-rw-r--r--app/models/serverless/virtual_domain.rb22
-rw-r--r--app/presenters/ci/build_runner_presenter.rb4
-rw-r--r--app/presenters/label_presenter.rb18
-rw-r--r--app/presenters/merge_request_presenter.rb20
-rw-r--r--app/presenters/project_presenter.rb262
-rw-r--r--app/presenters/snippet_blob_presenter.rb8
-rw-r--r--app/serializers/cluster_application_entity.rb20
-rw-r--r--app/serializers/cluster_entity.rb1
-rw-r--r--app/serializers/cluster_serializer.rb2
-rw-r--r--app/services/serverless/associate_domain_service.rb30
-rw-r--r--app/views/admin/sessions/two_factor.html.haml1
-rw-r--r--app/views/devise/shared/_sign_in_link.html.haml2
-rw-r--r--db/docs/serverless_domain_cluster.yml2
-rw-r--r--db/post_migrate/20230202135758_queue_backfill_prepared_at_data.rb23
-rw-r--r--db/schema_migrations/202302021357581
-rw-r--r--doc/architecture/blueprints/ci_pipeline_components/dev_workflow.md2
-rw-r--r--doc/ci/chatops/img/gitlab-chatops-icon-small.pngbin2922 -> 0 bytes
-rw-r--r--doc/ci/chatops/index.md124
-rw-r--r--doc/development/fe_guide/vue.md16
-rw-r--r--doc/topics/git/useful_git_commands.md6
-rw-r--r--doc/user/project/remote_development/index.md2
-rw-r--r--doc/user/project/repository/tags/index.md79
-rw-r--r--lib/gitlab/background_migration/backfill_prepared_at_merge_requests.rb18
-rw-r--r--lib/gitlab/ci/config/yaml.rb2
-rw-r--r--lib/gitlab/prometheus/queries/knative_invocation_query.rb42
-rw-r--r--lib/gitlab/serverless/service.rb102
-rw-r--r--locale/gitlab.pot8
-rw-r--r--spec/factories/serverless/domain.rb11
-rw-r--r--spec/factories/serverless/domain_cluster.rb17
-rw-r--r--spec/finders/serverless_domain_finder_spec.rb103
-rw-r--r--spec/fixtures/api/schemas/cluster_status.json11
-rw-r--r--spec/lib/atlassian/jira_issue_key_extractor_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_prepared_at_merge_requests_spec.rb57
-rw-r--r--spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb31
-rw-r--r--spec/lib/gitlab/serverless/service_spec.rb136
-rw-r--r--spec/migrations/queue_backfill_prepared_at_data_spec.rb24
-rw-r--r--spec/models/clusters/applications/knative_spec.rb12
-rw-r--r--spec/models/pages_domain_spec.rb1
-rw-r--r--spec/models/serverless/domain_cluster_spec.rb75
-rw-r--r--spec/models/serverless/domain_spec.rb97
-rw-r--r--spec/models/serverless/function_spec.rb21
-rw-r--r--spec/presenters/blob_presenter_spec.rb10
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb78
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb9
-rw-r--r--spec/presenters/packages/detail/package_presenter_spec.rb3
-rw-r--r--spec/requests/api/internal/pages_spec.rb88
-rw-r--r--spec/serializers/cluster_application_entity_spec.rb81
-rw-r--r--spec/serializers/cluster_entity_spec.rb14
-rw-r--r--spec/serializers/cluster_serializer_spec.rb4
-rw-r--r--spec/services/serverless/associate_domain_service_spec.rb91
60 files changed, 489 insertions, 1501 deletions
diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml
index 1249df0bd64..4c0f89e9400 100644
--- a/.rubocop_todo/layout/argument_alignment.yml
+++ b/.rubocop_todo/layout/argument_alignment.yml
@@ -607,11 +607,6 @@ Layout/ArgumentAlignment:
- 'app/models/wiki_page.rb'
- 'app/models/work_item.rb'
- 'app/policies/project_snippet_policy.rb'
- - 'app/presenters/ci/build_runner_presenter.rb'
- - 'app/presenters/label_presenter.rb'
- - 'app/presenters/merge_request_presenter.rb'
- - 'app/presenters/project_presenter.rb'
- - 'app/presenters/snippet_blob_presenter.rb'
- 'app/serializers/build_details_entity.rb'
- 'app/serializers/environment_serializer.rb'
- 'app/serializers/error_tracking/detailed_error_entity.rb'
@@ -1577,7 +1572,6 @@ Layout/ArgumentAlignment:
- 'ee/spec/policies/merge_request_policy_spec.rb'
- 'ee/spec/policies/vulnerabilities/feedback_policy_spec.rb'
- 'ee/spec/policies/vulnerabilities/merge_request_link_policy_spec.rb'
- - 'ee/spec/presenters/ci/pipeline_presenter_spec.rb'
- 'ee/spec/requests/admin/impersonation_tokens_controller_spec.rb'
- 'ee/spec/requests/api/analytics/product_analytics_spec.rb'
- 'ee/spec/requests/api/analytics/project_deployment_frequency_spec.rb'
@@ -2691,10 +2685,6 @@ Layout/ArgumentAlignment:
- 'spec/policies/ci/pipeline_schedule_policy_spec.rb'
- 'spec/policies/environment_policy_spec.rb'
- 'spec/policies/group_policy_spec.rb'
- - 'spec/presenters/blob_presenter_spec.rb'
- - 'spec/presenters/ci/build_runner_presenter_spec.rb'
- - 'spec/presenters/merge_request_presenter_spec.rb'
- - 'spec/presenters/packages/detail/package_presenter_spec.rb'
- 'spec/requests/admin/applications_controller_spec.rb'
- 'spec/requests/admin/impersonation_tokens_controller_spec.rb'
- 'spec/requests/api/access_requests_spec.rb'
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 31745a9299f..bb5925c82fc 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-906fdaa2fd6f4dc4baec1b36b9341f4157e2042a
+220959f0ffc3d01fa448cc2c7b45b082d56690ef
diff --git a/app/finders/serverless_domain_finder.rb b/app/finders/serverless_domain_finder.rb
deleted file mode 100644
index 661cd0ca363..00000000000
--- a/app/finders/serverless_domain_finder.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class ServerlessDomainFinder
- attr_reader :match, :serverless_domain_cluster, :environment
-
- def initialize(uri)
- @match = ::Serverless::Domain::REGEXP.match(uri)
- end
-
- def execute
- return unless serverless?
-
- @serverless_domain_cluster = ::Serverless::DomainCluster.for_uuid(serverless_domain_cluster_uuid)
- return unless serverless_domain_cluster&.knative&.external_ip
-
- @environment = ::Environment.for_id_and_slug(match[:environment_id].to_i(16), match[:environment_slug])
- return unless environment
-
- ::Serverless::Domain.new(
- function_name: match[:function_name],
- serverless_domain_cluster: serverless_domain_cluster,
- environment: environment
- )
- end
-
- def serverless_domain_cluster_uuid
- return unless serverless?
-
- match[:cluster_left] + match[:cluster_middle] + match[:cluster_right]
- end
-
- def serverless?
- !!match
- end
-end
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 64366594583..41f6bf67ba8 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -13,8 +13,6 @@ module Clusters
self.table_name = 'clusters_applications_knative'
- has_one :serverless_domain_cluster, class_name: '::Serverless::DomainCluster', foreign_key: 'clusters_applications_knative_id', inverse_of: :knative
-
include ::Clusters::Concerns::ApplicationCore
include ::Clusters::Concerns::ApplicationStatus
include ::Clusters::Concerns::ApplicationVersion
@@ -49,8 +47,6 @@ module Clusters
scope :for_cluster, -> (cluster) { where(cluster: cluster) }
- has_one :pages_domain, through: :serverless_domain_cluster
-
def chart
'knative/knative'
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 071759318c7..0c3146fba0b 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -363,12 +363,6 @@ module Clusters
end
end
- def serverless_domain
- strong_memoize(:serverless_domain) do
- self.application_knative&.serverless_domain_cluster
- end
- end
-
def prometheus_adapter
integration_prometheus
end
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 554753dd4b2..446c4a6187c 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -15,7 +15,6 @@ class PagesDomain < ApplicationRecord
belongs_to :project
has_many :acme_orders, class_name: "PagesDomainAcmeOrder"
- has_many :serverless_domain_clusters, class_name: 'Serverless::DomainCluster', inverse_of: :pages_domain
after_initialize :set_verification_code
before_validation :clear_auto_ssl_failure, unless: :auto_ssl_enabled
diff --git a/app/models/serverless/domain.rb b/app/models/serverless/domain.rb
deleted file mode 100644
index 164f93afa9a..00000000000
--- a/app/models/serverless/domain.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Serverless
- class Domain
- include ActiveModel::Model
-
- REGEXP = %r{^(?<scheme>https?://)?(?<function_name>[^.]+)-(?<cluster_left>\h{2})a1(?<cluster_middle>\h{10})f2(?<cluster_right>\h{2})(?<environment_id>\h+)-(?<environment_slug>[^.]+)\.(?<pages_domain_name>.+)}.freeze
- UUID_LENGTH = 14
-
- attr_accessor :function_name, :serverless_domain_cluster, :environment
-
- validates :function_name, presence: true, allow_blank: false
- validates :serverless_domain_cluster, presence: true
- validates :environment, presence: true
-
- def self.generate_uuid
- SecureRandom.hex(UUID_LENGTH / 2)
- end
-
- def uri
- URI("https://#{function_name}-#{serverless_domain_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}")
- end
-
- def knative_uri
- URI("http://#{function_name}.#{namespace}.#{serverless_domain_cluster.knative.hostname}")
- end
-
- private
-
- def namespace
- serverless_domain_cluster.cluster.kubernetes_namespace_for(environment)
- end
-
- def serverless_domain_cluster_uuid
- [
- serverless_domain_cluster.uuid[0..1],
- 'a1',
- serverless_domain_cluster.uuid[2..-3],
- 'f2',
- serverless_domain_cluster.uuid[-2..]
- ].join
- end
- end
-end
diff --git a/app/models/serverless/domain_cluster.rb b/app/models/serverless/domain_cluster.rb
deleted file mode 100644
index 561bfc65b2b..00000000000
--- a/app/models/serverless/domain_cluster.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-module Serverless
- class DomainCluster < ApplicationRecord
- self.table_name = 'serverless_domain_cluster'
-
- HEX_REGEXP = %r{\A\h+\z}.freeze
-
- belongs_to :pages_domain
- belongs_to :knative, class_name: 'Clusters::Applications::Knative', foreign_key: 'clusters_applications_knative_id'
- belongs_to :creator, class_name: 'User', optional: true
-
- attr_encrypted :key,
- mode: :per_attribute_iv,
- key: Settings.attr_encrypted_db_key_base_32,
- algorithm: 'aes-256-gcm'
-
- validates :pages_domain, :knative, presence: true
- validates :uuid, presence: true, uniqueness: true, length: { is: ::Serverless::Domain::UUID_LENGTH },
- format: { with: HEX_REGEXP, message: 'only allows hex characters' }
-
- after_initialize :set_uuid, if: :new_record?
-
- delegate :domain, to: :pages_domain
- delegate :cluster, to: :knative
-
- def self.for_uuid(uuid)
- joins(:pages_domain, :knative)
- .includes(:pages_domain, :knative)
- .find_by(uuid: uuid)
- end
-
- private
-
- def set_uuid
- self.uuid = ::Serverless::Domain.generate_uuid
- end
- end
-end
diff --git a/app/models/serverless/function.rb b/app/models/serverless/function.rb
deleted file mode 100644
index 5d4f8e0c9e2..00000000000
--- a/app/models/serverless/function.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Serverless
- class Function
- attr_accessor :name, :namespace
-
- def initialize(project, name, namespace)
- @project = project
- @name = name
- @namespace = namespace
- end
-
- def id
- @project.id.to_s + "/" + @name + "/" + @namespace
- end
-
- def self.find_by_id(id)
- array = id.split("/")
- project = Project.find_by_id(array[0])
- name = array[1]
- namespace = array[2]
-
- self.new(project, name, namespace)
- end
- end
-end
diff --git a/app/models/serverless/lookup_path.rb b/app/models/serverless/lookup_path.rb
deleted file mode 100644
index c09b3718651..00000000000
--- a/app/models/serverless/lookup_path.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Serverless
- class LookupPath
- attr_reader :serverless_domain
-
- delegate :serverless_domain_cluster, to: :serverless_domain
- delegate :knative, to: :serverless_domain_cluster
- delegate :certificate, to: :serverless_domain_cluster
- delegate :key, to: :serverless_domain_cluster
-
- def initialize(serverless_domain)
- @serverless_domain = serverless_domain
- end
-
- def source
- {
- type: 'serverless',
- service: serverless_domain.knative_uri.host,
- cluster: {
- hostname: knative.hostname,
- address: knative.external_ip,
- port: 443,
- cert: certificate,
- key: key
- }
- }
- end
- end
-end
diff --git a/app/models/serverless/virtual_domain.rb b/app/models/serverless/virtual_domain.rb
deleted file mode 100644
index d6a23a4c0ce..00000000000
--- a/app/models/serverless/virtual_domain.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Serverless
- class VirtualDomain
- attr_reader :serverless_domain
-
- delegate :serverless_domain_cluster, to: :serverless_domain
- delegate :pages_domain, to: :serverless_domain_cluster
- delegate :certificate, to: :pages_domain
- delegate :key, to: :pages_domain
-
- def initialize(serverless_domain)
- @serverless_domain = serverless_domain
- end
-
- def lookup_paths
- [
- ::Serverless::LookupPath.new(serverless_domain)
- ]
- end
- end
-end
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 5da0655d21a..79c1946f3d2 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -34,9 +34,7 @@ module Ci
def runner_variables
variables
- .sort_and_expand_all(keep_undefined: true,
- expand_file_refs: false,
- expand_raw_refs: false)
+ .sort_and_expand_all(keep_undefined: true, expand_file_refs: false, expand_raw_refs: false)
.to_runner_variables
end
diff --git a/app/presenters/label_presenter.rb b/app/presenters/label_presenter.rb
index e60cdf4088c..56d986a9c23 100644
--- a/app/presenters/label_presenter.rb
+++ b/app/presenters/label_presenter.rb
@@ -27,14 +27,18 @@ class LabelPresenter < Gitlab::View::Presenter::Delegated
def filter_path(type: :issue)
case context_subject
when Group
- send("#{type.to_s.pluralize}_group_path", # rubocop:disable GitlabSecurity/PublicSend
- context_subject,
- label_name: [label.name])
+ send( # rubocop:disable GitlabSecurity/PublicSend
+ "#{type.to_s.pluralize}_group_path",
+ context_subject,
+ label_name: [label.name]
+ )
when Project
- send("namespace_project_#{type.to_s.pluralize}_path", # rubocop:disable GitlabSecurity/PublicSend
- context_subject.namespace,
- context_subject,
- label_name: [label.name])
+ send( # rubocop:disable GitlabSecurity/PublicSend
+ "namespace_project_#{type.to_s.pluralize}_path",
+ context_subject.namespace,
+ context_subject,
+ label_name: [label.name]
+ )
end
end
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 353e0fad6fb..12f4b0496e4 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -57,9 +57,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
notice_now: edit_in_new_fork_notice_now
}
- project_forks_path(merge_request.project,
- namespace_key: current_user.namespace.id,
- continue: continue_params)
+ project_forks_path(merge_request.project, namespace_key: current_user.namespace.id, continue: continue_params)
end
end
@@ -71,9 +69,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
notice_now: edit_in_new_fork_notice_now
}
- project_forks_path(project,
- namespace_key: current_user.namespace.id,
- continue: continue_params)
+ project_forks_path(project, namespace_key: current_user.namespace.id, continue: continue_params)
end
end
@@ -155,12 +151,12 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
def assign_to_closing_issues_count
# rubocop: disable CodeReuse/ServiceClass
- issues = MergeRequests::AssignIssuesService.new(project: project,
- current_user: current_user,
- params: {
- merge_request: merge_request,
- closes_issues: closing_issues
- }).assignable_issues
+ issues = MergeRequests::AssignIssuesService.new(
+ project: project,
+ current_user: current_user,
+ params: { merge_request: merge_request, closes_issues: closing_issues }
+ ).assignable_issues
+
issues.count
# rubocop: enable CodeReuse/ServiceClass
end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 392a2fcd390..c02f3021069 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -99,11 +99,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
def contribution_guide_path
if project && contribution_guide = repository.contribution_guide
- project_blob_path(
- project,
- tree_join(project.default_branch,
- contribution_guide.name)
- )
+ project_blob_path(project, tree_join(project.default_branch, contribution_guide.name))
end
end
@@ -166,14 +162,16 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
def storage_anchor_data
can_show_quota = can?(current_user, :admin_project, project) && !empty_repo?
- AnchorData.new(true,
- statistic_icon('disk') +
- _('%{strong_start}%{human_size}%{strong_end} Project Storage').html_safe % {
- human_size: storage_counter(statistics.storage_size),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- can_show_quota ? project_usage_quotas_path(project) : nil)
+ AnchorData.new(
+ true,
+ statistic_icon('disk') +
+ _('%{strong_start}%{human_size}%{strong_end} Project Storage').html_safe % {
+ human_size: storage_counter(statistics.storage_size),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ can_show_quota ? project_usage_quotas_path(project) : nil
+ )
end
def releases_anchor_data
@@ -182,14 +180,16 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
releases_count = project.releases.count
return if releases_count < 1
- AnchorData.new(true,
- statistic_icon('deployments') +
- n_('%{strong_start}%{release_count}%{strong_end} Release', '%{strong_start}%{release_count}%{strong_end} Releases', releases_count).html_safe % {
- release_count: number_with_delimiter(releases_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- project_releases_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('deployments') +
+ n_('%{strong_start}%{release_count}%{strong_end} Release', '%{strong_start}%{release_count}%{strong_end} Releases', releases_count).html_safe % {
+ release_count: number_with_delimiter(releases_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ project_releases_path(project)
+ )
end
def environments_anchor_data
@@ -198,67 +198,76 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
environments_count = project.environments.available.count
return if environments_count == 0
- AnchorData.new(true,
- statistic_icon('environment') +
- n_('%{strong_start}%{count}%{strong_end} Environment', '%{strong_start}%{count}%{strong_end} Environments', environments_count).html_safe % {
- count: number_with_delimiter(environments_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- project_environments_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('environment') +
+ n_('%{strong_start}%{count}%{strong_end} Environment', '%{strong_start}%{count}%{strong_end} Environments', environments_count).html_safe % {
+ count: number_with_delimiter(environments_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ project_environments_path(project)
+ )
end
def commits_anchor_data
- AnchorData.new(true,
- statistic_icon('commit') +
- n_('%{strong_start}%{commit_count}%{strong_end} Commit', '%{strong_start}%{commit_count}%{strong_end} Commits', statistics.commit_count).html_safe % {
- commit_count: number_with_delimiter(statistics.commit_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- empty_repo? ? nil : project_commits_path(project, default_branch_or_main))
+ AnchorData.new(
+ true,
+ statistic_icon('commit') +
+ n_('%{strong_start}%{commit_count}%{strong_end} Commit', '%{strong_start}%{commit_count}%{strong_end} Commits', statistics.commit_count).html_safe % {
+ commit_count: number_with_delimiter(statistics.commit_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ empty_repo? ? nil : project_commits_path(project, default_branch_or_main)
+ )
end
def branches_anchor_data
- AnchorData.new(true,
- statistic_icon('branch') +
- n_('%{strong_start}%{branch_count}%{strong_end} Branch', '%{strong_start}%{branch_count}%{strong_end} Branches', repository.branch_count).html_safe % {
- branch_count: number_with_delimiter(repository.branch_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- empty_repo? ? nil : project_branches_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('branch') +
+ n_('%{strong_start}%{branch_count}%{strong_end} Branch', '%{strong_start}%{branch_count}%{strong_end} Branches', repository.branch_count).html_safe % {
+ branch_count: number_with_delimiter(repository.branch_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ empty_repo? ? nil : project_branches_path(project)
+ )
end
def tags_anchor_data
- AnchorData.new(true,
- statistic_icon('label') +
- n_('%{strong_start}%{tag_count}%{strong_end} Tag', '%{strong_start}%{tag_count}%{strong_end} Tags', repository.tag_count).html_safe % {
- tag_count: number_with_delimiter(repository.tag_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- empty_repo? ? nil : project_tags_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('label') +
+ n_('%{strong_start}%{tag_count}%{strong_end} Tag', '%{strong_start}%{tag_count}%{strong_end} Tags', repository.tag_count).html_safe % {
+ tag_count: number_with_delimiter(repository.tag_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ empty_repo? ? nil : project_tags_path(project)
+ )
end
def upload_anchor_data
strong_memoize(:upload_anchor_data) do
next unless can_current_user_push_to_default_branch?
- AnchorData.new(false,
- statistic_icon('upload') + _('Upload file'),
- '#modal-upload-blob',
- 'js-upload-file-trigger',
- nil,
- nil,
- {
- 'target_branch' => default_branch_or_main,
- 'original_branch' => default_branch_or_main,
- 'can_push_code' => 'true',
- 'path' => project_create_blob_path(project, default_branch_or_main),
- 'project_path' => project.full_path
- }
- )
+ AnchorData.new(
+ false,
+ statistic_icon('upload') + _('Upload file'),
+ '#modal-upload-blob',
+ 'js-upload-file-trigger',
+ nil,
+ nil,
+ {
+ 'target_branch' => default_branch_or_main,
+ 'original_branch' => default_branch_or_main,
+ 'can_push_code' => 'true',
+ 'path' => project_create_blob_path(project, default_branch_or_main),
+ 'project_path' => project.full_path
+ }
+ )
end
end
@@ -266,37 +275,38 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if can_current_user_push_to_default_branch?
new_file_path = empty_repo? ? ide_edit_path(project, default_branch_or_main) : project_new_blob_path(project, default_branch_or_main)
- AnchorData.new(false,
- statistic_icon + _('New file'),
- new_file_path,
- 'btn-dashed')
+ AnchorData.new(false, statistic_icon + _('New file'), new_file_path, 'btn-dashed')
end
end
def readme_anchor_data
if can_current_user_push_to_default_branch? && readme_path.nil?
- AnchorData.new(false,
- statistic_icon + _('Add README'),
- empty_repo? ? add_readme_ide_path : add_readme_path)
+ AnchorData.new(false, statistic_icon + _('Add README'), empty_repo? ? add_readme_ide_path : add_readme_path)
elsif readme_path
- AnchorData.new(false,
- statistic_icon('doc-text') + _('README'),
- default_view != 'readme' ? readme_path : '#readme',
- 'btn-default',
- 'doc-text')
+ AnchorData.new(
+ false,
+ statistic_icon('doc-text') + _('README'),
+ default_view != 'readme' ? readme_path : '#readme',
+ 'btn-default',
+ 'doc-text'
+ )
end
end
def changelog_anchor_data
if can_current_user_push_to_default_branch? && repository.changelog.blank?
- AnchorData.new(false,
- statistic_icon + _('Add CHANGELOG'),
- empty_repo? ? add_changelog_ide_path : add_changelog_path)
+ AnchorData.new(
+ false,
+ statistic_icon + _('Add CHANGELOG'),
+ empty_repo? ? add_changelog_ide_path : add_changelog_path
+ )
elsif repository.changelog.present?
- AnchorData.new(false,
- statistic_icon('doc-text') + _('CHANGELOG'),
- changelog_path,
- 'btn-default')
+ AnchorData.new(
+ false,
+ statistic_icon('doc-text') + _('CHANGELOG'),
+ changelog_path,
+ 'btn-default'
+ )
end
end
@@ -304,29 +314,37 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
icon = statistic_icon('scale')
if repository.license_blob.present?
- AnchorData.new(false,
- icon + content_tag(:span, license_short_name, class: 'project-stat-value'),
- license_path,
- 'btn-default',
- nil,
- 'license')
+ AnchorData.new(
+ false,
+ icon + content_tag(:span, license_short_name, class: 'project-stat-value'),
+ license_path,
+ 'btn-default',
+ nil,
+ 'license'
+ )
elsif can_current_user_push_to_default_branch?
- AnchorData.new(false,
- content_tag(:span, statistic_icon + _('Add LICENSE'), class: 'add-license-link d-flex'),
- empty_repo? ? add_license_ide_path : add_license_path)
+ AnchorData.new(
+ false,
+ content_tag(:span, statistic_icon + _('Add LICENSE'), class: 'add-license-link d-flex'),
+ empty_repo? ? add_license_ide_path : add_license_path
+ )
end
end
def contribution_guide_anchor_data
if can_current_user_push_to_default_branch? && repository.contribution_guide.blank?
- AnchorData.new(false,
- statistic_icon + _('Add CONTRIBUTING'),
- empty_repo? ? add_contribution_guide_ide_path : add_contribution_guide_path)
+ AnchorData.new(
+ false,
+ statistic_icon + _('Add CONTRIBUTING'),
+ empty_repo? ? add_contribution_guide_ide_path : add_contribution_guide_path
+ )
elsif repository.contribution_guide.present?
- AnchorData.new(false,
- statistic_icon('doc-text') + _('CONTRIBUTING'),
- contribution_guide_path,
- 'btn-default')
+ AnchorData.new(
+ false,
+ statistic_icon('doc-text') + _('CONTRIBUTING'),
+ contribution_guide_path,
+ 'btn-default'
+ )
end
end
@@ -335,35 +353,32 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
if auto_devops_enabled?
- AnchorData.new(false,
- statistic_icon('settings') + _('Auto DevOps enabled'),
- project_settings_ci_cd_path(project, anchor: 'autodevops-settings'),
- 'btn-default')
+ AnchorData.new(
+ false,
+ statistic_icon('settings') + _('Auto DevOps enabled'),
+ project_settings_ci_cd_path(project, anchor: 'autodevops-settings'),
+ 'btn-default'
+ )
else
- AnchorData.new(false,
- statistic_icon + _('Enable Auto DevOps'),
- project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
+ AnchorData.new(
+ false,
+ statistic_icon + _('Enable Auto DevOps'),
+ project_settings_ci_cd_path(project, anchor: 'autodevops-settings')
+ )
end
elsif auto_devops_enabled?
- AnchorData.new(false,
- _('Auto DevOps enabled'),
- nil)
+ AnchorData.new(false, _('Auto DevOps enabled'), nil)
end
end
def kubernetes_cluster_anchor_data
if can_instantiate_cluster?
if clusters.empty?
- AnchorData.new(false,
- statistic_icon + _('Add Kubernetes cluster'),
- project_clusters_path(project))
+ AnchorData.new(false, statistic_icon + _('Add Kubernetes cluster'), project_clusters_path(project))
else
cluster_link = clusters.count == 1 ? project_cluster_path(project, clusters.first) : project_clusters_path(project)
- AnchorData.new(false,
- _('Kubernetes'),
- cluster_link,
- 'btn-default')
+ AnchorData.new(false, _('Kubernetes'), cluster_link, 'btn-default')
end
end
end
@@ -372,14 +387,9 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
return unless can_view_pipeline_editor?(project)
if cicd_missing?
- AnchorData.new(false,
- statistic_icon + _('Set up CI/CD'),
- project_ci_pipeline_editor_path(project))
+ AnchorData.new(false, statistic_icon + _('Set up CI/CD'), project_ci_pipeline_editor_path(project))
elsif repository.gitlab_ci_yml.present?
- AnchorData.new(false,
- statistic_icon('doc-text') + _('CI/CD configuration'),
- project_ci_pipeline_editor_path(project),
- 'btn-default')
+ AnchorData.new(false, statistic_icon('doc-text') + _('CI/CD configuration'), project_ci_pipeline_editor_path(project), 'btn-default')
end
end
diff --git a/app/presenters/snippet_blob_presenter.rb b/app/presenters/snippet_blob_presenter.rb
index 2e5d3ae21d9..84e98e18e32 100644
--- a/app/presenters/snippet_blob_presenter.rb
+++ b/app/presenters/snippet_blob_presenter.rb
@@ -40,9 +40,11 @@ class SnippetBlobPresenter < BlobPresenter
end
def render_rich_partial
- renderer.render("projects/blob/viewers/_#{blob.rich_viewer.partial_name}",
- locals: { viewer: blob.rich_viewer, blob: blob, blob_raw_path: raw_path, blob_raw_url: raw_url, parent_dir_raw_path: raw_directory },
- layout: false)
+ renderer.render(
+ "projects/blob/viewers/_#{blob.rich_viewer.partial_name}",
+ locals: { viewer: blob.rich_viewer, blob: blob, blob_raw_path: raw_path, blob_raw_url: raw_url, parent_dir_raw_path: raw_directory },
+ layout: false
+ )
end
def renderer
diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb
deleted file mode 100644
index f57ac4af113..00000000000
--- a/app/serializers/cluster_application_entity.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class ClusterApplicationEntity < Grape::Entity
- expose :name
- expose :status_name, as: :status
- expose :status_reason
- expose :version, if: -> (e, _) { e.respond_to?(:version) }
- expose :external_ip, if: -> (e, _) { e.respond_to?(:external_ip) }
- expose :external_hostname, if: -> (e, _) { e.respond_to?(:external_hostname) }
- expose :hostname, if: -> (e, _) { e.respond_to?(:hostname) }
- expose :email, if: -> (e, _) { e.respond_to?(:email) }
- expose :stack, if: -> (e, _) { e.respond_to?(:stack) }
- expose :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) }
- expose :can_uninstall?, as: :can_uninstall
- expose :available_domains, using: Serverless::DomainEntity, if: -> (e, _) { e.respond_to?(:available_domains) }
- expose :pages_domain, using: Serverless::DomainEntity, if: -> (e, _) { e.respond_to?(:pages_domain) }
- expose :host, if: -> (e, _) { e.respond_to?(:host) }
- expose :port, if: -> (e, _) { e.respond_to?(:port) }
- expose :protocol, if: -> (e, _) { e.respond_to?(:protocol) }
-end
diff --git a/app/serializers/cluster_entity.rb b/app/serializers/cluster_entity.rb
index 8e256863bcd..161758debca 100644
--- a/app/serializers/cluster_entity.rb
+++ b/app/serializers/cluster_entity.rb
@@ -13,7 +13,6 @@ class ClusterEntity < Grape::Entity
expose :provider_type
expose :status_name, as: :status
expose :status_reason
- expose :applications, using: ClusterApplicationEntity
expose :path do |cluster|
Clusters::ClusterPresenter.new(cluster).show_path # rubocop: disable CodeReuse/Presenter
diff --git a/app/serializers/cluster_serializer.rb b/app/serializers/cluster_serializer.rb
index 30b8863efa2..a4e12e51f69 100644
--- a/app/serializers/cluster_serializer.rb
+++ b/app/serializers/cluster_serializer.rb
@@ -22,6 +22,6 @@ class ClusterSerializer < BaseSerializer
end
def represent_status(resource)
- represent(resource, { only: [:status, :status_reason, :applications] })
+ represent(resource, { only: [:status, :status_reason] })
end
end
diff --git a/app/services/serverless/associate_domain_service.rb b/app/services/serverless/associate_domain_service.rb
deleted file mode 100644
index 0c6ee58924c..00000000000
--- a/app/services/serverless/associate_domain_service.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Serverless
- class AssociateDomainService
- PLACEHOLDER_HOSTNAME = 'example.com'
-
- def initialize(knative, pages_domain_id:, creator:)
- @knative = knative
- @pages_domain_id = pages_domain_id
- @creator = creator
- end
-
- def execute
- return if unchanged?
-
- knative.hostname ||= PLACEHOLDER_HOSTNAME
-
- knative.pages_domain = knative.find_available_domain(pages_domain_id)
- knative.serverless_domain_cluster.update(creator: creator) if knative.pages_domain
- end
-
- private
-
- attr_reader :knative, :pages_domain_id, :creator
-
- def unchanged?
- knative.pages_domain&.id == pages_domain_id
- end
- end
-end
diff --git a/app/views/admin/sessions/two_factor.html.haml b/app/views/admin/sessions/two_factor.html.haml
index 86bc5af6c2a..d05cc51af41 100644
--- a/app/views/admin/sessions/two_factor.html.haml
+++ b/app/views/admin/sessions/two_factor.html.haml
@@ -1,4 +1,3 @@
-- @hide_breadcrumbs = true
- page_title _('Enter 2FA for Admin Mode')
.row.justify-content-center
diff --git a/app/views/devise/shared/_sign_in_link.html.haml b/app/views/devise/shared/_sign_in_link.html.haml
index 0a48c342502..a1d10898c5b 100644
--- a/app/views/devise/shared/_sign_in_link.html.haml
+++ b/app/views/devise/shared/_sign_in_link.html.haml
@@ -1,6 +1,6 @@
%p.text-center
%span.light
- = _('Already have login and password?')
+ = _('Already have an account?')
- path_params = { redirect_to_referer: 'yes' }
- path_params[:invite_email] = @invite_email if @invite_email.present?
= link_to _('Sign in'), new_session_path(:user, path_params)
diff --git a/db/docs/serverless_domain_cluster.yml b/db/docs/serverless_domain_cluster.yml
index 23c77b2c043..72b231171ba 100644
--- a/db/docs/serverless_domain_cluster.yml
+++ b/db/docs/serverless_domain_cluster.yml
@@ -1,7 +1,5 @@
---
table_name: serverless_domain_cluster
-classes:
-- Serverless::DomainCluster
feature_categories:
- kubernetes_management
description: "(Deprecated) A custom domain for a GitLab managed Knative installation"
diff --git a/db/post_migrate/20230202135758_queue_backfill_prepared_at_data.rb b/db/post_migrate/20230202135758_queue_backfill_prepared_at_data.rb
new file mode 100644
index 00000000000..227b469b625
--- /dev/null
+++ b/db/post_migrate/20230202135758_queue_backfill_prepared_at_data.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class QueueBackfillPreparedAtData < Gitlab::Database::Migration[2.1]
+ MIGRATION = 'BackfillPreparedAtMergeRequests'
+ DELAY_INTERVAL = 2.minutes
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :merge_requests,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: 5000,
+ sub_batch_size: 250
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :merge_requests, :id, [])
+ end
+end
diff --git a/db/schema_migrations/20230202135758 b/db/schema_migrations/20230202135758
new file mode 100644
index 00000000000..2afb3886ade
--- /dev/null
+++ b/db/schema_migrations/20230202135758
@@ -0,0 +1 @@
+877ea1462505cfc9986353e5fb5f8cfc68a7557140bdc162bcfbd7a68c266f97 \ No newline at end of file
diff --git a/doc/architecture/blueprints/ci_pipeline_components/dev_workflow.md b/doc/architecture/blueprints/ci_pipeline_components/dev_workflow.md
index 6d293f41a94..266ea13c275 100644
--- a/doc/architecture/blueprints/ci_pipeline_components/dev_workflow.md
+++ b/doc/architecture/blueprints/ci_pipeline_components/dev_workflow.md
@@ -133,7 +133,7 @@ Now run a new pipeline for the `main` branch, by pushing a change or manually ru
## 5. Create a tag
-As the pipeline for `main` is green, we can now [create our first tag](../../../user/project/repository/tags/index.md#tags-sample-workflow): `v1.0`.
+As the pipeline for `main` is green, we can now [create our first tag](../../../user/project/repository/tags/index.md#create-a-tag): `v1.0`.
As soon as the `v1.0` tag is created, we see a tag pipeline start.
This time the pipeline also has a `create-release` job in the `release` stage:
diff --git a/doc/ci/chatops/img/gitlab-chatops-icon-small.png b/doc/ci/chatops/img/gitlab-chatops-icon-small.png
deleted file mode 100644
index 71cc5dba5cf..00000000000
--- a/doc/ci/chatops/img/gitlab-chatops-icon-small.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/chatops/index.md b/doc/ci/chatops/index.md
index f0efb5fc884..d827fda67a1 100644
--- a/doc/ci/chatops/index.md
+++ b/doc/ci/chatops/index.md
@@ -9,62 +9,70 @@ type: index, concepts, howto
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in GitLab Ultimate 10.6.
> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to GitLab Free in 11.9.
-> - `CHAT_USER_ID` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/341798) in GitLab 14.4.
+> - `CHAT_USER_ID` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/341798) in GitLab 14.4.
-GitLab ChatOps provides a method to interact with CI/CD jobs through chat services
-like Slack. Many organizations' discussion, collaboration, and troubleshooting takes
-place in chat services. Having a method to run CI/CD jobs with output
-posted back to the channel can significantly augment your team's workflow.
+Use GitLab ChatOps to interact with CI/CD jobs through chat services
+like Slack.
-## How GitLab ChatOps works
+Many organizations use chat services to collaborate, troubleshoot, and plan work. With ChatOps,
+you can discuss work with your team, run CI/CD jobs, and view job output, all from the same
+application.
-GitLab ChatOps is built upon [GitLab CI/CD](../index.md) and
-[Slack Slash Commands](../../user/project/integrations/slack_slash_commands.md).
-ChatOps provides a `run` action for [slash commands](../../integration/slash_commands.md)
-with the following arguments:
+## ChatOps workflow and CI/CD configuration
-- A `<job name>` to execute.
-- The `<job arguments>`.
+ChatOps looks for the specified job in the
+[`.gitlab-ci.yml`](../yaml/index.md) on the project's default
+branch. If the job is found, ChatOps creates a pipeline that contains
+only the specified job. If you set `when: manual`, ChatOps creates the
+pipeline, but the job doesn't start automatically.
+
+A job run with ChatOps has the same functionality as a job run from
+GitLab. The job can use existing [CI/CD variables](../variables/index.md#predefined-cicd-variables) like
+`GITLAB_USER_ID` to perform additional rights validation, but these
+variables can be [overridden](../variables/index.md#cicd-variable-precedence).
+
+You should set [`rules`](../yaml/index.md#rules) so the job does not
+run as part of the standard CI/CD pipeline.
ChatOps passes the following [CI/CD variables](../variables/index.md#predefined-cicd-variables)
to the job:
-- `CHAT_INPUT` contains any additional arguments.
-- `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
-- `CHAT_USER_ID` is set to the chat service's user ID of the user who triggered the slash command.
+- `CHAT_INPUT` - The arguments passed to `/project-name run`.
+- `CHAT_CHANNEL` - The name of the chat channel the job is run from.
+- `CHAT_USER_ID` - The chat service ID of the user who runs the job.
-When executed, ChatOps looks up the specified job name and attempts to match it
-to a corresponding job in [`.gitlab-ci.yml`](../yaml/index.md). If a matching job
-is found on the default branch, a pipeline containing only that job is scheduled. After the
-job completes:
+When the job runs:
-- If the job completes in *less than 30 minutes*, the ChatOps sends the job's output to Slack.
-- If the job completes in *more than 30 minutes*, the job must use the
+- If the job completes in less than 30 minutes, ChatOps sends the job output to the chat channel.
+- If the job completes in more than 30 minutes, you must use a method like the
[Slack API](https://api.slack.com/) to send data to the channel.
-To use the `run` command, you must have at least the
-Developer role.
-If a job shouldn't be able to be triggered from chat, you can set the job to `except: [chat]`.
+## Run a CI/CD job
+
+You can run a CI/CD job from chat with the `/project-name run`
+[slash command](../../integration/slash_commands.md).
+
+Prerequisites:
+
+- You must have at least the Developer role for the project.
+
+To run a CI/CD job:
-## Best practices for ChatOps CI jobs
+- In the chat client, enter `/project-name run <job name> <arguments>`.
-Since ChatOps is built upon GitLab CI/CD, the job has all the same features and
-functions available. Consider these best practices when creating ChatOps jobs:
+ChatOps schedules a pipeline that contains only the specified job.
-- GitLab strongly recommends you set [`rules`](../yaml/index.md#rules) so the job does not run as part
- of the standard CI pipeline.
-- If the job is set to `when: manual`, ChatOps creates the pipeline, but the job waits to be started.
-- ChatOps provides limited support for access control. If the user triggering the
- slash command has at least the Developer role
- in the project, the job runs. The job itself can use existing
- [CI/CD variables](../variables/index.md#predefined-cicd-variables) like
- `GITLAB_USER_ID` to perform additional rights validation, but
- these variables can be [overridden](../variables/index.md#cicd-variable-precedence).
+### Exclude a job from ChatOps
-### Controlling the ChatOps reply
+To prevent a job from being run from chat:
-The output for jobs with a single command is sent to the channel as a reply. For
-example, the chat reply of the following job is `Hello World` in the channel:
+- In `.gitlab-ci.yml`, set the job to `except: [chat]`.
+
+## Customize the ChatOps reply
+
+ChatOps sends the output for a job with a single command to the
+channel as a reply. For example, when the following job runs,
+the chat reply is `Hello world`:
```yaml
stages:
@@ -78,13 +86,12 @@ hello-world:
- echo "Hello World"
```
-Jobs that contain multiple commands (or `before_script`) return additional
-content in the chat reply. In these cases, both the commands and their output are
-included, with the commands wrapped in ANSI color codes.
+If the job contains multiple commands, or if `before_script` is set, ChatOps sends the commands
+and their output to the channel. The commands are wrapped in ANSI color codes.
-To selectively reply with the output of one command, its output must be bounded by
-the `chat_reply` section. For example, the following job lists the files in the
-current directory:
+To selectively reply with the output of one command, place the output
+in a `chat_reply` section. For example, the following job lists the
+files in the current directory:
```yaml
stages:
@@ -99,28 +106,11 @@ ls:
- echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K"
```
-## GitLab ChatOps examples
-
-The GitLab.com team created a repository of [common ChatOps scripts](https://gitlab.com/gitlab-com/chatops)
-they use to interact with our Production instance of GitLab. Administrators of
-other GitLab instances may find them useful. They can serve as inspiration for ChatOps
-scripts you can write to interact with your own applications.
-
-## GitLab ChatOps icon
-
-The [official GitLab ChatOps icon](img/gitlab-chatops-icon.png) is available for download.
-You can find and download the official GitLab ChatOps icon here.
-
-![GitLab ChatOps bot icon](img/gitlab-chatops-icon-small.png)
+## Example scripts
-<!-- ## Troubleshooting
+The GitLab team maintains a repository of [common ChatOps scripts](https://gitlab.com/gitlab-com/chatops)
+they use to interact with GitLab.com.
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
+## Related topics
-Each scenario can be a third-level heading, for example `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+- Download the [official GitLab ChatOps icon](img/gitlab-chatops-icon.png).
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 898dfec2119..7dff2b76e80 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -453,6 +453,22 @@ Composition API allows you to place the logic in the `<script>` section of the c
</script>
```
+### `v-bind` limitations
+
+Avoid using `v-bind="$attrs"` unless absolutely necessary. You might need this when
+developing a native control wrapper. (This is a good candidate for a `gitlab-ui` component.)
+In any other cases, always prefer using `props` and explicit data flow.
+
+Using `v-bind="$attrs"` leads to:
+
+1. A loss in component's contract. The `props` were designed specifically
+ to address this problem.
+1. High maintenance cost for each component in the tree. `v-bind="$attrs"` is specifically
+ hard to debug because you must scan the whole hierarchy of components to understand
+ the data flow.
+1. Problems during migration to Vue 3. `$attrs` in Vue 3 include event listeners which
+ could cause unexpected side-effects after Vue 3 migration is completed.
+
### Aim to have one API style per component
When adding `setup()` property to Vue component, consider refactoring it to Composition API entirely. It's not always feasible, especially for large components, but we should aim to have one API style per component for readability and maintainability.
diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md
index 235412f511a..22548be2e8b 100644
--- a/doc/topics/git/useful_git_commands.md
+++ b/doc/topics/git/useful_git_commands.md
@@ -130,12 +130,6 @@ Use this to check the Git history of the file:
git log -- <file>
```
-### Find the tags that contain a particular SHA
-
-```shell
-git tag --contains <sha>
-```
-
### Check the content of each change to a file
```shell
diff --git a/doc/user/project/remote_development/index.md b/doc/user/project/remote_development/index.md
index 1abcca547db..58d43f64812 100644
--- a/doc/user/project/remote_development/index.md
+++ b/doc/user/project/remote_development/index.md
@@ -97,7 +97,7 @@ docker run -d \
-v "${CERTS_DIR}/fullchain.pem:/gitlab-rd-web-ide/certs/fullchain.pem" \
-v "${CERTS_DIR}/privkey.pem:/gitlab-rd-web-ide/certs/privkey.pem" \
-v "${PROJECTS_DIR}:/projects" \
- registry.gitlab.com/gitlab-com/create-stage/editor-poc/remote-development/gitlab-rd-web-ide-docker:0.1-alpha \
+ registry.gitlab.com/gitlab-org/remote-development/gitlab-rd-web-ide-docker:0.2-alpha \
--log-level warn --domain "${DOMAIN}" --ignore-version-mismatch
```
diff --git a/doc/user/project/repository/tags/index.md b/doc/user/project/repository/tags/index.md
index 869012c64cc..6cd6fa91238 100644
--- a/doc/user/project/repository/tags/index.md
+++ b/doc/user/project/repository/tags/index.md
@@ -6,15 +6,65 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Tags **(FREE)**
-Tags help you mark certain deployments and releases for later
-reference. Git supports two types of tags:
+In Git, a tag marks an important point in a repository's history.
+Git supports two types of tags:
-- Annotated tags: An unchangeable part of Git history.
-- Lightweight (soft) tags: Tags that can be set and removed as needed.
+- **Lightweight tags** point to specific commits, and contain no other information.
+ Also known as soft tags. Create or remove them as needed.
+- **Annotated tags** contain metadata, can be signed for verification purposes,
+ and can't be changed.
+The creation or deletion of a tag can be used as a trigger for automation, including:
+
+- Using a [webhook](../../integrations/webhook_events.md#tag-events) to automate actions
+ like Slack notifications.
+- Signaling a [repository mirror](../mirror/index.md) to update.
+- Running a CI/CD pipeline with [`if: $CI_COMMIT_TAG`](../../../../ci/jobs/job_control.md#common-if-clauses-for-rules).
+
+When you [create a release](../../releases/index.md),
+GitLab also creates a tag to mark the release point.
Many projects combine an annotated release tag with a stable branch. Consider
setting deployment or release tags automatically.
+To prevent users from removing a tag with `git push`, create a [push rule](../push_rules.md).
+
+## Create a tag
+
+Tags can be created from the command line, or the GitLab UI.
+
+### From the command line
+
+To create either a lightweight or annotated tag from the command line, and push it upstream:
+
+1. To create a lightweight tag, run the command `git tag TAG_NAME`, changing
+ `TAG_NAME` to your desired tag name.
+1. To create an annotated tag, run one of the versions of `git tag` from the command line:
+
+ ```shell
+ # In this short version, the annotated tag's name is "v1.0",
+ # and the message is "Version 1.0".
+ git tag -a v1.0 -m "Version 1.0"
+
+ # Use this version to write a longer tag message
+ # for annotated tag "v1.0" in your text editor.
+ git tag -a v1.0
+ ```
+
+1. Push your tags upstream with `git push origin --tags`.
+
+### From the UI
+
+To create a tag from the GitLab UI:
+
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Repository > Tags**.
+1. Select **New tag**.
+1. Provide a **Tag name**.
+1. For **Create from**, select an existing branch name, tag, or commit SHA.
+1. Optional. Add a **Message** to create an annotated tag, or leave blank to
+ create a lightweight tag.
+1. Select **Create tag**.
+
## View tags for a project
1. On the top bar, select **Main menu > Projects** and find your project.
@@ -34,25 +84,13 @@ In the GitLab UI, each tag displays:
- A [**Create release**](../../releases/index.md#create-a-release) (**{pencil}**) link.
- A link to delete the tag.
-## Tags sample workflow
+## Find tags containing a commit
-1. Create a lightweight tag.
-1. Create an annotated tag.
-1. Push the tags to the remote repository.
+To search all Git tags for a particular SHA (commit identifier), run this
+command from the command line, replacing `SHA` with the SHA of the commit:
```shell
-git checkout main
-
-# Lightweight tag
-git tag my_lightweight_tag
-
-# Annotated tag
-git tag -a v1.0 -m 'Version 1.0'
-
-# Show list of the existing tags
-git tag
-
-git push origin --tags
+git tag --contains SHA
```
## Related topics
@@ -60,4 +98,3 @@ git push origin --tags
- [Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging) Git reference page.
- [Protected tags](../../protected_tags.md).
- [Tags API](../../../../api/tags.md).
-- [Use `if: $CI_COMMIT_TAG` to run CI/CD pipelines for tags](../../../../ci/jobs/job_control.md#common-if-clauses-for-rules).
diff --git a/lib/gitlab/background_migration/backfill_prepared_at_merge_requests.rb b/lib/gitlab/background_migration/backfill_prepared_at_merge_requests.rb
new file mode 100644
index 00000000000..9bf503bd6e7
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_prepared_at_merge_requests.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfill prepared_at for an array of merge requests
+ class BackfillPreparedAtMergeRequests < ::Gitlab::BackgroundMigration::BatchedMigrationJob
+ scope_to ->(relation) { relation }
+ operation_name :update_all
+ feature_category :code_review_workflow
+
+ def perform
+ each_sub_batch do |sub_batch|
+ sub_batch.where(prepared_at: nil).where.not(merge_status: 'preparing').update_all('prepared_at = created_at')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/yaml.rb b/lib/gitlab/ci/config/yaml.rb
index 11165570e81..4111000d43b 100644
--- a/lib/gitlab/ci/config/yaml.rb
+++ b/lib/gitlab/ci/config/yaml.rb
@@ -30,7 +30,7 @@ module Gitlab
end
def to_result
- Yaml::Result.new(load!)
+ Yaml::Result.new(load!, error: nil)
rescue ::Gitlab::Config::Loader::FormatError => e
Yaml::Result.new(error: e)
end
diff --git a/lib/gitlab/prometheus/queries/knative_invocation_query.rb b/lib/gitlab/prometheus/queries/knative_invocation_query.rb
deleted file mode 100644
index 6438995b576..00000000000
--- a/lib/gitlab/prometheus/queries/knative_invocation_query.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Prometheus
- module Queries
- class KnativeInvocationQuery < BaseQuery
- include QueryAdditionalMetrics
-
- def query(serverless_function_id)
- PrometheusMetricsFinder
- .new(identifier: :system_metrics_knative_function_invocation_count, common: true)
- .execute
- .first
- .to_query_metric
- .tap do |q|
- q.queries[0][:result] = run_query(q.queries[0][:query_range], context(serverless_function_id))
- end
- end
-
- protected
-
- def context(function_id)
- function = ::Serverless::Function.find_by_id(function_id)
- {
- function_name: function.name,
- kube_namespace: function.namespace
- }
- end
-
- def run_query(query, context)
- query %= context
- client_query_range(query, start_time: 8.hours.ago.to_f, end_time: Time.now.to_f)
- end
-
- def self.transform_reactive_result(result)
- result[:metrics] = result.delete :data
- result
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/serverless/service.rb b/lib/gitlab/serverless/service.rb
deleted file mode 100644
index c3ab2e9ddeb..00000000000
--- a/lib/gitlab/serverless/service.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-
-class Gitlab::Serverless::Service
- include Gitlab::Utils::StrongMemoize
-
- def initialize(attributes)
- @attributes = attributes
- end
-
- def name
- @attributes.dig('metadata', 'name')
- end
-
- def namespace
- @attributes.dig('metadata', 'namespace')
- end
-
- def environment_scope
- @attributes.dig('environment_scope')
- end
-
- def environment
- @attributes.dig('environment')
- end
-
- def podcount
- @attributes.dig('podcount')
- end
-
- def created_at
- strong_memoize(:created_at) do
- timestamp = @attributes.dig('metadata', 'creationTimestamp')
- DateTime.parse(timestamp) if timestamp
- end
- end
-
- def image
- @attributes.dig(
- 'spec',
- 'runLatest',
- 'configuration',
- 'build',
- 'template',
- 'name')
- end
-
- def description
- knative_07_description || knative_05_06_description
- end
-
- def cluster
- @attributes.dig('cluster')
- end
-
- def url
- proxy_url || knative_06_07_url || knative_05_url
- end
-
- private
-
- def proxy_url
- if cluster&.serverless_domain
- ::Serverless::Domain.new(
- function_name: name,
- serverless_domain_cluster: cluster.serverless_domain,
- environment: environment
- ).uri.to_s
- end
- end
-
- def knative_07_description
- @attributes.dig(
- 'spec',
- 'template',
- 'metadata',
- 'annotations',
- 'Description'
- )
- end
-
- def knative_05_06_description
- @attributes.dig(
- 'spec',
- 'runLatest',
- 'configuration',
- 'revisionTemplate',
- 'metadata',
- 'annotations',
- 'Description')
- end
-
- def knative_05_url
- domain = @attributes.dig('status', 'domain')
- return unless domain
-
- "http://#{domain}"
- end
-
- def knative_06_07_url
- @attributes.dig('status', 'url')
- end
-end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e4c87db88e0..3b4b52d50b7 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4254,7 +4254,7 @@ msgstr ""
msgid "Already blocked"
msgstr ""
-msgid "Already have login and password?"
+msgid "Already have an account?"
msgstr ""
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
@@ -41984,6 +41984,9 @@ msgstr ""
msgid "SubscriptionTable|Last invoice"
msgstr ""
+msgid "SubscriptionTable|Last updated at %{seatsLastUpdated} UTC"
+msgstr ""
+
msgid "SubscriptionTable|Loading subscriptions"
msgstr ""
@@ -42044,6 +42047,9 @@ msgstr ""
msgid "SubscriptionTable|Trial start date"
msgstr ""
+msgid "SubscriptionTable|Up to date"
+msgstr ""
+
msgid "SubscriptionTable|Usage"
msgstr ""
diff --git a/spec/factories/serverless/domain.rb b/spec/factories/serverless/domain.rb
deleted file mode 100644
index c09af068d19..00000000000
--- a/spec/factories/serverless/domain.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :serverless_domain, class: '::Serverless::Domain' do
- function_name { 'test-function' }
- serverless_domain_cluster { association(:serverless_domain_cluster) }
- environment { association(:environment) }
-
- skip_create
- end
-end
diff --git a/spec/factories/serverless/domain_cluster.rb b/spec/factories/serverless/domain_cluster.rb
deleted file mode 100644
index e8ff6cf42b2..00000000000
--- a/spec/factories/serverless/domain_cluster.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :serverless_domain_cluster, class: '::Serverless::DomainCluster' do
- pages_domain { association(:pages_domain) }
- knative { association(:clusters_applications_knative) }
- creator { association(:user) }
-
- certificate do
- File.read(Rails.root.join('spec/fixtures/', 'ssl_certificate.pem'))
- end
-
- key do
- File.read(Rails.root.join('spec/fixtures/', 'ssl_key.pem'))
- end
- end
-end
diff --git a/spec/finders/serverless_domain_finder_spec.rb b/spec/finders/serverless_domain_finder_spec.rb
deleted file mode 100644
index 4e6b9f07544..00000000000
--- a/spec/finders/serverless_domain_finder_spec.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ServerlessDomainFinder do
- let(:function_name) { 'test-function' }
- let(:pages_domain_name) { 'serverless.gitlab.io' }
- let(:valid_cluster_uuid) { 'aba1cdef123456f278' }
- let(:invalid_cluster_uuid) { 'aba1cdef123456f178' }
- let!(:environment) { create(:environment, name: 'test') }
-
- let(:pages_domain) do
- create(
- :pages_domain,
- :instance_serverless,
- domain: pages_domain_name
- )
- end
-
- let(:knative_with_ingress) do
- create(
- :clusters_applications_knative,
- external_ip: '10.0.0.1'
- )
- end
-
- let!(:serverless_domain_cluster) do
- create(
- :serverless_domain_cluster,
- uuid: 'abcdef12345678',
- pages_domain: pages_domain,
- knative: knative_with_ingress
- )
- end
-
- let(:valid_uri) { "https://#{function_name}-#{valid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
- let(:valid_fqdn) { "#{function_name}-#{valid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
- let(:invalid_uri) { "https://#{function_name}-#{invalid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
-
- let(:valid_finder) { described_class.new(valid_uri) }
- let(:invalid_finder) { described_class.new(invalid_uri) }
-
- describe '#serverless?' do
- context 'with a valid URI' do
- subject { valid_finder.serverless? }
-
- it { is_expected.to be_truthy }
- end
-
- context 'with an invalid URI' do
- subject { invalid_finder.serverless? }
-
- it { is_expected.to be_falsy }
- end
- end
-
- describe '#serverless_domain_cluster_uuid' do
- context 'with a valid URI' do
- subject { valid_finder.serverless_domain_cluster_uuid }
-
- it { is_expected.to eq serverless_domain_cluster.uuid }
- end
-
- context 'with an invalid URI' do
- subject { invalid_finder.serverless_domain_cluster_uuid }
-
- it { is_expected.to be_nil }
- end
- end
-
- describe '#execute' do
- context 'with a valid URI' do
- let(:serverless_domain) do
- create(
- :serverless_domain,
- function_name: function_name,
- serverless_domain_cluster: serverless_domain_cluster,
- environment: environment
- )
- end
-
- subject { valid_finder.execute }
-
- it 'has the correct function_name' do
- expect(subject.function_name).to eq function_name
- end
-
- it 'has the correct serverless_domain_cluster' do
- expect(subject.serverless_domain_cluster).to eq serverless_domain_cluster
- end
-
- it 'has the correct environment' do
- expect(subject.environment).to eq environment
- end
- end
-
- context 'with an invalid URI' do
- subject { invalid_finder.execute }
-
- it { is_expected.to be_nil }
- end
- end
-end
diff --git a/spec/fixtures/api/schemas/cluster_status.json b/spec/fixtures/api/schemas/cluster_status.json
index efc609b3c3f..0ef4d6f82a9 100644
--- a/spec/fixtures/api/schemas/cluster_status.json
+++ b/spec/fixtures/api/schemas/cluster_status.json
@@ -1,8 +1,7 @@
{
"type": "object",
"required": [
- "status",
- "applications"
+ "status"
],
"properties": {
"status": {
@@ -10,12 +9,6 @@
},
"status_reason": {
"$ref": "types/nullable_string.json"
- },
- "applications": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/application_status"
- }
}
},
"additionalProperties": false,
@@ -115,4 +108,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/spec/lib/atlassian/jira_issue_key_extractor_spec.rb b/spec/lib/atlassian/jira_issue_key_extractor_spec.rb
index ce29e03f818..42fc441b868 100644
--- a/spec/lib/atlassian/jira_issue_key_extractor_spec.rb
+++ b/spec/lib/atlassian/jira_issue_key_extractor_spec.rb
@@ -2,7 +2,7 @@
require 'fast_spec_helper'
-RSpec.describe Atlassian::JiraIssueKeyExtractor do
+RSpec.describe Atlassian::JiraIssueKeyExtractor, feature_category: :integrations do
describe '.has_keys?' do
subject { described_class.has_keys?(string) }
diff --git a/spec/lib/gitlab/background_migration/backfill_prepared_at_merge_requests_spec.rb b/spec/lib/gitlab/background_migration/backfill_prepared_at_merge_requests_spec.rb
new file mode 100644
index 00000000000..b33a1a31c40
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_prepared_at_merge_requests_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillPreparedAtMergeRequests, :migration,
+ feature_category: :code_review_workflow, schema: 20230202135758 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:mr_table) { table(:merge_requests) }
+
+ let(:namespace) { namespaces.create!(name: 'batchtest1', type: 'Group', path: 'space1') }
+ let(:proj_namespace) { namespaces.create!(name: 'proj1', path: 'proj1', type: 'Project', parent_id: namespace.id) }
+ let(:project) do
+ projects.create!(name: 'proj1', path: 'proj1', namespace_id: namespace.id, project_namespace_id: proj_namespace.id)
+ end
+
+ let(:test_worker) do
+ described_class.new(
+ start_id: 1,
+ end_id: 100,
+ batch_table: :merge_requests,
+ batch_column: :id,
+ sub_batch_size: 10,
+ pause_ms: 0,
+ connection: ApplicationRecord.connection
+ )
+ end
+
+ it 'updates merge requests with prepared_at nil' do
+ time = Time.current
+
+ mr_1 = mr_table.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature',
+ prepared_at: nil, merge_status: 'checking')
+ mr_2 = mr_table.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature',
+ prepared_at: nil, merge_status: 'preparing')
+ mr_3 = mr_table.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature',
+ prepared_at: time)
+ mr_4 = mr_table.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature',
+ prepared_at: time, merge_status: 'checking')
+ mr_5 = mr_table.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature',
+ prepared_at: time, merge_status: 'preparing')
+
+ expect(mr_1.prepared_at).to be_nil
+ expect(mr_2.prepared_at).to be_nil
+ expect(mr_3.prepared_at.to_i).to eq(time.to_i)
+ expect(mr_4.prepared_at.to_i).to eq(time.to_i)
+ expect(mr_5.prepared_at.to_i).to eq(time.to_i)
+
+ test_worker.perform
+
+ expect(mr_1.reload.prepared_at.to_i).to eq(mr_1.created_at.to_i)
+ expect(mr_2.reload.prepared_at).to be_nil
+ expect(mr_3.reload.prepared_at.to_i).to eq(time.to_i)
+ expect(mr_4.reload.prepared_at.to_i).to eq(time.to_i)
+ expect(mr_5.reload.prepared_at.to_i).to eq(time.to_i)
+ end
+end
diff --git a/spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb b/spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb
deleted file mode 100644
index ff48b9ada90..00000000000
--- a/spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Prometheus::Queries::KnativeInvocationQuery do
- include PrometheusHelpers
-
- let(:project) { create(:project) }
- let(:serverless_func) { ::Serverless::Function.new(project, 'test-name', 'test-ns') }
- let(:client) { double('prometheus_client') }
-
- subject { described_class.new(client) }
-
- context 'verify queries' do
- before do
- create(:prometheus_metric,
- :common,
- identifier: :system_metrics_knative_function_invocation_count,
- query: 'sum(ceil(rate(istio_requests_total{destination_service_namespace="%{kube_namespace}", destination_service=~"%{function_name}.*"}[1m])*60))')
- end
-
- it 'has the query, but no data' do
- expect(client).to receive(:query_range).with(
- 'sum(ceil(rate(istio_requests_total{destination_service_namespace="test-ns", destination_service=~"test-name.*"}[1m])*60))',
- hash_including(:start_time, :end_time)
- )
-
- subject.query(serverless_func.id)
- end
- end
-end
diff --git a/spec/lib/gitlab/serverless/service_spec.rb b/spec/lib/gitlab/serverless/service_spec.rb
deleted file mode 100644
index 3400be5b48e..00000000000
--- a/spec/lib/gitlab/serverless/service_spec.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Serverless::Service do
- let(:cluster) { create(:cluster) }
- let(:environment) { create(:environment) }
- let(:attributes) do
- {
- 'apiVersion' => 'serving.knative.dev/v1alpha1',
- 'kind' => 'Service',
- 'metadata' => {
- 'creationTimestamp' => '2019-10-22T21:19:13Z',
- 'name' => 'kubetest',
- 'namespace' => 'project1-1-environment1'
- },
- 'spec' => {
- 'runLatest' => {
- 'configuration' => {
- 'build' => {
- 'template' => {
- 'name' => 'some-image'
- }
- }
- }
- }
- },
- 'environment_scope' => '*',
- 'cluster' => cluster,
- 'environment' => environment,
- 'podcount' => 0
- }
- end
-
- it 'exposes methods extracting data from the attributes hash' do
- service = Gitlab::Serverless::Service.new(attributes)
-
- expect(service.name).to eq('kubetest')
- expect(service.namespace).to eq('project1-1-environment1')
- expect(service.environment_scope).to eq('*')
- expect(service.podcount).to eq(0)
- expect(service.created_at).to eq(DateTime.parse('2019-10-22T21:19:13Z'))
- expect(service.image).to eq('some-image')
- expect(service.cluster).to eq(cluster)
- expect(service.environment).to eq(environment)
- end
-
- it 'returns nil for missing attributes' do
- service = Gitlab::Serverless::Service.new({})
-
- [:name, :namespace, :environment_scope, :cluster, :podcount, :created_at, :image, :description, :url, :environment].each do |method|
- expect(service.send(method)).to be_nil
- end
- end
-
- describe '#description' do
- it 'extracts the description in knative 7 format if available' do
- attributes = {
- 'spec' => {
- 'template' => {
- 'metadata' => {
- 'annotations' => {
- 'Description' => 'some description'
- }
- }
- }
- }
- }
- service = Gitlab::Serverless::Service.new(attributes)
-
- expect(service.description).to eq('some description')
- end
-
- it 'extracts the description in knative 5/6 format if 7 is not available' do
- attributes = {
- 'spec' => {
- 'runLatest' => {
- 'configuration' => {
- 'revisionTemplate' => {
- 'metadata' => {
- 'annotations' => {
- 'Description' => 'some description'
- }
- }
- }
- }
- }
- }
- }
- service = Gitlab::Serverless::Service.new(attributes)
-
- expect(service.description).to eq('some description')
- end
- end
-
- describe '#url' do
- let(:serverless_domain) { instance_double(::Serverless::Domain, uri: URI('https://proxy.example.com')) }
-
- it 'returns proxy URL if cluster has serverless domain' do
- # cluster = create(:cluster)
- knative = create(:clusters_applications_knative, :installed, cluster: cluster)
- create(:serverless_domain_cluster, clusters_applications_knative_id: knative.id)
- service = Gitlab::Serverless::Service.new(attributes.merge('cluster' => cluster))
-
- expect(::Serverless::Domain).to receive(:new).with(
- function_name: service.name,
- serverless_domain_cluster: service.cluster.serverless_domain,
- environment: service.environment
- ).and_return(serverless_domain)
-
- expect(service.url).to eq('https://proxy.example.com')
- end
-
- it 'returns the URL from the knative 6/7 format' do
- attributes = {
- 'status' => {
- 'url' => 'https://example.com'
- }
- }
- service = Gitlab::Serverless::Service.new(attributes)
-
- expect(service.url).to eq('https://example.com')
- end
-
- it 'returns the URL from the knative 5 format' do
- attributes = {
- 'status' => {
- 'domain' => 'example.com'
- }
- }
- service = Gitlab::Serverless::Service.new(attributes)
-
- expect(service.url).to eq('http://example.com')
- end
- end
-end
diff --git a/spec/migrations/queue_backfill_prepared_at_data_spec.rb b/spec/migrations/queue_backfill_prepared_at_data_spec.rb
new file mode 100644
index 00000000000..ac3ea2f59c5
--- /dev/null
+++ b/spec/migrations/queue_backfill_prepared_at_data_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe QueueBackfillPreparedAtData, feature_category: :code_review_workflow do
+ let!(:batched_migration) { described_class::MIGRATION }
+
+ it 'schedules a new batched migration' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+
+ migration.after -> {
+ expect(batched_migration).to have_scheduled_batched_migration(
+ table_name: :merge_requests,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL
+ )
+ }
+ end
+ end
+end
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index f6b13f4a93f..a95cb672d9e 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -17,10 +17,6 @@ RSpec.describe Clusters::Applications::Knative do
include_examples 'cluster application version specs', :clusters_applications_knative
include_examples 'cluster application initial status specs'
- describe 'associations' do
- it { is_expected.to have_one(:serverless_domain_cluster).class_name('::Serverless::DomainCluster').with_foreign_key('clusters_applications_knative_id').inverse_of(:knative) }
- end
-
describe 'default values' do
it { expect(subject.version).to eq(described_class::VERSION) }
end
@@ -249,12 +245,4 @@ RSpec.describe Clusters::Applications::Knative do
expect(subject.find_available_domain(domain.id)).to eq(domain)
end
end
-
- describe '#pages_domain' do
- let!(:sdc) { create(:serverless_domain_cluster, knative: knative) }
-
- it 'returns the the associated pages domain' do
- expect(knative.reload.pages_domain).to eq(sdc.pages_domain)
- end
- end
end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index ee198f73785..b218d4dce09 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe PagesDomain do
describe 'associations' do
it { is_expected.to belong_to(:project) }
- it { is_expected.to have_many(:serverless_domain_clusters) }
end
describe '.for_project' do
diff --git a/spec/models/serverless/domain_cluster_spec.rb b/spec/models/serverless/domain_cluster_spec.rb
deleted file mode 100644
index 487385c62c1..00000000000
--- a/spec/models/serverless/domain_cluster_spec.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Serverless::DomainCluster do
- subject { create(:serverless_domain_cluster) }
-
- describe 'default values' do
- subject(:domain_cluster) { build(:serverless_domain_cluster) }
-
- before do
- allow(::Serverless::Domain).to receive(:generate_uuid).and_return('randomtoken')
- end
-
- it { expect(domain_cluster.uuid).to eq('randomtoken') }
- end
-
- describe 'validations' do
- it { is_expected.to validate_presence_of(:pages_domain) }
- it { is_expected.to validate_presence_of(:knative) }
-
- it { is_expected.to validate_presence_of(:uuid) }
- it { is_expected.to validate_length_of(:uuid).is_equal_to(::Serverless::Domain::UUID_LENGTH) }
- it { is_expected.to validate_uniqueness_of(:uuid) }
-
- it 'validates that uuid has only hex characters' do
- subject = build(:serverless_domain_cluster, uuid: 'z1234567890123')
- subject.valid?
-
- expect(subject.errors[:uuid]).to include('only allows hex characters')
- end
- end
-
- describe 'associations' do
- it { is_expected.to belong_to(:pages_domain) }
- it { is_expected.to belong_to(:knative) }
- it { is_expected.to belong_to(:creator).optional }
- end
-
- describe 'uuid' do
- context 'when nil' do
- it 'generates a value by default' do
- attributes = build(:serverless_domain_cluster).attributes.merge(uuid: nil)
- expect(::Serverless::Domain).to receive(:generate_uuid).and_call_original
-
- subject = Serverless::DomainCluster.new(attributes)
-
- expect(subject.uuid).not_to be_blank
- end
- end
-
- context 'when not nil' do
- it 'does not override the existing value' do
- uuid = 'abcd1234567890'
- expect(build(:serverless_domain_cluster, uuid: uuid).uuid).to eq(uuid)
- end
- end
- end
-
- describe 'cluster' do
- it { is_expected.to respond_to(:cluster) }
- end
-
- describe 'domain' do
- it { is_expected.to respond_to(:domain) }
- end
-
- describe 'certificate' do
- it { is_expected.to respond_to(:certificate) }
- end
-
- describe 'key' do
- it { is_expected.to respond_to(:key) }
- end
-end
diff --git a/spec/models/serverless/domain_spec.rb b/spec/models/serverless/domain_spec.rb
deleted file mode 100644
index f997b28b149..00000000000
--- a/spec/models/serverless/domain_spec.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Serverless::Domain do
- let(:function_name) { 'test-function' }
- let(:pages_domain_name) { 'serverless.gitlab.io' }
- let(:pages_domain) { create(:pages_domain, :instance_serverless, domain: pages_domain_name) }
- let!(:serverless_domain_cluster) { create(:serverless_domain_cluster, uuid: 'abcdef12345678', pages_domain: pages_domain) }
- let(:valid_cluster_uuid) { 'aba1cdef123456f278' }
- let(:invalid_cluster_uuid) { 'aba1cdef123456f178' }
- let!(:environment) { create(:environment, name: 'test') }
-
- let(:valid_uri) { "https://#{function_name}-#{valid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
- let(:valid_fqdn) { "#{function_name}-#{valid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
- let(:invalid_uri) { "https://#{function_name}-#{invalid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
-
- shared_examples 'a valid Domain' do
- describe '#uri' do
- it 'matches valid URI' do
- expect(subject.uri.to_s).to eq valid_uri
- end
- end
-
- describe '#function_name' do
- it 'returns function_name' do
- expect(subject.function_name).to eq function_name
- end
- end
-
- describe '#serverless_domain_cluster' do
- it 'returns serverless_domain_cluster' do
- expect(subject.serverless_domain_cluster).to eq serverless_domain_cluster
- end
- end
-
- describe '#environment' do
- it 'returns environment' do
- expect(subject.environment).to eq environment
- end
- end
- end
-
- describe '.new' do
- context 'with valid arguments' do
- subject do
- described_class.new(
- function_name: function_name,
- serverless_domain_cluster: serverless_domain_cluster,
- environment: environment
- )
- end
-
- it_behaves_like 'a valid Domain'
- end
-
- context 'with invalid arguments' do
- subject do
- described_class.new(
- function_name: function_name,
- environment: environment
- )
- end
-
- it { is_expected.not_to be_valid }
- end
-
- context 'with nil cluster argument' do
- subject do
- described_class.new(
- function_name: function_name,
- serverless_domain_cluster: nil,
- environment: environment
- )
- end
-
- it { is_expected.not_to be_valid }
- end
- end
-
- describe '.generate_uuid' do
- it 'has 14 characters' do
- expect(described_class.generate_uuid.length).to eq(described_class::UUID_LENGTH)
- end
-
- it 'consists of only hexadecimal characters' do
- expect(described_class.generate_uuid).to match(/\A\h+\z/)
- end
-
- it 'uses random characters' do
- uuid = 'abcd1234567890'
-
- expect(SecureRandom).to receive(:hex).with(described_class::UUID_LENGTH / 2).and_return(uuid)
- expect(described_class.generate_uuid).to eq(uuid)
- end
- end
-end
diff --git a/spec/models/serverless/function_spec.rb b/spec/models/serverless/function_spec.rb
deleted file mode 100644
index 632f5eba5c3..00000000000
--- a/spec/models/serverless/function_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Serverless::Function do
- let(:project) { create(:project) }
- let(:func) { described_class.new(project, 'test', 'test-ns') }
-
- it 'has a proper id' do
- expect(func.id).to eql("#{project.id}/test/test-ns")
- expect(func.name).to eql("test")
- expect(func.namespace).to eql("test-ns")
- end
-
- it 'can decode an identifier' do
- f = described_class.find_by_id("#{project.id}/testfunc/dummy-ns")
-
- expect(f.name).to eql("testfunc")
- expect(f.namespace).to eql("dummy-ns")
- end
-end
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index f8cba8e9203..f10150b819a 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -60,9 +60,13 @@ RSpec.describe BlobPresenter do
describe '#pipeline_editor_path' do
context 'when blob is .gitlab-ci.yml' do
before do
- project.repository.create_file(user, '.gitlab-ci.yml', '',
- message: 'Add a ci file',
- branch_name: 'main')
+ project.repository.create_file(
+ user,
+ '.gitlab-ci.yml',
+ '',
+ message: 'Add a ci file',
+ branch_name: 'main'
+ )
end
let(:blob) { repository.blob_at('main', '.gitlab-ci.yml') }
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index dedfe6925c5..3f30127b07f 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -228,16 +228,20 @@ RSpec.describe Ci::BuildRunnerPresenter do
let(:pipeline) { build.pipeline }
it 'returns the correct refspecs' do
- is_expected.to contain_exactly("+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}",
- "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
+ is_expected.to contain_exactly(
+ "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}",
+ "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}"
+ )
end
context 'when ref is tag' do
let(:build) { create(:ci_build, :tag) }
it 'returns the correct refspecs' do
- is_expected.to contain_exactly("+refs/tags/#{build.ref}:refs/tags/#{build.ref}",
- "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
+ is_expected.to contain_exactly(
+ "+refs/tags/#{build.ref}:refs/tags/#{build.ref}",
+ "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}"
+ )
end
context 'when GIT_DEPTH is zero' do
@@ -246,9 +250,11 @@ RSpec.describe Ci::BuildRunnerPresenter do
end
it 'returns the correct refspecs' do
- is_expected.to contain_exactly('+refs/tags/*:refs/tags/*',
- '+refs/heads/*:refs/remotes/origin/*',
- "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
+ is_expected.to contain_exactly(
+ '+refs/tags/*:refs/tags/*',
+ '+refs/heads/*:refs/remotes/origin/*',
+ "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}"
+ )
end
end
end
@@ -273,10 +279,11 @@ RSpec.describe Ci::BuildRunnerPresenter do
end
it 'returns the correct refspecs' do
- is_expected
- .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
- '+refs/heads/*:refs/remotes/origin/*',
- '+refs/tags/*:refs/tags/*')
+ is_expected.to contain_exactly(
+ "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ '+refs/heads/*:refs/remotes/origin/*',
+ '+refs/tags/*:refs/tags/*'
+ )
end
end
@@ -284,8 +291,10 @@ RSpec.describe Ci::BuildRunnerPresenter do
let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) }
it 'returns the correct refspecs' do
- is_expected.to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
- "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
+ is_expected.to contain_exactly(
+ "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}"
+ )
end
end
end
@@ -301,9 +310,10 @@ RSpec.describe Ci::BuildRunnerPresenter do
end
it 'exposes the persistent pipeline ref' do
- is_expected
- .to contain_exactly("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
- "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
+ is_expected.to contain_exactly(
+ "+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}",
+ "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}"
+ )
end
end
end
@@ -327,16 +337,14 @@ RSpec.describe Ci::BuildRunnerPresenter do
context 'when there is a file variable to expand' do
before_all do
- create(:ci_variable, project: project,
- key: 'regular_var',
- value: 'value 1')
- create(:ci_variable, project: project,
- key: 'file_var',
- value: 'value 2',
- variable_type: :file)
- create(:ci_variable, project: project,
- key: 'var_with_variables',
- value: 'value 3 and $regular_var and $file_var and $undefined_var')
+ create(:ci_variable, project: project, key: 'regular_var', value: 'value 1')
+ create(:ci_variable, project: project, key: 'file_var', value: 'value 2', variable_type: :file)
+ create(
+ :ci_variable,
+ project: project,
+ key: 'var_with_variables',
+ value: 'value 3 and $regular_var and $file_var and $undefined_var'
+ )
end
it 'returns variables with expanded' do
@@ -353,16 +361,14 @@ RSpec.describe Ci::BuildRunnerPresenter do
context 'when there is a raw variable to expand' do
before_all do
- create(:ci_variable, project: project,
- key: 'regular_var',
- value: 'value 1')
- create(:ci_variable, project: project,
- key: 'raw_var',
- value: 'value 2',
- raw: true)
- create(:ci_variable, project: project,
- key: 'var_with_variables',
- value: 'value 3 and $regular_var and $raw_var and $undefined_var')
+ create(:ci_variable, project: project, key: 'regular_var', value: 'value 1')
+ create(:ci_variable, project: project, key: 'raw_var', value: 'value 2', raw: true)
+ create(
+ :ci_variable,
+ project: project,
+ key: 'var_with_variables',
+ value: 'value 3 and $regular_var and $raw_var and $undefined_var'
+ )
end
it 'returns expanded variables without expanding raws' do
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index 31aa4778d3c..6f40d3f5b48 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -125,9 +125,12 @@ RSpec.describe MergeRequestPresenter do
let_it_be(:issue_b) { create(:issue, project: project) }
let_it_be(:resource) do
- create(:merge_request,
- source_project: project, target_project: project,
- description: "Fixes #{issue_a.to_reference} Related #{issue_b.to_reference}")
+ create(
+ :merge_request,
+ source_project: project,
+ target_project: project,
+ description: "Fixes #{issue_a.to_reference} Related #{issue_b.to_reference}"
+ )
end
before_all do
diff --git a/spec/presenters/packages/detail/package_presenter_spec.rb b/spec/presenters/packages/detail/package_presenter_spec.rb
index 71ec3ee2d67..8caa70c988e 100644
--- a/spec/presenters/packages/detail/package_presenter_spec.rb
+++ b/spec/presenters/packages/detail/package_presenter_spec.rb
@@ -89,8 +89,7 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
let_it_be(:package) { create(:npm_package, :with_build, project: project) }
let_it_be(:package_file_build_info) do
- create(:package_file_build_info, package_file: package.package_files.first,
- pipeline: package.pipelines.first)
+ create(:package_file_build_info, package_file: package.package_files.first, pipeline: package.pipelines.first)
end
it 'returns details with package_file pipeline' do
diff --git a/spec/requests/api/internal/pages_spec.rb b/spec/requests/api/internal/pages_spec.rb
index 67f5b7f8ccb..1361498747d 100644
--- a/spec/requests/api/internal/pages_spec.rb
+++ b/spec/requests/api/internal/pages_spec.rb
@@ -76,94 +76,6 @@ RSpec.describe API::Internal::Pages, feature_category: :pages do
end
end
- context 'serverless domain' do
- let(:namespace) { create(:namespace, name: 'gitlab-org') }
- let(:project) { create(:project, namespace: namespace, name: 'gitlab-ce') }
- let(:environment) { create(:environment, project: project) }
- let(:pages_domain) { create(:pages_domain, domain: 'serverless.gitlab.io') }
- let(:knative_without_ingress) { create(:clusters_applications_knative) }
- let(:knative_with_ingress) { create(:clusters_applications_knative, external_ip: '10.0.0.1') }
-
- context 'without a knative ingress gateway IP' do
- let!(:serverless_domain_cluster) do
- create(
- :serverless_domain_cluster,
- uuid: 'abcdef12345678',
- pages_domain: pages_domain,
- knative: knative_without_ingress
- )
- end
-
- let(:serverless_domain) do
- create(
- :serverless_domain,
- serverless_domain_cluster: serverless_domain_cluster,
- environment: environment
- )
- end
-
- it 'responds with 204 no content' do
- query_host(serverless_domain.uri.host)
-
- expect(response).to have_gitlab_http_status(:no_content)
- expect(response.body).to be_empty
- end
- end
-
- context 'with a knative ingress gateway IP' do
- let!(:serverless_domain_cluster) do
- create(
- :serverless_domain_cluster,
- uuid: 'abcdef12345678',
- pages_domain: pages_domain,
- knative: knative_with_ingress
- )
- end
-
- let(:serverless_domain) do
- create(
- :serverless_domain,
- serverless_domain_cluster: serverless_domain_cluster,
- environment: environment
- )
- end
-
- it 'responds with 204 because of feature deprecation' do
- query_host(serverless_domain.uri.host)
-
- expect(response).to have_gitlab_http_status(:no_content)
- expect(response.body).to be_empty
-
- ##
- # Serverless serving and reverse proxy to Kubernetes / Knative has
- # been deprecated and disabled, as per
- # https://gitlab.com/gitlab-org/gitlab-pages/-/issues/467
- #
- # expect(response).to match_response_schema('internal/serverless/virtual_domain')
- # expect(json_response['certificate']).to eq(pages_domain.certificate)
- # expect(json_response['key']).to eq(pages_domain.key)
- #
- # expect(json_response['lookup_paths']).to eq(
- # [
- # {
- # 'source' => {
- # 'type' => 'serverless',
- # 'service' => "test-function.#{project.name}-#{project.id}-#{environment.slug}.#{serverless_domain_cluster.knative.hostname}",
- # 'cluster' => {
- # 'hostname' => serverless_domain_cluster.knative.hostname,
- # 'address' => serverless_domain_cluster.knative.external_ip,
- # 'port' => 443,
- # 'cert' => serverless_domain_cluster.certificate,
- # 'key' => serverless_domain_cluster.key
- # }
- # }
- # }
- # ]
- # )
- end
- end
- end
-
context 'custom domain' do
let(:namespace) { create(:namespace, name: 'gitlab-org') }
let(:project) { create(:project, namespace: namespace, name: 'gitlab-ce') }
diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb
deleted file mode 100644
index 1e71e45948c..00000000000
--- a/spec/serializers/cluster_application_entity_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ClusterApplicationEntity do
- describe '#as_json' do
- let(:application) { build(:clusters_applications_helm, version: '0.1.1') }
-
- subject { described_class.new(application).as_json }
-
- it 'has name' do
- expect(subject[:name]).to eq(application.name)
- end
-
- it 'has status' do
- expect(subject[:status]).to eq(:not_installable)
- end
-
- it 'has version' do
- expect(subject[:version]).to eq('0.1.1')
- end
-
- it 'has no status_reason' do
- expect(subject[:status_reason]).to be_nil
- end
-
- it 'has can_uninstall' do
- expect(subject[:can_uninstall]).to be_truthy
- end
-
- context 'non-helm application' do
- let(:application) { build(:clusters_applications_runner, version: '0.0.0') }
-
- it 'has update_available' do
- expect(subject[:update_available]).to be_truthy
- end
- end
-
- context 'when application is errored' do
- let(:application) { build(:clusters_applications_helm, :errored) }
-
- it 'has corresponded data' do
- expect(subject[:status]).to eq(:errored)
- expect(subject[:status_reason]).not_to be_nil
- expect(subject[:status_reason]).to eq(application.status_reason)
- end
- end
-
- context 'for ingress application' do
- let(:application) do
- build(
- :clusters_applications_ingress,
- :installed,
- external_ip: '111.222.111.222'
- )
- end
-
- it 'includes external_ip' do
- expect(subject[:external_ip]).to eq('111.222.111.222')
- end
- end
-
- context 'for knative application' do
- let(:pages_domain) { create(:pages_domain, :instance_serverless) }
- let(:application) { build(:clusters_applications_knative, :installed) }
-
- before do
- create(:serverless_domain_cluster, knative: application, pages_domain: pages_domain)
- end
-
- it 'includes available domains' do
- expect(subject[:available_domains].length).to eq(1)
- expect(subject[:available_domains].first).to eq(id: pages_domain.id, domain: pages_domain.domain)
- end
-
- it 'includes pages_domain' do
- expect(subject[:pages_domain]).to eq(id: pages_domain.id, domain: pages_domain.domain)
- end
- end
- end
-end
diff --git a/spec/serializers/cluster_entity_spec.rb b/spec/serializers/cluster_entity_spec.rb
index 2de27deeffe..ff1a9a4feac 100644
--- a/spec/serializers/cluster_entity_spec.rb
+++ b/spec/serializers/cluster_entity_spec.rb
@@ -41,19 +41,5 @@ RSpec.describe ClusterEntity do
expect(subject[:status_reason]).to be_nil
end
end
-
- context 'when no application has been installed' do
- let(:cluster) { create(:cluster, :instance) }
-
- subject { described_class.new(cluster, request: request).as_json[:applications] }
-
- it 'contains helm as not_installable' do
- expect(subject).not_to be_empty
-
- helm = subject[0]
- expect(helm[:name]).to eq('helm')
- expect(helm[:status]).to eq(:not_installable)
- end
- end
end
end
diff --git a/spec/serializers/cluster_serializer_spec.rb b/spec/serializers/cluster_serializer_spec.rb
index 7ec6d3c8bb8..cf102e11b90 100644
--- a/spec/serializers/cluster_serializer_spec.rb
+++ b/spec/serializers/cluster_serializer_spec.rb
@@ -34,13 +34,13 @@ RSpec.describe ClusterSerializer do
end
it 'serializes attrs correctly' do
- is_expected.to contain_exactly(:status, :status_reason, :applications)
+ is_expected.to contain_exactly(:status, :status_reason)
end
end
context 'when provider type is user' do
it 'serializes attrs correctly' do
- is_expected.to contain_exactly(:status, :status_reason, :applications)
+ is_expected.to contain_exactly(:status, :status_reason)
end
end
end
diff --git a/spec/services/serverless/associate_domain_service_spec.rb b/spec/services/serverless/associate_domain_service_spec.rb
deleted file mode 100644
index 2f45806589e..00000000000
--- a/spec/services/serverless/associate_domain_service_spec.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Serverless::AssociateDomainService do
- let_it_be(:sdc_pages_domain) { create(:pages_domain, :instance_serverless) }
- let_it_be(:sdc_cluster) { create(:cluster, :with_installed_helm, :provided_by_gcp) }
- let_it_be(:sdc_knative) { create(:clusters_applications_knative, cluster: sdc_cluster) }
- let_it_be(:sdc_creator) { create(:user) }
-
- let(:sdc) do
- create(:serverless_domain_cluster,
- knative: sdc_knative,
- creator: sdc_creator,
- pages_domain: sdc_pages_domain)
- end
-
- let(:knative) { sdc.knative }
- let(:creator) { sdc.creator }
- let(:pages_domain_id) { sdc.pages_domain_id }
-
- subject { described_class.new(knative, pages_domain_id: pages_domain_id, creator: creator) }
-
- context 'when the domain is unchanged' do
- let(:creator) { create(:user) }
-
- it 'does not update creator' do
- expect { subject.execute }.not_to change { sdc.reload.creator }
- end
- end
-
- context 'when domain is changed to nil' do
- let_it_be(:creator) { create(:user) }
- let_it_be(:pages_domain_id) { nil }
-
- it 'removes the association between knative and the domain' do
- expect { subject.execute }.to change { knative.reload.pages_domain }.from(sdc.pages_domain).to(nil)
- end
-
- it 'does not attempt to update creator' do
- expect { subject.execute }.not_to raise_error
- end
- end
-
- context 'when a new domain is associated' do
- let_it_be(:creator) { create(:user) }
- let_it_be(:pages_domain_id) { create(:pages_domain, :instance_serverless).id }
-
- it 'creates an association with the domain' do
- expect { subject.execute }.to change { knative.reload.pages_domain.id }
- .from(sdc.pages_domain.id)
- .to(pages_domain_id)
- end
-
- it 'updates creator' do
- expect { subject.execute }.to change { sdc.reload.creator }.from(sdc.creator).to(creator)
- end
- end
-
- context 'when knative is not authorized to use the pages domain' do
- let_it_be(:pages_domain_id) { create(:pages_domain).id }
-
- before do
- expect(knative).to receive(:available_domains).and_return(PagesDomain.none)
- end
-
- it 'sets pages_domain_id to nil' do
- expect { subject.execute }.to change { knative.reload.pages_domain }.from(sdc.pages_domain).to(nil)
- end
- end
-
- describe 'for new knative application' do
- let_it_be(:cluster) { create(:cluster, :with_installed_helm, :provided_by_gcp) }
-
- context 'when knative hostname is nil' do
- let(:knative) { build(:clusters_applications_knative, cluster: cluster, hostname: nil) }
-
- it 'sets hostname to a placeholder value' do
- expect { subject.execute }.to change { knative.hostname }.to('example.com')
- end
- end
-
- context 'when knative hostname exists' do
- let(:knative) { build(:clusters_applications_knative, cluster: cluster, hostname: 'hostname.com') }
-
- it 'does not change hostname' do
- expect { subject.execute }.not_to change { knative.hostname }
- end
- end
- end
-end