GitLab CIを使用してプロジェクトを構築:数百のアプリケーション用の1つの.gitlab-ci.yml



この記事は、多数の同様のアプリケーションのアセンブリ記述を管理する問題を解決します。 GitLab CIをプロジェクトで機能させるには、リポジトリに.gitlab-ci.ymlファイルを追加する必要があります。 しかし、100のリポジトリで、これが同じ内容のファイルである場合はどうでしょうか? 一度リポジトリに分解しても、後でそれを変更する方法はありますか? しかし、1つの.gitlab-ci.ymlでアセンブリが不十分な場合はどうでしょうかDappfileまたはDappfile 、異なるスクリプト、HelmのYAMLファイルの構造が必要ですか? それらを更新する方法は?

何百もの類似のアプリケーションを組み立てるタスクの解決をどこから始めますか? もちろん、GitLab CIを指定して別のリポジトリの.gitlab-ci.ymlを使用したり、他のリポジトリのファイルから.gitlab-ci.yml.gitlab-ci.ymlたりできるかどうかを確認してください...

そのような機会を探して、次の問題がすぐに現れます。


ある種の一般的な.gitlab-ci.ymlを持つ能力はコミュニティに興味があることが.gitlab-ci.ymlます。 別のリポジトリ内のファイルからインクルードセクションを追加する決定は非常に単純なようです。これは長年のプログラミングの実践に基づいており、誰にも明らかです。 ただし、ソースツリーの場合はコンセプトが適切に機能しますが、いくつかのGitリポジトリの場合は、このソリューションにこのような欠点があります。

  1. インクルードでは、ファイルを接続するブランチを指定する必要があるため、アセンブリは再生されません。
  2. インクルードでは、ファイルの接続元のブランチを指定する必要があるため、有効な.gitlab-ci.ymlをキャッシュし、保存して、それに基づいて再構築する必要があります。
  3. 一部のプロジェクトでは、パラグラフ1を解決する必要がありますが、一部のプロジェクトでは、パラグラフ2は相互に排他的です。
  4. 接続されたファイルで何かが変更された場合、 .gitlab-ci.yml基本的に変更しようとしているプロジェクトを変更しますが、変更履歴は表示されません。

同様のアプリケーションの場合、さらに2つのマイナスが追加されます。

  1. 何百もの同一の.gitlab-ci.ymlの問題は残っています。
  2. 追加ファイルの更新に関する問題も残っています。

別の角度から見る


includeを使用したソリューションはプルモデルです。 アセンブリプロジェクトは、CI構成の一部を描画します。 プルをプッシュに置き換えると、次のようになります。


このオプションは次のように機能します.gitlab-ci.yml ci-configプロジェクト.gitlab-ci.yml他の何百ものプロジェクトに共通の.gitlab-ci.ymlファイルを保存します。 このファイルが変更されると、 gitlab-ci-distributorは他のプロジェクトにコミットします。

ビルドファイルの場合、選択できます:コミットに追加するか、プロジェクトの.gitlab-ci.ymlで、ビルドタスクで、 common-ci-configプロジェクトのgit cloneを追加します。

このアプローチの利点:


GitLab API


そのため、問題が特定され、解決策があります。 続行するには、GitLab API( GitLab Webサイトのドキュメント)について話す必要があります。 次の方法が必要です。


APIメソッドはcurlを使用して呼び出すことができ、応答として返されるJSONはjq( フィルタードキュメンテーション )を使用して処理できます。

メソッドを呼び出すには、アクセストークンを作成する必要があります。 これについてはこの記事でさらに説明しますが、今のところは、グループ内のプロジェクトのリストを取得する方法の例です。

 $ curl -s --header "PRIVATE-TOKEN: $TOKEN" https://gitlab.example.com/api/v4/groups/group-of-alike-projects/projects?simple=true | \ jq -r '.[] | "\(.path_with_namespace)\t\(.id)"' group-of-alike-projects/project-pasiphae 7 group-of-alike-projects/project-megaclite 6 group-of-alike-projects/project-helike 5 group-of-alike-projects/project-erinome 4 group-of-alike-projects/project-callisto 3 group-of-alike-projects/project-aitne 2 group-of-alike-projects/project-adrastea 1 

GitLabを構成する


APIメソッドを呼び出すことは、許可なしでは不可能です。 GitLabは、アクセストークンを介して承認を提供します。 このようなトークンを取得するには、必要なリポジトリを管理する権限を付与される別のユーザーを作成する必要があります。 これをgitlab-ci-distributorユーザーとします:





次に、このユーザーになり、アクセストークンを作成する必要があります。



アセンブリファイルを管理する必要があるプロジェクトにアクセスするには、 gitlab-ci-distributorユーザーをグループに追加する必要があります。



プロジェクト共有ファイルはプロジェクトcomm-ci-configに保存されます。 プロジェクトは、別のグループ(たとえば、 infra)で作成する必要があります。 プロジェクト設定で、受信したトークンの値を持つ秘密変数が追加されます。



説明されているアクションは、管理者によって1回実行されます。 さらに、すべての構成はcommon-ci-configリポジトリー内のファイルを介して行われます。

Common-ci-configリポジトリ


これで、GitLab CIを介してAPIの操作をテストできます。 これを行うには、単純な.gitlab-ci.yml common-ci-config .gitlab-ci.yml追加され.gitlab-ci.yml

 stages: - distribute distribute: stage: distribute script: - ./distribute.sh 

...およびdistribute.shスクリプト。これまでのところ、選択したグループのコミットおよびプロジェクトに関する情報が表示されます。

 #!/usr/bin/env bash curl -s --header "PRIVATE-TOKEN: $DISTRIBUTOR_TOKEN" https://gitlab.example.com/api/v4/projects/infra%2Fcommon-ci-config/repository/commits/$CI_COMMIT_SHA | jq '.' curl -s --header "PRIVATE-TOKEN: $DISTRIBUTOR_TOKEN" https://gitlab.example.com/api/v4/groups/group-of-alike-projects/projects?simple=true | \ jq -r '.[] | "\(.path_with_namespace)\t\(.id)"' 

ジョブ結果の配布

 Running with gitlab-runner 10.1.0 (c1ecf97f) on gitlab (d82a6d8f) Using Shell executor... Running on gitlab... Fetching changes... HEAD is now at 08dcc92 Initial .gitlab-ci.yml and distribute.sh Checking out 08dcc92a as master... Skipping Git submodules setup $ ./distribute.sh { "id": "08dcc92abf0d951194ad1ffcc23deeb875855320", "short_id": "08dcc92a", "title": "Initial .gitlab-ci.yml and distribute.sh", "created_at": "2017-10-25T16:35:15.000+03:00", "parent_ids": [ "d9bdea91d081025c2af658209f23f684c96b5cee" ], "message": "Initial .gitlab-ci.yml and distribute.sh\n", "author_name": "root root", "author_email": "root.root@gitlab.example.com", "authored_date": "2017-10-25T16:35:15.000+03:00", "committer_name": "root root", "committer_email": "root.root@gitlab.example.com", "committed_date": "2017-10-25T16:35:15.000+03:00", "stats": { "additions": 0, "deletions": 0, "total": 0 }, "status": "running", "last_pipeline": { "id": 2, "sha": "08dcc92abf0d951194ad1ffcc23deeb875855320", "ref": "master", "status": "running" } } group-of-alike-projects/project-pasiphae 7 group-of-alike-projects/project-megaclite 6 group-of-alike-projects/project-helike 5 group-of-alike-projects/project-erinome 4 group-of-alike-projects/project-callisto 3 group-of-alike-projects/project-aitne 2 group-of-alike-projects/project-adrastea 1 Job succeeded 

distribute.shスクリプトの完了


スクリプトは、共通の.gitalb-ci.ymlを配布し.gitalb-ci.ymlcommon-ci-configプロジェクトの.gitlab-ci.ymlプロジェクトと混同しないように、ファイルはcommonディレクトリーにあります。 ファイルには、簡単な自動タスクが記述されています。

 # common/.gitlab-ci.yml stages: - build build: stage: build script: - echo Building project $CI_PROJECT_PATH 

distribute.shスクリプトには、すでにコミットに関する情報とプロジェクトのリストが含まれています。 プロジェクトへの美しいコミットを取得するには、作成者の名前とメール、およびコミットの完全なメッセージを強調する必要があります。 また、受信したプロジェクトにループを追加し、各プロジェクトに対してコミットを作成するメソッドを呼び出す必要があります。

変更distribute.shれたdistribute.sh

 #!/usr/bin/env bash COMMIT_INFO=$(curl -s --header "PRIVATE-TOKEN: $DISTRIBUTOR_TOKEN" https://gitlab.example.com/api/v4/projects/infra%2Fcommon-ci-config/repository/commits/$CI_COMMIT_SHA) #     ,  jq  -r MESSAGE=$(echo "$COMMIT_INFO" | jq '.message') AUTHOR_NAME=$(echo "$COMMIT_INFO" | jq -r '.author_name') AUTHOR_EMAIL=$(echo "$COMMIT_INFO" | jq -r '.author_email') CONTENT=$(base64 -w0 common/.gitlab-ci.yml) PAYLOAD=$(cat <<- JSON { "branch": "master", "commit_message": $MESSAGE, "author_name": "$AUTHOR_NAME", "author_email": "$AUTHOR_EMAIL", "actions": [ { "action": "update", "file_path": ".gitlab-ci.yml", "content": "$CONTENT", "encoding": "base64" } ] } JSON ) echo "$PAYLOAD" curl -s --header "PRIVATE-TOKEN: $DISTRIBUTOR_TOKEN" https://gitlab.example.com/api/v4/groups/group-of-alike-projects/projects?simple=true | \ jq -r '.[] | "\(.path_with_namespace)\t\(.id)"' | \ while read project do name=`echo $project | awk '{print $1}'` id=`echo $project | awk '{print $2}'` echo Update project $name curl -s --request POST --header "PRIVATE-TOKEN: $DISTRIBUTOR_TOKEN" \ --header "Content-Type: application/json" \ --data "$PAYLOAD" https://gitlab.example.com/api/v4/projects/$id/repository/commits done echo Stop 

ジョブ結果の配布



group-of-alike-projects / project-pasiphaeプロジェクトでは、コミットは次のようになります。



group-of-alike-projects / project-pasiphaeプロジェクトビルドタスクの結果:



タスクを実行するユーザーはgitlab-ci-distributorであることがわかります。 しかし同時に、コミットの作成者はcommon-ci-configでコミットしたユーザーです。

同時自動ビルドを無効にする


distribute.shスクリプトは、一度に複数のプロジェクトにコミットを追加します。 これにより、新しいパイプラインが作成され、アセンブリタスクが同時に起動されます。 この効果は必ずしも必要ではありません。 .gitlab-ci.ymlを更新するコミット.gitlab-ci.ymlビルド.gitlab-ci.ymlようにするには、最初に警告メッセージで条件を設定できます。

 script: - 'if [ "x$GITLAB_USER_NAME" == "xgitlab-ci-distributor" ] ; then echo -e "\033[0;31m\n\n    .gitlab-ci.yml .\n\n\033[0m"; exit 1; fi' 

注意! GITLAB_USER_NAME変数はGitLab 10.0 (2017年9月22日リリース )に登場しました。 以前のバージョンではGITLAB_USER_IDのみがあり、条件にはユーザーIDを使用する必要があります。 このIDは、たとえば、 script: [export]または次のAPIリクエストを使用してタスクを実行することで見つけることができます。

 curl -s --header "PRIVATE-TOKEN: $DISTRIBUTOR_TOKEN" https://gitlab.example.com/api/v4/users?username=gitlab-ci-distributor | jq '.[] | .id' 

結果:



このタスクを通常のユーザーから再度実行すると、すべてが成功します。



おわりに


一般に、この情報は、大規模プロジェクト管理を独自に実験し続けるのに十分です。

実験を簡素化し、記事で説明されていることを繰り返すために、たとえばgitlab-vagrantプロジェクトを使用して、仮想マシンにGitLabをインストールできます。 Vagrantfileを修正する必要があることに注意してください。ベースイメージをubuntu/xenial64変更し、メモリvb.memory = "3072"を増やします。 そして、起動後、 指示に従ってgitlab-runnerを追加します

ソリューションの開発時に、次のリソースが使用されました。


PS


私たちのブログも読んでください(そして、新しい出版物を見逃さないように購読してください!)

Source: https://habr.com/ru/post/J340996/


All Articles