スクリプトとジョブログのフォーマット

script セクションでは、次のような特別な構文を使用できます:

特殊文字をscript

script コマンドを一重引用符または二重引用符で囲む必要がある場合があります。たとえば、コロン (:) を含むコマンドはシングルクォート (') でラップしなければなりません。YAML パーサーはテキストを “key: value” のペアではなく文字列として解釈する必要があります。

たとえば、このスクリプトはコロンを使います:

job:
  script:
    - curl --request POST --header 'Content-Type: application/json' "https://gitlab/api/v4/projects"

有効な YAML とみなすには、コマンド全体をシングルクォートで囲む必要があります。コマンドがすでに一重引用符を使用している場合、可能であれば二重引用符 (") に変更してください:

job:
  script:
    - 'curl --request POST --header "Content-Type: application/json" "https://gitlab/api/v4/projects"'

CI Lintツールで構文が有効であることを確認できます。

これらの文字を使用する場合にも注意してください:

  • { },[,],,,&,*,#,?,|,-,<,>,=,!,%,@,`.

ゼロ以外の終了コードは無視

スクリプトコマンドがゼロ以外の終了コードを返した場合、ジョブは失敗し、それ以降のコマンドは実行されません。

この動作を回避するには、終了コードを変数に格納します:

job:
  script:
    - false || exit_code=$?
    - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;

すべてのジョブに対してデフォルトのbefore_script またはafter_script を設定します。

before_script およびafter_scriptdefaultとともに使用できます:

  • すべてのジョブでscript コマンドの前に実行されるデフォルトのコマンド配列を定義するには、default とともにbefore_script を使用してください。
  • ジョブが完了した後に実行されるデフォルトのコマンド配列を定義するには、after_script を default とともに使用します。

ジョブの中で別のものを定義することで、デフォルトを上書きすることができます。デフォルトを無視するには、before_script: [] またはafter_script: [] を使用してください:

default:
  before_script:
    - echo "Execute this `before_script` in all jobs by default."
  after_script:
    - echo "Execute this `after_script` in all jobs by default."

job1:
  script:
    - echo "These script commands execute after the default `before_script`,"
    - echo "and before the default `after_script`."

job2:
  before_script:
    - echo "Execute this script instead of the default `before_script`."
  script:
    - echo "This script executes after the job's `before_script`,"
    - echo "but the job does not use the default `after_script`."
  after_script: []

長いコマンドの分割

| (リテラル) と> (折りたたみ) のYAML 複数行ブロックスカラーインジケータを使うことで読みやすくするために長いコマンドを複数行のコマンドに分割できます。

caution
複数のコマンドが1つの文字列にまとめられる場合、最後のコマンドの失敗もしくは成功だけがレポーターされます。それ以前のコマンドの失敗はバグによって無視されます。これを回避するには、各コマンドを個別のscript アイテムとして実行するか、各コマンド文字列にexit 1 コマンドを追加します。

| (リテラル) YAML マルチラインブロックスカラーインジケータを使って、ジョブ記述のscript セクションに複数行にわたってコマンドを書くことができます。 それぞれの行は個別のコマンドとして扱われます。 最初のコマンドだけがジョブログで繰り返されますが、追加のコマンドは実行されます:

job:
  script:
    - |
      echo "First command line."
      echo "Second command line."
      echo "Third command line."

上記の例では、ジョブログに以下のように表示されます。

$ echo First command line # collapsed multiline command
First command line
Second command line.
Third command line.

> (折りたたみ) YAML マルチラインブロックスカラーインジケータはセクション間の空行を新しいコマンドの開始として扱います:

job:
  script:
    - >
      echo "First command line
      is split over two lines."

      echo "Second command line."

これは> もしくは| ブロックスカラーインジケーターを使わない複数行コマンドと同じようにふるまいます:

job:
  script:
    - echo "First command line
      is split over two lines."

      echo "Second command line."

上記の両方の例は、ジョブログに以下のように表示されます。

$ echo First command line is split over two lines. # collapsed multiline command
First command line is split over two lines.
Second command line.

>| ブロックスカラーインジケーターを省略すると、GitLab はコマンドを形成するために空でない行を連結します。行が連結されても実行できることを確認してください。

ここのShellドキュメントは |> のオペレーションでも動作します。以下の例では、小文字を大文字に変換しています:

job:
  script:
    - |
      tr a-z A-Z << END_TEXT
        one two three
        four five six
      END_TEXT

以下の結果になります。

$ tr a-z A-Z << END_TEXT # collapsed multiline command
  ONE TWO THREE
  FOUR FIVE SIX

スクリプト出力にカラーコードを追加

スクリプトの出力は、ANSI エスケープコードを使って色をつけるか、ANSI エスケープコードを出力するコマンドやプログラムを実行することで色をつけることができます。

以下は、Bashでカラーコードを使用する例です。

job:
  script:
    - echo -e "\e[31mThis text is red,\e[0m but this text isn't\e[31m however this text is red again."

カラーコードをShell環境変数やCI/CD変数に定義することで、コマンドを読みやすく、再利用しやすくすることができます。

例えば、上記と同じ例で、before_script で定義された環境変数を使います:

job:
  before_script:
    - TXT_RED="\e[31m" && TXT_CLEAR="\e[0m"
  script:
    - echo -e "${TXT_RED}This text is red,${TXT_CLEAR} but this part isn't${TXT_RED} however this part is again."
    - echo "This text is not colored"

以下は、PowerShellでカラーコードを使用する例です。

job:
  before_script:
    - $esc="$([char]27)"; $TXT_RED="$esc[31m"; $TXT_CLEAR="$esc[0m"
  script:
    - Write-Host $TXT_RED"This text is red,"$TXT_CLEAR" but this text isn't"$TXT_RED" however this text is red again."
    - Write-Host "This text is not colored"

トラブルシューティング

Syntax is incorrect を使用するスクリプトでは:

スクリプトの中でコロン (:) を使うと、GitLab は出力することがあります:

  • Syntax is incorrect
  • script config should be a string or a nested array of strings up to 10 levels deep

例えば、cURLコマンドの一部として"PRIVATE-TOKEN: ${PRIVATE_TOKEN}"

pages-job:
  stage: deploy
  script:
    - curl --header 'PRIVATE-TOKEN: ${PRIVATE_TOKEN}' "https://gitlab.example.com/api/v4/projects"
  environment: production

YAML パーサーは: が YAML キーワードを定義していると考え、Syntax is incorrect エラーを出力します。

コロンを含むコマンドを使うには、コマンド全体をシングルクォートで囲む必要があります。既存の一重引用符 (') を二重引用符 (") に変更する必要があるかもしれません:

pages-job:
  stage: deploy
  script:
    - 'curl --header "PRIVATE-TOKEN: ${PRIVATE_TOKEN}" "https://gitlab.example.com/api/v4/projects"'
  environment: production

スクリプト内で&& を使用してもジョブが失敗しません。

&& を使って2つのコマンドを1つのスクリプト行にまとめると、片方のコマンドが失敗しても、ジョブが成功として返されることがあります。例えば

job-does-not-fail:
  script:
    - invalid-command xyz && invalid-command abc
    - echo $?
    - echo "The job should have failed already, but this is executed unexpectedly."

たとえば、&& 演算子は、2 つのコマンドが失敗しても終了コード0 を返し、ジョブは実行され続けます。いずれかのコマンドが失敗したときにスクリプトを強制終了するには、行全体を括弧で囲みます:

job-fails:
  script:
    - (invalid-command xyz && invalid-command abc)
    - echo "The job failed already, and this is not executed."

折りたたまれたYAMLの複数行ブロックスカラーによって保存されない複数行コマンド

長いコマンドを分割するために- > folded YAML multiline block scalar を使う場合、追加のインデントによって行が個別のコマンドとして処理されます。

使用例:

script:
  - >
    RESULT=$(curl --silent
      --header
        "Authorization: Bearer $CI_JOB_TOKEN"
      "${CI_API_V4_URL}/job"
    )

インデントによって改行が保持されるため、これは失敗します:

$ RESULT=$(curl --silent # collapsed multi-line command
curl: no URL specified!
curl: try 'curl --help' or 'curl --manual' for more information
/bin/bash: line 149: --header: command not found
/bin/bash: line 150: https://gitlab.example.com/api/v4/job: No such file or directory

これを解決するには

  • 余分なインデントを削除します:

     script:
       - >
         RESULT=$(curl --silent
         --header
         "Authorization: Bearer $CI_JOB_TOKEN"
         "${CI_API_V4_URL}/job"
         )
    
  • 余分な改行が処理されるようにスクリプトを修正する、例えばShellの行継続を使用するなど:

     script:
       - >
         RESULT=$(curl --silent \
           --header \
             "Authorization: Bearer $CI_JOB_TOKEN" \
           "${CI_API_V4_URL}/job")