- 새로운 통합 추가
- 구성 테스트 정의
- 프론트엔드 폼 사용자 정의
- REST API에서 통합 노출
- 통합의 가용성
- 문서화
- 테스팅
- 국제화
- 통합 폐지 및 삭제
- 지속적인 마이그레이션 및 리팩터링
- 통합 예시
통합 개발 지침
이 페이지는 GitLab 통합을 구현하기 위한 개발 지침을 제공합니다. 이는 주요 레일즈 프로젝트의 일부입니다.
또한 통합에 대한 전략에 대한 개요를 보려면 방향 페이지를 참조하세요.
이 안내서는 진행 중인 작업입니다. 오래된 정보를 확인하거나 업데이트된 정보를 발견하면 언제든지 @gitlab-org/manage/import-and-integrate
을 ping할 수 있습니다.
새로운 통합 추가
통합 정의
-
Integration
을 확장한 새로운 모델을app/models/integrations
에 추가하십시오.- 예를 들어,
app/models/integrations/foo_bar.rb
에Integrations::FooBar
와 같은 모델을 추가하십시오. - 특정 유형의 통합의 경우 이러한 기본 클래스에서 작성할 수도 있습니다:
Integrations::BaseChatNotification
Integrations::BaseCi
Integrations::BaseIssueTracker
Integrations::BaseMonitoring
Integrations::BaseSlashCommands
Integrations::BaseThirdPartyWiki
- 주로 외부 서비스로 HTTP 호출을 트리거하는 통합의 경우
Integrations::HasWebHook
concern을 사용할 수도 있습니다. 이를 통해 webhook functionality를 GitLab에서ServiceHook
모델을 통해 재사용하고 통합 설정에서 볼 수 있는 요청 로그를 자동으로 기록합니다.
- 예를 들어,
- 통합의 underscored 이름(
'foo_bar'
)을Integration::INTEGRATION_NAMES
에 추가하십시오. -
Project
에서 통합을 연관시킵니다:has_one :foo_bar_integration, class_name: 'Integrations::FooBar'
필드 정의
통합은 Integration.field
클래스 메서드를 사용하여 구성을 저장하는 임의의 필드를 정의할 수 있습니다.
값은 integrations.encrypted_properties
열에 암호화된 JSON 해시로 저장됩니다.
예를 들어:
module Integrations
class FooBar < Integration
field :url
field :tags
end
end
Integration.field
는 클래스에 accessor 메서드를 설치합니다.
여기서 url
필드를 관리하기 위해 #url
, #url=
, 그리고 #url_changed?
을 사용할 수 있습니다.
이러한 accessor는 다른 ActiveRecord
속성과 마찬가지로 모델에서 Integration#properties
에 직접 액세스해야 합니다.
필드는 항상 그들의 getters
를 통해 액세스해야 하며 properties
해시와 직접 상호 작용해서는 안 됩니다.
properties
해시에 직접 쓰지 말아야 하며, 생성된 setter 메서드를 대신 사용해야 합니다. 이 해시에 직접 작성하는 것은 지속되지 않습니다.
이러한 필드가 통합의 프론트엔드 폼에서 어떻게 노출되는지 보려면 프론트엔드 폼 사용자 정의를 참조하십시오.
Integration.prop_accessor
나 Integration.data_field
를 사용하는 기타 접근 방법은 통합의 이전 버전에서 볼 수 있지만 새로운 통합에는 이러한 접근 방법을 사용해서는 안 됩니다.
유효성 검사 정의
모든 필드에 대해 Rails 유효성을 정의해야 합니다.
유효성은 #activated?
메서드를 확인하여 통합이 활성화된 경우에만 적용해야 합니다.
required:
property를 가진 필드는 프론트엔드를 위한 것이므로 #activated?
메서드를 테스트하여 presence
에 대한 해당 유효성을 가져야 합니다.
예를 들어:
module Integrations
class FooBar < Integration
with_options if: :activated? do
validates :key, presence: true, format: { with: KEY_REGEX }
validates :bar, inclusion: [true, false]
end
field :key, required: true
field :bar, type: :checkbox
end
end
트리거 이벤트 정의
통합은 GitLab의 이벤트에 응답하여 자체 #execute
메서드를 호출하여 트리거됩니다. 이는 이벤트에 대한 자세한 정보를 담은 페이로드 해시를 전달받습니다.
지원되는 이벤트는 webhook events에서 볼 수 있는 것과 일부 겹칠 수 있으며, 동일한 페이로드를 받습니다.
모델에서 클래스 메서드 Integration.supported_events
를 오버라이드하여 관심 있는 이벤트를 지정할 수 있습니다.
다음 이벤트가 통합을 위해 지원됩니다:
이벤트 유형 | 기본값 | 값 | 트리거 |
---|---|---|---|
경고 이벤트 | alert
| 새로운 고유한 경고가 기록됩니다. | |
커밋 이벤트 | ✓ | commit
| 커밋이 생성되거나 업데이트됩니다. |
배포 이벤트 | deployment
| 배포가 시작되거나 완료됩니다. | |
이슈 이벤트 | ✓ | issue
| 이슈가 생성, 업데이트되거나 닫힙니다. |
기밀 이슈 이벤트 | ✓ | confidential_issue
| 기밀 이슈가 생성, 업데이트되거나 닫힙니다. |
작업(job) 이벤트 | job
| ||
병합 요청 이벤트 | ✓ | merge_request
| 병합 요청이 생성되거나 업데이트되거나 병합됩니다. |
코멘트 이벤트 | comment
| 새로운 코멘트가 추가됩니다. | |
기밀 코멘트 이벤트 | confidential_note
| 기밀 이슈의 새로운 코멘트가 추가됩니다. | |
파이프라인 이벤트 | pipeline
| 파이프라인 상태가 변경됩니다. | |
푸시(push) 이벤트 | ✓ | push
| 리포지토리로 푸시가 되었습니다. |
태그 푸시 이벤트 | ✓ | tag_push
| 새로운 태그가 리포지토리에 푸시되었습니다. |
취약점 이벤트 | vulnerability
| 새로운 고유한 취약점이 기록됩니다. Ultimate 전용. | |
위키 페이지 이벤트 | ✓ | wiki_page
| 위키 페이지가 생성되거나 업데이트됩니다. |
이벤트 예시
이 예제는 commit
및 merge_request
이벤트에 응답하는 통합을 정의합니다:
module Integrations
class FooBar < Integration
def self.supported_events
%w[commit merge_request]
end
end
end
통합은 또한 이벤트에 응답하지 않을 수도 있고, 다른 방법으로 사용자 정의 기능을 구현할 수도 있습니다:
module Integrations
class FooBar < Integration
def self.supported_events
[]
end
end
end
보안 향상 기능
채널 값 마스킹
Integrations::BaseChatNotification
을 상속하는 통합은 채널 입력 필드의 값을 숨길 수 있습니다. 통합은 채널이 민감한 정보(예: 인증 토큰)를 포함할 때마다 해당 값을 숨겨야 합니다.
기본적으로 #mask_configurable_channels?
는 false
를 반환합니다. 채널 값을 마스킹하려면 통합의 #mask_configurable_channels?
메서드를 오버라이드하여 true
를 반환하도록 설정하세요:
override :mask_configurable_channels?
def mask_configurable_channels?
true
end
구성 테스트 정의
선택적으로 통합 설정의 구성 테스트를 정의할 수 있습니다. 테스트는 통합 폼의 테스트 버튼에서 실행되며 결과가 사용자에게 반환됩니다.
좋은 구성 테스트는 다음과 같습니다:
- 서비스의 데이터를 변경하지 않아야 합니다. 예를 들어 CI 빌드를 트리거해서는 안 됩니다. 메시지를 보내는 것은 허용됩니다.
- 의미 있고 가능한 철저해야 합니다.
위의 지침을 따르기 어려운 경우 구성 테스트를 추가하지 않는 것을 고려해보세요.
구성 테스트를 추가하려면 통합 모델에 #test
메서드를 정의하세요.
해당 메서드는 테스트 푸시 이벤트 페이로드를 나타내는 data
를 받습니다.
이 메서드는 다음과 같은 키를 포함한 해시를 반환해야 합니다:
-
success
(필수): 구성 테스트가 통과했음을 나타내는 부울 값입니다. -
result
(옵션): 구성 테스트가 실패한 경우 사용자에게 반환되는 메시지입니다.
예:
module Integrations
class FooBar < Integration
def test(data)
success = test_api_key(data)
{ success: success, result: 'API 키가 유효하지 않습니다' }
end
end
end
프론트엔드 폼 사용자 정의
모델에 정의된 메타데이터를 기반으로 프론트엔드 폼이 동적으로 생성됩니다.
기본적으로 통합 폼은 다음을 제공합니다:
- 통합을 활성화 또는 비활성화하는 확인란.
-
Integration#configurable_events
에서 반환된 각 트리거 이벤트에 대한 확인란.
폼 상단에 사용자 지원 텍스트를 추가하려면 Integration#help
를 오버라이드하거나 app/views/shared/integrations/$INTEGRATION_NAME/_help.html.haml
에 템플릿을 제공하세요.
폼에 사용자 지정 속성을 추가하려면 해당 속성에 대한 메타데이터를 Integration#fields
에 정의하세요.
해당 메서드는 각 필드에 대한 해시 배열을 반환해야 하며, 키는 다음과 같을 수 있습니다:
키 | 유형 | 필수 | 기본값 | 설명 |
---|---|---|---|---|
type:
| 심볼 | true | :text
| 폼 필드의 유형입니다. :text , :textarea , :password , :checkbox , 또는 :select 가 될 수 있습니다.
|
section:
| 심볼 | false | 필드가 속하는 섹션을 지정합니다. | |
name:
| 문자열 | true | 폼 필드의 속성 이름입니다. | |
required:
| 부울 | false | false
| 폼 필드가 필수인지 선택사항인지 지정합니다. 뒤쪽의 백엔드 유효성 검사는 여전히 존재합니다. |
title:
| 문자열 | false |
name: 의 대문자화된 값
| 폼 필드의 레이블입니다. |
placeholder:
| 문자열 | false | 폼 필드의 플레이스홀더입니다. | |
help:
| 문자열 | false | 폼 필드 아래에 표시되는 도움말 텍스트입니다. | |
api_only:
| 부울 | false | false
| 해당 필드가 API를 통해서만 이용 가능하고 프론트엔드 폼에서 제외되어야 하는지 지정합니다. |
description
| 문자열 | false | API 필드 설명입니다. | |
if:
| 부울 또는 람다 | false | true
| 해당 필드가 이용 가능해야 하는지 지정합니다. 값으로는 부울 또는 람다가 될 수 있습니다. |
type: :checkbox
에 대한 추가 키
키 | 유형 | 필수 | 기본값 | 설명 |
---|---|---|---|---|
checkbox_label:
| 문자열 | false |
title: 의 값
| 확인란 옆에 표시되는 사용자 정의 레이블입니다. |
type: :select
에 대한 추가 키
키 | 유형 | 필수 | 기본값 | 설명 |
---|---|---|---|---|
choices:
| 배열 | true |
[label, value] 튜플의 중첩 배열입니다.
|
type: :password
에 대한 추가 키
키 | 유형 | 필수 | 기본값 | 설명 |
---|---|---|---|---|
non_empty_password_title:
| 문자열 | false |
title: 의 값
| 값이 이미 저장된 경우에 표시되는 대체 레이블입니다. |
non_empty_password_help:
| 문자열 | false |
help: 의 값
| 값이 이미 저장된 경우에 표시되는 대체 도움말 텍스트입니다. |
섹션 정의
모든 통합은 Integration#sections
을 정의해야 하며, 이를 통해 폼을 작은 섹션으로 분할하여 통합 설정을 보다 쉽게 만들 수 있습니다.
가장 일반적으로 사용되는 섹션은 사전에 정의되어 있으며 이미 몇 가지 UI를 포함하고 있습니다:
-
SECTION_TYPE_CONNECTION
:url
,username
,password
와 같이 통합에 연결하고 인증하는 데 필요한 기본 필드를 포함합니다. -
SECTION_TYPE_CONFIGURATION
: 통합이 작동하는 방식에 대한 더 많은 고급 구성 및 선택적 설정을 포함합니다. -
SECTION_TYPE_TRIGGER
: 통합을 트리거할 이벤트 목록을 포함합니다.
SECTION_TYPE_CONNECTION
및 SECTION_TYPE_CONFIGURATION
에서는 dynamic-field
컴포넌트를 내부적으로 렌더링합니다. dynamic-field
컴포넌트는 통합의 type
에 따라 checkbox
, input
, select
, 또는 textarea
중 하나를 렌더링합니다.
예를 들어:
module Integrations
class FooBar < Integration
def sections
[
{
type: SECTION_TYPE_CONNECTION,
title: s_('Integrations|연결 세부 정보'),
description: help
},
{
type: SECTION_TYPE_CONFIGURATION,
title: _('구성'),
description: s_('통합에 대한 고급 구성')
}
]
end
end
end
새로운 사용자 정의 섹션
기존 섹션으로는 UI 사용자 정의 요구 사항이 충족되지 않을 경우, 새로운 사용자 정의 섹션을 만들 수 있습니다.
-
#sections
메서드에 새로운 상수SECTION_TYPE_*
를 추가하고 해당 메서드에 추가하여 새로운 섹션을 추가합니다:module Integrations class FooBar < Integration SECTION_TYPE_SUPER = :my_custom_section def sections [ { type: SECTION_TYPE_SUPER, title: s_('Integrations|Custom section'), description: s_('Integrations|Help') } ] end end end
-
~/integrations/constants.js
의 프론트엔드 상수integrationFormSections
및integrationFormSectionComponents
를 업데이트합니다. -
app/assets/javascripts/integrations/edit/components/sections/*
에서 새로운 섹션 컴포넌트를 추가합니다. -
app/assets/javascripts/integrations/edit/components/integration_forms/section.vue
에서 새로운 섹션을 포함하고 렌더링합니다.
프론트엔드 양식 예제
이 예제는 Connection details
섹션 아래에서 필수 url
필드와 선택적인 username
및 password
필드를 정의합니다:
module Integrations
class FooBar < Integration
field :url,
section: SECTION_TYPE_CONNECTION,
type: :text,
title: s_('FooBarIntegration|Server URL'),
placeholder: 'https://example.com/',
required: true
field :username,
section: SECTION_TYPE_CONNECTION,
type: :text,
title: s_('FooBarIntegration|Username')
field :password,
section: SECTION_TYPE_CONNECTION,
type: 'password',
title: s_('FoobarIntegration|Password'),
non_empty_password_title: s_('FooBarIntegration|Enter new password')
def sections
[
{
type: SECTION_TYPE_CONNECTION,
title: s_('Integrations|Connection details'),
description: s_('Integrations|Help')
}
]
end
end
end
REST API에서 통합 노출
통합을 REST API에서 노출시키려면:
- 통합 클래스(
::Integrations::FooBar
)를API::Helpers::IntegrationsHelpers.integration_classes
에 추가합니다. -
통합의 API 인수를
API::Helpers::IntegrationsHelpers.integrations
에 추가합니다. 예:'foo-bar' => ::Integrations::FooBar.api_arguments
-
doc/api/integrations.md
의 참조 문서를 업데이트하여 통합에 대한 새로운 섹션을 추가하고 모든 속성을 문서화합니다.
또한 REST API 스타일 가이드를 참조하실 수 있습니다.
민감한 필드는 API를 통해 노출되지 않습니다. 민감한 필드란 이름에 다음 중 하나를 포함하는 필드를 가리킵니다:
key
passphrase
password
secret
token
webhook
통합의 가용성
기본적으로, 통합은 특정 프로젝트나 그룹 또는 인스턴스 전체에 적용될 수 있습니다. 대부분의 통합은 프로젝트 컨텍스트에서만 작동하지만 그룹 및 인스턴스에 대해 구성할 수 있습니다.
일부 통합의 경우 특정 수준(project, group, 또는 instance)에서만 사용할 수 있도록 하는 것이 합리적일 수 있습니다.
이를 위해 통합을 Integration::INTEGRATION_NAMES
에서 제거하고 대신 다음에 추가해야 합니다:
-
Integration::PROJECT_LEVEL_ONLY_INTEGRATION_NAMES
에서 프로젝트 수준에서만 활성화할 수 있도록합니다. -
Integration::INSTANCE_LEVEL_ONLY_INTEGRATION_NAMES
에서 인스턴스 수준에서만 활성화할 수 있도록 합니다. -
Integration::PROJECT_AND_GROUP_LEVEL_ONLY_INTEGRATION_NAMES
에서 인스턴스 수준에서 활성화하는 것을 방지합니다.
새로운 통합을 개발할 때, 해당 통합이 Integration.available_integration_names
의 기능 플래그 뒤에 가용하도록 하는 것을 권장합니다.
문서화
통합에 대한 문서를 추가합니다:
-
doc/user/project/integrations
에 페이지를 추가합니다. - Integrations overview에서 연결하실 수 있습니다.
- 문서가 병합된 후에, 문서 탐색에 Integrations 카테고리 제목 아래에 항목을 추가합니다.
또한 우리의 일반 문서화 지침을 참조하실 수 있습니다.
Customize the frontend form에서 설명한대로, 통합 양식에서의 도움말 텍스트 및 외부 문서 링크를 제공할 수 있습니다. 도움말 텍스트에는 usability guidelines를 참조하실 수 있습니다.
테스팅
테스팅은 구성 테스트 정의하는 것과 혼동되어서는 안 됩니다.
일반적으로, 통합 모델의 테스트를 spec/models/integrations
에 추가하고 spec/factories/integrations.rb
에 예제 설정이 있는 팩토리를 추가하는 것이 충분합니다.
또한 각 통합은 일반화된 테스트의 일환으로 테스트됩니다. 예를 들어, 모든 통합의 설정 양식이 올바르게 렌더링되는지를 확인하는 feature 스펙이 있습니다.
통합의 특정 동작을 구현한 경우, 특히 프론트엔드에서 커스텀 동작을 구현한 경우 추가 테스트가 필요합니다.
또한 일반적인 테스팅 가이드라인을 참조하실 수 있습니다.
국제화
모든 UI 문자열은 저희의 국제화 가이드라인을 따라 번역할 수 있도록 준비되어야 합니다.
문자열은 통합 이름을 네임스페이스로 사용해야 합니다. 예: s_('FooBarIntegration|My string')
.
통합 폐지 및 삭제
통합을 제거하려면 먼저 통합을 폐지해야 합니다. 자세한 내용은 기능 폐지 가이드라인을 참조하실 수 있습니다.
통합 폐지
통합을 폐지하려면, 삭제되지 않은 기능을 폐지하기 위해 사용자에 무리를 주지 않도록, 의도된 제거의 세 번째 마일스톤 전까지 알림을 추가해야 합니다:
- 폐지 앨리먼트 추가.
- 통합 문서를 폐지된 것으로 표시합니다(../../development/documentation/styleguide/deprecations_and_removals.md).
- 옵션. 새로운 프로젝트 수준 레코드가 생성되는 것을 방지하려면
Project#disabled_integrations
에 통합을 추가합니다(예제 MR 참조).
통합 제거
통합을 안전하게 제거하려면 제거를 두 단계의 마일스톤에 걸쳐 진행해야 합니다.
의도한 제거의 주요 마일스톤(M.0)에서 통합을 비활성화하고 데이터베이스에서 레코드를 삭제하세요:
-
Integration::INTEGRATION_NAMES
에서 통합 제거. - 통합 모델의
#execute
및#test
메서드(정의된 경우)를 삭제하지만 모델은 유지합니다. - PostgreSQL에서 통합 레코드를 삭제하기 위해 사후 마이그레이션 추가(자세한 내용은 예시 병합 요청 참조).
- 통합 문서를 삭제로 표시.
- 통합 API 문서를 업데이트.
다음 소규모 릴리스(M.1)에서:
- 통합 모델 및 나머지 코드를 제거합니다.
- 통합 레이블(
~Integration::<name>
)이 있는 모든 이슈, 병합 요청 및 에픽을 닫습니다. -
gitlab-org
에서 통합 레이블(~Integration::<name>
)을 삭제합니다.
지속적인 마이그레이션 및 리팩터링
개발자들은 통합 팀이 통합 속성을 정의하는 방식을 통합하고 있는 과정을 인식해야 합니다.
통합 예시
새로운 통합을 추가하는 예시는 다음 이슈를 참조할 수 있습니다:
- Datadog: Prometheus 통합과 유사한 메트릭 수집기.
- EWM/RTC: 외부 이슈 트래커.
- Webex Teams: 채팅 알림.
- ZenTao: Jira 통합과 유사한 사용자 정의 이슈 뷰를 갖는 외부 이슈 트래커.