- 新しいインテグレーションを追加
- 設定テストの定義
- フロントエンドのフォームをカスタマイズ
- REST API でインテグレーションを公開します。
- インテグレーションの有無
- ドキュメント
- テスト
- 国際化
- インテグレーションの廃止と削除
- 進行中のマイグレーションとリファクタリング
- インテグレーション例
インテグレーション開発者向けガイドライン
このページでは、メインのRailsプロジェクトの一部であるGitLabインテグレーションを実装するための開発ガイドラインを提供します。
インテグレーションに関する私たちの戦略の概要については、方向性のページもご覧ください。
このガイドは進行中です。説明が必要な場合や古い情報を見つけた場合は、@gitlab-org/manage/integrations
までご連絡ください。
新しいインテグレーションを追加
インテグレーションを定義します。
-
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
を使うこともできます。これは、関連するServiceHook
モデルを通して GitLab のWebhook 機能を再利用し、インテグレーション設定で見ることができるリクエストログを自動的に記録します。
- 例えば、
-
Integration::INTEGRATION_NAMES
にインテグレーション名 ('foo_bar'
) を追加します。 -
Project
にインテグレーションをアソシエーションとして追加します:has_one :foo_bar_integration, class_name: 'Integrations::FooBar'
プロパティの定義
インテグレーションは、クラスメソッドIntegration.prop_accessor
を使って、設定を保存するための任意のプロパティを定義できます。値は暗号化された JSON ハッシュとしてintegrations.encrypted_properties
カラムに保存されます。
使用例:
module Integrations
class FooBar < Integration
prop_accessor :url
prop_accessor :tags
end
end
Integration.prop_accessor
はクラスにアクセサ・メソッドをインストールします。ここでは、url
フィールドを管理するために、#url
、#url=
、#url_changed?
を用意します。Integration#properties
に格納されたフィールドは、他のActiveRecordの属性と同じように、モデル上で直接これらのアクセサによってアクセスされなければなりません。
プロパティへのアクセスは常にgetters
を通して行い、properties
ハッシュを直接 properties
操作してはいけません。properties
ハッシュへの書き込み properties
はproperties
行わず properties
、生成されたセッターメソッドを使用する必要があります。このハッシュへの直接の書き込みは永続化されません。
また、すべてのプロパティに対してバリデーションを定義する必要があります。
これらのプロパティがインテグレーション用のフロントエンドフォームでどのように公開されるかについては、以下のフロントエンドフォームのカスタマイズのセクションも参照してください。
Integration.data_field
を使った別のアプローチもあります。データフィールドでは、値はインテグレーションごとに別のテーブルに保存されます。現時点では、新しいインテグレーションにこの方法を使用することはお勧めしません。
トリガーイベントの定義
インテグレーションはGitLabのイベントに応じて#execute
メソッドを呼び出すことでトリガーされます。 メソッドにはイベントの詳細が書かれたペイロードハッシュが渡されます。
サポートされているイベントはWebhook イベントと重複しており、同じペイロードを受け取ります。モデルのクラスメソッドIntegration.supported_events
をオーバーライドすることで、興味のあるイベントを指定することができます。
以下のイベントがインテグレーションでサポートされています:
イベントタイプ | デフォルト | 値 | トリガー |
---|---|---|---|
アラートイベント | alert | 新しい固有のアラートが記録されます。 | |
コミットイベント | ✓ | commit | コミットが作成または更新されます。 |
デプロイイベント | deployment | デプロイが開始または終了します。 | |
イシューイベント | ✓ | issue | イシューを作成、更新、クローズします。 |
コンフィデンシャル・イシュー・イベント | ✓ | confidential_issue | 機密イシューが作成、更新、クローズされました。 |
ジョブイベント | job | ||
マージリクエストイベント | ✓ | merge_request | マージリクエストが作成、更新、マージされました。 |
コメントイベント | comment | 新しいコメントが追加されました。 | |
秘密コメントイベント | confidential_note | 機密イシューに関する新しいコメントが追加されました。 | |
パイプラインイベント | pipeline | パイプラインのステータスが変更されました。 | |
プッシュイベント | ✓ | push | リポジトリにプッシュが行われます。 |
タグプッシュイベント | ✓ | tag_push | 新しいタグがリポジトリにプッシュされます。 |
脆弱性イベント | vulnerability | 新しい固有の脆弱性が記録されます。 | |
Wiki ページイベント | ✓ | wiki_page | Wiki ページが作成または更新されました。 |
イベントの例
この例では、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 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 ,textarea ,password ,checkbox , またはselect のいずれかです。 | |
name: | 文字列です。 | true | フォーム・フィールドのプロパティ名。これは、クラスで定義されているprop_accessor と一致しなければなりません。 | |
required: | boolean | false | false | フォームフィールドが必須か任意かを指定します。 |
title: | 文字列です。 | false | の資本値name:
| フォームフィールドのラベル。 |
placeholder: | 文字列です。 | false | フォームフィールドのプレースホルダ。 | |
help: | 文字列です。 | false | フォームフィールドの下に表示されるヘルプテキスト。 | |
api_only: | boolean | false | false | フィールドをAPIからのみ利用可能とし、フロントエンドのフォームからは除外する場合に指定します。 |
if: | boolean あるいは lambda | 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:
| 値が既に格納されている場合に表示される代替ヘルプテキスト。 |
フロントエンド・フォームの例
この例では、必須のurl
フィールドと、オプションのusername
とpassword
フィールドを定義します:
module Integrations
class FooBar < Integration
prop_accessor :url, :username, :password
def fields
[
{
type: 'text',
name: 'url',
title: s_('FooBarIntegration|Server URL'),
placeholder: 'https://example.com/',
required: true
},
{
type: 'text',
name: 'username',
title: s_('FooBarIntegration|Username'),
},
{
type: 'password',
name: 'password',
title: s_('FoobarIntegration|Password'
non_empty_password_title: s_('FooBarIntegration|Enter new password')
}
]
end
end
end
REST API でインテグレーションを公開します。
インテグレーションをREST API に公開します:
-
API::Helpers::IntegrationsHelpers.integration_classes
にインテグレーションクラス (::Integrations::FooBar
) を追加します。 -
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
に追加する必要があります。
新しいインテグレーションを開発する場合、Integration.available_integration_names
の機能フラグの後ろに、利用可能かどうかをゲートすることをお勧めします。
ドキュメント
フロントエンドフォームのカスタマイズ で説明したように、インテグレーションフォームにヘルプテキストを記述することができます。ヘルプテキストについてはユーザビリティガイドラインを参照してください。
より詳細なドキュメントについては、doc/user/project/integrations
にページを作成し、インテグレーション概要からリンクしてください。
また、一般的なドキュメントのガイドラインを参照することもできます。
テスト
テストを設定テストの定義と混同してはいけません。
spec/models/integrations
にインテグレーションモデルのテストを追加し、spec/factories/integrations.rb
に設定例のファクトリーのテストを追加すれば十分です。
各インテグレーションは一般化されたテストの一部としてもテストされます。たとえば、すべてのインテグレーションで設定フォームが正しくレンダリングされることを検証する機能仕様があります。
もしあなたのインテグレーションがカスタムな振る舞いを実装しているのなら、 特にフロントエンドにおいて、追加のテストが必要です。
一般的なテストのガイドラインも参照ください。
国際化
すべてのUI文字列は、私たちの国際化ガイドラインに従って、翻訳のために準備されるべきです。
文字列はインテグレーション名を名前空間として使用する必要があります。例えば、s_('FooBarIntegration|My string')
.
インテグレーションの廃止と削除
インテグレーションを削除するには、まずインテグレーションを非推奨にする必要があります。詳細については、機能の非推奨ガイドラインを参照してください。
インテグレーションの非推奨化
非推奨を発表するのは、廃止予定の3つ前のマイルストーンまでにしてください。インテグレーションを非推奨にするには
- 非推奨エントリを追加します。
- インテグレーション・ドキュメントを非推奨とマークします。
- オプション。新しいプロジェクトレベルのレコードが作成されないようにするには、インテグレーションを
Project#disabled_integrations
に追加します (マージリクエストの例を参照)。
インテグレーションを削除
インテグレーションを安全に削除するには、2つのマイルストーンにわたって削除をステージする必要があります。
削除予定の主要マイルストーン(M.0)では、インテグレーションを無効にし、データベースからレコードを削除します:
-
Integration::INTEGRATION_NAMES
からインテグレーションを削除します。 - インテグレーションモデルの
#execute
と#test
メソッド(定義されている場合)を削除します。 - PostgreSQLからインテグレーションレコードを削除するマイグレーションを追加します(マージリクエストの例を参照)。
- インテグレーションドキュメントを削除済みとしてマークしてください。
- インテグレーション API ドキュメントを更新します。
次のマイナーリリース(M.1)で:
- インテグレーションのモデルと残りのコードを削除します。
- インテグレーションのラベル (
~Integration::<name>
) を持つイシュー、マージリクエスト、エピックはすべて閉じます。 -
gitlab-org
から、インテグレーションのラベル (~Integration::<name>
) を削除します。
進行中のマイグレーションとリファクタリング
開発者は、インテグレーションチームがインテグレーションプロパティの定義方法を統一している最中であることを知っておく必要があります。
インテグレーション例
新しいインテグレーションを追加する例については、以下のイシューを参照してください:
- Datadog:Prometheusインテグレーションと同様のメトリクスコレクター。
- EWM/RTC: 外部イシュー・トラッカー。
- Shimo:Confluence と External Wiki のインテグレーションに似た外部 Wiki。
- Webex Teams:チャット通知。
- ZenTao: Jiraインテグレーションに似たカスタムイシュービューを持つ外部イシュートラッカー。