- 構文の確認
- 変数の検証
- GitLab CI/CD ドキュメント
-
よくあるCI/CDのイシュー
- ジョブやパイプラインが期待通りに実行されない
- 多くのジョブを持つパイプラインが起動に失敗します。
- ジョブの予期せぬ実行
- “fatal: reference is not a tree” エラー
- マージリクエストパイプラインメッセージ
- マージリクエストステータスメッセージ
- マージリクエストルールウィジェットは、スキャン結果ポリシーが無効または重複していることを示します。
- プロジェクト
group/project
が見つからないか、アクセスが拒否されました。 - 「パースされた YAML が大きすぎます。
.gitlab-ci.yml
ファイルの編集時に 500 エラーが発生します。- CI/CD ジョブが再実行されたときに新しい設定を使用しません。
- 他のプロジェクトからイメージをプルできない
- パイプラインの警告
- ディザスタリカバリ
- CI/CD トラブルシューティング Rails コンソールコマンド
- ヘルプの入手方法
CI/CDのトラブルシューティング
GitLab はパイプラインのトラブルシューティングを簡単にするためのツールをいくつか提供しています。
このガイドでは、よくあるイシューと考えられる解決策も挙げています。
構文の確認
問題の初期の原因は、構文が正しくないことです。パイプラインはyaml invalid
バッジを表示し、構文やフォーマットの問題が見つかった場合は実行を開始しません。
パイプラインエディタで.gitlab-ci.yml
を編集します。
パイプラインエディタは、(シングルファイルエディタやWeb IDEよりも)推奨される編集環境です。これには以下が含まれます:
- 使用可能なキーワードのみを使用するようにするコード補完の提案。
- 自動シンタックスハイライトと検証
-
CI/CD 設定を視覚化し、
.gitlab-ci.yml
ファイルをグラフィカルに表示します。
.gitlab-ci.yml
を内部で編集します。
パイプライン設定をローカルで編集したい場合は、エディタでGitLab CI/CDスキーマを使って基本的な構文の問題を確認することができます。Schemastore をサポートしているエディタは、デフォルトで GitLab CI/CD スキーマを使います。
スキーマに直接リンクする必要がある場合は、以下にあります:
https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/editor/schema/ci.json
CI/CDスキーマがカバーするカスタムタグの全リストを見るには、スキーマの最新版をチェックしてください。
CI Lintツールで構文を確認
CI LintツールはCI/CD設定ファイルの構文が正しいことを確認する簡単な方法です。基本的な構文を確認するために、完全な.gitlab-ci.yml
ファイルまたは個々のジョブの設定を貼り付けてください。
プロジェクトに.gitlab-ci.yml
ファイルが存在する場合、CI Lint ツールを使って完全なパイプラインの作成をシミュレートすることもできます。このツールは設定構文をより深く検証します。
変数の検証
CI/CDのトラブルシューティングで重要なのは、パイプラインに存在する変数とその値を確認することです。パイプラインの設定の多くは変数に依存しており、変数の検証は問題の原因を見つける最も早い方法の1つです。
問題のある各ジョブで利用可能な変数の完全なリストをエクスポートします。期待する変数が存在するかどうか、そしてその値が期待するものであるかどうかをチェックします。
GitLab CI/CD ドキュメント
complete.gitlab-ci.yml
reference には、パイプラインの設定に使える全てのキーワードの完全なリストが含まれています。
また、多くのパイプライン設定例や テンプレートを見ることもできます。
パイプラインタイプのドキュメント
ブランチパイプラインは最も基本的なタイプです。他のパイプラインタイプには、それぞれ詳細な使用ガイドがあります:
- マルチプロジェクトパイプライン:パイプラインが別のプロジェクトのパイプラインをトリガーします。
- 親/子パイプライン:メイン パイプラインをトリガーして、同じプロジェクト内の別のパイプラインを実行できます。実行時に子パイプラインの設定を動的に生成することもできます。
-
マージ リクエスト パイプライン:マージリクエストのコンテキストでパイプラインを実行します。
- マージ結果パイプライン:マージリクエストパイプライン: ソースブランチとターゲットブランチを結合して実行します。
- マージトレイン:変更がマージされる前にキューに入れられ、自動的に実行される複数のマージ結果パイプライン。
CI/CD 機能のトラブルシューティングガイド
CI/CDのいくつかの機能と関連するトピックについて、トラブルシューティングガイドを用意しています:
よくあるCI/CDのイシュー
よくあるパイプラインの問題の多くは、rules
またはonly/except
設定の動作を分析することで解決できます。挙動が異なるので、同じパイプラインでこの2つの設定を使うべきではありません。動作が異なるため、同じパイプラインでこの2つの設定を使うべきではありません。このように動作が異なるパイプラインの動作を予測するのは困難です。
rules
やonly/except
設定がCI_PIPELINE_SOURCE
やCI_MERGE_REQUEST_ID
のような定義済みの変数を使用している場合、最初のトラブルシューティングとしてそれらを検証する必要があります。
ジョブやパイプラインが期待通りに実行されない
ジョブがパイプラインに追加されるかどうかはrules
またはonly/except
キーワードによって決まります。パイプラインが実行されているにもかかわらず、ジョブがパイプラインに追加されない場合、通常はrules
またはonly/except
の設定に問題があることが原因です。
エラーメッセージもなく、パイプラインがまったく実行されないようであれば、rules
やonly/except
の設定、あるいはworkflow: rules
キーワードが原因かもしれません。
only/except
rules
キーワードに only/except
変換する場合は、only/except
rules
設定の詳細 を注意深く確認する必要が only/except
あります。とrules
のonly/except
動作は異なって only/except
おり、両者間のマイグレーション時に予期しない動作を引き起こす可能性があります。
rules
](jobs/job_control.md#common-if-clauses-for-rules) の[共通のif
節は、期待通りの動作をするルールを書く方法の例として非常に役に立ちます。
2つのパイプラインを同時に実行
マージリクエストが開かれているブランチにコミットをプッシュする際に、2つのパイプラインを同時に実行することができます。通常、一方のパイプラインはマージリクエストパイプラインで、もう一方はブランチパイプラインです。
この状況は通常rules
の設定に起因するもので、パイプラインの重複を防ぐ方法がいくつかあります。
ジョブがパイプラインにない
GitLab はジョブがパイプラインに追加されたかどうかを、ジョブに対して定義されたonly/except
やrules
に基づいて判断します。実行されなかったのであれば、おそらく期待通りに評価されていないのでしょう。
パイプラインが実行されないか、間違ったタイプのパイプラインが実行された場合
パイプラインが実行される前に、GitLabは設定内のすべてのジョブを評価し、利用可能なすべてのパイプラインタイプに追加しようとします。評価の最後にジョブが追加されていなければ、パイプラインは実行されません。
パイプラインが実行されなかった場合、すべてのジョブにrules
やonly/except
があり、パイプラインへの追加がブロックされている可能性があります。
間違ったパイプラインタイプが実行された場合、rules
またはonly/except
の設定をチェックし、ジョブが正しいパイプラインタイプに追加されていることを確認する必要があります。例えば、マージリクエストパイプラインが実行されなかった場合、ジョブはブランチパイプラインに追加された可能性があります。
また、workflow: rules
の設定がパイプラインをブロックしているか、間違ったパイプラインタイプを許可している可能性もあります。
多くのジョブを持つパイプラインが起動に失敗します。
インスタンスで定義されたCI/CD の制限を超える数のジョブを持つパイプラインが起動に失敗します。
パイプラインのジョブ数を減らすには、親子パイプラインを使用して.gitlab-ci.yml
設定を分割します。
ジョブの予期せぬ実行
ジョブがパイプラインに予期せず追加される一般的な理由は、changes
特定の場合にキーワードが常にtrueと評価される changes
ためです。changes
例えば changes
、スケジュールされたパイプラインやタグのパイプラインなど、特定のパイプラインタイプでは常に真になります。
changes
キーワードは、only/except
またはrules
と組み合わせて使用します。)ジョブがブランチパイプラインまたはマージリクエストパイプラインにのみ追加されるように、rules
またはonly/except
設定と一緒にchanges
を使用することをお勧めします。
“fatal: reference is not a tree” エラー
GitLab 12.4で導入されました。
以前はブランチをリモートリポジトリに強制的にプッシュすると、予期せぬパイプラインの障害が発生することがありました。次のようなワークフローで、問題を説明します。
- ユーザーが
example
という名前の機能ブランチを作成し、それをリモートリポジトリにプッシュしたとします。 - 新しいパイプラインが
example
ブランチで実行を開始します。 - ユーザーが
example
ブランチを最新のデフォルトブランチにリベースし、リモートリポジトリに強制プッシュします。 - 新しいパイプラインが再び
example
ブランチで実行を開始しますが、以前のパイプライン(2)はfatal: reference is not a tree:
エラーのために失敗します。
これは、前のパイプラインがexample
ブランチからcheckout-SHA(パイプラインレコードに関連付けられている)を見つけることができず、コミット履歴がすでにforce-pushによって上書きされているために発生します。同様に、マージ結果のパイプラインも 同じ理由で断続的に失敗することがあります。
GitLab 12.4では、パイプラインの参照を排他的に保持することで、この動作を改善しました。
-
example
という名前の機能ブランチにパイプラインが作成されます。 -
refs/pipelines/<pipeline-id>
に永続的なパイプライン参照が作成され、関連するパイプラインレコードのチェックアウト-SHAが保持されます。この永続的なrefは、example
ブランチのコミット履歴がforce-pushによって上書きされても、パイプラインの実行中そのままの状態を保ちます。 - ランナーは永続的なパイプラインrefをフェッチし、checkout-SHAからソースコードを取得します。
- パイプラインが終了すると、永続的な ref はバックグラウンドプロセスでクリーンアップされます。
マージリクエストパイプラインメッセージ
マージリクエストパイプラインウィジェットは、マージリクエストのパイプラインステータスに関する情報を表示します。マージステータスウィジェットの上に表示されます。
「自動的にマージする能力をチェックしています。
マージリクエストがChecking ability to merge automatically
メッセージで立ち往生する既知のイシューがあります。
マージリクエストにこのメッセージが表示され、数分経っても消えない場合は、以下の回避策をお試しください:
- マージリクエストページを更新してください。
- マージリクエストを閉じて再度開きます。
-
/rebase
クイックアクションでマージリクエストを再ベースします。 - マージリクエストがマージ可能であることをすでに確認している場合、
/merge
クイックアクションでマージすることができます。
「パイプラインステータスの確認」メッセージ
このメッセージはマージリクエストが最新のコミットに関連付けられているパイプラインを持っていない場合に表示されます。これは次のような理由が考えられます:
- GitLab はまだパイプラインの作成を完了していません。
- 外部のCIサービスを使っていて、GitLabがそのサービスからまだ返答を受け取っていません。
- プロジェクトで CI/CD パイプラインを使っていない場合。
- プロジェクトで CI/CD パイプラインを使用しているが、設定によってマージリクエストのソースブランチ上でパイプラインが実行できない状態になっています。
- 最新のパイプラインが削除されました (これは既知のイシューです)。
- マージリクエストのソースブランチは非公開フォークにあります。
パイプラインが作成されると、メッセージはパイプラインのステータスで更新されます。
マージリクエストステータスメッセージ
マージリクエストステータスウィジェットは表示します:
- マージリクエストがマージ可能な場合。マージリクエストがマージできない場合、その理由が表示されます。
- パイプラインが完了している場合はマージし、パイプラインが実行中の場合は自動マージに設定します。
「CI/CD パイプラインはマージする前に実行し、成功する必要があります。
このメッセージは、プロジェクトでパイプラインが成功する必要がある設定が有効で、パイプラインがまだ正常に実行されていない場合に表示されます。パイプラインがまだ作成されていない場合や、外部の CI サービスを待っている場合にも適用されます。プロジェクトでパイプラインを使用しない場合は、Pipelines must succeedを無効にしてマージリクエストを受け付けるようにしてください。
“マージがブロックされました: パイプラインが成功しなければなりません。失敗を修正する新しいコミットをプッシュしてください” メッセージ
このメッセージはマージリクエストパイプライン、マージ結果パイプライン、マージトレインパイプラインが失敗した場合、もしくはキャンセルされた場合に表示されます。基本ブランチパイプラインが失敗した場合は発生しません。
マージ・リクエスト・パイプラインまたはマージ結果パイプラインがキャンセルされた、または失敗した場合、次のことができます:
- マージリクエストのパイプラインタブでパイプラインの実行を選択して、パイプライン全体を再実行します。
- 失敗したジョブのみを再試行します。パイプライン全体を再実行する場合は、この操作は必要ありません。
- 失敗を修正するために新しいコミットをプッシュします。
マージトレインパイプラインが失敗した場合は、次のようにします:
- 失敗を確認し、
/merge
クイックアクション を使用して、マージリクエストを直ちにトレインに再度追加できるかどうかを判断します。 - マージリクエストのパイプラインタブでパイプラインの実行を選択してパイプライン全体を再実行し、マ ージリクエストを列車に再度追加します。
- コミットをプッシュして失敗を修正し、再度マージリクエストを列車に追加します。
マージトレインパイプラインが、マージリクエストがマージされる前に、失敗せずにキャンセルされた場合:
- 再度列車に追加してください。
マージリクエストルールウィジェットは、スキャン結果ポリシーが無効または重複していることを示します。
GitLab 15.0 以降のセルフマネージメントでは、プロジェクトがグループからエクスポートされ、別のグループにインポートされ、スキャン結果のポリシールールがあったことが最も考えられる原因です。これらのルールはエクスポートされたプロジェクトとは別のプロジェクトに保存されています。その結果、プロジェクトには、インポートされたプロジェクトのグループには存在しないエンティティを参照するポリシールールが含まれています。その結果、ポリシー ルールが無効、重複、またはその両方になります。
GitLabインスタンスから無効なスキャン結果のポリシールールをすべて削除するには、管理者がRailsコンソールで以下のスクリプトを実行します。
Project.joins(:approval_rules).where(approval_rules: { report_type: %i[scan_finding license_scanning] }).where.not(approval_rules: { security_orchestration_policy_configuration_id: nil }).find_in_batches.flat_map do |batch|
batch.map do |project|
# Get projects and their configuration_ids for applicable project rules
[project, project.approval_rules.where(report_type: %i[scan_finding license_scanning]).pluck(:security_orchestration_policy_configuration_id).uniq]
end.uniq.map do |project, configuration_ids| # We take only unique combinations of project + configuration_ids
# If we find more configurations than what is available for the project, we take records with the extra configurations
[project, configuration_ids - project.all_security_orchestration_policy_configurations.pluck(:id)]
end.select { |_project, configuration_ids| configuration_ids.any? }
end.each do |project, configuration_ids|
# For each found pair project + ghost configuration, we remove these rules for a given project
Security::OrchestrationPolicyConfiguration.where(id: configuration_ids).each do |configuration|
configuration.delete_scan_finding_rules_for_project(project.id)
end
# Ensure we sync any potential rules from new group's policy
Security::ScanResultPolicies::SyncProjectWorker.perform_async(project.id)
end
プロジェクトgroup/project
が見つからないか、アクセスが拒否されました。
このメッセージは、設定がinclude
、以下のいずれかで追加された場合に表示されます:
- 設定が見つからないプロジェクトを参照しています。
- パイプラインを実行しているユーザーは、含まれているプロジェクトにアクセスできません。
これを解決するには、以下を確認します:
- プロジェクトのパスは
my-group/my-project
形式で、リポジトリ内のフォルダを含んでいません。 - パイプラインを実行するユーザーは、インクルードされたファイルを含むプロジェクトのメンバーです。ユーザーは、同じプロジェクトで CI/CD ジョブを実行する権限も持っている必要があります。
「パースされた YAML が大きすぎます。
このメッセージは YAML 設定が大きすぎる、もしくはネストが深すぎる場合に表示されます。インクルードの数が多く、全体で数千行の YAML ファイルはこのメモリ制限にぶつかる可能性が高くなります。たとえば、200kbのYAMLファイルはデフォルトのメモリ制限にぶつかる可能性が高いです。
設定サイズを小さくするには、次のようにします:
- パイプラインエディタの[Full configuration]タブで、展開されたCI/CD設定の長さを確認します。削除または簡略化できる重複設定を探します。
- 長い、または繰り返される
script
セクションをプロジェクト内のスタンドアロンスクリプトに移動します。 - 親パイプラインと子パイプラインを使用して、一部のジョブを独立した子パイプラインのジョブに移動します。
セルフマネージドインスタンスでは、サイズ制限を増やすことができます。
.gitlab-ci.yml
ファイルの編集時に 500 エラーが発生します。
ウェブエディタで .gitlab-ci.yml
ファイルを編集する際に、インクルードされた設定ファイルのループにより 500
エラーが発生することがあります。
CI/CD ジョブが再実行されたときに新しい設定を使用しません。
パイプラインの設定はパイプラインが作成されたときだけ取得されます。ジョブを再実行すると、毎回同じ設定が使われます。include
で追加された個別のファイルを含め、設定ファイルを更新した場合、新しい設定を使用するには新しいパイプラインを開始する必要があります。
他のプロジェクトからイメージをプルできない
GitLab16.3では、CI_JOB_TOKENの設定をLimit access_to_this projectに変更して、このプロジェクトへのアクセスを許可します。
Runner が非公開プロジェクトからイメージをプルしようとすると、以下のエラーでジョブが失敗することがありました:
WARNING: Failed to pull image with policy "always": Error response from daemon: pull access denied for registry.example.com/path/to/project, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
このエラーは以下の両方が真である場合に発生します:
- 画像をホストしている非公開プロジェクトで、この_プロジェクトへの_アクセスを制限するオプションが有効になっている場合。
- 画像を取得しようとしているジョブが、非公開プロジェクトの許可リストにないプロジェクトで実行されています。
推奨される解決策は、非公開プロジェクトのジョブトークンスコープのallowlistにプロジェクトを追加することです。
パイプラインの警告
パイプライン設定の警告は、以下の場合に表示されます:
- CI Lintツールで設定を検証します。
- 手動でパイプラインを実行します。
“ジョブは1つのアクションに対して複数のパイプラインを実行することができます” 警告
when
節でif
節を指定せずにrules
を使うと、複数のパイプラインが実行される可能性があります。通常、これはマージリクエストが開かれているブランチにコミットをプッシュしたときに発生します。
パイプラインの重複を防ぐには、workflow: rules
を使用するか、実行可能なパイプラインを制御するルールを書き換えてください。
resource_group
を使ったジョブがスタックした場合のコンソールでの回避策
# find resource group by name
resource_group = Project.find_by_full_path('...').resource_groups.find_by(key: 'the-group-name')
busy_resources = resource_group.resources.where('build_id IS NOT NULL')
# identify which builds are occupying the resource
# (I think it should be 1 as of today)
busy_resources.pluck(:build_id)
# it's good to check why this build is holding the resource.
# Is it stuck? Has it been forcefully dropped by the system?
# free up busy resources
busy_resources.update_all(build_id: nil)
ジョブログの更新が遅い
実行中のジョブのログページにアクセスすると、ログが更新されるまでに最大60秒の遅延が発生することがあります。デフォルトの更新時間は 60 秒ですが、ログが UI で表示された後、次のようなログの更新が 3 秒ごとに発生するはずです。
ディザスタリカバリ
継続的なダウンタイム中にデータベースへのストレスを軽減するために、アプリケーションの重要だが計算コストのかかる部分を無効にすることができます。
共有ランナーでのフェアスケジューリングの無効化
大量のジョブのバックログをクリアする場合、ci_queueing_disaster_recovery_disable_fair_scheduling
機能フラグを一時的に有効にすることができます。このフラグは共有 Runner のフェアスケジューリングを無効にし、jobs/request
エンドポイントのシステムリソース使用量を削減します。
有効にすると、ジョブは多くのプロジェクトにまたがってバランスされるのではなく、システムに投入された順番に処理されます。
コンピュートクォータ強制の無効化
共有Runner上の計算クォータの実施を無効にするには、ci_queueing_disaster_recovery_disable_quota
機能フラグを一時的に有効にします。このフラグは、jobs/request
エンドポイントのシステムリソース使用量を削減します。
この機能を有効にすると、直近の 1 時間に作成されたジョブは、クォータが不足しているプロジェクトで実行することができます。それ以前のジョブは、定期的なバックグラウンドワーカー (StuckCiJobsWorker
) によってすでにキャンセルされています。
CI/CD トラブルシューティング Rails コンソールコマンド
以下のコマンドはrailsコンソールで実行します。
保留中のパイプラインのキャンセル
project = Project.find_by_full_path('<project_path>')
Ci::Pipeline.where(project_id: project.id).where(status: 'pending').count
Ci::Pipeline.where(project_id: project.id).where(status: 'pending').each {|p| p.cancel if p.stuck?}
Ci::Pipeline.where(project_id: project.id).where(status: 'pending').count
マージリクエストのインテグレーションをお試しください。
project = Project.find_by_full_path('<project_path>')
mr = project.merge_requests.find_by(iid: <merge_request_iid>)
mr.project.try(:ci_integration)
.gitlab-ci.yml
ファイルの検証
project = Project.find_by_full_path('<project_path>')
content = p.repository.gitlab_ci_yml_for(project.repository.root_ref_sha)
Gitlab::Ci::Lint.new(project: project, current_user: User.first).validate(content)
既存のプロジェクトで AutoDevOps を無効にします。
Project.all.each do |p|
p.auto_devops_attributes={"enabled"=>"0"}
p.save
end
ランナー登録トークンの取得
Gitlab::CurrentSettings.current_application_settings.runners_registration_token
ランナー登録トークンの発行
appSetting = Gitlab::CurrentSettings.current_application_settings
appSetting.set_runners_registration_token('<new-runners-registration-token>')
appSetting.save!
パイプラインスケジュールを手動で実行
Railsコンソールからパイプラインスケジュールを手動で実行することで、通常は表示されないエラーを明らかにすることができます。
# schedule_id can be obtained from Edit Pipeline Schedule page
schedule = Ci::PipelineSchedule.find_by(id: <schedule_id>)
# Select the user that you want to run the schedule for
user = User.find_by_username('<username>')
# Run the schedule
ps = Ci::CreatePipelineService.new(schedule.project, user, ref: schedule.ref).execute!(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
ヘルプの入手方法
パイプラインのイシューを解決できない場合は、以下のヘルプをご利用ください:
- GitLab コミュニティフォーラム
- GitLabサポート