Cascading Settings

케스케이딩 설정 프레임워크는 그룹이 설정 값을 상속받는 것을 허용하여 (상위 그룹에서 하위 그룹으로) 및 인스턴스 수준의 응용 프로그램 설정에서 값을 상속받는 것을 핵심으로 합니다. 또한 프레임워크는 계층 구조에서 하위 그룹에 대한 설정 값을 강제 적용할 수 있도록 합니다.

현재 케스케이딩 설정은 NamespaceSetting 내에서만 정의될 수 있지만, 향후 다른 객체로 확장될 수 있습니다.

새 케스케이딩 설정 추가

설정은 기본적으로 케스케이딩되지 않습니다. 케스케이딩 설정을 정의하려면 다음 단계를 따르세요:

  1. NamespaceSetting 모델에서 cascading_attr 도우미 메서드를 사용하여 새 속성을 정의합니다. 하나의 줄에 여러 속성을 정의하려면 배열을 사용할 수 있습니다.

    class NamespaceSetting
      include CascadingNamespaceSettingAttribute
    
      cascading_attr :delayed_project_removal
    end
    
  2. 데이터베이스 열을 만듭니다.

    새로운 설정에는 다음 데이터베이스 마이그레이션 도우미를 사용할 수 있습니다. 이 도우미는 namespace_settingsapplication_settings 각각 두 개의 열을 만듭니다.

    class AddDelayedProjectRemovalCascadingSetting < Gitlab::Database::Migration[2.1]
      include Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings
    
      def up
        add_cascading_namespace_setting :delayed_project_removal, :boolean, default: false, null: false
      end
    
      def down
       remove_cascading_namespace_setting :delayed_project_removal
      end
    end
    

    기존 설정을 케스케이딩 설정으로 변환하는 경우에는 각각의 마이그레이션을 사용하여 열을 추가하고 기존 열을 변경해야 합니다. 필요에 따라 아래 사양을 사용하여 마이그레이션을 만듭니다:

    1. namespace_settings 테이블의 열:
      • delayed_project_removal: 기본값 없음. Null 값 허용. 원하는 열 유형 사용.
      • lock_delayed_project_removal: 부울 열. 기본 값은 false입니다. Null 값 허용되지 않음.
    2. application_settings 테이블의 열:
      • delayed_project_removal: namespace_settings에서 생성된 열과 일치하는 유형. 원하는 대로 기본값 설정. Null 값 허용되지 않음.
      • lock_delayed_project_removal: 부울 열. 기본 값은 false입니다. Null 값 허용되지 않음.

편의 메서드

cascading_attr 메서드를 사용하여 속성을 정의하면 여러 가지 편의 메서드가 자동으로 정의됩니다.

정의:

cascading_attr :delayed_project_removal

사용 가능한 편의 메서드:

  • delayed_project_removal
  • delayed_project_removal=
  • delayed_project_removal_locked?
  • delayed_project_removal_locked_by_ancestor?
  • delayed_project_removal_locked_by_application_setting?
  • delayed_project_removal? (부울 속성에만 해당)
  • delayed_project_removal_locked_ancestor (잠긴 네임스페이스 설정 개체 [namespace_id]를 반환)

속성 리더 메서드 (delayed_project_removal)

속성 리더 메서드 (delayed_project_removal)는 다음 기준을 사용하여 올바른 케스케이딩된 값을 반환합니다:

  1. 속성이 변경된 경우 변경된 값이 반환됩니다. 이를 통해 표준 Rails 유효성 검사기를 속성에 사용할 수 있지만 nil 값은 반드시 허용되어야 합니다.
  2. 잠긴 상위 항목 값이 반환됩니다.
  3. 잠긴 인스턴스 수준 응용 설정 값이 반환됩니다.
  4. 만약 nil이 아닌 경우, 이 네임스페이스의 속성이 반환됩니다.
  5. 값이 nil이 아닌 가장 가까운 상위 항목에서 값을 반환합니다.
  6. 인스턴스 수준 응용 설정이 반환됩니다.

_locked? 메서드

기본적으로 _locked? 메서드(delayed_project_removal_locked?)는 그룹 또는 응용 프로그램 설정의 조상이 속성을 잠그면 true를 반환합니다. 그룹이 속성을 잠근 경우에는 false를 반환합니다.

include_self: true가 지정된 경우에는 그룹이 속성을 잠갔을 때 true를 반환합니다. 예를 들어 프로젝트에서 속성이 잠겼는지 확인할 때 유용할 수 있습니다.

프론트엔드에서 케스케이딩 설정 표시하기

프론트엔드에서 케스케이딩 설정을 표시하는 데 사용할 수 있는 몇 가지 Rails 뷰 도우미, HAML 부분 및 JavaScript 함수가 있습니다.

Rails 뷰 도우미

cascading_namespace_setting_locked?

설정이 잠겨 있는지 확인하려면 _locked? 메서드로 전달됩니다.

인수 설명 유형 필수 (기본값)
attribute 설정의 이름입니다. 예: :delayed_project_removal String 또는 Symbol true
group 현재 그룹입니다. Group true
**args _locked? 메서드로 전달할 추가 인수   false

HAML 부분

_enforcement_checkbox.html.haml

강제 체크박스를 렌더링합니다.

로컬 설명 유형 필수 (기본값)
attribute 설정의 이름입니다. 예: :delayed_project_removal String 또는 Symbol true
group 현재 그룹입니다. Group true
form Rails FormBuilder 객체. ActionView::Helpers::FormBuilder true
setting_locked 상위 그룹 또는 관리자 설정에 의해 설정이 잠겼는지 여부. cascading_namespace_setting_locked?를 사용하여 계산됩니다. Boolean true
help_text 체크박스 아래에 표시되는 텍스트입니다. String false (하위 그룹은 이 설정을 변경할 수 없습니다.)

_setting_checkbox.html.haml

체크박스 설정의 레이블을 렌더링합니다.

로컬 설명 유형 필수 (기본값)
attribute 설정의 이름입니다. 예: :delayed_project_removal String 또는 Symbol true
group 현재 그룹입니다. Group true
form Rails FormBuilder 객체. ActionView::Helpers::FormBuilder true
setting_locked 상위 그룹 또는 관리자 설정에 의해 설정이 잠겼는지 여부. cascading_namespace_setting_locked?를 사용하여 계산됩니다. Boolean true
settings_path_helper 조상 설정으로의 경로를 생성하는 람다 함수. 예: settings_path_helper: -> (locked_ancestor) { edit_group_path(locked_ancestor, anchor: 'js-permissions-settings') } 람다 true
help_text 체크박스 아래에 표시되는 텍스트입니다. String false (nil)

_setting_label_fieldset.html.haml

fieldset 설정의 레이블을 렌더링합니다.

로컬 설명 유형 필수 (기본값)
attribute 설정의 이름입니다. 예: :delayed_project_removal String 또는 Symbol true
group 현재 그룹입니다. Group true
setting_locked 설정이 잠겼는지 여부. cascading_namespace_setting_locked?로 계산됩니다. Boolean true
settings_path_helper 조상 설정으로의 경로를 생성하는 람다 함수. 예: -> (locked_ancestor) { edit_group_path(locked_ancestor, anchor: 'js-permissions-settings') } 람다 true
help_text 체크박스 아래에 표시되는 텍스트입니다. String false (nil)

_lock_tooltips.html.haml

툴팁을 표시하는 데 사용되는 JavaScript를 초기화하는 데 필요한 마운트 요소를 렌더링합니다. 이 부분은 페이지당 한 번만 필요합니다.

JavaScript

initCascadingSettingsLockTooltips

툴팁을 표시하는 데 필요한 JavaScript를 초기화하고, 잠금 아이콘()에 마우스를 가져다 댔을 때 툴팁을 표시하는 기능을 초기화합니다. 이 함수는 페이지별 JavaScript에서 가져와 호출해야 합니다.

모두 결합하기

-# app/views/groups/edit.html.haml

= render 'shared/namespaces/cascading_settings/lock_tooltips'

- delayed_project_removal_locked = cascading_namespace_setting_locked?(:delayed_project_removal, @group)
- merge_method_locked = cascading_namespace_setting_locked?(:merge_method, @group)

= form_for @group do |f|
  .form-group{ data: { testid: 'delayed-project-removal-form-group' } }
    = render 'shared/namespaces/cascading_settings/setting_checkbox', attribute: :delayed_project_removal,
        group: @group,
        form: f,
        setting_locked: delayed_project_removal_locked,
        settings_path_helper: -> (locked_ancestor) { edit_group_path(locked_ancestor, anchor: 'js-permissions-settings') },
        help_text: s_('Settings|Projects will be permanently deleted after a 7-day delay. Inherited by subgroups.') do
      = s_('Settings|Enable delayed project deletion')
    = render 'shared/namespaces/cascading_settings/enforcement_checkbox',
        attribute: :delayed_project_removal,
        group: @group,
        form: f,
        setting_locked: delayed_project_removal_locked

  %fieldset.form-group
    = render 'shared/namespaces/cascading_settings/setting_label_fieldset', attribute: :merge_method,
        group: @group,
        setting_locked: merge_method_locked,
        settings_path_helper: -> (locked_ancestor) { edit_group_path(locked_ancestor, anchor: 'js-permissions-settings') },
        help_text: s_('Settings|Determine what happens to the commit history when you merge a merge request.') do
      = s_('Settings|Merge method')

    .gl-form-radio.custom-control.custom-radio
      = f.gitlab_ui_radio_component :merge_method, :merge, s_('Settings|Merge commit'), help_text: s_('Settings|Every merge creates a merge commit.'), radio_options: { disabled: merge_method_locked }

    .gl-form-radio.custom-control.custom-radio
      = f.gitlab_ui_radio_component :merge_method, :rebase_merge, s_('Settings|Merge commit with semi-linear history'), help_text: s_('Settings|Every merge creates a merge commit.'), radio_options: { disabled: merge_method_locked }

    .gl-form-radio.custom-control.custom-radio
      = f.gitlab_ui_radio_component :merge_method, :ff, s_('Settings|Fast-forward merge'), help_text: s_('Settings|No merge commits are created.'), radio_options: { disabled: merge_method_locked }

    = render 'shared/namespaces/cascading_settings/enforcement_checkbox',
      attribute: :merge_method,
      group: @group,
      form: f,
      setting_locked: merge_method_locked
// app/assets/javascripts/pages/groups/edit/index.js

import { initCascadingSettingsLockTooltips } from '~/namespaces/cascading_settings';

initCascadingSettingsLockTooltips();

Vue

cascading_lock_icon.vue

Local Description Type Required (default value)
ancestorNamespace 연결된 그룹의 조상에 대한 네임스페이스입니다. Object false (null)
isLockedByApplicationSettings 인스턴스에서 locked_by_application_settings에 설정된 경계 값을 나타내는 부울입니다. Boolean true
isLockedByGroupAncestor 그룹에 대해 locked_by_ancestor로 설정된 경계 값을 나타내는 부울입니다. Boolean true

Vue 사용하기

  1. Ruby 도우미에서 다음을 호출하여 Vue 구성 요소로 데이터를 전송해야 합니다. :replace_attribute_here를 원하는 대상 속성으로 교체해야 합니다.
 # 그룹에 대한 Ruby 도우미 메서드에서의 예제 호출
 cascading_settings_data = cascading_namespace_settings_tooltip_data(:replace_attribute_here, @group, method(:edit_group_path))[:tooltip_data]
 # 프로젝트에 대한 Ruby 도우미 메서드에서의 예제 호출
cascading_settings_data = project_cascading_namespace_settings_tooltip_data(:duo_features_enabled, project, method(:edit_group_path)).to_json
  1. Vue의 index.js 파일에서 데이터를 JSON 및 낙타 표기 형식으로 변환해야 합니다. 이렇게 하면 Vue에서 쉽게 사용할 수 있습니다.
let cascadingSettingsDataParsed;
try {
  cascadingSettingsDataParsed = convertObjectPropsToCamelCase(JSON.parse(cascadingSettingsData), {
    deep: true,
  });
} catch {
  cascadingSettingsDataParsed = null;
}
  1. Vue 구성 요소에서 provide/inject를 사용하거나 cascadingSettingsDataParsed 변수를 구성 요소에 전달해야 합니다. 또한 반환된 캐스케이딩 데이터가 null이거나 빈 객체인 경우 cascading-lock-icon 구성 요소를 표시하지 않기 위한 도우미 메서드가 있어야 합니다.
// ./ee/my_component.vue

<script>
export default {
  computed: {
    showCascadingIcon() {
      return (
        this.cascadingSettingsData &&
        Object.keys(this.cascadingSettingsData).length
      );
    },
  },
}
</script>

<template>
  <cascading-lock-icon
    v-if="showCascadingIcon"
    :is-locked-by-group-ancestor="cascadingSettingsData.lockedByAncestor"
    :is-locked-by-application-settings="cascadingSettingsData.lockedByApplicationSetting"
    :ancestor-namespace="cascadingSettingsData.ancestorNamespace"
    class="gl-ml-1"
  />
</template>

HAML 및 Vue를 지원하는 이유

새 프론트엔드 기능을 모두 Vue로 구축하고 최종적으로 HAML에서 기능을 빌드하는 것을 중단하는 것이 목표입니다. 그러나 여전히 HAML 프론트엔드 기능 중에는 계단식 설정을 활용하는 것이 있으므로 해당 구성 요소가 Vue로 이관될 때까지 initCascadingSettingsLockTooltips를 지원할 것입니다.