Cadena YAML multilínea para GitLab CI (.gitlab-ci.yml)

83

Estoy tratando de escribir un gitlab-ci.ymlarchivo que usa una cadena de varias líneas para el comando. Sin embargo, parece que no se está analizando. Probé tanto el - |como - >con resultados idénticos.

stages:
  - mystage

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

Cuando intenta ejecutarse, solo se muestra echo -e 'como el script a ejecutar, y no como la cadena de varias líneas completa. Esto me causa problemas.

¿Cuál sería la sintaxis correcta para escribir algo como esto?

samanime
fuente
Hay un problema para esto: gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/166 No tengo claro cuál es el problema, ya que su código debería ser equivalente (suficiente) YAML a las soluciones propuestas allí . Puede intentar agregar \a sus líneas, pero no puedo decir si funcionará o no.
Jordan Running

Respuestas:

35

TL; DR; Desea utilizar un escalar YAML de varias líneas (para facilitar la lectura) que se carga como una cadena de una sola línea que se puede emitir como un comando por Gitlab-CI. Para hacerlo, use un escalar simple (sin comillas) en YAML que se extienda en varias líneas:

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

Tenga en cuenta que YAML impone algunas restricciones a dichos escalares. Lo que ciertamente necesita saber es que cada línea siguiente tiene una sangría de al menos una posición más que echo -e(que tiene dos posiciones con sangría en relación con su nodo de colección, que no tiene sangría en absoluto), y que cada nueva línea se reemplaza por un espacio cuando se carga (por lo que debe tener un poco de cuidado de dónde colocar las nuevas líneas).


Hay varios conceptos erróneos en tu publicación que te llevan a hacer la pregunta incorrecta.

No existe una cadena YAML de varias líneas . YAML tiene escalares y algunos de estos escalares se pueden cargar mediante un programa como cadenas, mientras que otros se cargarán como enteros, flotantes, etc.

Obviamente, está interesado en los nodos escalares que se cargan como una cadena, ya que esa cadena se puede interpretar como una línea de comandos. Pero no desea tener una línea de comandos de varias líneas (es decir, con nuevas líneas incrustadas), ya que los scripts de varias líneas no son compatibles con Gitlab CI (como indicó @Jordan).

Para facilitar la lectura, desea utilizar la capacidad estándar de YAML para cargar escalares de varias líneas como una cadena de una sola línea.

Si no le importa la legibilidad, puede usar:

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

y dado que su escalar no está citado (es decir, comienza con echo), no necesita hacer nada especial en YAML para las barras invertidas o las comillas.

El resultado del guión es el mismo (imprima una línea vacía, imprima echo 'hi';en una línea con sangría de cuatro espacios, imprima echo 'bye';en una línea con sangría de cuatro espacios).

Si desea utilizar la entrada multilínea para facilitar la lectura, que se cargan como una sola línea, existen esencialmente dos opciones: utilizar un escalar plano multilínea o utilizar un escalar plegado en su YAML.

escalar simple multilínea

Sencillo significa que el escalar no está entre comillas y, como con cualquier cosa de varias líneas en YAML, las siguientes líneas deben tener una sangría adecuada, en este caso más allá de la línea inicial.

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

las nuevas líneas se reemplazan por espacios, así que no lo hagas:

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

ya que obtendrá un espacio visible antes bye.

Existen algunas restricciones como que no puede tener dos puntos seguidos de un espacio dentro de dicho escalar (lo que lo haría parecer un par clave-valor).

No hay necesidad de escapar de las barras invertidas en escalares simples, ya que no puede escapar de ningún carácter en un escalar simple, pero por supuesto puede incluir una barra invertida, que terminará en la cadena cargada desde el YAML y puede tener significado para el comando ejecutado de esa cadena.

escalar doblado

Un escalar plegado es similar a un escalar simple en que todas las líneas nuevas (únicas) se sustituyen por un espacio durante la carga:

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

Necesita sangrar la información real del comando al menos tanto como el indicador escalar plegado ( >).

Al contrario de los escalares simples, cosas como :no tienen un significado especial. Entonces, si los escalares simples fallan al lanzar un error YAML, lo más probable es que los escalares plegados similares no lo hagan.

Anthon
fuente
Quiero escribirlo en varias líneas para mayor claridad y facilidad de mantenimiento. Si bien mi ejemplo es trivial, los guiones reales definitivamente no lo son.
samanime
Puedo entender eso. ¿Sería aceptable preprocesar su archivo YAML legible antes de que GitLab CI lo procese?
Anthon
Lo he considerado. Es un paso adicional y un poco más de complejidad, pero puede valer la pena.
samanime
Agregué una posible solución.
Anthon
3
Oh chico. Si bien técnicamente es correcta, esta respuesta es ridículamente detallada hasta el punto de que no se puede leer. Todo el mundo no escribir un analizador YAML probablemente sólo quiere PotatoFarmer 's altamente upvoted y mucho respuesta más concisa , en su lugar.
Cecil Curry
111

Vine aquí de forma preventiva esperando que esto fuera un problema, pero el siguiente comando "multilínea" para mejorar la legibilidad me está funcionando:

Gitlab Runner: Shell Runner versión 1.11.0 / Gitlab versión: 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}
Granjero De Patatas
fuente
2
¿Cuál es el truco aquí? ¿Ha sangrado la segunda línea al mismo nivel que la primera?
Victor Grazi
6
@ victor-grazi Según tengo entendido: en YAML simple (escalar de flujo simple), los escapes (como la nueva línea \n) no hacen nada y se ignoran los espacios en blanco iniciales; parece que Gitlab YAML analiza los bloques de script de esta manera. Sobre la sangría: la especificación YAML dice In YAML block styles, structure is determined by indentationy, por lo tanto, la segunda línea tiene sangría tanto como sea necesario para la especificación YAML (un espacio relativo a la sangría principal) y uno más para la legibilidad (que es técnicamente superflua pero más bonita).
PotatoFarmer
Funciona de maravilla. También funciona con todos los parámetros en la nueva línea
bodolsog
25

Puede utilizar cualquier script / comando de varias líneas a través de yaml literal_block y la función de anclajes. Ejemplo:

.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
fuente
Gracias por compartir: esta funcionalidad más avanzada será particularmente útil para la legibilidad del trabajo / poder reutilizar fragmentos de código en toda la receta.
PotatoFarmer
5
Este es un gran ejemplo, pero sería más claro si define .rsync
Victor Grazi
13

El comando wp config create era bastante complicado ... desde el .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
fuente
4

Esto funciona para mí en 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

Aquí también se interpolarán dos variables env ( ${GITHUB_USERNAME}y ${GITHUB_PASSWORD})

Maksim Kostromin
fuente
0

Este formato funcionará. use un escalar simple (sin comillas) en YAML. Por ejemplo, script utilizado para inicializar terraform backend

  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"
trabajando
fuente