タスク実行の分散 (DTE)
Lerna は、キャッシングと--since
フラグにより、平均的な CI 時間を短縮します。しかし、これらの機能は最悪のシナリオには効果がありません。リポジトリの中核部分に変更があった場合、すべてのタスクを CI で実行する必要があり、パフォーマンスを向上させる唯一の方法は、エージェントジョブを増やし、タスクを効率的に並列化することです。
タスクを並列化するための最も分かりやすい方法は、タスクの種類別に分割することです。テストタスクを1つのジョブで、ビルドタスクを別のジョブで、lint タスクを3つ目のジョブで実行します。この戦略はビニングと呼ばれます。一部のテストタスクにビルドタスクが前提条件としてある場合、これは困難になる可能性がありますが、何らかの方法でそれを処理できると仮定すると、典型的な設定は以下の図のようになります。ここでは、テストタスクは必要なビルドアーティファクトがすべて準備できるまで遅延されますが、ビルドタスクとlintタスクはすぐに開始できます。
ビニングアプローチの問題点は、1つ以上のジョブでアイドル時間が発生することです。Nx の分散タスク実行は、タスクの平均実行時間に基づいて各タスクをエージェントジョブに割り当てることで、アイドル時間を最小限に抑えます。Nx はまた、タスクが正しい順序で実行されることを保証し、分散キャッシュを使用して、前のタスクのビルドアーティファクトがそれを必要とするすべてのエージェントジョブに存在することを確認します。
Nx の分散タスク実行を設定すると、タスクグラフは次のようになります。
CI がより高速に完了するだけでなく、デバッグエクスペリエンスは、すべての CI を単一のジョブで実行した場合と同じです。これは、Nx が分散キャッシュを使用して、メインジョブですべてのログとビルドアーティファクトを再作成するためです。
最悪のケースの CI 時間を改善するための詳細なガイドについては、この詳細ガイドをご覧ください。
設定
タスク実行を分散するには、(1) Nx Cloud に接続し、(2) CI ワークフローで DTE を有効にする必要があります。これらの手順は、それぞれ1つのコマンドで有効にできます。
nx connect-to-nx-cloud
nx generate @nrwl/workspace:ci-workflow --ci=github
--ci
フラグは、github
、circleci
、またはazure
にすることができます。DTE の設定の詳細については、このガイドをお読みください。
CI 実行フロー
分散タスク実行は、任意の CI プロバイダーで動作します。CI システムでジョブを起動する責任はユーザーにあります。Nx Cloud は、それらのジョブが連携する方法を調整します。CI システムで作成する必要がある2種類のジョブがあります。
- 実行するものを制御する1つのメインジョブ
- タスクを実際に実行する複数のエージェントジョブ
メインジョブの実行フローは以下のようになります。
# Coordinate the agents to run the tasks
- npx nx-cloud start-ci-run
# Run any commands you want here
- lerna run lint --since=main & lerna run test --since=main & lerna run build --since=main
# Stop any run away agents
- npx nx-cloud stop-all-agents
エージェントジョブの実行フローは非常にシンプルです。
# Wait for tasks to execute
- npx nx-cloud start-agent
メインジョブは、分散を使用していない場合とほぼ同じように見えます。実行する必要があるのは、最初にnpx nx-cloud start-ci-run
を呼び出し、必要に応じて最後にnpx nx-cloud stop-all-agents
を呼び出すだけです。
エージェントジョブは、特定の CI ランに関連付けられたすべてのタスクを実行する、長期間実行されるstart-agent
プロセスを実行します。設定するために必要なのは、npx nx-cloud start-agent
を呼び出すだけです。このプロセスは、Nx Cloud が終了するように指示するまで実行され続けます。
メインジョブとエージェントジョブは、同じ環境とソースコードを持っていることが重要です。ほぼ同時に開始します。そして、メインジョブが完了すると、すべてのアージェントが停止します。
Nx Cloud エージェントはマシンではなく、マシン上で実行される長期間実行されるプロセスであることにも注意してください。つまり、Nx Cloud はエージェントを管理しません。CI 設定で管理する必要があります(以下の CI の例を参照してください)。
Nx Cloud はオーケストレーターです。メインジョブは Nx Cloud に実行したいものを伝え、Nx Cloud はそれらのタスクをエージェント間で分散します。Nx Cloud は、エージェント間、エージェントからメインジョブへのファイルの移動を自動的に行います。
最終的な結果は、メインジョブでlerna run build --since=main
が完了すると、エージェントで作成されたすべてのファイルアーティファクトがメインジョブにコピーされることです。まるでメインジョブがローカルですべてをビルドしたかのように。
並列実行
--concurrency
はエージェントに伝達されます。たとえば、npx lerna run build --since=main --concurrency=3 --dte
は、Nx Cloud に各エージェントで最大3つのビルドターゲットを並列で実行するように指示します。したがって、たとえば10個のエージェントがある場合、それらすべてで最大30個のビルドを並列で実行します。
できるだけ多くのコマンドを並列で実行することも重要です。たとえば、
- lerna run lint --since=main
- lerna run test --since=main
- lerna run build --since=main
は、
- lerna run lint --since=main & lerna run test --since=main & lerna run build --since=main
より劣ります。後者は、3つのコマンドすべてを同時にスケジュールするため、エージェントがビルドするものを何も見つけられない場合、テストとlintを実行し始めます。その結果、エージェントの利用率が向上し、CI時間が短縮されます。
CI/CD の例
以下の例は、分散タスク実行と分散キャッシュを使用して Nx と Nx Cloud を使用した CI を設定する方法を示しています。
すべての組織が CI/CD パイプラインを異なる方法で管理しているため、これらの例は、CI/CD の組織固有の側面(たとえば、デプロイメント)をカバーしていません。主に Nx の正しい設定に焦点を当てています。
CI でそれらを構成する方法の詳細については、ガイドをお読みください。
キャッシュ可能な操作のみを分散できることに注意してください。メインジョブで再現する必要があるためです。