- 새로운 통합 추가
- 구성 테스트 정의
- 프런트엔드 양식 사용자 정의
- REST API에서 통합 노출
- 통합의 가용성
- 문서화
- 테스트
- 국제화
- 통합을 사용 중단하고 제거하기
- 진행 중인 마이그레이션 및 리팩토링
- 통합 예시
통합 개발 지침
이 페이지는 GitLab 통합 구현을 위한 개발 지침을 제공합니다. 이는 우리의 주요 Rails 프로젝트의 일부입니다.
통합에 대한 전략 개요는 방향 페이지를 참조하세요.
이 가이드는 진행 중인 작업입니다. 설명이 필요하거나 오래된 정보를 발견하신 경우 @gitlab-org/manage/import-and-integrate
에 문의해 주세요.
새로운 통합 추가
통합 정의
-
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
컨cern을 사용할 수도 있습니다. 이는 연관된ServiceHook
모델을 통해 GitLab의 웹후크 기능을 재사용하며,
통합 설정에서 볼 수 있는 요청 로그를 자동으로 기록합니다.
- 예:
- 통합의 언더스코어 이름(
'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
는 클래스에 접근자 메서드를 설치합니다.
여기에서 우리는 #url
, #url=
, #url_changed?
를 사용하여 url
필드를 관리할 수 있게 됩니다.
이 접근자들은 ActiveRecord
속성과 마찬가지로 모델의 Integration#properties
에서 직접 필드에 접근해야 합니다.
항상 접근자를 통해 필드에 접근해야 하며 properties
해시와 직접 상호작용하지 않아야 합니다.
properties
해시에 직접 쓰기를 해선 안 되며, 생성된 setter 메서드를 대신 사용해야 합니다.
이 해시에 대한 직접 쓰기는 영속되지 않습니다.
이 필드가 통합의 프론트엔드 양식에서 어떻게 노출되는지 보려면,
프론트엔드 양식 사용자화를 참조하세요.
다른 접근법으로는 이전 버전의 통합에서 볼 수 있는 Integration.prop_accessor
또는 Integration.data_field
가 있습니다.
새로운 통합에 대해서는 이 접근법을 사용하지 않아야 합니다.
유효성 검사 정의
모든 필드에 대해 Rails 유효성 검사를 정의해야 합니다.
유효성 검사는 통합이 활성화된 경우에만 적용되어야 하며, #activated?
메서드를 테스트하여 확인합니다.
required:
속성이 있는 필드는 presence
에 대한 유효성 검증이 있어야 합니다.
required:
필드 속성은 프론트엔드 전용이기 때문입니다.
예를 들어:
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
메서드를 호출하여 트리거되며, 이 메서드는 이벤트에 대한 세부 정보를 포함하는 페이로드 해시를 전달받습니다.
지원되는 이벤트는 웹훅 이벤트와 일부 겹치며, 동일한 페이로드를 수신합니다. 모델에서 클래스 메서드 Integration.supported_events
를 재정의하여 관심 있는 이벤트를 지정할 수 있습니다.
다음 이벤트가 통합을 위해 지원됩니다:
이벤트 유형 | 기본 | 값 | 트리거 |
---|---|---|---|
경고 이벤트 | alert |
새로운 고유 경고가 기록됩니다. | |
커밋 이벤트 | ✓ | commit |
커밋이 생성되거나 업데이트됩니다. |
배포 이벤트 | deployment |
배포가 시작되거나 완료됩니다. | |
이슈 이벤트 | ✓ | issue |
이슈가 생성, 업데이트 또는 종료됩니다. |
비밀 이슈 이벤트 | ✓ | confidential_issue |
비밀 이슈가 생성, 업데이트 또는 종료됩니다. |
작업 이벤트 | job |
||
병합 요청 이벤트 | ✓ | merge_request |
병합 요청이 생성, 업데이트 또는 병합됩니다. |
댓글 이벤트 | comment |
새로운 댓글이 추가됩니다. | |
비밀 댓글 이벤트 | confidential_note |
비밀 이슈에 새로운 댓글이 추가됩니다. | |
파이프라인 이벤트 | pipeline |
파이프라인 상태가 변경됩니다. | |
푸시 이벤트 | ✓ | 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: |
문자열 | 아니요 |
title: 의 값 |
체크박스 옆에 표시되는 사용자 정의 레이블입니다. |
type: :select
에 대한 추가 키
키 | 유형 | 필수 | 기본값 | 설명 |
---|---|---|---|---|
choices: |
배열 | 예 |
[레이블, 값] 튜플의 중첩 배열입니다. |
type: :password
에 대한 추가 키
키 | 유형 | 필수 | 기본값 | 설명 |
---|---|---|---|---|
non_empty_password_title: |
문자열 | 아니요 |
title: 의 값 |
값이 이미 저장된 경우 표시되는 대체 레이블입니다. |
non_empty_password_help: |
문자열 | 아니요 |
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|Connection details'),
description: help
},
{
type: SECTION_TYPE_CONFIGURATION,
title: _('Configuration'),
description: s_('Advanced configuration for integration')
}
]
end
end
end
특정 섹션에 필드를 추가하려면 필드 메타데이터에 section:
키를 추가할 수 있습니다.
새로운 사용자 정의 섹션
기존 섹션이 UI 사용자 정의 요구 사항을 충족하지 않으면 새로운 사용자 정의 섹션을 만들 수 있습니다:
-
새 섹션을 추가하려면 새로운 상수
SECTION_TYPE_*
를 추가하고#sections
메서드에 추가합니다: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
통합의 가용성
기본적으로 통합은 특정 프로젝트나 그룹 또는 전체 인스턴스에 적용할 수 있습니다.
대부분의 통합은 프로젝트 컨텍스트에서만 작동하지만, 여전히 그룹과 인스턴스에 대해 구성할 수 있습니다.
일부 통합의 경우 특정 수준(프로젝트, 그룹 또는 인스턴스)에서만 사용할 수 있도록 하는 것이 의미가 있을 수 있습니다.
이를 위해서는 통합을 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 category title 아래에 추가합니다.
또한 우리의 일반 문서화 지침을 참조할 수 있습니다.
통합 폼에 도움말 텍스트를 제공할 수 있으며, 외부 문서에 대한 링크를 포함할 수 있습니다.
위에서 설명한 대로 프론트엔드 폼 사용자 정의를 참조하세요. 도움말 텍스트에 대한 사용성 지침을 참조하세요.
테스트
테스트는 구성 테스트 정의와 혼동해서는 안 됩니다.
spec/models/integrations
에 통합 모델에 대한 테스트를 추가하는 것이 종종 충분하며,
spec/factories/integrations.rb
에 예제 설정이 있는 팩토리를 추가합니다.
각 통합은 일반화된 테스트의 일환으로도 테스트됩니다. 예를 들어,
모든 통합에 대해 설정 양식이 올바르게 렌더링되고 있는지 확인하는 기능 사양이 있습니다.
통합이 프론트엔드에서 사용자 정의 동작을 구현하는 경우,
추가 테스트로 그 부분을 커버해야 합니다.
일반적인 테스트 가이드라인도 참조할 수 있습니다.
국제화
모든 UI 문자열은 국제화 가이드라인에 따라
번역을 위해 준비되어야 합니다.
문자열은 통합 이름을 네임스페이스로 사용해야 하며, 예를 들어 s_('FooBarIntegration|My string')
와 같은 형식입니다.
통합을 사용 중단하고 제거하기
통합을 제거하려면 먼저 통합을 사용 중단해야 합니다. 자세한 내용은
기능 사용 중단 가이드라인을 참조하세요.
통합 사용 중단하기
통합 사용 중단은 예정된 제거 이전 세 번째 마일스톤까지 발표해야 합니다.
통합을 사용 중단하려면:
- 사용 중단 항목 추가하기.
- 통합 문서를 사용 중단으로 표시하기.
-
선택 사항. 새로운 프로젝트 수준의 기록이 생성되지 않도록 하려면,
Project#disabled_integrations
에 통합을 추가합니다 (참고: 예제 병합 요청).
통합 제거하기
안전하게 통합을 제거하려면 두 개의 마일스톤에 걸쳐 제거를 준비해야 합니다.
예정된 제거의 주요 마일스톤(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 통합과 유사한 사용자 정의 이슈 뷰가 있는 외부 이슈 트래커.