0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GitLab CI/CDのPipelinesからMRを読み取り流れを変える

Posted at

はじめに

目的

  • MRのdescriptionでGitLabのCI/CDの流れを変えること

利益

  • 流れを細分化した一つのpipelineで類似しているテストをまとめて管理できます
  • 文字列を解析するから直感的な記述でCI/CDをコントロールすることができます

使用例

  • マルチのリポジトリをまとめてビルドできます
  • MRがブロックされてる場合ビルドをスキップできます

PipelinesからMRを読み取り流れを変える

シナリオ

readyステージのCheck MRというジョブでMRを読み取り以後のパイプラインで使う環境変数を設定すると仮定します。

シナリオの最終目的は

  1. REPO1でMRがpipelineをトリガーした時
  2. REPO1のMRに記載された依存情報を利用して
  3. REPO2のMRの情報を読み取り
  4. ビルドに使用する依存先のブレンチの名前を得る事です。

適用例

Merge request

mr_example.png

Pipelineスクリプト

.gitlab-ci.yml
variables:
  GITLAB_URL: "http://gitlab_url"
  #MRはREPO-1で作成されREPO-1はREPO-2に依存していると仮定
  PROJECT_REPO1_ID: "120" # REPO-1
  PROJECT_REPO2_ID: "121" # REPO-2

stages:
  - ready

Check MR:
  stage: ready
  only: 
    - web
    - schedule
    - merge_request
  script:
    - |-
      if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]
      then
        echo "Initialing..."
        MR_DESCRIPTION=$(curl --silent --header "PRIVATE-TOKEN:$GITLAB_PRIVATE_TOKEN" "${GITLAB_URL}/api/v4/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}")
        echo "MR_DESCRIPTION=$(echo "$MR_DESCRIPTION" | python3 -c 'import sys, json; print(json.load(sys.stdin)["description"])')" >> build.env
        DEPEND_MR_IID=$(echo "$MR_DESCRIPTION" | python3 -c 'import sys,re; m=re.search(“MY_PROJECT_REPO2!
\\\{0,1}!([0-9]+)”, str(*sys.stdin)); print("-1") if m is None else print(m.group(1))')
        echo "DEPEND_MR_IID=$DEPEND_MR_IID" >> build.env
        echo "REQUEST_SOURCE_BRANCH_NAME=${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}" >> build.env
        if [ "$DEPEND_MR_IID" == "-1" ]
        then 
          echo "DEPEND_REPO2_BRANCH=master >> build.env
        else 
          echo "DEPEND_REPO2_BRANCH=$(curl --silent --header "PRIVATE-TOKEN:$GITLAB_PRIVATE_TOKEN" "${GITLAB_URL}/api/v4/projects/${PROJECT_REPO2_ID}/merge_requests/${DEPEND_MR_IID}" | python3 -c 'import sys, json; print(json.load(sys.stdin)['source_branch'])')" >> build.env
        fi
      else
        {
          echo "REQUEST_SOURCE_BRANCH_NAME=${CI_COMMIT_REF_NAME}"
          echo "DEPEND_REPO2_BRANCH=master"
        } >> build.env
      fi
  artifacts:
    reports:
      dotenv: build.env

使用している変数

Predefined variables1

  • CI_PIPELINE_SOURCE:トリガーの種類。上記の例ではマージリクエストを判断するために使いました。
CI_PIPELINE_SOURCE
  script:
    - |-
      if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]
      then
        ~~~~~~
      else
        ~~~~~~
      fi
  • CI_MERGE_REQUEST_PROJECT_ID:MRのプロジェクトID
  • CI_MERGE_REQUEST_IID:MRのID
  • CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:MRのソースブレンチの名前
  • CI_COMMIT_REF_NAME:パイプラインが作動されたブレンチの名前

Variables in the .gitlab-ci.yml file

  • GITLAB_URL:GitLabのURL
  • PROJECT_REPO1_ID:現在パイプラインが動作しているリポジトリのID。
  • PROJECT_REPO2_ID:REPO1が依存しているリポジトリのID。

PROJECT_REPO1_IDとPROJECT_REPO2_IDは二つ以上のリポジトリを使うシナリオのための変数です。単一のリポジトリを使う場合はこの二つの変数が関わっている部分は無視してください。

Project CI/CD variables

  • GITLAB_PRIVATE_TOKEN:GitLab APIのためのTOKEN

Variables in artifact "build.env" file (ステージ間の値の受け渡しのための変数)

  • MR_DESCRIPTION:MRのDESCRIPTIONを読み取り保管する変数
  • DEPEND_MR_IID:依存先のMRのIDを保持する変数
  • REQUEST_SOURCE_BRANCH_NAME:REPO1のMRのブレンチの名前
  • DEPEND_REPO2_BRANCH:REPO2のMRのブレンチの名前

スクリプトの解説

MRのDESCRIPTIONが読みたい

GitLabのAPI(/api/v4/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID})を叩くことでMRに関する情報をJSONの形で得ることができます。DESCRIPTIONの所はPYTHONを使って読み取ります。

MR_INFO=$(curl --silent --header "PRIVATE-TOKEN:$GITLAB_PRIVATE_TOKEN" "${GITLAB_URL}/api/v4/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}")
MR_DESCRIPTION=$(echo "$MR_DESCRIPTION" | python3 -c 'import sys, json; print(json.load(sys.stdin)["description"])')

MRのDESCRIPTIONを解析したい

MRのdescriptionを得たのであとは文字列をどう解析して使うかの問題です。ここは決められた方法はありません。自分の目的のデスクリップションに記載されたMR間の依存情報を読み取ることです。
上記の例ではデスクリップション欄にDepends: MY_PROJECT_REPO2!100のように依存先のMRのリンクを記しておいてPythonで100という数字(GitLabでいうMR_IID)だけをパーシングしました。このIIDを利用してまた依存先のREPOのMRの情報を獲得できるようになります。

DEPEND_MR_IID=$(echo "$MR_DESCRIPTION" | python3 -c 'import sys,re; m=re.search(“MY_PROJECT_REPO2\\\{0,1}!([0-9]+)”, str(*sys.stdin)); print("-1") if m is None else print(m.group(1))')

MRが依存している外部のリポジトリのブランチ名を知りたい

上記で読み取ったIIDを利用して今回は依存先のMRの情報を読み取ります。ここではsource_branchを利用してREPO2のどのブレンチを利用するべきかを決めます。

DEPEND_REPO2_BRANCH=$(curl --silent --header "PRIVATE-TOKEN:$GITLAB_PRIVATE_TOKEN" "${GITLAB_URL}/api/v4/projects/${PROJECT_REPO2_ID}/merge_requests/${DEPEND_MR_IID}" | python3 -c 'import sys, json; print(json.load(sys.stdin)['source_branch'])')
  1. Predefined variables reference, https://docs.gitlab.com/ee/ci/variables/predefined_variables.html

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?