통합 개발 지침
이 페이지는 GitLab 통합을 구현하기 위한 개발 지침을 제공하며, 이는 주요 Rails 프로젝트의 일부입니다.
또한 통합에 대한 전략에 대한 개요를 보려면 direction page를 참조하세요.
이 안내서는 진행 중인 작업입니다. 이해를 돕거나 오래된 정보를 발견하면 언제든지 @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
concern을 사용할 수도 있습니다. 이를 통해 연계된ServiceHook
모델을 통해 GitLab의 webhook functionality를 재사용하고 요청 로그를 자동으로 기록할 수 있습니다. 이 로그는 통합 설정에서 확인할 수 있습니다.
- 예:
- 통합의 underscored name(
'foo_bar'
)을Integration::INTEGRATION_NAMES
에 추가합니다. -
Project
에 통합을 연관시킵니다:has_one :foo_bar_integration, class_name: 'Integrations::FooBar'
필드 정의
통합은 Integration.field
클래스 메소드를 사용하여 구성을 저장하는 임의의 필드를 정의할 수 있습니다. 값은 integrations.encrypted_properties
열에서 암호화된 JSON 해시로 저장됩니다.
예:
ruby
module Integrations
class FooBar < Integration
field :url
field :tags
end
end
Integration.field
는 클래스에 accessor 메소드를 설치합니다. 여기서 #url
, #url=
, #url_changed?
을 가지게 되며, 이를 통해 url
필드를 관리할 수 있습니다. 이러한 accessor는 다른 ActiveRecord
속성과 마찬가지로 모델의 Integration#properties
에 직접적으로 접근해야 합니다.
필드는 반드시 생성된 setter 메소드를 사용해야 하며, properties
해시에 직접 쓰면 안 됩니다. 이 해시에 직접적으로 쓰는 것은 지속되지 않습니다.
이러한 필드에 접근할 때 항상 getters
를 통해 접근해야 하며, properties
해시와 직접적으로 상호 작용해서는 안 됩니다.
통합을 위한 frontend form에서 이러한 필드가 어떻게 노출되는지 확인하려면 Customize the frontend form을 참조하세요.
지난 버전의 통합에서 볼 수 있는 Integration.prop_accessor
나 Integration.data_field
를 사용하는 다른 방법도 있지만, 이러한 접근 방식은 새 통합에 사용하면 안 됩니다.
유효성 정의
모든 필드에 대해 Rails 유효성을 정의해야 합니다.
유효성은 #activated?
메소드를 테스트하여 통합이 활성화될 때만 적용되어야 합니다.
required:
property를 가진 필드는 frontend 전용 필드이므로 presence
에 대한 해당 유효성이 있어야 합니다.
예: ```ruby 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 event | alert
| 새로운 고유 경보가 기록됩니다. | |
Commit event | ✓ | commit
| 커밋이 생성되거나 업데이트됩니다. |
Deployment event | deployment
| 배포가 시작되거나 완료됩니다. | |
Issue event | ✓ | issue
| 이슈가 생성, 업데이트, 또는 닫힙니다. |
Confidential issue event | ✓ | confidential_issue
| 비밀 이슈가 생성, 업데이트, 또는 닫힙니다. |
Job event | job
| ||
Merge request event | ✓ | merge_request
| Merge Request이 생성, 업데이트, 또는 Merge됩니다. |
Comment event | comment
| 새 댓글이 추가됩니다. | |
Confidential comment event | confidential_note
| 비밀 댓글이 추가됩니다. | |
Pipeline event | pipeline
| 파이프라인 상태가 변경됩니다. | |
Push event | ✓ | push
| 리포지터리에 푸시가 이루어집니다. |
Tag push event | ✓ | tag_push
| 새로운 태그가 리포지터리에 푸시됩니다. |
Vulnerability event | vulnerability
| 새로운 고유한 취약점이 기록됩니다. Ultimate 전용. | |
Wiki page event | ✓ | wiki_page
| 위키 페이지가 생성되거나 업데이트됩니다. |
이벤트 예시
이 예시는 commit
및 merge_request
이벤트에 응답하는 통합을 정의합니다:
module Integrations
class FooBar < Integration
def self.supported_events
%w[commit merge_request]
end
end
end
통합은 이벤트에 응답하지 않을 수도 있으며, 다른 방법으로 추가 기능을 구현할 수 있습니다:
ruby
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
를 포함한 해시를 반환해아 합니다.
-
success
(필수): 구성 테스트가 통과되었는지 여부를 나타내는 부울입니다. -
result
(옵션): 구성 테스트가 실패한 경우 사용자에게 반환되는 메시지입니다.
예를 들어:
module Integrations
class FooBar < Integration
def test(data)
success = test_api_key(data)
{ success: success, result: 'API key is invalid' }
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를 통해서만 사용 가능하고 프론트엔드 폼에서는 제외되어야 하는지를 지정합니다. |
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|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
에서 새 섹션을 포함하고 렌더링하세요.
프론트엔드 폼 예시
이 예시에서는 연결 세부정보
섹션 아래 필수 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::Helpers::IntegrationsHelpers.integrations
에 추가하세요. -
doc/api/integrations.md
에 레퍼런스 문서를 업데이트하고, 통합에 대한 새 섹션을 추가하고 모든 속성을 문서화하세요.
또한 REST API 스타일 가이드를 참조할 수 있습니다.
민감한 필드는 API를 통해 노출되지 않습니다. 민감한 필드에는 이름에 다음 중 하나가 포함된 필드가 포함됩니다:
key
passphrase
password
secret
token
webhook
통합 가능성
기본적으로 통합은 프로젝트, 그룹 및 인스턴스 수준에서 사용할 수 있습니다. 대부분의 통합은 프로젝트 컨텍스트에서만 작동하지만, 그룹 및 인스턴스 수준에서도 구성할 수 있습니다.
일부 통합에서는 프로젝트 수준에서만 사용할 수 있도록 하는 것이 합리적일 수 있습니다.
이를 위해 해당 통합은 Integration::INTEGRATION_NAMES
에서 제거되고
대신 Integration::PROJECT_SPECIFIC_INTEGRATION_NAMES
에 추가되어야 합니다.
새로운 통합을 개발할 때에는 피처 플래그를 통해 사용 가능성을 제한하는 것을 권장합니다.
문서
통합 양식에 도움말 텍스트를 제공할 수 있으며, 이는 프론트엔드 양식 사용자 정의에서 설명한 대로, 외부 문서로의 링크를 포함할 수 있습니다. 도움말 텍스트에 대해서는 사용성 지침을 참조하세요.
더 자세한 문서는 doc/user/project/integrations
에 페이지를 제공하고,
통합 개요에서 이에 링크를 제공할 수 있습니다.
또한 문서 작성 지침을 참조할 수 있습니다.
테스트
테스트는 구성 테스트 정의와 혼동되어서는 안 됩니다.
일반적으로 spec/models/integrations
의 통합 모델에 대한 테스트와
spec/factories/integrations.rb
의 예제 설정이 포함된 팩토리를 추가하는 것이 충분합니다.
각 통합은 일반화된 테스트의 일부로서도 테스트됩니다. 예를 들어, 모든 통합의 설정 양식이 올바르게 렌더링되는지 확인하는 기능 스펙이 있습니다.
통합이 특정한 사용자 정의 동작을 구현한 경우, 특히 프론트엔드에서는 이에 대한 추가 테스트가 필요합니다.
또한 테스트 작성 지침을 참조할 수 있습니다.
국제화
모든 UI 문자열은 국제화 지침을 따라 번역을 위해 준비되어야 합니다.
문자열은 네임스페이스로서 통합 이름을 사용해야 합니다. 예를 들어 s_('FooBarIntegration|My string')
.
통합 해제 및 삭제
통합을 제거하려면 먼저 해당 통합을 폐기해야 합니다. 자세한 정보는 기능 폐기 지침을 참조하세요.
통합 폐기
통합을 폐기하려면 제거를 의도한 세 번째 마일스톤을 넘기기 전까지 반드시 폐기를 발표해야 합니다:
- 폐기 항목 추가.
- 폐기된 통합 문서를 표시하세요.
- 선택 사항. 새로운 프로젝트 레벨 레코드의 생성을 방지하려면,
Project#disabled_integrations
에 통합을 추가하세요 (예: Merge Request 참조).
통합 삭제
통합을 안전하게 제거하려면 두 개의 마일스톤 동안 단계적으로 제거해야 합니다.
제거를 의도한 주요 마일스톤(M.0)에서 통합을 비활성화하고 데이터베이스에서 레코드를 삭제하세요:
-
Integration::INTEGRATION_NAMES
에서 통합을 제거하세요. - 통합 모델의
#execute
및#test
메서드(정의된 경우)를 삭제하지만, 모델은 유지하세요. - PostgreSQL에서 통합 레코드를 삭제하기 위한 포스트 마이그레이션을 추가하세요 (예: Merge Request 참조).
- 통합 문서를 삭제함.
- 통합 API 문서를 업데이트.
다음 마이너 릴리스(M.1)에서:
- 통합 모델 및 남은 코드를 제거하세요.
- 통합의 라벨(
~Integration::<name>
)이 있는 모든 이슈, Merge Request 및 에픽을 닫으세요. -
gitlab-org
에서 통합 라벨(~Integration::<name>
)을 삭제하세요.
진행 중인 마이그레이션 및 리팩터링
개발자는 통합 팀이 통합 속성 정의 방식을 통일시키고 있음을 알아야 합니다.
통합 예시
새로운 통합 추가 예시를 위해 다음 이슈들을 참조할 수 있습니다:
- Datadog: Prometheus 통합과 유사한 메트릭 수집기.
- EWM/RTC: 외부 이슈 추적기.
- Webex Teams: 채팅 알림.
- ZenTao: Jira 통합과 유사한 사용자 정의 이슈 보기를 가진 외부 이슈 추적기.