Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-10-05 18:12:53 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-10-05 18:12:53 +0300
commita84626f13d61d190b2db5e44caf71b22fc541276 (patch)
tree5cf591ce134ac0ad5b8c101e3518b2e49101b6ad /app
parentc9b0dfef1ba43a9e04264023b08c589bcb9eb397 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue22
-rw-r--r--app/assets/javascripts/error_tracking/queries/details.query.graphql1
-rw-r--r--app/assets/javascripts/issuable/components/csv_export_modal.vue69
-rw-r--r--app/assets/javascripts/issuable/components/csv_import_export_buttons.vue9
-rw-r--r--app/assets/javascripts/issuable/components/csv_import_modal.vue68
-rw-r--r--app/assets/javascripts/pages/admin/serverless/domains/index.js17
-rw-r--r--app/assets/stylesheets/pages/pages.scss12
-rw-r--r--app/controllers/admin/instance_review_controller.rb2
-rw-r--r--app/controllers/admin/serverless/domains_controller.rb78
-rw-r--r--app/controllers/groups/dependency_proxy_for_containers_controller.rb46
-rw-r--r--app/graphql/types/error_tracking/sentry_detailed_error_type.rb3
-rw-r--r--app/helpers/workhorse_helper.rb9
-rw-r--r--app/models/error_tracking/error.rb15
-rw-r--r--app/models/error_tracking/error_event.rb4
-rw-r--r--app/models/group.rb2
-rw-r--r--app/models/note.rb2
-rw-r--r--app/models/project.rb4
-rw-r--r--app/services/projects/update_pages_service.rb10
-rw-r--r--app/services/users/upsert_credit_card_validation_service.rb17
-rw-r--r--app/uploaders/dependency_proxy/file_uploader.rb1
-rw-r--r--app/views/admin/serverless/domains/_form.html.haml99
-rw-r--r--app/views/admin/serverless/domains/index.html.haml25
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml5
23 files changed, 181 insertions, 339 deletions
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 0a15cb56447..4adbf5362b7 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -128,6 +128,12 @@ export default {
lastReleaseLink() {
return `${this.error.externalBaseUrl}/releases/${this.error.lastReleaseVersion}`;
},
+ firstCommitLink() {
+ return `${this.error.externalBaseUrl}/-/commit/${this.error.firstReleaseVersion}`;
+ },
+ lastCommitLink() {
+ return `${this.error.externalBaseUrl}/-/commit/${this.error.lastReleaseVersion}`;
+ },
showStacktrace() {
return Boolean(this.stacktrace?.length);
},
@@ -394,7 +400,7 @@ export default {
<span>{{ error.gitlabIssuePath }}</span>
</gl-link>
</li>
- <li>
+ <li v-if="!error.integrated">
<strong class="bold">{{ __('Sentry event') }}:</strong>
<gl-link
v-track-event="trackClickErrorLinkToSentryOptions(error.externalUrl)"
@@ -409,15 +415,21 @@ export default {
<li v-if="error.firstReleaseVersion">
<strong class="bold">{{ __('First seen') }}:</strong>
<time-ago-tooltip :time="error.firstSeen" />
- <gl-link :href="firstReleaseLink" target="_blank">
- <span>{{ __('Release') }}: {{ error.firstReleaseVersion }}</span>
+ <gl-link v-if="error.integrated" :href="firstCommitLink">
+ {{ __('GitLab commit') }}: {{ error.firstReleaseVersion }}
+ </gl-link>
+ <gl-link v-else :href="firstReleaseLink" target="_blank">
+ {{ __('Release') }}: {{ error.firstReleaseVersion }}
</gl-link>
</li>
<li v-if="error.lastReleaseVersion">
<strong class="bold">{{ __('Last seen') }}:</strong>
<time-ago-tooltip :time="error.lastSeen" />
- <gl-link :href="lastReleaseLink" target="_blank">
- <span>{{ __('Release') }}: {{ error.lastReleaseVersion }}</span>
+ <gl-link v-if="error.integrated" :href="lastCommitLink">
+ {{ __('GitLab commit') }}: {{ error.lastReleaseVersion }}
+ </gl-link>
+ <gl-link v-else :href="lastReleaseLink" target="_blank">
+ {{ __('Release') }}: {{ error.lastReleaseVersion }}
</gl-link>
</li>
<li>
diff --git a/app/assets/javascripts/error_tracking/queries/details.query.graphql b/app/assets/javascripts/error_tracking/queries/details.query.graphql
index 593cbf2ae52..af386528f00 100644
--- a/app/assets/javascripts/error_tracking/queries/details.query.graphql
+++ b/app/assets/javascripts/error_tracking/queries/details.query.graphql
@@ -23,6 +23,7 @@ query errorDetails($fullPath: ID!, $errorId: ID!) {
gitlabCommit
gitlabCommitPath
gitlabIssuePath
+ integrated
}
}
}
diff --git a/app/assets/javascripts/issuable/components/csv_export_modal.vue b/app/assets/javascripts/issuable/components/csv_export_modal.vue
index 1c88f8dfdca..b0af3612e05 100644
--- a/app/assets/javascripts/issuable/components/csv_export_modal.vue
+++ b/app/assets/javascripts/issuable/components/csv_export_modal.vue
@@ -1,9 +1,14 @@
<script>
import { GlButton, GlModal, GlSprintf, GlIcon } from '@gitlab/ui';
+import { __, n__ } from '~/locale';
import { ISSUABLE_TYPE } from '../constants';
export default {
- name: 'CsvExportModal',
+ i18n: {
+ exportText: __(
+ 'The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment.',
+ ),
+ },
components: {
GlButton,
GlModal,
@@ -32,53 +37,39 @@ export default {
required: true,
},
},
- data() {
- return {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- issuableName: this.issuableType === ISSUABLE_TYPE.issues ? 'issues' : 'merge requests',
- };
+ computed: {
+ isIssue() {
+ return this.issuableType === ISSUABLE_TYPE.issues;
+ },
+ exportText() {
+ return this.isIssue ? __('Export issues') : __('Export merge requests');
+ },
+ issuableCountText() {
+ return this.isIssue
+ ? n__('1 issue selected', '%d issues selected', this.issuableCount)
+ : n__('1 merge request selected', '%d merge requests selected', this.issuableCount);
+ },
},
- issueableType: ISSUABLE_TYPE,
};
</script>
<template>
- <gl-modal :modal-id="modalId" body-class="gl-p-0!" data-qa-selector="export_issuable_modal">
- <template #modal-title>
- <gl-sprintf :message="__('Export %{name}')">
- <template #name>{{ issuableName }}</template>
- </gl-sprintf>
- </template>
+ <gl-modal
+ :modal-id="modalId"
+ body-class="gl-p-0!"
+ :title="exportText"
+ data-qa-selector="export_issuable_modal"
+ >
<div
- v-if="issuableCount > -1"
class="gl-justify-content-start gl-align-items-center gl-p-4 gl-border-b-solid gl-border-1 gl-border-gray-50"
>
<gl-icon name="check" class="gl-color-green-400" />
- <strong class="gl-m-3">
- <gl-sprintf
- v-if="issuableType === $options.issueableType.issues"
- :message="n__('1 issue selected', '%d issues selected', issuableCount)"
- >
- <template #issuableCount>{{ issuableCount }}</template>
- </gl-sprintf>
- <gl-sprintf
- v-else
- :message="n__('1 merge request selected', '%d merge requests selected', issuableCount)"
- >
- <template #issuableCount>{{ issuableCount }}</template>
- </gl-sprintf>
- </strong>
+ <strong class="gl-m-3">{{ issuableCountText }}</strong>
</div>
<div class="modal-text gl-px-4 gl-py-5">
- <gl-sprintf
- :message="
- __(
- `The CSV export will be created in the background. Once finished, it will be sent to %{strongStart}${email}%{strongEnd} in an attachment.`,
- )
- "
- >
- <template #strong="{ content }">
- <strong>{{ content }}</strong>
+ <gl-sprintf :message="$options.i18n.exportText">
+ <template #email>
+ <strong>{{ email }}</strong>
</template>
</gl-sprintf>
</div>
@@ -92,9 +83,7 @@ export default {
data-track-action="click_button"
:data-track-label="`export_${issuableType}_csv`"
>
- <gl-sprintf :message="__('Export %{name}')">
- <template #name>{{ issuableName }}</template>
- </gl-sprintf>
+ {{ exportText }}
</gl-button>
</template>
</gl-modal>
diff --git a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
index 4fdd094072c..269f720bac9 100644
--- a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
+++ b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
@@ -15,6 +15,8 @@ import CsvImportModal from './csv_import_modal.vue';
export default {
i18n: {
exportAsCsvButtonText: __('Export as CSV'),
+ importCsvText: __('Import CSV'),
+ importFromJiraText: __('Import from Jira'),
importIssuesText: __('Import issues'),
},
name: 'CsvImportExportButtons',
@@ -101,13 +103,16 @@ export default {
:text-sr-only="!showLabel"
:icon="importButtonIcon"
>
- <gl-dropdown-item v-gl-modal="importModalId">{{ __('Import CSV') }}</gl-dropdown-item>
+ <gl-dropdown-item v-gl-modal="importModalId">
+ {{ $options.i18n.importCsvText }}
+ </gl-dropdown-item>
<gl-dropdown-item
v-if="canEdit"
:href="projectImportJiraPath"
data-qa-selector="import_from_jira_link"
- >{{ __('Import from Jira') }}</gl-dropdown-item
>
+ {{ $options.i18n.importFromJiraText }}
+ </gl-dropdown-item>
</gl-dropdown>
</gl-button-group>
<csv-export-modal
diff --git a/app/assets/javascripts/issuable/components/csv_import_modal.vue b/app/assets/javascripts/issuable/components/csv_import_modal.vue
index c85efd60b8b..b72abe14ee1 100644
--- a/app/assets/javascripts/issuable/components/csv_import_modal.vue
+++ b/app/assets/javascripts/issuable/components/csv_import_modal.vue
@@ -1,23 +1,28 @@
<script>
-import { GlModal, GlSprintf, GlFormGroup, GlButton } from '@gitlab/ui';
+import { GlModal, GlFormGroup } from '@gitlab/ui';
import csrf from '~/lib/utils/csrf';
-import { ISSUABLE_TYPE } from '../constants';
+import { __, sprintf } from '~/locale';
export default {
- name: 'CsvImportModal',
+ i18n: {
+ maximumFileSizeText: __('The maximum file size allowed is %{size}.'),
+ importIssuesText: __('Import issues'),
+ uploadCsvFileText: __('Upload CSV file'),
+ mainText: __(
+ "Your issues will be imported in the background. Once finished, you'll get a confirmation email.",
+ ),
+ helpText: __(
+ 'It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected.',
+ ),
+ },
+ actionPrimary: {
+ text: __('Import issues'),
+ },
components: {
GlModal,
- GlSprintf,
GlFormGroup,
- GlButton,
},
inject: {
- issuableType: {
- default: '',
- },
- exportCsvPath: {
- default: '',
- },
importCsvIssuesPath: {
default: '',
},
@@ -31,11 +36,10 @@ export default {
required: true,
},
},
- data() {
- return {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- issuableName: this.issuableType === ISSUABLE_TYPE.issues ? 'issues' : 'merge requests',
- };
+ computed: {
+ maxFileSizeText() {
+ return sprintf(this.$options.i18n.maximumFileSizeText, { size: this.maxAttachmentSize });
+ },
},
methods: {
submitForm() {
@@ -47,34 +51,22 @@ export default {
</script>
<template>
- <gl-modal :modal-id="modalId" :title="__('Import issues')">
+ <gl-modal
+ :modal-id="modalId"
+ :title="$options.i18n.importIssuesText"
+ :action-primary="$options.actionPrimary"
+ @primary="submitForm"
+ >
<form ref="form" :action="importCsvIssuesPath" enctype="multipart/form-data" method="post">
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
- <p>
- {{
- __(
- "Your issues will be imported in the background. Once finished, you'll get a confirmation email.",
- )
- }}
- </p>
- <gl-form-group :label="__('Upload CSV file')" label-for="file">
+ <p>{{ $options.i18n.mainText }}</p>
+ <gl-form-group :label="$options.i18n.uploadCsvFileText" label-for="file">
<input id="file" type="file" name="file" accept=".csv,text/csv" />
</gl-form-group>
<p class="text-secondary">
- {{
- __(
- 'It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected.',
- )
- }}
- <gl-sprintf :message="__('The maximum file size allowed is %{size}.')"
- ><template #size>{{ maxAttachmentSize }}</template></gl-sprintf
- >
+ {{ $options.i18n.helpText }}
+ {{ maxFileSizeText }}
</p>
</form>
- <template #modal-footer>
- <gl-button category="primary" variant="confirm" @click="submitForm">{{
- __('Import issues')
- }}</gl-button>
- </template>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/pages/admin/serverless/domains/index.js b/app/assets/javascripts/pages/admin/serverless/domains/index.js
deleted file mode 100644
index 4fab7a1d9cb..00000000000
--- a/app/assets/javascripts/pages/admin/serverless/domains/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import initSettingsPanels from '~/settings_panels';
-
-// Initialize expandable settings panels
-initSettingsPanels();
-
-const domainCard = document.querySelector('.js-domain-cert-show');
-const domainForm = document.querySelector('.js-domain-cert-inputs');
-const domainReplaceButton = document.querySelector('.js-domain-cert-replace-btn');
-const domainSubmitButton = document.querySelector('.js-serverless-domain-submit');
-
-if (domainReplaceButton && domainCard && domainForm) {
- domainReplaceButton.addEventListener('click', () => {
- domainCard.classList.add('hidden');
- domainForm.classList.remove('hidden');
- domainSubmitButton.removeAttribute('disabled');
- });
-}
diff --git a/app/assets/stylesheets/pages/pages.scss b/app/assets/stylesheets/pages/pages.scss
index 93caa345f8a..ebaf875ad8f 100644
--- a/app/assets/stylesheets/pages/pages.scss
+++ b/app/assets/stylesheets/pages/pages.scss
@@ -55,16 +55,4 @@
border-bottom-right-radius: $border-radius-default;
border-top-right-radius: $border-radius-default;
}
-
- &.floating-status-badge {
- position: absolute;
- right: $gl-padding-24;
- bottom: $gl-padding-4;
- margin-bottom: 0;
- }
-}
-
-.form-control.has-floating-status-badge {
- position: relative;
- padding-right: 120px;
}
diff --git a/app/controllers/admin/instance_review_controller.rb b/app/controllers/admin/instance_review_controller.rb
index 88ca2c88aab..5567ffbdc84 100644
--- a/app/controllers/admin/instance_review_controller.rb
+++ b/app/controllers/admin/instance_review_controller.rb
@@ -3,7 +3,7 @@ class Admin::InstanceReviewController < Admin::ApplicationController
feature_category :devops_reports
def index
- redirect_to("#{::Gitlab::SubscriptionPortal::SUBSCRIPTIONS_URL}/instance_review?#{instance_review_params}")
+ redirect_to("#{Gitlab::SubscriptionPortal.subscriptions_instance_review_url}?#{instance_review_params}")
end
def instance_review_params
diff --git a/app/controllers/admin/serverless/domains_controller.rb b/app/controllers/admin/serverless/domains_controller.rb
deleted file mode 100644
index 99eea8c35b4..00000000000
--- a/app/controllers/admin/serverless/domains_controller.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-class Admin::Serverless::DomainsController < Admin::ApplicationController
- before_action :check_feature_flag
- before_action :domain, only: [:update, :verify, :destroy]
-
- feature_category :not_owned
-
- def index
- @domain = PagesDomain.instance_serverless.first_or_initialize
- end
-
- def create
- if PagesDomain.instance_serverless.exists?
- return redirect_to admin_serverless_domains_path, notice: _('An instance-level serverless domain already exists.')
- end
-
- @domain = PagesDomain.instance_serverless.create(create_params)
-
- if @domain.persisted?
- redirect_to admin_serverless_domains_path, notice: _('Domain was successfully created.')
- else
- render 'index'
- end
- end
-
- def update
- if domain.update(update_params)
- redirect_to admin_serverless_domains_path, notice: _('Domain was successfully updated.')
- else
- render 'index'
- end
- end
-
- def destroy
- if domain.serverless_domain_clusters.exists?
- return redirect_to admin_serverless_domains_path,
- status: :conflict,
- notice: _('Domain cannot be deleted while associated to one or more clusters.')
- end
-
- domain.destroy!
-
- redirect_to admin_serverless_domains_path,
- status: :found,
- notice: _('Domain was successfully deleted.')
- end
-
- def verify
- result = VerifyPagesDomainService.new(domain).execute
-
- if result[:status] == :success
- flash[:notice] = _('Successfully verified domain ownership')
- else
- flash[:alert] = _('Failed to verify domain ownership')
- end
-
- redirect_to admin_serverless_domains_path
- end
-
- private
-
- def domain
- @domain = PagesDomain.instance_serverless.find(params[:id])
- end
-
- def check_feature_flag
- render_404 unless Feature.enabled?(:serverless_domain)
- end
-
- def update_params
- params.require(:pages_domain).permit(:user_provided_certificate, :user_provided_key)
- end
-
- def create_params
- params.require(:pages_domain).permit(:domain, :user_provided_certificate, :user_provided_key)
- end
-end
diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
index f7dc552bd3e..e19b8ae35f8 100644
--- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb
+++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
@@ -5,11 +5,15 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
include DependencyProxy::GroupAccess
include SendFileUpload
include ::PackagesHelper # for event tracking
+ include WorkhorseRequest
before_action :ensure_group
- before_action :ensure_token_granted!
+ before_action :ensure_token_granted!, only: [:blob, :manifest]
before_action :ensure_feature_enabled!
+ before_action :verify_workhorse_api!, only: [:authorize_upload_blob, :upload_blob]
+ skip_before_action :verify_authenticity_token, only: [:authorize_upload_blob, :upload_blob]
+
attr_reader :token
feature_category :dependency_proxy
@@ -38,6 +42,8 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
end
def blob
+ return blob_via_workhorse if Feature.enabled?(:dependency_proxy_workhorse, group, default_enabled: :yaml)
+
result = DependencyProxy::FindOrCreateBlobService
.new(group, image, token, params[:sha]).execute
@@ -50,11 +56,47 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
end
end
+ def authorize_upload_blob
+ set_workhorse_internal_api_content_type
+
+ render json: DependencyProxy::FileUploader.workhorse_authorize(has_length: false)
+ end
+
+ def upload_blob
+ @group.dependency_proxy_blobs.create!(
+ file_name: blob_file_name,
+ file: params[:file],
+ size: params[:file].size
+ )
+
+ event_name = tracking_event_name(object_type: :blob, from_cache: false)
+ track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user)
+
+ head :ok
+ end
+
private
+ def blob_via_workhorse
+ blob = @group.dependency_proxy_blobs.find_by_file_name(blob_file_name)
+
+ if blob.present?
+ event_name = tracking_event_name(object_type: :blob, from_cache: true)
+ track_package_event(event_name, :dependency_proxy, namespace: group, user: auth_user)
+
+ send_upload(blob.file)
+ else
+ send_dependency(token, DependencyProxy::Registry.blob_url(image, params[:sha]), blob_file_name)
+ end
+ end
+
+ def blob_file_name
+ @blob_file_name ||= params[:sha].sub('sha256:', '') + '.gz'
+ end
+
def group
strong_memoize(:group) do
- Group.find_by_full_path(params[:group_id], follow_redirects: request.get?)
+ Group.find_by_full_path(params[:group_id], follow_redirects: true)
end
end
diff --git a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
index 79e789d3f8b..826ae61a1a3 100644
--- a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
+++ b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
@@ -13,6 +13,9 @@ module Types
field :id, GraphQL::Types::ID,
null: false,
description: 'ID (global ID) of the error.'
+ field :integrated, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Error tracking backend.'
field :sentry_id, GraphQL::Types::String,
method: :id,
null: false,
diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb
index 8785c4cdcbb..4862282bc73 100644
--- a/app/helpers/workhorse_helper.rb
+++ b/app/helpers/workhorse_helper.rb
@@ -41,6 +41,15 @@ module WorkhorseHelper
head :ok
end
+ def send_dependency(token, url, filename)
+ headers.store(*Gitlab::Workhorse.send_dependency(token, url))
+ headers['Content-Disposition'] =
+ ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename)
+ headers['Content-Type'] = 'application/gzip'
+
+ head :ok
+ end
+
def set_workhorse_internal_api_content_type
headers['Content-Type'] = Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
end
diff --git a/app/models/error_tracking/error.rb b/app/models/error_tracking/error.rb
index 39ecc487806..2d6a4694def 100644
--- a/app/models/error_tracking/error.rb
+++ b/app/models/error_tracking/error.rb
@@ -7,6 +7,14 @@ class ErrorTracking::Error < ApplicationRecord
has_many :events, class_name: 'ErrorTracking::ErrorEvent'
+ has_one :first_event,
+ -> { order(id: :asc) },
+ class_name: 'ErrorTracking::ErrorEvent'
+
+ has_one :last_event,
+ -> { order(id: :desc) },
+ class_name: 'ErrorTracking::ErrorEvent'
+
scope :for_status, -> (status) { where(status: status) }
validates :project, presence: true
@@ -90,7 +98,10 @@ class ErrorTracking::Error < ApplicationRecord
status: status,
tags: { level: nil, logger: nil },
external_url: external_url,
- external_base_url: external_base_url
+ external_base_url: external_base_url,
+ integrated: true,
+ first_release_version: first_event&.release,
+ last_release_version: last_event&.release
)
end
@@ -106,6 +117,6 @@ class ErrorTracking::Error < ApplicationRecord
# For compatibility with sentry integration
def external_base_url
- Gitlab::Routing.url_helpers.root_url
+ Gitlab::Routing.url_helpers.project_url(project)
end
end
diff --git a/app/models/error_tracking/error_event.rb b/app/models/error_tracking/error_event.rb
index 4de13de7e2e..686518a39fb 100644
--- a/app/models/error_tracking/error_event.rb
+++ b/app/models/error_tracking/error_event.rb
@@ -22,6 +22,10 @@ class ErrorTracking::ErrorEvent < ApplicationRecord
)
end
+ def release
+ payload.dig('release')
+ end
+
private
def build_stacktrace
diff --git a/app/models/group.rb b/app/models/group.rb
index 23b0d7e2197..77cdff68d49 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -276,7 +276,7 @@ class Group < Namespace
def dependency_proxy_image_prefix
# The namespace path can include uppercase letters, which
# Docker doesn't allow. The proxy expects it to be downcased.
- url = "#{web_url.downcase}#{DependencyProxy::URL_SUFFIX}"
+ url = "#{Gitlab::Routing.url_helpers.group_url(self).downcase}#{DependencyProxy::URL_SUFFIX}"
# Docker images do not include the protocol
url.partition('//').last
diff --git a/app/models/note.rb b/app/models/note.rb
index 2defa1d1ca5..37473518892 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -355,8 +355,6 @@ class Note < ApplicationRecord
end
def noteable_author?(noteable)
- return false unless ::Feature.enabled?(:show_author_on_note, project)
-
noteable.author == self.author
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 39ddec223e7..7ecd736b410 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2655,10 +2655,6 @@ class Project < ApplicationRecord
ProjectStatistics.increment_statistic(self, statistic, delta)
end
- def merge_requests_author_approval
- !!read_attribute(:merge_requests_author_approval)
- end
-
def ci_forward_deployment_enabled?
return false unless ci_cd_settings
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index dc75fe1014a..0000e713cb4 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -136,13 +136,11 @@ module Projects
def validate_outdated_sha!
return if latest?
- if Feature.enabled?(:pages_smart_check_outdated_sha, project, default_enabled: :yaml)
- # use pipeline_id in case the build is retried
- last_deployed_pipeline_id = project.pages_metadatum&.pages_deployment&.ci_build&.pipeline_id
+ # use pipeline_id in case the build is retried
+ last_deployed_pipeline_id = project.pages_metadatum&.pages_deployment&.ci_build&.pipeline_id
- return unless last_deployed_pipeline_id
- return if last_deployed_pipeline_id <= build.pipeline_id
- end
+ return unless last_deployed_pipeline_id
+ return if last_deployed_pipeline_id <= build.pipeline_id
raise InvalidStateError, 'build SHA is outdated for this ref'
end
diff --git a/app/services/users/upsert_credit_card_validation_service.rb b/app/services/users/upsert_credit_card_validation_service.rb
index 70a96b3ec6b..86b5b923418 100644
--- a/app/services/users/upsert_credit_card_validation_service.rb
+++ b/app/services/users/upsert_credit_card_validation_service.rb
@@ -7,6 +7,14 @@ module Users
end
def execute
+ @params = {
+ user_id: params.fetch(:user_id),
+ credit_card_validated_at: params.fetch(:credit_card_validated_at),
+ expiration_date: get_expiration_date(params),
+ last_digits: Integer(params.fetch(:credit_card_mask_number), 10),
+ holder_name: params.fetch(:credit_card_holder_name)
+ }
+
::Users::CreditCardValidation.upsert(@params)
ServiceResponse.success(message: 'CreditCardValidation was set')
@@ -16,5 +24,14 @@ module Users
Gitlab::ErrorTracking.track_exception(e, params: @params, class: self.class.to_s)
ServiceResponse.error(message: "Could not set CreditCardValidation: #{e.message}")
end
+
+ private
+
+ def get_expiration_date(params)
+ year = params.fetch(:credit_card_expiration_year)
+ month = params.fetch(:credit_card_expiration_month)
+
+ Date.new(year, month, -1) # last day of the month
+ end
end
end
diff --git a/app/uploaders/dependency_proxy/file_uploader.rb b/app/uploaders/dependency_proxy/file_uploader.rb
index 5154f180454..f0222d4cf06 100644
--- a/app/uploaders/dependency_proxy/file_uploader.rb
+++ b/app/uploaders/dependency_proxy/file_uploader.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class DependencyProxy::FileUploader < GitlabUploader
+ extend Workhorse::UploadPath
include ObjectStorage::Concern
before :cache, :set_content_type
diff --git a/app/views/admin/serverless/domains/_form.html.haml b/app/views/admin/serverless/domains/_form.html.haml
deleted file mode 100644
index a3e1ccc5d4a..00000000000
--- a/app/views/admin/serverless/domains/_form.html.haml
+++ /dev/null
@@ -1,99 +0,0 @@
-- form_name = 'js-serverless-domain-settings'
-- form_url = @domain.persisted? ? admin_serverless_domain_path(@domain.id, anchor: form_name) : admin_serverless_domains_path(anchor: form_name)
-- show_certificate_card = @domain.persisted? && @domain.errors.blank?
-= form_for @domain, url: form_url, html: { class: 'fieldset-form' } do |f|
- = form_errors(@domain)
-
- %fieldset
- - if @domain.persisted?
- - dns_record = "*.#{@domain.domain} CNAME #{Settings.pages.host}."
- - verification_record = "#{@domain.verification_domain} TXT #{@domain.keyed_verification_code}"
- .form-group.row
- .col-sm-6.position-relative
- = f.label :domain, _('Domain'), class: 'label-bold'
- = f.text_field :domain, class: 'form-control has-floating-status-badge', readonly: true
- .status-badge.floating-status-badge
- - text, status = @domain.unverified? ? [_('Unverified'), 'badge-danger'] : [_('Verified'), 'badge-success']
- .badge{ class: status }
- = text
- = link_to sprite_icon("redo"), verify_admin_serverless_domain_path(@domain.id), method: :post, class: "gl-button btn has-tooltip", title: _("Retry verification")
-
- .col-sm-6
- = f.label :serverless_domain_dns, _('DNS'), class: 'label-bold'
- .input-group
- = text_field_tag :serverless_domain_dns, dns_record , class: "monospace js-select-on-focus form-control", readonly: true
- .input-group-append
- = clipboard_button(target: '#serverless_domain_dns', class: 'btn-default input-group-text d-none d-sm-block')
-
- .col-sm-12.form-text.text-muted
- = _("To access this domain create a new DNS record")
-
- .form-group
- = f.label :serverless_domain_verification, _('Verification status'), class: 'label-bold'
- .input-group
- = text_field_tag :serverless_domain_verification, verification_record, class: "monospace js-select-on-focus form-control", readonly: true
- .input-group-append
- = clipboard_button(target: '#serverless_domain_verification', class: 'btn-default d-none d-sm-block')
- %p.form-text.text-muted
- - link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
- = _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration.").html_safe % { link_to_help: link_to_help }
-
- - else
- .form-group
- = f.label :domain, _('Domain'), class: 'label-bold'
- = f.text_field :domain, class: 'form-control'
-
- - if show_certificate_card
- .card.js-domain-cert-show
- .card-header
- = _('Certificate')
- .d-flex.justify-content-between.align-items-center.p-3
- %span
- = @domain.subject || _('missing')
- %button.gl-button.btn.btn-danger.btn-sm.js-domain-cert-replace-btn{ type: 'button' }
- = _('Replace')
-
- .js-domain-cert-inputs{ class: ('hidden' if show_certificate_card) }
- .form-group
- = f.label :user_provided_certificate, _('Certificate (PEM)'), class: 'label-bold'
- = f.text_area :user_provided_certificate, rows: 5, class: 'form-control', value: ''
- %span.form-text.text-muted
- = _("Upload a certificate for your domain with all intermediates")
- .form-group
- = f.label :user_provided_key, _('Key (PEM)'), class: 'label-bold'
- = f.text_area :user_provided_key, rows: 5, class: 'form-control', value: ''
- %span.form-text.text-muted
- = _("Upload a private key for your certificate")
-
- = f.submit @domain.persisted? ? _('Save changes') : _('Add domain'), class: "gl-button btn btn-confirm js-serverless-domain-submit", disabled: @domain.persisted?
- - if @domain.persisted?
- %button.gl-button.btn.btn-danger{ type: 'button', data: { toggle: 'modal', target: "#modal-delete-domain" } }
- = _('Delete domain')
-
--# haml-lint:disable NoPlainNodes
-- if @domain.persisted?
- - domain_attached = @domain.serverless_domain_clusters.count > 0
- .modal{ id: "modal-delete-domain", tabindex: -1 }
- .modal-dialog
- .modal-content
- .modal-header
- %h3.page-title= _('Delete serverless domain?')
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": "true" } &times;
-
- .modal-body
- - if domain_attached
- = _("You must disassociate %{domain} from all clusters it is attached to before deletion.").html_safe % { domain: "<code>#{@domain.domain}</code>".html_safe }
- - else
- = _("You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application.").html_safe % { domain: "<code>#{@domain.domain}</code>".html_safe }
-
- .modal-footer
- %a{ href: '#', data: { dismiss: 'modal' }, class: 'gl-button btn btn-default' }
- = _('Cancel')
-
- = link_to _('Delete domain'),
- admin_serverless_domain_path(@domain.id),
- title: _('Delete'),
- method: :delete,
- class: "gl-button btn btn-danger",
- disabled: domain_attached
diff --git a/app/views/admin/serverless/domains/index.html.haml b/app/views/admin/serverless/domains/index.html.haml
deleted file mode 100644
index c2b6baed4de..00000000000
--- a/app/views/admin/serverless/domains/index.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-- breadcrumb_title _("Operations")
-- page_title _("Operations")
-- @content_class = "limit-container-width" unless fluid_layout
-
--# normally expanded_by_default? is used here, but since this is the only panel
--# in this settings page, let's leave it always open by default
-- expanded = true
-
-%section.settings.as-serverless-domain.no-animate#js-serverless-domain-settings{ class: ('expanded' if expanded) }
- .settings-header
- %h4
- = _('Serverless domain')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
- %p
- = _('Set an instance-wide domain that will be available to all clusters when installing Knative.')
- .settings-content
- - if Gitlab.config.pages.enabled
- = render 'form'
- - else
- .card
- .card-header
- = s_('GitLabPages|Domains')
- .nothing-here-block
- = s_("GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it.")
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 13f2bf0019e..0a91194db51 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -257,11 +257,6 @@
= link_to ci_cd_admin_application_settings_path, title: _('CI/CD') do
%span
= _('CI/CD')
- - if Feature.enabled?(:serverless_domain)
- = nav_link(path: 'application_settings#operations') do
- = link_to admin_serverless_domains_path, title: _('Operations') do
- %span
- = _('Operations')
= nav_link(path: 'application_settings#reporting') do
= link_to reporting_admin_application_settings_path, title: _('Reporting') do
%span