Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-01-30 21:09:38 +00:00
parent cd99e8611a
commit dd8c199e98
72 changed files with 3263 additions and 888 deletions

View File

@ -108,7 +108,7 @@ review-deploy:
- .review-workflow-base
- .review:rules:review-deploy
stage: deploy
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}dtzar/helm-kubectl:3.10.3
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}dtzar/helm-kubectl:3.9.3
needs:
- review-build-cng
- review-delete-deployment # We always want to start from a clean slate (i.e. no helm release, no k8s namespace)

View File

@ -2,25 +2,7 @@
# Cop supports --autocorrect.
Style/RedundantSelf:
Exclude:
- 'app/channels/awareness_channel.rb'
- 'app/controllers/application_controller.rb'
- 'app/finders/security/jobs_finder.rb'
- 'app/graphql/types/permission_types/base_permission_type.rb'
- 'app/models/abuse_report.rb'
- 'app/models/analytics/usage_trends/measurement.rb'
- 'app/models/application_record.rb'
- 'app/models/application_setting.rb'
- 'app/models/application_setting_implementation.rb'
- 'app/models/audit_event.rb'
- 'app/models/award_emoji.rb'
- 'app/models/board.rb'
- 'app/models/ci/application_record.rb'
- 'app/models/ci/bridge.rb'
- 'app/models/ci/build.rb'
- 'app/models/ci/build_metadata.rb'
- 'app/models/ci/build_runner_session.rb'
- 'app/models/ci/build_trace_chunk.rb'
- 'app/models/ci/deleted_object.rb'
- 'app/models/ci/group.rb'
- 'app/models/ci/job_artifact.rb'
- 'app/models/ci/job_token/project_scope_link.rb'

View File

@ -15,7 +15,7 @@ gem 'bundler-checksum', '~> 0.1.0', path: 'vendor/gems/bundler-checksum', requir
# https://gitlab.com/gitlab-org/gitlab/-/issues/375713
gem 'rails', '~> 6.1.7.1'
gem 'bootsnap', '~> 1.15.0', require: false
gem 'bootsnap', '~> 1.16.0', require: false
# Pin openssl to match the version bundled with our supported Rubies.
# See https://stdgems.org/openssl/#gem-version.
@ -174,9 +174,9 @@ gem 'seed-fu', '~> 2.3.7'
gem 'elasticsearch-model', '~> 7.2'
gem 'elasticsearch-rails', '~> 7.2', require: 'elasticsearch/rails/instrumentation'
gem 'elasticsearch-api', '7.13.3'
gem 'aws-sdk-core', '~> 3.168.4'
gem 'aws-sdk-core', '~> 3.169.0'
gem 'aws-sdk-cloudformation', '~> 1'
gem 'aws-sdk-s3', '~> 1.117.2'
gem 'aws-sdk-s3', '~> 1.118.0'
gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
gem 'typhoeus', '~> 1.4.0' # Used with Elasticsearch to support http keep-alive connections

View File

@ -35,11 +35,11 @@
{"name":"awesome_print","version":"1.9.2","platform":"ruby","checksum":"e99b32b704acff16d768b3468680793ced40bfdc4537eb07e06a4be11133786e"},
{"name":"awrence","version":"1.1.1","platform":"ruby","checksum":"9be584c97408ed92d5e1ca11740853646fe270de675f2f8dd44e8233226dfc97"},
{"name":"aws-eventstream","version":"1.2.0","platform":"ruby","checksum":"ffa53482c92880b001ff2fb06919b9bb82fd847cbb0fa244985d2ebb6dd0d1df"},
{"name":"aws-partitions","version":"1.674.0","platform":"ruby","checksum":"f96e70d85490bbabc2d4b911bad62412fa5e0a643701499e59f8e38d4ab69128"},
{"name":"aws-partitions","version":"1.695.0","platform":"ruby","checksum":"f48ded613316522f5e44905af9c029dc62b43b7acaa917d9322831029ed45174"},
{"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"},
{"name":"aws-sdk-core","version":"3.168.4","platform":"ruby","checksum":"2c9bf6cb0c19f9d23fe2a9d5eca15381b0b904d19f2dd7801d094528f8632a8c"},
{"name":"aws-sdk-kms","version":"1.61.0","platform":"ruby","checksum":"fe6f50aed34f38bd421e43fe997780c86beeecef2898573b30ad2467b73f572a"},
{"name":"aws-sdk-s3","version":"1.117.2","platform":"ruby","checksum":"2159b3cbc45fc4a129f178ce54770023684fad078ce5c0577e8005fe1143ebf6"},
{"name":"aws-sdk-core","version":"3.169.0","platform":"ruby","checksum":"81e75e70dfd4a17c55554b593ad2de5534b6cab9197cd8e278eb8b0a9ad4051b"},
{"name":"aws-sdk-kms","version":"1.62.0","platform":"ruby","checksum":"b9111c698d783f3f092dcc6a8b9b7e3f53f00e6e501bdc5a4409afdcaf411a1c"},
{"name":"aws-sdk-s3","version":"1.118.0","platform":"ruby","checksum":"85358b4e56a4b56bba0b8995127f1f6123929d9eb7007534925b359a4a0433db"},
{"name":"aws-sigv4","version":"1.5.1","platform":"ruby","checksum":"d68c87fff4ee843b4b92b23c7f31f957f254ec6eb064181f7119124aab8b8bb4"},
{"name":"azure-storage-blob","version":"2.0.3","platform":"ruby","checksum":"61b76118843c91776bd24bee22c74adafeb7c4bb3a858a325047dae3b59d0363"},
{"name":"azure-storage-common","version":"2.0.4","platform":"ruby","checksum":"608f4daab0e06b583b73dcffd3246ea39e78056de31630286b0cf97af7d6956b"},
@ -59,7 +59,7 @@
{"name":"bindata","version":"2.4.11","platform":"ruby","checksum":"c38e0c99ffcd80c10a0a7ae6c8586d2fe26bf245cbefac90bec8764523220f6a"},
{"name":"binding_ninja","version":"0.2.3","platform":"java","checksum":"bbcf70b211d6e397493bf57c249bbec6aaf28fa7dafeb78e447b1b2f0610484f"},
{"name":"binding_ninja","version":"0.2.3","platform":"ruby","checksum":"4a85550a0066ee4721506b4e150857486808e50c9ddfeed04bdc896bb61eca9d"},
{"name":"bootsnap","version":"1.15.0","platform":"ruby","checksum":"f246bb1152159098f5d5619b92e373c73db77769bf3e0c4b6336feeb934bc8d2"},
{"name":"bootsnap","version":"1.16.0","platform":"ruby","checksum":"f87410c00f69cd84a6e72a6c4bdba733f800d80d934f4315849d18ca9f288fed"},
{"name":"bootstrap_form","version":"4.2.0","platform":"ruby","checksum":"f578b3c900d2cf15fab641064d357318b29e285bd5fdf090f903727912889710"},
{"name":"browser","version":"5.3.1","platform":"ruby","checksum":"62745301701ff2c6c5d32d077bb12532b20be261929dcb52c6781ed0d5658b3c"},
{"name":"builder","version":"3.2.4","platform":"ruby","checksum":"99caf08af60c8d7f3a6b004029c4c3c0bdaebced6c949165fe98f1db27fbbc10"},

View File

@ -200,19 +200,19 @@ GEM
awesome_print (1.9.2)
awrence (1.1.1)
aws-eventstream (1.2.0)
aws-partitions (1.674.0)
aws-partitions (1.695.0)
aws-sdk-cloudformation (1.41.0)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
aws-sdk-core (3.168.4)
aws-sdk-core (3.169.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.61.0)
aws-sdk-kms (1.62.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.117.2)
aws-sdk-s3 (1.118.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
@ -244,7 +244,7 @@ GEM
rack (>= 0.9.0)
bindata (2.4.11)
binding_ninja (0.2.3)
bootsnap (1.15.0)
bootsnap (1.16.0)
msgpack (~> 1.2)
bootstrap_form (4.2.0)
actionpack (>= 5.0)
@ -1599,8 +1599,8 @@ DEPENDENCIES
autoprefixer-rails (= 10.2.5.1)
awesome_print
aws-sdk-cloudformation (~> 1)
aws-sdk-core (~> 3.168.4)
aws-sdk-s3 (~> 1.117.2)
aws-sdk-core (~> 3.169.0)
aws-sdk-s3 (~> 1.118.0)
babosa (~> 1.0.4)
base32 (~> 0.3.0)
batch-loader (~> 2.0.1)
@ -1608,7 +1608,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.9.1)
bootsnap (~> 1.15.0)
bootsnap (~> 1.16.0)
bootstrap_form (~> 4.2.0)
browser (~> 5.3.1)
bullet (~> 7.0.2)

View File

@ -3,6 +3,10 @@ import { GlButton, GlForm, GlFormGroup, GlFormInput, GlLink, GlSprintf } from '@
import { helpPagePath } from '~/helpers/help_page_helper';
import { isAbsolute } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import {
ENVIRONMENT_NEW_HELP_TEXT,
ENVIRONMENT_EDIT_HELP_TEXT,
} from 'ee_else_ce/environments/constants';
export default {
components: {
@ -13,6 +17,7 @@ export default {
GlLink,
GlSprintf,
},
inject: ['protectedEnvironmentSettingsPath'],
props: {
environment: {
required: true,
@ -34,9 +39,8 @@ export default {
},
i18n: {
header: __('Environments'),
helpMessage: __(
'Environments allow you to track deployments of your application. %{linkStart}More information%{linkEnd}.',
),
helpNewMessage: ENVIRONMENT_NEW_HELP_TEXT,
helpEditMessage: ENVIRONMENT_EDIT_HELP_TEXT,
nameLabel: __('Name'),
nameFeedback: __('This field is required'),
nameDisabledHelp: __("You cannot rename an environment after it's created."),
@ -62,6 +66,9 @@ export default {
isNameDisabled() {
return Boolean(this.environment.id);
},
showEditHelp() {
return this.isNameDisabled && Boolean(this.protectedEnvironmentSettingsPath);
},
valid() {
return {
name: this.visited.name && this.environment.name !== '',
@ -89,9 +96,14 @@ export default {
{{ $options.i18n.header }}
</h4>
<p class="gl-w-full">
<gl-sprintf :message="$options.i18n.helpMessage">
<gl-sprintf
:message="showEditHelp ? $options.i18n.helpEditMessage : $options.i18n.helpNewMessage"
>
<template #link="{ content }">
<gl-link :href="$options.helpPagePath">{{ content }}</gl-link>
<gl-link
:href="showEditHelp ? protectedEnvironmentSettingsPath : $options.helpPagePath"
>{{ content }}</gl-link
>
</template>
</gl-sprintf>
</p>

View File

@ -81,3 +81,9 @@ export const REVIEW_APP_MODAL_I18N = {
export const MIN_STALE_ENVIRONMENT_DATE = getDateInPast(new Date(), 3650); // 10 years ago
export const MAX_STALE_ENVIRONMENT_DATE = getDateInPast(new Date(), 7); // one week ago
export const ENVIRONMENT_NEW_HELP_TEXT = __(
'Environments allow you to track deployments of your application.%{linkStart} More information.%{linkEnd}',
);
export const ENVIRONMENT_EDIT_HELP_TEXT = ENVIRONMENT_NEW_HELP_TEXT;

View File

@ -7,6 +7,7 @@ export default (el) =>
provide: {
projectEnvironmentsPath: el.dataset.projectEnvironmentsPath,
updateEnvironmentPath: el.dataset.updateEnvironmentPath,
protectedEnvironmentSettingsPath: el.dataset.protectedEnvironmentSettingsPath,
},
render(h) {
return h(EditEnvironment, {

View File

@ -0,0 +1,37 @@
<script>
import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import CancelJobsModal from './cancel_jobs_modal.vue';
import { CANCEL_JOBS_MODAL_ID, CANCEL_JOBS_BUTTON_TEXT, CANCEL_BUTTON_TOOLTIP } from './constants';
export default {
name: 'CancelJobs',
components: {
GlButton,
CancelJobsModal,
},
directives: {
GlModal: GlModalDirective,
GlTooltip: GlTooltipDirective,
},
props: {
url: {
type: String,
required: true,
},
},
modalId: CANCEL_JOBS_MODAL_ID,
buttonText: CANCEL_JOBS_BUTTON_TEXT,
buttonTooltip: CANCEL_BUTTON_TOOLTIP,
};
</script>
<template>
<div>
<gl-button
v-gl-modal="$options.modalId"
v-gl-tooltip="$options.buttonTooltip"
variant="danger"
>{{ $options.buttonText }}</gl-button
>
<cancel-jobs-modal :modal-id="$options.modalId" :url="url" @confirm="$emit('confirm')" />
</div>
</template>

View File

@ -5,10 +5,9 @@ import axios from '~/lib/utils/axios_utils';
import { redirectTo } from '~/lib/utils/url_utility';
import {
CANCEL_TEXT,
STOP_JOBS_MODAL_ID,
STOP_JOBS_FAILED_TEXT,
STOP_JOBS_MODAL_TITLE,
STOP_JOBS_WARNING,
CANCEL_JOBS_FAILED_TEXT,
CANCEL_JOBS_MODAL_TITLE,
CANCEL_JOBS_WARNING,
PRIMARY_ACTION_TEXT,
} from './constants';
@ -21,6 +20,10 @@ export default {
type: String,
required: true,
},
modalId: {
type: String,
required: true,
},
},
methods: {
onSubmit() {
@ -32,7 +35,7 @@ export default {
})
.catch((error) => {
createAlert({
message: STOP_JOBS_FAILED_TEXT,
message: CANCEL_JOBS_FAILED_TEXT,
});
throw error;
});
@ -45,20 +48,19 @@ export default {
cancelAction: {
text: CANCEL_TEXT,
},
STOP_JOBS_WARNING,
STOP_JOBS_MODAL_ID,
STOP_JOBS_MODAL_TITLE,
CANCEL_JOBS_WARNING,
CANCEL_JOBS_MODAL_TITLE,
};
</script>
<template>
<gl-modal
:modal-id="$options.STOP_JOBS_MODAL_ID"
:modal-id="modalId"
:action-primary="$options.primaryAction"
:action-cancel="$options.cancelAction"
:title="$options.CANCEL_JOBS_MODAL_TITLE"
@primary="onSubmit"
>
<template #modal-title>{{ $options.STOP_JOBS_MODAL_TITLE }}</template>
{{ $options.STOP_JOBS_WARNING }}
{{ $options.CANCEL_JOBS_WARNING }}
</gl-modal>
</template>

View File

@ -1,11 +1,12 @@
import { s__, __ } from '~/locale';
export const STOP_JOBS_MODAL_ID = 'stop-jobs-modal';
export const STOP_JOBS_MODAL_TITLE = s__('AdminArea|Stop all jobs?');
export const STOP_JOBS_BUTTON_TEXT = s__('AdminArea|Stop all jobs');
export const CANCEL_JOBS_MODAL_ID = 'cancel-jobs-modal';
export const CANCEL_JOBS_MODAL_TITLE = s__('AdminArea|Are you sure?');
export const CANCEL_JOBS_BUTTON_TEXT = s__('AdminArea|Cancel all jobs');
export const CANCEL_BUTTON_TOOLTIP = s__('AdminArea|Cancel all running and pending jobs');
export const CANCEL_TEXT = __('Cancel');
export const STOP_JOBS_FAILED_TEXT = s__('AdminArea|Stopping jobs failed');
export const PRIMARY_ACTION_TEXT = s__('AdminArea|Stop jobs');
export const STOP_JOBS_WARNING = s__(
'AdminArea|Youre about to stop all jobs. This will halt all current jobs that are running.',
export const CANCEL_JOBS_FAILED_TEXT = s__('AdminArea|Canceling jobs failed');
export const PRIMARY_ACTION_TEXT = s__('AdminArea|Yes, proceed');
export const CANCEL_JOBS_WARNING = s__(
"AdminArea|You're about to cancel all running and pending jobs across this instance. Do you want to proceed?",
);

View File

@ -1,31 +1,32 @@
import Vue from 'vue';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import Translate from '~/vue_shared/translate';
import { STOP_JOBS_MODAL_ID } from './components/constants';
import StopJobsModal from './components/stop_jobs_modal.vue';
import { CANCEL_JOBS_MODAL_ID } from './components/constants';
import CancelJobsModal from './components/cancel_jobs_modal.vue';
Vue.use(Translate);
function initJobs() {
const buttonId = 'js-stop-jobs-button';
const stopJobsButton = document.getElementById(buttonId);
if (stopJobsButton) {
const cancelJobsButton = document.getElementById(buttonId);
if (cancelJobsButton) {
// eslint-disable-next-line no-new
new Vue({
el: `#js-${STOP_JOBS_MODAL_ID}`,
el: `#js-${CANCEL_JOBS_MODAL_ID}`,
components: {
StopJobsModal,
CancelJobsModal,
},
mounted() {
stopJobsButton.classList.remove('disabled');
stopJobsButton.addEventListener('click', () => {
this.$root.$emit(BV_SHOW_MODAL, STOP_JOBS_MODAL_ID, `#${buttonId}`);
cancelJobsButton.classList.remove('disabled');
cancelJobsButton.addEventListener('click', () => {
this.$root.$emit(BV_SHOW_MODAL, CANCEL_JOBS_MODAL_ID, `#${buttonId}`);
});
},
render(createElement) {
return createElement(STOP_JOBS_MODAL_ID, {
return createElement(CANCEL_JOBS_MODAL_ID, {
props: {
url: stopJobsButton.dataset.url,
url: cancelJobsButton.dataset.url,
modalId: CANCEL_JOBS_MODAL_ID,
},
});
},

View File

@ -15,7 +15,7 @@ class AwarenessChannel < ApplicationCable::Channel # rubocop:disable Gitlab/Name
private_class_method :refresh_interval
# keep clients updated about session membership
periodically every: self.refresh_interval do
periodically every: refresh_interval do
transmit payload
end

View File

@ -69,7 +69,7 @@ class ApplicationController < ActionController::Base
:masked_page_url
def self.endpoint_id_for_action(action_name)
"#{self.name}##{action_name}"
"#{name}##{action_name}"
end
rescue_from Encoding::CompatibilityError do |exception|

View File

@ -20,7 +20,7 @@ module Security
end
def initialize(pipeline:, job_types: [])
if self.instance_of?(Security::JobsFinder)
if instance_of?(Security::JobsFinder)
raise NotImplementedError, 'This is an abstract class, please instantiate its descendants'
end

View File

@ -28,7 +28,7 @@ module Types
end
def self.define_field_resolver_method(ability)
unless self.respond_to?(ability)
unless respond_to?(ability)
define_method ability.to_sym do |*args|
Ability.allowed?(context[:current_user], ability, object, args.to_h)
end

View File

@ -113,7 +113,7 @@ module GroupsHelper
end
def render_setting_to_allow_project_access_token_creation?(group)
group.root? && current_user.can?(:admin_setting_to_allow_project_access_token_creation, group)
group.root? && current_user.can?(:admin_setting_to_allow_resource_access_token_creation, group)
end
def show_thanks_for_purchase_alert?(quantity)

View File

@ -72,9 +72,9 @@ class AbuseReport < ApplicationRecord
end
def notify
return unless self.persisted?
return unless persisted?
AbuseReportMailer.notify(self.id).deliver_later
AbuseReportMailer.notify(id).deliver_later
end
private

View File

@ -24,8 +24,8 @@ module Analytics
scope :order_by_latest, -> { order(recorded_at: :desc) }
scope :with_identifier, ->(identifier) { where(identifier: identifier) }
scope :recorded_after, ->(date) { where(self.model.arel_table[:recorded_at].gteq(date)) if date.present? }
scope :recorded_before, ->(date) { where(self.model.arel_table[:recorded_at].lteq(date)) if date.present? }
scope :recorded_after, ->(date) { where(model.arel_table[:recorded_at].gteq(date)) if date.present? }
scope :recorded_before, ->(date) { where(model.arel_table[:recorded_at].lteq(date)) if date.present? }
def self.identifier_query_mapping
{

View File

@ -36,7 +36,7 @@ class ApplicationRecord < ActiveRecord::Base
end
def self.pluck_primary_key
where(nil).pluck(self.primary_key)
where(nil).pluck(primary_key)
end
def self.safe_ensure_unique(retries: 0)
@ -95,7 +95,7 @@ class ApplicationRecord < ActiveRecord::Base
end
def self.underscore
Gitlab::SafeRequestStore.fetch("model:#{self}:underscore") { self.to_s.underscore }
Gitlab::SafeRequestStore.fetch("model:#{self}:underscore") { to_s.underscore }
end
def self.where_exists(query)
@ -111,7 +111,7 @@ class ApplicationRecord < ActiveRecord::Base
end
def self.cached_column_list
self.column_names.map { |column_name| self.arel_table[column_name] }
column_names.map { |column_name| arel_table[column_name] }
end
def self.default_select_columns

View File

@ -303,11 +303,11 @@ module ApplicationSettingImplementation
end
def domain_allowlist_raw
array_to_string(self.domain_allowlist)
array_to_string(domain_allowlist)
end
def domain_denylist_raw
array_to_string(self.domain_denylist)
array_to_string(domain_denylist)
end
def domain_allowlist_raw=(values)
@ -323,7 +323,7 @@ module ApplicationSettingImplementation
end
def outbound_local_requests_allowlist_raw
array_to_string(self.outbound_local_requests_whitelist)
array_to_string(outbound_local_requests_whitelist)
end
def outbound_local_requests_allowlist_raw=(values)
@ -356,7 +356,7 @@ module ApplicationSettingImplementation
end
def protected_paths_raw
array_to_string(self.protected_paths)
array_to_string(protected_paths)
end
def protected_paths_raw=(values)
@ -364,7 +364,7 @@ module ApplicationSettingImplementation
end
def notes_create_limit_allowlist_raw
array_to_string(self.notes_create_limit_allowlist)
array_to_string(notes_create_limit_allowlist)
end
def notes_create_limit_allowlist_raw=(values)
@ -372,7 +372,7 @@ module ApplicationSettingImplementation
end
def users_get_by_id_limit_allowlist_raw
array_to_string(self.users_get_by_id_limit_allowlist)
array_to_string(users_get_by_id_limit_allowlist)
end
def users_get_by_id_limit_allowlist_raw=(values)
@ -536,7 +536,7 @@ module ApplicationSettingImplementation
def set_max_key_restriction!(key_type)
attr_name = "#{key_type}_key_restriction"
current = self.attributes[attr_name].to_i
current = attributes[attr_name].to_i
return if current == KeyRestrictionValidator::FORBIDDEN
@ -549,7 +549,7 @@ module ApplicationSettingImplementation
[min_size, current].max
end
self.assign_attributes({ attr_name => new_value })
assign_attributes({ attr_name => new_value })
end
def separate_allowlists(string_array)

View File

@ -55,7 +55,7 @@ class AuditEvent < ApplicationRecord
end
def initialize_details
return unless self.has_attribute?(:details)
return unless has_attribute?(:details)
self.details = {} if details&.nil?
end
@ -82,7 +82,7 @@ class AuditEvent < ApplicationRecord
def as_json(options = {})
super(options).tap do |json|
json['ip_address'] = self.ip_address.to_s
json['ip_address'] = ip_address.to_s
end
end
@ -114,10 +114,10 @@ class AuditEvent < ApplicationRecord
def parallel_persist
PARALLEL_PERSISTENCE_COLUMNS.each do |name|
original = self[name] || self.details[name]
original = self[name] || details[name]
next unless original
self[name] = self.details[name] = original
self[name] = details[name] = original
end
end

View File

@ -55,11 +55,11 @@ class AwardEmoji < ApplicationRecord
end
def downvote?
self.name == DOWNVOTE_NAME
name == DOWNVOTE_NAME
end
def upvote?
self.name == UPVOTE_NAME
name == UPVOTE_NAME
end
def url

View File

@ -18,7 +18,7 @@ class Board < ApplicationRecord
# Sort by case-insensitive name, then ascending ids. This ensures that we will always
# get the same list/first board no matter how many other boards are named the same
scope :order_by_name_asc, -> { order(arel_table[:name].lower.asc).order(id: :asc) }
scope :first_board, -> { where(id: self.order_by_name_asc.limit(1).select(:id)) }
scope :first_board, -> { where(id: order_by_name_asc.limit(1).select(:id)) }
def project_needed?
!group

View File

@ -13,7 +13,7 @@ module Ci
end
def self.model_name
@model_name ||= ActiveModel::Name.new(self, nil, self.name.demodulize)
@model_name ||= ActiveModel::Name.new(self, nil, name.demodulize)
end
end
end

View File

@ -80,9 +80,9 @@ module Ci
def inherit_status_from_downstream!(pipeline)
case pipeline.status
when 'success'
self.success!
success!
when 'failed', 'canceled', 'skipped'
self.drop!
drop!
else
false
end

View File

@ -386,21 +386,21 @@ module Ci
def detailed_status(current_user)
Gitlab::Ci::Status::Build::Factory
.new(self.present, current_user)
.new(present, current_user)
.fabricate!
end
def other_manual_actions
pipeline.manual_actions.reject { |action| action.name == self.name }
pipeline.manual_actions.reject { |action| action.name == name }
end
def other_scheduled_actions
pipeline.scheduled_actions.reject { |action| action.name == self.name }
pipeline.scheduled_actions.reject { |action| action.name == name }
end
def pages_generator?
Gitlab.config.pages.enabled &&
self.name == 'pages'
name == 'pages'
end
def runnable?
@ -456,7 +456,7 @@ module Ci
end
def retries_count
pipeline.builds.retried.where(name: self.name).count
pipeline.builds.retried.where(name: name).count
end
override :all_met_to_become_pending?
@ -529,19 +529,19 @@ module Ci
end
def deployment_job?
has_environment_keyword? && self.environment_action == 'start'
has_environment_keyword? && environment_action == 'start'
end
def stops_environment?
has_environment_keyword? && self.environment_action == 'stop'
has_environment_keyword? && environment_action == 'stop'
end
def environment_action
self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options
options.fetch(:environment, {}).fetch(:action, 'start') if options
end
def environment_tier_from_options
self.options.dig(:environment, :deployment_tier) if self.options
options.dig(:environment, :deployment_tier) if options
end
def environment_tier
@ -831,7 +831,7 @@ module Ci
end
def erased?
!self.erased_at.nil?
!erased_at.nil?
end
def artifacts_expired?
@ -864,8 +864,8 @@ module Ci
end
def keep_artifacts!
self.update(artifacts_expire_at: nil)
self.job_artifacts.update_all(expire_at: nil)
update(artifacts_expire_at: nil)
job_artifacts.update_all(expire_at: nil)
end
def artifacts_file_for_type(type)
@ -1096,11 +1096,11 @@ module Ci
# without actually loading data.
#
def all_queuing_entries
::Ci::PendingBuild.where(build_id: self.id)
::Ci::PendingBuild.where(build_id: id)
end
def all_runtime_metadata
::Ci::RunningBuild.where(build_id: self.id)
::Ci::RunningBuild.where(build_id: id)
end
def shared_runner_build?

View File

@ -68,7 +68,7 @@ module Ci
private
def set_build_project
self.project_id ||= self.build.project_id
self.project_id ||= build.project_id
end
def timeout_with_highest_precedence

View File

@ -20,7 +20,7 @@ module Ci
validates :url, public_url: { schemes: %w(https) }
def terminal_specification
wss_url = Gitlab::UrlHelpers.as_wss(Addressable::URI.escape(self.url))
wss_url = Gitlab::UrlHelpers.as_wss(Addressable::URI.escape(url))
return {} unless wss_url.present?
parsed_wss_url = URI.parse(wss_url)
@ -33,7 +33,7 @@ module Ci
port = port.presence || DEFAULT_PORT_NAME
service = service.presence || DEFAULT_SERVICE_NAME
parsed_url = URI.parse(Addressable::URI.escape(self.url))
parsed_url = URI.parse(Addressable::URI.escape(url))
parsed_url.path += "/proxy/#{service}/#{port}/#{path}"
subprotocols = subprotocols.presence || ::Ci::BuildRunnerSession::TERMINAL_SUBPROTOCOL

View File

@ -108,7 +108,7 @@ module Ci
raise ArgumentError, 'Offset is out of range' if offset > size || offset < 0
return if offset == size # Skip the following process as it doesn't affect anything
self.append(+"", offset)
append(+"", offset)
end
def append(new_data, offset)
@ -166,7 +166,7 @@ module Ci
raise FailedToPersistDataError, 'Modifed build trace chunk detected' if has_changes_to_save?
self.class.with_read_consistency(build) do
self.reset.then(&:unsafe_persist_data!)
reset.then(&:unsafe_persist_data!)
end
end
rescue FailedToObtainLockError
@ -205,9 +205,9 @@ module Ci
end
def <=>(other)
return unless self.build_id == other.build_id
return unless build_id == other.build_id
self.chunk_index <=> other.chunk_index
chunk_index <=> other.chunk_index
end
protected

View File

@ -21,7 +21,7 @@ module Ci
accumulator << record if record[:store_dir] && record[:file]
end
self.insert_all(attributes) if attributes.any?
insert_all(attributes) if attributes.any?
end
def delete_file_from_storage

View File

@ -1,129 +0,0 @@
# frozen_string_literal: true
module Clusters
module Applications
# DEPRECATED for removal in %14.0
# See https://gitlab.com/groups/gitlab-org/-/epics/4280
class CertManager < ApplicationRecord
VERSION = 'v0.10.1'
CRD_VERSION = '0.10'
self.table_name = 'clusters_applications_cert_managers'
include ::Clusters::Concerns::ApplicationCore
include ::Clusters::Concerns::ApplicationStatus
include ::Clusters::Concerns::ApplicationVersion
include ::Clusters::Concerns::ApplicationData
attribute :version, default: VERSION
after_initialize :set_default_email, if: :new_record?
validates :email, presence: true
def chart
'certmanager/cert-manager'
end
def repository
'https://charts.jetstack.io'
end
def install_command
helm_command_module::InstallCommand.new(
name: 'certmanager',
repository: repository,
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
chart: chart,
files: files.merge(cluster_issuer_file),
preinstall: pre_install_script,
postinstall: post_install_script
)
end
def uninstall_command
helm_command_module::DeleteCommand.new(
name: 'certmanager',
rbac: cluster.platform_kubernetes_rbac?,
files: files,
postdelete: post_delete_script
)
end
private
def set_default_email
self.email ||= self.cluster&.user&.email
end
def pre_install_script
[
apply_file("https://raw.githubusercontent.com/jetstack/cert-manager/release-#{CRD_VERSION}/deploy/manifests/00-crds.yaml"),
"kubectl label --overwrite namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} certmanager.k8s.io/disable-validation=true"
]
end
def post_install_script
[retry_command(apply_file('/data/helm/certmanager/config/cluster_issuer.yaml'))]
end
def retry_command(command)
Gitlab::Kubernetes::PodCmd.retry_command(command, times: 90)
end
def post_delete_script
[
delete_private_key,
delete_crd('certificates.certmanager.k8s.io'),
delete_crd('certificaterequests.certmanager.k8s.io'),
delete_crd('challenges.certmanager.k8s.io'),
delete_crd('clusterissuers.certmanager.k8s.io'),
delete_crd('issuers.certmanager.k8s.io'),
delete_crd('orders.certmanager.k8s.io')
].compact
end
def private_key_name
@private_key_name ||= cluster_issuer_content.dig('spec', 'acme', 'privateKeySecretRef', 'name')
end
def delete_private_key
return unless private_key_name.present?
args = %W(secret -n #{Gitlab::Kubernetes::Helm::NAMESPACE} #{private_key_name} --ignore-not-found)
Gitlab::Kubernetes::KubectlCmd.delete(*args)
end
def delete_crd(definition)
Gitlab::Kubernetes::KubectlCmd.delete("crd", definition, "--ignore-not-found")
end
def apply_file(filename)
Gitlab::Kubernetes::KubectlCmd.apply_file(filename)
end
def cluster_issuer_file
{
'cluster_issuer.yaml': cluster_issuer_yaml_content
}
end
def cluster_issuer_yaml_content
YAML.dump(cluster_issuer_content.deep_merge(cluster_issue_overlay))
end
def cluster_issuer_content
YAML.safe_load(File.read(cluster_issuer_file_path))
end
def cluster_issue_overlay
{ "spec" => { "acme" => { "email" => self.email } } }
end
def cluster_issuer_file_path
Rails.root.join('vendor', 'cert_manager', 'cluster_issuer.yaml')
end
end
end
end

View File

@ -14,7 +14,6 @@ module Clusters
APPLICATIONS = {
Clusters::Applications::Helm.application_name => Clusters::Applications::Helm,
Clusters::Applications::Ingress.application_name => Clusters::Applications::Ingress,
Clusters::Applications::CertManager.application_name => Clusters::Applications::CertManager,
Clusters::Applications::Crossplane.application_name => Clusters::Applications::Crossplane,
Clusters::Applications::Prometheus.application_name => Clusters::Applications::Prometheus,
Clusters::Applications::Runner.application_name => Clusters::Applications::Runner,
@ -57,7 +56,6 @@ module Clusters
has_one_cluster_application :helm
has_one_cluster_application :ingress
has_one_cluster_application :cert_manager
has_one_cluster_application :crossplane
has_one_cluster_application :prometheus
has_one_cluster_application :runner

View File

@ -12,6 +12,12 @@ module Ml
has_many :candidates, class_name: 'Ml::Candidate'
has_many :metadata, class_name: 'Ml::ExperimentMetadata'
scope :with_candidate_count, -> {
left_outer_joins(:candidates)
.select("ml_experiments.*, count(ml_candidates.id) as candidate_count")
.group(:id)
}
has_internal_id :iid, scope: :project
class << self

View File

@ -76,6 +76,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
with_scope :subject
condition(:resource_access_token_feature_available) { resource_access_token_feature_available? }
condition(:resource_access_token_creation_allowed) { resource_access_token_creation_allowed? }
condition(:resource_access_token_create_feature_available) { resource_access_token_create_feature_available? }
with_scope :subject
condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? }
@ -277,8 +278,8 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :destroy_resource_access_tokens
end
rule { can?(:admin_group) & resource_access_token_creation_allowed }.policy do
enable :admin_setting_to_allow_project_access_token_creation
rule { can?(:admin_group) & resource_access_token_create_feature_available }.policy do
enable :admin_setting_to_allow_resource_access_token_creation
end
rule { resource_access_token_creation_allowed & can?(:read_resource_access_tokens) }.policy do

View File

@ -4,7 +4,7 @@
- add_page_specific_style 'page_bundles/issuable_list'
.top-area
= render 'shared/issuable/nav', type: :merge_requests
= render 'shared/issuable/nav', type: :merge_requests, display_count: !@search_timeout_occurred
- if current_user
.nav-controls
- if @can_bulk_update
@ -16,4 +16,7 @@
- if @can_bulk_update
= render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :merge_requests
= render 'shared/merge_requests'
- if @search_timeout_occurred
= render 'shared/dashboard/search_timeout_occurred'
- else
= render 'shared/merge_requests'

View File

@ -3,4 +3,5 @@
#js-edit-environment{ data: { project_environments_path: project_environments_path(@project),
update_environment_path: project_environment_path(@project, @environment),
protected_environment_settings_path: (project_settings_ci_cd_path(@project, anchor: 'js-protected-environments-settings') if @project.licensed_feature_available?(:protected_environments)),
environment: environment_data(@environment)} }

View File

@ -1,7 +1,5 @@
---
table_name: clusters_applications_cert_managers
classes:
- Clusters::Applications::CertManager
feature_categories:
- kubernetes_management
description: "(Deprecated) A GitLab managed cert-manager installation in a Kubernetes cluster"

View File

@ -62,7 +62,7 @@ To enable the agent server on multiple nodes:
gitlab_rails['gitlab_kas_enabled'] = true
gitlab_rails['gitlab_kas_external_url'] = 'wss://gitlab.example.com/-/kubernetes-agent/'
gitlab_rails['gitlab_kas_internal_url'] = 'grpc://kas.internal.gitlab.example.com'
gitlab_rails['gitlab_kas_external_k8s_proxy_url'] = 'https://gitlab.example.com/-/kubernetes-agent/'
gitlab_rails['gitlab_kas_external_k8s_proxy_url'] = 'https://gitlab.example.com/-/kubernetes-agent/k8s-proxy/'
```
In this configuration:

View File

@ -105,7 +105,13 @@ When the consolidated form is:
See the section on [ETag mismatch errors](#etag-mismatch) for more details.
**In Omnibus installations:**
#### Use AWS S3
The following example uses AWS S3 to enable object storage for all supported services:
::Tabs
:::TabTitle Linux package (Omnibus)
1. Edit `/etc/gitlab/gitlab.rb` and add the following lines, substituting
the values you want:
@ -116,7 +122,7 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
gitlab_rails['object_store']['proxy_download'] = true
gitlab_rails['object_store']['connection'] = {
'provider' => 'AWS',
'region' => '<eu-central-1>',
'region' => 'eu-central-1',
'aws_access_key_id' => '<AWS_ACCESS_KEY_ID>',
'aws_secret_access_key' => '<AWS_SECRET_ACCESS_KEY>'
}
@ -125,62 +131,231 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
'server_side_encryption' => '<AES256 or aws:kms>',
'server_side_encryption_kms_key_id' => '<arn:aws:kms:xxx>'
}
gitlab_rails['object_store']['objects']['artifacts']['bucket'] = '<artifacts>'
gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = '<external-diffs>'
gitlab_rails['object_store']['objects']['lfs']['bucket'] = '<lfs-objects>'
gitlab_rails['object_store']['objects']['uploads']['bucket'] = '<uploads>'
gitlab_rails['object_store']['objects']['packages']['bucket'] = '<packages>'
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = '<dependency-proxy>'
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = '<terraform-state>'
gitlab_rails['object_store']['objects']['pages']['bucket'] = '<pages>'
gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'gitlab-artifacts'
gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'gitlab-mr-diffs'
gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'gitlab-lfs'
gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'gitlab-uploads'
gitlab_rails['object_store']['objects']['packages']['bucket'] = 'gitlab-packages'
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'gitlab-dependency-proxy'
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'gitlab-terraform-state'
gitlab_rails['object_store']['objects']['ci_secure_files']['bucket'] = 'gitlab-ci-secure-files'
gitlab_rails['object_store']['objects']['pages']['bucket'] = 'gitlab-pages'
```
If you're using AWS IAM profiles, omit the AWS access key and secret access
key/value pairs. For example:
If youre using [AWS IAM profiles](#using-amazon-instance-profiles), omit
the AWS access key and secret access key/value pairs. For example:
```ruby
gitlab_rails['object_store']['connection'] = {
'provider' => 'AWS',
'region' => 'eu-central-1',
'use_iam_profile' => true
}
```
1. Save the file and reconfigure GitLab:
```shell
sudo gitlab-ctl reconfigure
```
:::TabTitle Helm chart (Kubernetes)
1. Put the following content in a file named `object_storage.yaml` to be used as a
[Kubernetes Secret](https://docs.gitlab.com/charts/charts/globals.html#connection):
```yaml
provider: AWS
region: us-east-1
aws_access_key_id: <AWS_ACCESS_KEY_ID>
aws_secret_access_key: <AWS_SECRET_ACCESS_KEY>
```
If youre using [AWS IAM profiles](#using-amazon-instance-profiles), omit
the AWS access key and secret access key/value pairs. For example:
```yaml
provider: AWS
region: us-east-1
use_iam_profile: true
```
1. Create the Kubernetes Secret:
```shell
kubectl create secret generic -n <namespace> gitlab-object-storage --from-file=connection=object_storage.yaml
```
1. Export the Helm values:
```shell
helm get values gitlab > gitlab_values.yaml
```
1. Edit `gitlab_values.yaml`:
```yaml
global:
appConfig:
object_store:
enabled: false
proxy_download: true
storage_options: {}
# server_side_encryption:
# server_side_encryption_kms_key_id
connection:
secret: gitlab-object-storage
lfs:
enabled: true
proxy_download: true
bucket: gitlab-lfs
connection: {}
# secret:
# key:
artifacts:
enabled: true
proxy_download: true
bucket: gitlab-artifacts
connection: {}
# secret:
# key:
uploads:
enabled: true
proxy_download: true
bucket: gitlab-uploads
connection: {}
# secret:
# key:
packages:
enabled: true
proxy_download: true
bucket: gitlab-packages
connection: {}
externalDiffs:
enabled: true
when:
proxy_download: true
bucket: gitlab-mr-diffs
connection: {}
terraformState:
enabled: true
bucket: gitlab-terraform-state
connection: {}
ciSecureFiles:
enabled: true
bucket: gitlab-ci-secure-files
connection: {}
dependencyProxy:
enabled: true
proxy_download: true
bucket: gitlab-dependency-proxy
connection: {}
```
1. Save the file and apply the new values:
```shell
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
```
:::TabTitle Docker
1. Edit `docker-compose.yml`:
```yaml
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
# Consolidated object storage configuration
gitlab_rails['object_store']['enabled'] = true
gitlab_rails['object_store']['proxy_download'] = true
gitlab_rails['object_store']['connection'] = {
'provider' => 'AWS',
'region' => 'eu-central-1',
'aws_access_key_id' => '<AWS_ACCESS_KEY_ID>',
'aws_secret_access_key' => '<AWS_SECRET_ACCESS_KEY>'
}
# OPTIONAL: The following lines are only needed if server side encryption is required
gitlab_rails['object_store']['storage_options'] = {
'server_side_encryption' => '<AES256 or aws:kms>',
'server_side_encryption_kms_key_id' => '<arn:aws:kms:xxx>'
}
gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'gitlab-artifacts'
gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'gitlab-mr-diffs'
gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'gitlab-lfs'
gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'gitlab-uploads'
gitlab_rails['object_store']['objects']['packages']['bucket'] = 'gitlab-packages'
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'gitlab-dependency-proxy'
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'gitlab-terraform-state'
gitlab_rails['object_store']['objects']['ci_secure_files']['bucket'] = 'gitlab-ci-secure-files'
gitlab_rails['object_store']['objects']['pages']['bucket'] = 'gitlab-pages'
```
If youre using [AWS IAM profiles](#using-amazon-instance-profiles), omit
the AWS access key and secret access key/value pairs. For example:
```ruby
gitlab_rails['object_store']['connection'] = {
'provider' => 'AWS',
'region' => '<eu-central-1>',
'region' => 'eu-central-1',
'use_iam_profile' => true
}
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Save the file and restart GitLab:
**In installations from source:**
```shell
docker compose up -d
```
:::TabTitle Self-compiled (source)
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
```yaml
object_store:
enabled: true
proxy_download: true
connection:
provider: AWS
aws_access_key_id: <AWS_ACCESS_KEY_ID>
aws_secret_access_key: <AWS_SECRET_ACCESS_KEY>
region: <eu-central-1>
storage_options:
server_side_encryption: <AES256 or aws:kms>
server_side_encryption_key_kms_id: <arn:aws:kms:xxx>
objects:
artifacts:
bucket: <artifacts>
external_diffs:
bucket: <external-diffs>
lfs:
bucket: <lfs-objects>
uploads:
bucket: <uploads>
packages:
bucket: <packages>
dependency_proxy:
bucket: <dependency_proxy>
terraform_state:
bucket: <terraform>
pages:
bucket: <pages>
production: &base
object_store:
enabled: true
proxy_download: true
connection:
provider: AWS
aws_access_key_id: <AWS_ACCESS_KEY_ID>
aws_secret_access_key: <AWS_SECRET_ACCESS_KEY>
region: eu-central-1
storage_options:
server_side_encryption: <AES256 or aws:kms>
server_side_encryption_key_kms_id: <arn:aws:kms:xxx>
objects:
artifacts:
bucket: gitlab-artifacts
external_diffs:
bucket: gitlab-mr-diffs
lfs:
bucket: gitlab-lfs
uploads:
bucket: gitlab-uploads
packages:
bucket: gitlab-packages
dependency_proxy:
bucket: gitlab-dependency-proxy
terraform_state:
bucket: gitlab-terraform-state
ci_secure_files:
bucket: gitlab-ci-secure-files
pages:
bucket: gitlab-pages
```
If youre using [AWS IAM profiles](#using-amazon-instance-profiles), omit
the AWS access key and secret access key/value pairs. For example:
```yaml
connection:
provider: AWS
region: eu-central-1
use_iam_profile: true
```
1. Edit `/home/git/gitlab-workhorse/config.toml` and add or amend the following lines:
@ -194,7 +369,25 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
aws_secret_access_key = "<AWS_SECRET_ACCESS_KEY>"
```
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
If youre using [AWS IAM profiles](#using-amazon-instance-profiles), omit
the AWS access key and secret access key/value pairs. For example:
```yaml
[object_storage.s3]
use_iam_profile = true
```
1. Save the file and restart GitLab:
```shell
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
```
::EndTabs
#### Common parameters

View File

@ -57,8 +57,70 @@ The issue is created. You can view it by going to **Issues > List**.
For the title text, use the structure `active verb` + `noun`.
For example, `Create an issue`.
If you have several tasks on a page that share prerequisites, you can use the title
`Prerequisites` and link to it.
If several tasks on a page share prerequisites, you can create a separate
topic with the title `Prerequisites`.
### When more than one way exists to perform a task
If more than one way exists to perform a task in the UI, you should
document the primary way only.
However, sometimes you must document multiple ways to perform a task.
When this situation occurs:
- Introduce the task as usual. Then, for each way of performing the task, add a topic title.
- Nest the topic titles one level below the task topic title.
- List the tasks in descending order, with the most likely method first.
- Make the task titles as brief as possible. When possible,
use `infinitive` + `noun`.
Here is an example.
```markdown
# Change the default branch name
You can change the default branch name for the instance or group.
If the name is set for the instance, you can override it for a group.
## For the instance
Prerequisites:
- You must have at least the Maintainer role for the instance.
To change the default branch name for an instance:
1. Step.
1. Step.
## For the group
Prerequisites:
- You must have at least the Developer role for the group.
To change the default branch name for a group:
1. Step.
1. Step.
```
### To perform the task in the UI and API
Usually an API exists to perform the same task that you perform in the UI.
When this situation occurs:
- Do not use a separate heading for a one-sentence link to the API.
- Do not include API examples in the **Use GitLab** documentation. API examples
belong in the API documentation. If you have GraphQL examples, put them on
their own page, because the API documentation might move some day.
- Do not mention the API if you do not need to. Users can search for
the API documentation, and extra linking adds clutter.
- If someone feels strongly that you mention the API, at the end
of the UI task, add this sentence:
`To create an issue, you can also [use the API](link).`
## Task introductions

View File

@ -93,17 +93,25 @@ To check if a user failed to sign in because the ArkoseLabs challenge was not so
KQL: json.message:"Challenge was not solved" AND json.username:replace_username_here`
```
## QA tests caveat
## Allowlists
Several GitLab QA test suites need to sign in to the app to test its features. This can conflict
with Arkose Protect as it would identify QA users as being malicious because they are being run with
a headless browser. To work around this, ArkoseLabs has allowlisted the unique token
that serves as QA session's User Agent. While this doesn't guarantee that the session is not
flagged as malicious, the Arkose API returns a specific telltale when we verify the sign in
attempt's token. We are leveraging this telltale to bypass the verification step entirely so that the
test suite doesn't fail. This bypass is done in the `UserVerificationService` class.
To ensure end-to-end QA test suites can pass during staging and production, we've [allowlisted](https://developer.arkoselabs.com/docs/verify-api-v4#creating-allowlists-and-denylists) the [GITLAB_QA_USER_AGENT](https://start.1password.com/open/i?a=LKATQYUATRBRDHRRABEBH4RJ5Y&v=6gq44ckmq23vqk5poqunurdgay&i=u2wvs63affaxzi22gnfbjjw2zm&h=gitlab.1password.com). Each QA user receives an `ALLOWLIST` [risk category](https://developer.arkoselabs.com/docs/risk-score).
You can find the usage of the allowlist telltale in our [Arkose::VerifyResponse](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/arkose/verify_response.rb#L38) class.
## Feedback Job
To help Arkose improve their protection service, we created a daily background job to send them the list of blocked users by us.
This job is performed by the `Arkose::BlockedUsersReportWorker` class.
## Additional resources
<!-- markdownlint-disable MD044 -->
The [Anti-abuse team](https://about.gitlab.com/handbook/engineering/development/data-science/anti-abuse/#team-members) owns the ArkoseLabs Protect feature. You can join our ArkoseLabs/GitLab collaboration channel on Slack: [#ext-gitlab-arkose](https://gitlab.slack.com/archives/C02SGF6RLPQ).
<!-- markdownlint-enable MD044 -->
ArkoseLabs also maintains the following resources:
- [ArkoseLabs portal](https://portal.arkoselabs.com/)
- [ArkoseLabs Zendesk](https://support.arkoselabs.com/)
- [ArkoseLabs documentation](https://developer.arkoselabs.com/docs/documentation-guide)

View File

@ -43,7 +43,7 @@ GitLab supports the following OmniAuth providers.
Before you configure the OmniAuth provider,
configure the settings that are common for all providers.
Omnibus, Docker, and source | Helm chart | Description | Default value
Linux package, Docker, and self-compiled | Helm chart | Description | Default value
----------------------------|------------|-------------|-----------
`allow_single_sign_on` | `allowSingleSignOn` | List of providers that automatically create a GitLab account. The provider names are available in the **OmniAuth provider name** column in the [supported providers table](#supported-providers). | `false`, which means that signing in using your OmniAuth provider account without a pre-existing GitLab account is not allowed. You must create a GitLab account first, and then connect it to your OmniAuth provider account through your profile settings.
`auto_link_ldap_user` | `autoLinkLdapUser` | Creates an LDAP identity in GitLab for users that are created through an OmniAuth provider. You can enable this setting if you have [LDAP integration](../administration/auth/ldap/index.md) enabled. Requires the `uid` of the user to be the same in both LDAP and the OmniAuth provider. | `false`
@ -104,6 +104,27 @@ To change the OmniAuth settings:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
```
:::TabTitle Docker
1. Edit `docker-compose.yml`:
```yaml
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['omniauth_allow_single_sign_on'] = ['saml', 'twitter']
gitlab_rails['omniauth_auto_link_ldap_user'] = true
gitlab_rails['omniauth_block_auto_created_users'] = true
```
1. Save the file and restart GitLab:
```shell
docker compose up -d
```
:::TabTitle Self-compiled (source)
1. Edit `/home/git/gitlab/config/gitlab.yml`:

File diff suppressed because it is too large Load Diff

View File

@ -241,8 +241,6 @@ You can exclude specific directories from the backup by adding the environment v
- `repositories` (Git repositories data)
- `packages` (Packages)
All wikis are backed up as part of the `repositories` group. Non-existent wikis are skipped during a backup.
NOTE:
When [backing up and restoring Helm Charts](https://docs.gitlab.com/charts/architecture/backup-restore.html), there is an additional option `packages`, which refers to any packages managed by the GitLab [package registry](../user/packages/package_registry/index.md).
For more information see [command line arguments](https://docs.gitlab.com/charts/architecture/backup-restore.html#command-line-arguments).

View File

@ -461,9 +461,15 @@ for more details on what other GitLab CI patterns are demonstrated.
## Troubleshooting
### Clear NuGet cache
To improve performance, NuGet caches files related to a package. If you encounter issues, clear the
cache with this command:
```shell
nuget locals all -clear
```
### `Error publishing` or `Invalid Package: Failed metadata extraction error` messages when trying to publish NuGet packages in a Docker-based GitLab installation
Webhook requests to local network addresses are blocked to prevent the exploitation of internal web services. If you get `Error publishing` or `Invalid Package` messages when you try to publish NuGet packages, change your network settings to [allow webhook and service requests to the local network](../../../security/webhooks.md#allow-webhook-and-service-requests-to-local-network).

View File

@ -624,8 +624,9 @@ module API
merge_request = find_project_merge_request(params[:merge_request_iid])
# Merge request can not be merged
# because user dont have permissions to push into target branch
# Merge request can not be merged because the user doesn't have
# permissions to push into target branch
#
unauthorized! unless merge_request.can_be_merged_by?(current_user)
merge_when_pipeline_succeeds = to_boolean(params[:merge_when_pipeline_succeeds])

View File

@ -2584,6 +2584,9 @@ msgstr ""
msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
msgstr ""
msgid "AdminArea|Are you sure?"
msgstr ""
msgid "AdminArea|Blocked users"
msgstr ""
@ -2596,6 +2599,15 @@ msgstr ""
msgid "AdminArea|Breakdown of Non-Billable users"
msgstr ""
msgid "AdminArea|Cancel all jobs"
msgstr ""
msgid "AdminArea|Cancel all running and pending jobs"
msgstr ""
msgid "AdminArea|Canceling jobs failed"
msgstr ""
msgid "AdminArea|Components"
msgstr ""
@ -2668,15 +2680,6 @@ msgstr ""
msgid "AdminArea|Stop all jobs"
msgstr ""
msgid "AdminArea|Stop all jobs?"
msgstr ""
msgid "AdminArea|Stop jobs"
msgstr ""
msgid "AdminArea|Stopping jobs failed"
msgstr ""
msgid "AdminArea|Total Billable users"
msgstr ""
@ -2713,7 +2716,10 @@ msgstr ""
msgid "AdminArea|View latest users"
msgstr ""
msgid "AdminArea|Youre about to stop all jobs. This will halt all current jobs that are running."
msgid "AdminArea|Yes, proceed"
msgstr ""
msgid "AdminArea|You're about to cancel all running and pending jobs across this instance. Do you want to proceed?"
msgstr ""
msgid "AdminArea|active users + blocked users"
@ -15698,7 +15704,10 @@ msgstr ""
msgid "Environments Dashboard"
msgstr ""
msgid "Environments allow you to track deployments of your application. %{linkStart}More information%{linkEnd}."
msgid "Environments allow you to track deployments of your application. To protect this environment, go to the CI/CD settings %{linkStart}Protected environments%{linkEnd} section."
msgstr ""
msgid "Environments allow you to track deployments of your application.%{linkStart} More information.%{linkEnd}"
msgstr ""
msgid "Environments in %{name}"

View File

@ -552,6 +552,53 @@ RSpec.describe GroupsController, factory_default: :keep do
expect(assigns(:merge_requests)).to eq [merge_request_2, merge_request_1]
end
end
context 'rendering views' do
render_views
it 'displays MR counts in nav' do
get :merge_requests, params: { id: group.to_param }
expect(response.body).to have_content('Open 2 Merged 0 Closed 0 All 2')
expect(response.body).not_to have_content('Open Merged Closed All')
end
end
context 'when an ActiveRecord::QueryCanceled is raised' do
before do
allow_next_instance_of(Gitlab::IssuableMetadata) do |instance|
allow(instance).to receive(:data).and_raise(ActiveRecord::QueryCanceled)
end
end
it 'sets :search_timeout_occurred' do
get :merge_requests, params: { id: group.to_param }
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:search_timeout_occurred)).to eq(true)
end
it 'logs the exception' do
get :merge_requests, params: { id: group.to_param }
end
context 'rendering views' do
render_views
it 'shows error message' do
get :merge_requests, params: { id: group.to_param }
expect(response.body).to have_content('Too many results to display. Edit your search or add a filter.')
end
it 'does not display MR counts in nav' do
get :merge_requests, params: { id: group.to_param }
expect(response.body).to have_content('Open Merged Closed All')
expect(response.body).not_to have_content('Open 0 Merged 0 Closed 0 All 0')
end
end
end
end
describe 'DELETE #destroy' do

View File

@ -98,11 +98,6 @@ FactoryBot.define do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
factory :clusters_applications_cert_manager, class: 'Clusters::Applications::CertManager' do
email { 'admin@example.com' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
factory :clusters_applications_crossplane, class: 'Clusters::Applications::Crossplane' do
stack { 'gcp' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)

View File

@ -94,7 +94,6 @@ FactoryBot.define do
trait :with_all_applications do
application_helm factory: %i(clusters_applications_helm installed)
application_ingress factory: %i(clusters_applications_ingress installed)
application_cert_manager factory: %i(clusters_applications_cert_manager installed)
application_crossplane factory: %i(clusters_applications_crossplane installed)
application_prometheus factory: %i(clusters_applications_prometheus installed)
application_runner factory: %i(clusters_applications_runner installed)

View File

@ -28,8 +28,8 @@ RSpec.describe 'Admin Jobs', feature_category: :continuous_integration do
expect(page).to have_button 'Stop all jobs'
click_button 'Stop all jobs'
expect(page).to have_button 'Stop jobs'
expect(page).to have_content 'Stop all jobs?'
expect(page).to have_button 'Yes, proceed'
expect(page).to have_content 'Are you sure?'
end
end

View File

@ -14,6 +14,7 @@ const DEFAULT_OPTS = {
provide: {
projectEnvironmentsPath: '/projects/environments',
updateEnvironmentPath: '/proejcts/environments/1',
protectedEnvironmentSettingsPath: '/projects/1/settings/ci_cd',
},
propsData: { environment: { id: '0', name: 'foo', external_url: 'https://foo.example.com' } },
};

View File

@ -10,11 +10,14 @@ const DEFAULT_PROPS = {
cancelPath: '/cancel',
};
const PROVIDE = { protectedEnvironmentSettingsPath: '/projects/not_real/settings/ci_cd' };
describe('~/environments/components/form.vue', () => {
let wrapper;
const createWrapper = (propsData = {}) =>
mountExtended(EnvironmentForm, {
provide: PROVIDE,
propsData: {
...DEFAULT_PROPS,
...propsData,
@ -31,7 +34,7 @@ describe('~/environments/components/form.vue', () => {
});
it('links to documentation regarding environments', () => {
const link = wrapper.findByRole('link', { name: 'More information' });
const link = wrapper.findByRole('link', { name: 'More information.' });
expect(link.attributes('href')).toBe('/help/ci/environments/index.md');
});
@ -124,6 +127,10 @@ describe('~/environments/components/form.vue', () => {
expect(urlInput.element.value).toBe('');
});
it('does not show protected environment documentation', () => {
expect(wrapper.findByRole('link', { name: 'Protected environments' }).exists()).toBe(false);
});
});
describe('when an existing environment is being edited', () => {

View File

@ -11,7 +11,10 @@ jest.mock('~/lib/utils/url_utility');
jest.mock('~/flash');
const DEFAULT_OPTS = {
provide: { projectEnvironmentsPath: '/projects/environments' },
provide: {
projectEnvironmentsPath: '/projects/environments',
protectedEnvironmentSettingsPath: '/projects/not_real/settings/ci_cd',
},
};
describe('~/environments/components/new.vue', () => {

View File

@ -4,30 +4,27 @@ import { GlModal } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import { redirectTo } from '~/lib/utils/url_utility';
import StopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
import CancelJobsModal from '~/pages/admin/jobs/index/components/cancel_jobs_modal.vue';
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
redirectTo: jest.fn(),
}));
describe('stop_jobs_modal.vue', () => {
describe('Cancel jobs modal', () => {
const props = {
url: `${TEST_HOST}/stop_jobs_modal.vue/stopAll`,
url: `${TEST_HOST}/cancel_jobs_modal.vue/cancelAll`,
modalId: 'cancel-jobs-modal',
};
let wrapper;
beforeEach(() => {
wrapper = mount(StopJobsModal, { propsData: props });
});
afterEach(() => {
wrapper.destroy();
wrapper = mount(CancelJobsModal, { propsData: props });
});
describe('on submit', () => {
it('stops jobs and redirects to overview page', async () => {
const responseURL = `${TEST_HOST}/stop_jobs_modal.vue/jobs`;
it('cancels jobs and redirects to overview page', async () => {
const responseURL = `${TEST_HOST}/cancel_jobs_modal.vue/jobs`;
// TODO: We can't use axios-mock-adapter because our current version
// does not support responseURL
//
@ -47,10 +44,10 @@ describe('stop_jobs_modal.vue', () => {
expect(redirectTo).toHaveBeenCalledWith(responseURL);
});
it('displays error if stopping jobs failed', async () => {
it('displays error if canceling jobs failed', async () => {
Vue.config.errorHandler = () => {}; // silencing thrown error
const dummyError = new Error('stopping jobs failed');
const dummyError = new Error('canceling jobs failed');
// TODO: We can't use axios-mock-adapter because our current version
// does not support responseURL
//

View File

@ -0,0 +1,57 @@
import { GlButton } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { TEST_HOST } from 'helpers/test_constants';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import CancelJobs from '~/pages/admin/jobs/index/components/cancel_jobs.vue';
import CancelJobsModal from '~/pages/admin/jobs/index/components/cancel_jobs_modal.vue';
import {
CANCEL_JOBS_MODAL_ID,
CANCEL_BUTTON_TOOLTIP,
} from '~/pages/admin/jobs/index/components/constants';
describe('CancelJobs component', () => {
let wrapper;
const findCancelJobs = () => wrapper.findComponent(CancelJobs);
const findButton = () => wrapper.findComponent(GlButton);
const findModal = () => wrapper.findComponent(CancelJobsModal);
const createComponent = (props = {}) => {
wrapper = shallowMountExtended(CancelJobs, {
directives: {
GlModal: createMockDirective(),
GlTooltip: createMockDirective(),
},
propsData: {
url: `${TEST_HOST}/cancel_jobs_modal.vue/cancelAll`,
...props,
},
});
};
beforeEach(() => {
createComponent();
});
it('has correct inputs', () => {
expect(findCancelJobs().props().url).toBe(`${TEST_HOST}/cancel_jobs_modal.vue/cancelAll`);
});
it('has correct button variant', () => {
expect(findButton().props().variant).toBe('danger');
});
it('checks that button and modal are connected', () => {
const buttonModalDirective = getBinding(findButton().element, 'gl-modal');
const modalId = findModal().props('modalId');
expect(buttonModalDirective.value).toBe(CANCEL_JOBS_MODAL_ID);
expect(modalId).toBe(CANCEL_JOBS_MODAL_ID);
});
it('checks that tooltip is displayed', () => {
const buttonTooltipDirective = getBinding(findButton().element, 'gl-tooltip');
expect(buttonTooltipDirective.value).toBe(CANCEL_BUTTON_TOOLTIP);
});
});

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Types::Ci::RunnerArchitectureType do
RSpec.describe Types::Ci::RunnerArchitectureType, feature_category: :runner do
specify { expect(described_class.graphql_name).to eq('RunnerArchitecture') }
it 'exposes the expected fields' do

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Types::Ci::RunnerPlatformType do
RSpec.describe Types::Ci::RunnerPlatformType, feature_category: :runner_fleet do
specify { expect(described_class.graphql_name).to eq('RunnerPlatform') }
it 'exposes the expected fields' do

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Types::Ci::RunnerSetupType do
RSpec.describe Types::Ci::RunnerSetupType, feature_category: :runner_fleet do
specify { expect(described_class.graphql_name).to eq('RunnerSetup') }
it 'exposes the expected fields' do

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['CiRunner'] do
RSpec.describe GitlabSchema.types['CiRunner'], feature_category: :runner do
specify { expect(described_class.graphql_name).to eq('CiRunner') }
specify { expect(described_class).to require_graphql_authorizations(:read_runner) }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Types::Ci::RunnerUpgradeStatusEnum do
RSpec.describe Types::Ci::RunnerUpgradeStatusEnum, feature_category: :runner_fleet do
let(:model_only_enum_values) { %w[not_processed] }
let(:expected_graphql_source_values) do
Ci::RunnerVersion.statuses.keys - model_only_enum_values

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Types::Ci::RunnerWebUrlEdge do
RSpec.describe Types::Ci::RunnerWebUrlEdge, feature_category: :runner_fleet do
specify { expect(described_class.graphql_name).to eq('RunnerWebUrlEdge') }
it 'contains URL attributes' do

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerInstructions do
RSpec.describe Gitlab::Ci::RunnerInstructions, feature_category: :runner_fleet do
using RSpec::Parameterized::TableSyntax
let(:params) { {} }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerReleases do
RSpec.describe Gitlab::Ci::RunnerReleases, feature_category: :runner_fleet do
subject { described_class.instance }
let(:runner_releases_url) { 'http://testurl.com/runner_public_releases' }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
RSpec.describe Gitlab::Ci::RunnerUpgradeCheck, feature_category: :runner_fleet do
using RSpec::Parameterized::TableSyntax
subject(:instance) { described_class.new(gitlab_version, runner_releases) }

View File

@ -1,157 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Clusters::Applications::CertManager do
let(:cert_manager) { create(:clusters_applications_cert_manager) }
include_examples 'cluster application core specs', :clusters_applications_cert_manager
include_examples 'cluster application status specs', :clusters_applications_cert_manager
include_examples 'cluster application version specs', :clusters_applications_cert_manager
include_examples 'cluster application initial status specs'
describe 'default values' do
it { expect(cert_manager.version).to eq(described_class::VERSION) }
it { expect(cert_manager.email).to eq("admin@example.com") }
end
describe '#can_uninstall?' do
subject { cert_manager.can_uninstall? }
it { is_expected.to be_truthy }
end
describe '#install_command' do
let(:cert_email) { 'admin@example.com' }
let(:cluster_issuer_file) do
file_contents = <<~EOF
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: #{cert_email}
privateKeySecretRef:
name: letsencrypt-prod
http01: {}
EOF
{ "cluster_issuer.yaml": file_contents }
end
subject { cert_manager.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with cert_manager arguments' do
expect(subject.name).to eq('certmanager')
expect(subject.chart).to eq('certmanager/cert-manager')
expect(subject.repository).to eq('https://charts.jetstack.io')
expect(subject.version).to eq('v0.10.1')
expect(subject).to be_rbac
expect(subject.files).to eq(cert_manager.files.merge(cluster_issuer_file))
expect(subject.preinstall).to eq(
[
'kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.10/deploy/manifests/00-crds.yaml',
'kubectl label --overwrite namespace gitlab-managed-apps certmanager.k8s.io/disable-validation=true'
])
expect(subject.postinstall).to eq(
[
"for i in $(seq 1 90); do kubectl apply -f /data/helm/certmanager/config/cluster_issuer.yaml && s=0 && break || s=$?; sleep 1s; echo \"Retrying ($i)...\"; done; (exit $s)"
])
end
context 'for a specific user' do
let(:cert_email) { 'abc@xyz.com' }
before do
cert_manager.email = cert_email
end
it 'uses their email to register issuer with certificate provider' do
expect(subject.files).to eq(cert_manager.files.merge(cluster_issuer_file))
end
end
context 'on a non rbac enabled cluster' do
before do
cert_manager.cluster.platform_kubernetes.abac!
end
it { is_expected.not_to be_rbac }
end
context 'application failed to install previously' do
let(:cert_manager) { create(:clusters_applications_cert_manager, :errored, version: '0.0.1') }
it 'is initialized with the locked version' do
expect(subject.version).to eq('v0.10.1')
end
end
end
describe '#uninstall_command' do
subject { cert_manager.uninstall_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'is initialized with cert_manager arguments' do
expect(subject.name).to eq('certmanager')
expect(subject).to be_rbac
expect(subject.files).to eq(cert_manager.files)
end
it 'specifies a post delete command to remove custom resource definitions' do
expect(subject.postdelete).to eq(
[
'kubectl delete secret -n gitlab-managed-apps letsencrypt-prod --ignore-not-found',
'kubectl delete crd certificates.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd certificaterequests.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd challenges.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd clusterissuers.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd issuers.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd orders.certmanager.k8s.io --ignore-not-found'
])
end
context 'secret key name is not found' do
before do
allow(File).to receive(:read).and_call_original
expect(File).to receive(:read)
.with(Rails.root.join('vendor', 'cert_manager', 'cluster_issuer.yaml'))
.and_return('key: value')
end
it 'does not try and delete the secret' do
expect(subject.postdelete).to eq(
[
'kubectl delete crd certificates.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd certificaterequests.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd challenges.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd clusterissuers.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd issuers.certmanager.k8s.io --ignore-not-found',
'kubectl delete crd orders.certmanager.k8s.io --ignore-not-found'
])
end
end
end
describe '#files' do
let(:application) { cert_manager }
let(:values) { subject[:'values.yaml'] }
subject { application.files }
it 'includes cert_manager specific keys in the values.yaml file' do
expect(values).to include('ingressShim')
end
end
describe 'validations' do
it { is_expected.to validate_presence_of(:email) }
end
end

View File

@ -714,14 +714,13 @@ feature_category: :kubernetes_management do
context 'when all applications are created' do
let!(:helm) { create(:clusters_applications_helm, cluster: cluster) }
let!(:ingress) { create(:clusters_applications_ingress, cluster: cluster) }
let!(:cert_manager) { create(:clusters_applications_cert_manager, cluster: cluster) }
let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) }
let!(:runner) { create(:clusters_applications_runner, cluster: cluster) }
let!(:jupyter) { create(:clusters_applications_jupyter, cluster: cluster) }
let!(:knative) { create(:clusters_applications_knative, cluster: cluster) }
it 'returns a list of created applications' do
is_expected.to contain_exactly(helm, ingress, cert_manager, prometheus, runner, jupyter, knative)
is_expected.to contain_exactly(helm, ingress, prometheus, runner, jupyter, knative)
end
end

View File

@ -57,4 +57,21 @@ RSpec.describe Ml::Experiment do
it { is_expected.to be_empty }
end
end
describe '#with_candidate_count' do
let_it_be(:exp3) do
create(:ml_experiments, project: exp.project).tap do |e|
create_list(:ml_candidates, 3, experiment: e, user: nil)
create(:ml_candidates, experiment: exp2, user: nil)
end
end
subject { described_class.with_candidate_count.to_h { |e| [e.id, e.candidate_count] } }
it 'fetches the candidate count', :aggregate_failures do
expect(subject[exp.id]).to eq(0)
expect(subject[exp2.id]).to eq(1)
expect(subject[exp3.id]).to eq(3)
end
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe 'admin/application_settings/_jira_connect.html.haml' do
RSpec.describe 'admin/application_settings/_jira_connect.html.haml', feature_category: :integrations do
let_it_be(:admin) { create(:admin) }
let(:application_setting) { build(:application_setting) }

View File

@ -7,7 +7,7 @@ require (
github.com/BurntSushi/toml v1.2.1
github.com/FZambia/sentinel v1.1.1
github.com/alecthomas/chroma/v2 v2.4.0
github.com/aws/aws-sdk-go v1.44.184
github.com/aws/aws-sdk-go v1.44.189
github.com/disintegration/imaging v1.6.2
github.com/getsentry/raven-go v0.2.0
github.com/golang-jwt/jwt/v4 v4.4.3

View File

@ -542,8 +542,8 @@ github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.44.128/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.44.151/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.184 h1:/MggyE66rOImXJKl1HqhLQITvWvqIV7w1Q4MaG6FHUo=
github.com/aws/aws-sdk-go v1.44.184/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.189 h1:9PBrjndH1uL5AN8818qI3duhQ4hgkMuLvqkJlg9MRyk=
github.com/aws/aws-sdk-go v1.44.189/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehCazk=
github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw=