Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
cd99e8611a
commit
dd8c199e98
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
6
Gemfile
6
Gemfile
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
|
|
|
|||
16
Gemfile.lock
16
Gemfile.lock
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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, {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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|You’re 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?",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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)} }
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 you’re 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 you’re 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 you’re 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 you’re 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 you’re 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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|You’re 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}"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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' } },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) { {} }
|
||||
|
|
|
|||
|
|
@ -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' }
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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=
|
||||
|
|
|
|||
Loading…
Reference in New Issue