株式会社ネットワールドのエンジニアがお届けする技術情報ブログです。
各製品のエキスパートたちが旬なトピックをご紹介します。

GitとCI/CDに関する知識ゼロのSEが、GitLabにある自社のサブグループの公開範囲をGraphQL APIでチェックする

皆様こんにちは。SEの小池と申します。

GitLabをご利用の企業様におかれましては、場合によってはルートグループをPublicにしているケースもあるかと存じます。 こういったケースでは、Public 公開してよいグループと、Public 公開してはいけないグループの管理、慎重になりますよね・・・。

今回のブログでは、GitLab.comにおける自社のルートグループ配下のサブグループの公開範囲を、GraphQL APIを使って定期的にチェックする方法 を紹介いたします。
クエリの定期実行のツールにPostmanを使っていますが、他のツールでも実装可能な内容になっていると存じます。

本記事の対象の方

  • GitLab.comの特定のグループ配下のサブグループの公開範囲をAPIで定期的にチェックしたい。
  • チェックした結果をMicrosoft Teamsの特定チャネルに投稿したい。

今回のブログのゴール

このブログのゴールはこちらです。


今回のゴール
  • GitLab.comの自社のサブグループの公開範囲をAPIでチェックする。
  • チェック結果をTeamsに通知する。

このブログをお読みいただくにあたっての事前ご連絡事項

  • 本記事はSaaS版 (GitLab.com) の Enterprise Edition 15.11.0-pre における仕様をベースに記載しております。それ以外のエディションやバージョンではこの記事に記載の通りではない可能性がございます。
  • 本記事では、APIクエリを定期的に実行するツールとしてPostmanを使用しています。2023/04/11現在、本記事の内容はPostmanの無償版で実装可能ですが、将来的にPostmanの無償版の利用規約や利用可能機能が変更された場合は、本記事の内容を実装することができない可能性があります。
  • 本記事はGitやCI/CDに関する知識ゼロのSEによるなんちゃって記事です。GitLabのディープな使用法についてはGitLabの公式オンラインドキュメント (こちら) をご参照ください。
  • 本ブログに掲載されている情報は正確性・安全性を保証するものではありません。本ブログの情報を利用することによって発生した損失や損害については、一切の責任を負いかねます。

実装したい処理

実装したい処理の要件は以下の通りです。
2023/04/14時点で、GitLabは無償版 (CE) でも実装は可能です。 APIクエリの実行 および レスポンスの内容チェックは3rdパーティ製サービスであるPostmanを用います。

  • GitLab.comのルートグループ配下にあるサブグループの公開範囲をAPIでチェックする。
  • チェックは定期的 且つ 自動的に実施する。
  • 全てのサブグループの公開範囲が Private ならOKとする。
  • 1つ以上のサブグループの公開範囲が Public だった場合はNGとする。
  • OK , NG問わず、結果をMicrosoft Teamsの特定のチャネルに投稿する。
  • 公開範囲が Public のサブグループがあった場合は、そのグループ名も Teams に投稿する。

図にするとこんな感じです。

実装 Step1: Microsoft TeamsのIncoming Webhookを準備する

チェックの結果を投稿するTeamsのチャネルに、Incoming Webhookを作成します。
誠に申し訳ないのですがブログの尺の都合上、作成手順は割愛致します。
Incoming Webhookの作成方法は以下の参考URLをご参照ください。

参考 : 受信 Webhook を作成する - Teams | Microsoft Learn

作成したIncoming WebhookのURLをメモしておきます。

実装 Step2: APIトークン作成を作成する

GitLab側でAPIトークンを作成します。
個人のアクセストークンを使用する場合、対象のルートグループのメンバー (Guest 以上) である必要があります。必要なスコープはread_apiです。

作成したトークンをメモしておきます。

実装 Step3: ヘッダーの設定

ここからPostmanの設定になります。 以下をヘッダーに追記します。

表1. ヘッダーに追加する項目
キー
Authorization Bearer <APIトークン>

例) APIトークンがglpat-AAAAAA_BBBBBBの場合
Bearer glpat-AAAAAA_BBBBBB

Content-Type application/json

実装 Step3: GraphQL APIのクエリ作成

特定のルートグループ配下のサブグループ一覧 及び その公開範囲を取ってくるクエリを作成します。
今回はGraphQL API を使います。

GitLab.com (SaaS版) の場合、URLは https://gitlab.com/api/graphqlです。
仮にルートグループパスが https://gitlab.com/company-root-groupの場合、以下のクエリで配下のサブグループ名、公開範囲 (visibility) を取得します。

参考 : GraphQL API Resources | GitLab

query {
  groups(search: "company-root-group/") {
    nodes {
      name
      visibility
    }
  }
}

なおこのクエリでは、たまたま同じ文字列のパスで終わる関係ないルートグループが存在し、且つ、そのグループの公開範囲が Public だと、そのグループもヒットしてしまいます。この場合は前述の参考に記載したリファレンスを参照して、クエリを改善してください。

実装 Step4: テスト 及び 結果をTeamsに投稿するコード作成

次に、クエリの結果をテストする処理を追記します。

[Tests] タブに以下のコードを記載します。
2行目の変数 teamsUrl には、Step1 で作成した Incoming Webhook のURLを指定してください。
仮に Incoming Webhook のURLが、https://aaa.webhook.office.com/webhookb2/aaa@aaa/IncomingWebhook/aaa/aaa の場合、2行目は const teamsUrl = 'https://aaa.webhook.office.com/webhookb2/aaa@aaa/IncomingWebhook/aaa/aaa'; と指定します。

// TeamsのWebhook URL 
const teamsUrl = '<Incoming WebhookのURL>';

// Teamsへの投稿処理 
function postToTeams(themeColor, title, text) {
    pm.sendRequest({
        url: teamsUrl,
        method: 'POST',
        header: {
            'Content-Type': 'application/json'
        },
        body: {
            mode: 'raw',
            raw: JSON.stringify({
                '@type': 'MessageCard',
                '@context': 'http://schema.org/extensions',
                themeColor: themeColor,
                title: title,
                text: text
            })
        }
    }, function (err, res) {
        console.log(res)
    });
}

const publicGroups = pm.response.json().data.groups.nodes.filter(node => node.visibility === 'public');
if (publicGroups.length > 0) {
    // publicが含まれていたらエラー 
    const publicGroupNames = publicGroups.map(group => group.name).join('<br>');
    pm.test("visibility check", () => {
        postToTeams('#FF0000',
          '【要確認】公開範囲が Public のグループが存在します!', 
          `公開範囲が Public のグループが存在します。至急詳細を確認してください。<br><br>${publicGroupNames}`
        );
        throw new Error("There is a public group!")
    });
} else {
    // 全てprivateならOK 
    pm.test("visibility check", () => {
        pm.expect(pm.response.json().data.groups.nodes.every(node => node.visibility === 'private')).to.be.true;
        postToTeams('#0095d9', 
          '【情報】すべてのグループの公開範囲が Private です。', 
          'すべてのグループの公開範囲が Private です。'
        );
    });
}

実装 Step5: 定期実行の設定

作ったクエリとテストを定期的に実行するように設定します。

[Collections] > 対象のコレクション > [Run collection] を開きます。

今回作成したクエリにチェックを入れた状態で、[Schedule runs] を選択し、任意のスケジュールを設定し、[Schedule Run] をクリックします。

これで実装は完了です!

動作確認

作ったロジックをテストします。 前の手順で実装した定時実行を待っても良いですし、手動で実行しても大丈夫です。
手動で実行する場合は、Postmanの [Send] から実行できます。

正常に実行された場合、対象のTeamsチャネルに以下のような投稿がされているかと存じます。

最後に

この度はGitもCI/CDもよくわかっていないど素人SEによるGitLab検証ブログをお読みいただき、誠にありがとうございます。
このブログの目標は以下のとおりでしたが、皆さまはいかがでしたでしょうか。


今回のゴール
  • GitLab.comの自社のサブグループの公開範囲をAPIでチェックする。
  • チェック結果をTeamsに通知する。

最近知ったのですが、このブログにスマートフォンからアクセスしていらっしゃる方が結構いらっしゃるようでしたので、今回は文字を減らしてサンプルコードをシンプルに載せるだけの内容にしてみました。
ど、どうですかね・・・。

それはいいとして、GraphQL APIではもっと複雑なクエリを作成できます。
GitLabと3rd パーティ製のツールの統合にも利用できると存じますので、ご検討いただければと存じます。

この記事がGitLabを触り始めた方の一助となれば幸いにございます。


GitLabに関するお問い合わせは、以下のフォームからお願い致します。
GitLab製品 お問い合わせ

今までのGitLabの検証ブログはこちらです。
GitLab カテゴリーの記事一覧 - ネットワールド らぼ

GitLab操作デモ動画 (基本編) を作ってみました。(音声の録音は自宅でiPhoneのボイスメモ使うという超低クオリティですが…。)
つたない内容ではありますが、ご興味がおありでしたら是非ご視聴いただければと存じます。

www.youtube.com