2017-03-02 40 views
7

コマンドに複数行の文字列を使用するgitlab-ci.ymlファイルを書き込もうとしています。しかし、それは解析されていないようです。私は同じ結果を持つと- >の両方を試しました。GitLab CI(.gitlab-ci.yml)用の複数行のYAML文字列

stages: 
    - mystage 

Build: 
    stage: mystage 
    script: 
    - | 
     echo -e " 
      echo 'hi'; 
      echo 'bye'; 
     " 

それが実行しようとすると、それだけで全体の複数行の文字列を実行するスクリプトとしてecho -e '示し、そしてません。これは私にとって問題を引き起こします。

このような記述をする正しい構文は何でしょうか?

+0

これは間違っていますが、おそらく 'Build'の後にコロンがありません。 'echo -e'と' echo 'hi''に同じ一重引用符を使い、そのうちの一つに二重引用符を使いたくないのですか? – Anthon

+0

申し訳ありませんが、それらは両方とも私の例の間違いでした。私はそれらを修正しました。私が使用している実際のバージョンは、オンラインのYAML-JSONパーサーで動作しますが、GitLab CIでは失敗します。 – samanime

+0

これには問題があります:https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/166あなたのコードは同等でなければならないので、問題が何であるかは分かりません)YAMLがそこで提案された解決法に至りました。あなたの行に '' \ ''を追加しようとするかもしれませんが、動作するかどうかは言えません。 –

答えて

1

問題は(@Jordanが示されているように)Gitlab CIではサポートされていないmulti-line scriptsに関連すると思わや、あなたの「スクリプト」は、実際に単一のコマンドであるので、あなただけの1行であるためにそれを書き換える必要があります。

- echo -e "\n echo 'hi';\n echo 'bye';\n" 

あなたのスカラーが引用されていない(つまり、それはechoで始まる)ので、バックスラッシュまたは引用符のためにYAMLで特別なことをする必要はありません。

スクリプトの結果は、(4つのスペースをインデント行に、4つのスペースをインデント行に、印刷echo 'bye';を印刷echo 'hi';を空行を出力します。)

を使用すると、複数行を使用する場合と同じです読みやすくするために、入力を前処理することをお勧めします。 Pythonとruamel.yaml(免責:私は作者)を使用することをお勧めします。これにより、引用やコメントのような機能を保存することができます。

stages: 
    - 'mystage' 

Build: 
    stage: mystage 
    # the following is rewritten 
    script: 
    - | 
     echo -e " 
      echo 'hi'; 
      echo 'bye'; 
     " 

と次のPython(バージョン3)プログラム:このgitlab-ci.in.ymlを考える

from pathlib import Path 
import ruamel.yaml 


def flatten_multi_line(d): 
    if isinstance(d, list): 
     for idx, elem in enumerate(d): 
      if isinstance(elem, (list, dict)): 
       flatten_multi_line(elem) 
      elif isinstance(elem, ruamel.yaml.scalarstring.PreservedScalarString): 
       d[idx] = ruamel.yaml.scalarstring.DoubleQuotedScalarString(elem) 
    elif isinstance(d, dict): 
     for key in d: 
      if isinstance(d[key], (list, dict)): 
       flatten_multi_line(d[key]) 
      elif isinstance(d[key], ruamel.yaml.scalarstring.PreservedScalarString): 
       d[key] = ruamel.yaml.scalarstring.DoubleQuotedScalarString(elem) 


in_file = Path('gitlab-ci.in.yml') 
out_file = Path('gitlab-ci.yml') 

with in_file.open() as fp: 
    data = ruamel.yaml.round_trip_load(fp, preserve_quotes=True) 
flatten_multi_line(data) 
with out_file.open('w') as fp: 
    ruamel.yaml.round_trip_dump(data, fp) 

は、次gitlab-ci.ymlを与える:flatten_multi_line()せず

stages: 
- 'mystage' 

Build: 
    stage: mystage 
    # the following is rewritten 
    script: 
    - "echo -e \"\n echo 'hi';\n echo 'bye';\n\"\n" 

(マルチ行の文字列はwとして保存されますell)。あなたはまた、新しく生成されたYAMLファイルの処理を引き起こす可能性のプログラムから

+0

明快さと保守性のために、複数行に分けておきたいと思います。私の例は簡単ですが、実際のスクリプトは明らかにそうではありません。 – samanime

+0

私はそれを理解することができます。 GitLab CIで処理する前に、読み込み可能なYAMLファイルを前処理することは容認できますか? – Anthon

+0

私はそれを考えました。余計なステップと少し複雑さが増しますが、その価値があるかもしれません。 – samanime

11

は、私がここに来た先制期待を(例えばsubprocess.check_output()を使用して、あなたがそれをしたい場合はcheck_output()への引数としてstr()を使用してout_fileをキャストしてください)これは問題になるだろうが、読みやすくするために、次の「マルチライン」コマンドでは、私のために働いている:

Gitlabランナー:シェルランナーバージョン1.11.0 /Gitlabバージョン: 8.17.2

myjob: 
stage: deploy 
script: 
    # Single line command 
    - az component update --add sql 

    # Multi-line command 
    - az sql server create -n ${variable} -g ${variable} -l ${variable} 
    --administrator-login ${variable} --administrator-login-password ${variable} 

私が質問を誤解した場合、または私がいくつかの訴訟原因猶予を経験している場合は、お詫び申し上げます。

+0

これは複数行の文字列を指定するのにうまくいきます – dalore

2

yaml literal_blockとアンカー機能を使用して、任意の複数行のスクリプト/コマンドを使用できます。例:

.build: &build | 
    echo -e "\n$hl Building $green$build_path/$build_assets_dir/*.js $nl\n" 
    echo -e "javascript-obfuscator $build_path/$build_assets_dir/*.js" 
[...] 

build:master: 
    stage: build 
    script: 
    - *rsync 
    - *build 
[...] 
+0

ありがとうございます。この高度な機能は、ジョブの可読性/レシピ全体でコードチャンクを再利用できることに特に役立ちます。 – PotatoFarmer