Wielowierszowy ciąg YAML dla GitLab CI (.gitlab-ci.yml)

86

Próbuję napisać gitlab-ci.ymlplik, który używa ciągu wieloliniowego dla polecenia. Jednak wygląda na to, że nie jest analizowany. Wypróbowałem zarówno te, jak - |iz - >identycznymi wynikami.

stages:
  - mystage

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

Kiedy próbuje uruchomić, wyświetla się tylko echo -e 'jako skrypt do uruchomienia, a nie cały ciąg wielowierszowy. To powoduje dla mnie problemy.

Jaka byłaby poprawna składnia, aby napisać coś takiego?

samanime
źródło
Jest w tym problem: gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/166 Nie jest dla mnie jasne, na czym polega problem, ponieważ Twój kod powinien być równoważny (wystarczający) YAML do proponowanych tam rozwiązań . Możesz spróbować dołączyć \do swoich wierszy, ale nie mogę powiedzieć, czy to zadziała, czy nie.
Jordan Bieganie

Odpowiedzi:

37

TL; DR; Chcesz użyć wielowierszowego skalara YAML (dla czytelności), który jest ładowany jako ciąg pojedynczego wiersza, który może być wydany jako polecenie przez Gitlab-CI. Aby to zrobić, użyj zwykłego (bez cudzysłowów) skalara w YAML, który jest rozłożony na wiele linii:

script:
- echo -e 
   "echo 'hi';
    echo 'bye';"

Należy pamiętać, że YAML nakłada pewne ograniczenia na takie skalary. Z pewnością musisz wiedzieć, że każda następna linia jest wcięta o co najmniej jedną pozycję więcej niż echo -e(która jest wcięta o dwie pozycje względem jej węzła kolekcji, który nie jest w ogóle wcięty) i że każda nowa linia jest zastępowana spacją po załadowaniu (więc musisz trochę uważać, gdzie wstawiać znaki nowej linii).


W Twoim poście jest wiele nieporozumień, które powodują, że zadajesz niewłaściwe pytanie.

Nie ma czegoś takiego jak wieloliniowy ciąg YAML . YAML ma skalary i niektóre z nich mogą być ładowane przez program jako łańcuchy, podczas gdy inne zostaną załadowane jako liczby całkowite, zmiennoprzecinkowe itp.

Oczywiście jesteś zainteresowany węzłami skalarnymi, które są ładowane jako łańcuch, ponieważ ten ciąg może być następnie zinterpretowany jako wiersz poleceń. Ale nie chcesz mieć wielowierszowej linii poleceń (tj. Z osadzonymi znakami nowej linii), ponieważ skrypty wieloliniowe nie są obsługiwane w Gitlab CI (jak wskazał @Jordan).

Aby zwiększyć czytelność, chcesz użyć standardowej zdolności YAML do ładowania wieloliniowych skalarów jako ciągu jednowierszowego.

Jeśli nie dbałbyś o czytelność, możesz użyć:

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

a ponieważ twój skalar nie jest cytowany (tj. zaczyna się od echo), nie musisz robić nic specjalnego w YAML dla odwrotnych ukośników lub cudzysłowów.

Wynik działania skryptu jest taki sam (wypisuje pusty wiersz, wypisuje echo 'hi';wiersz z wcięciem czterech spacji, wypisuje echo 'bye';wiersz wcięty czterema spacjami).

Jeśli chcesz użyć wieloliniowego wejścia dla czytelności, które są ładowane jako pojedynczy wiersz, istnieją zasadniczo dwie opcje: użyj wieloliniowego skalara płaskiego lub użyj zagiętego skalara w swoim YAML.

wieloliniowy zwykły skalar

Zwykły oznacza, że ​​skalar nie jest cytowany i tak jak w przypadku każdej wieloliniowej rzeczy w YAML oznacza to, że kolejne wiersze muszą być odpowiednio wcięte, w tym przypadku dalej niż początkowa linia

script:
- echo -e 
   "echo 'hi';
    echo 'bye';"

znaki nowej linii są zastępowane spacjami, więc nie rób tego:

script:
- echo -e 
   "echo 'hi';
    echo '
   bye';"

jak wcześniej dostaniesz widoczną przestrzeń bye.

Istnieją pewne ograniczenia, takie jak dwukropek, po którym następuje spacja w takim skalarze (co sprawiłoby, że wyglądałby jak para klucz-wartość).

Nie ma potrzeby ucieczki od ukośników odwrotnych w zwykłych skalarach, ponieważ nie można uciec od żadnych znaków w zwykłym skalarze, ale oczywiście można dołączyć ukośnik odwrotny, który zakończy się w ciągu ładowanym z YAML i może mieć znaczenie dla wykonywanego polecenia z tego ciągu.

złożony skalar

Złożony skalar jest podobny do zwykłego skalara, ponieważ wszystkie (pojedyncze) znaki nowej linii są zastępowane spacją podczas ładowania:

script:
- >
  echo -e 
  "echo 'hi';
  echo 'bye';"

Musisz wciąć rzeczywiste informacje o poleceniu co najmniej tak samo, jak zagięty wskaźnik skalarny ( >).

W przeciwieństwie do zwykłych skalarów, takie rzeczy :nie mają specjalnego znaczenia. Więc jeśli zwykłe skalary zawiodą, rzucając błąd YAML, podobne zwinięte skalary najprawdopodobniej nie.

Anthon
źródło
Chcę napisać to w wielu wierszach dla przejrzystości i łatwości konserwacji. Chociaż mój przykład jest trywialny, prawdziwe skrypty zdecydowanie nie.
samanime
Mogę to zrozumieć. Czy byłoby dopuszczalne wstępne przetworzenie czytelnego pliku YAML przed jego przetworzeniem przez GitLab CI?
Anthon,
Rozważyłem to. To dodatkowy krok i nieco dodana złożoność, ale może być tego warta.
samanime
Dodałem możliwe rozwiązanie.
Anthon
3
O chłopie. Chociaż technicznie poprawna, ta odpowiedź jest absurdalnie rozwlekła do tego stopnia, że ​​jest nieczytelna. Wszyscy nie napisanie parsera YAML prawdopodobnie po prostu chce PotatoFarmer „s wysoce upvoted i wiele terser odpowiedź , zamiast.
Cecil Curry
115

Przyszedłem tutaj zapobiegawczo, spodziewając się, że będzie to problem, ale następujące polecenie „wielowierszowe” poprawiające czytelność działa dla mnie:

Gitlab Runner: Shell Runner wersja 1.11.0 / Gitlab wersja: 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}
PotatoFarmer
źródło
2
O co tu chodzi? Czy wcięcie drugiej linii jest takie samo, jak w pierwszej?
Victor Grazi
6
@ victor-grazi Jak rozumiem: W zwykłym YAML (zwykły przepływ skalarny) znaki specjalne (takie jak nowa linia \n) nic nie robią, a początkowe białe znaki są ignorowane - wygląda na to, że Gitlab YAML analizuje bloki skryptów w ten sposób. O wcięciach: specyfikacja YAML mówi In YAML block styles, structure is determined by indentation, że druga linia jest wcięta tak bardzo, jak jest to wymagane dla specyfikacji YAML (jedna spacja w stosunku do wcięcia rodzica), a jeszcze jedna dla czytelności (co jest technicznie zbędne, ale ładniejsze).
PotatoFarmer
Działa jak marzenie. Działa również ze wszystkimi parametrami w nowej linii
bodolsog
26

Możesz użyć dowolnych wielowierszowych skryptów / poleceń za pośrednictwem funkcji Yaml literal_block i anchors. Przykład:

.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
[...]
Benny K.
źródło
Dziękuję za udostępnienie - ta bardziej zaawansowana funkcjonalność będzie szczególnie przydatna ze względu na czytelność zadania / możliwość ponownego wykorzystania fragmentów kodu w całym przepisie.
PotatoFarmer
5
To świetny przykład, ale byłby jaśniejszy, gdybyś zdefiniował .rsync
Victor Grazi
13

Polecenie wp config create było dość skomplikowane ... z pliku .gitlab-ci ...

build:
  stage: build
  script:
    - echo "Building the app"
    - |
        wp config create --dbname=$vardb --dbhost=$varhost --dbuser=$varusr --dbpass=$varpas --extra-php <<PHP
            define( 'WP_DEBUG', false );
            define( 'FS_METHOD', 'direct' );
            define( 'WP_POST_REVISIONS', 5 );
            define( 'AUTOSAVE_INTERVAL', 600 );
        PHP
    - scp ./wp-config.php continued...
  allow_failure: true
mal
źródło
4

To działa dla mnie w Travis CI

before_install:
  - set -e
  - |
    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
    <settings xmlns=\"http://maven.apache.org/SETTINGS/1.0.0\"
              xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
              xsi:schemaLocation=\"http://maven.apache.org/SETTINGS/1.0.0
                                   http://maven.apache.org/xsd/settings-1.0.0.xsd\">
      <servers>
        <server>
          <id>github</id>
          <username>${GITHUB_USERNAME}</username>
          <password>${GITHUB_PASSWORD}</password>
        </server>
      </servers>
    </settings>
    " >  ${HOME}/.m2/settings.xml

Tutaj dwie zmienne env ( ${GITHUB_USERNAME}i ${GITHUB_PASSWORD}) również będą interpolowane

Maksim Kostromin
źródło
0

Ten format będzie działał. użyj zwykłego (bez cudzysłowu) skalara w YAML. Np. Skrypt używany do inicjalizacji zaplecza terraform

  before_script:
    - cd ${TF_ROOT}
    - terraform init -backend-config="address=${GITLAB_TF_ADDRESS}"
      -backend-config="lock_address=${GITLAB_TF_ADDRESS}/lock"
      -backend-config="unlock_address=${GITLAB_TF_ADDRESS}/lock"
      -backend-config="username=${GITLAB_USER_LOGIN}" -backend-config="password=${GITLAB_ACCESS_TOKEN}"
      -backend-config="lock_method=POST" -backend-config="unlock_method=DELETE"
      -backend-config="retry_wait_min=5"
Jobin James
źródło