Как вставить скрипт bash в файл YAML

#bash #yaml #gitlab-ci

#bash #yaml #gitlab-ci

Вопрос:

Я пытаюсь создать задание GitLab CI / CD, которое берет скрипт bash из файла YAML и проверяет, правильный ли синтаксис.

У меня есть файл YAML с именем .gitlab-ci.template.yml со следующим содержимым:

 image: node:10.15.3-alpine

stages:
  - deploy

deploy:
  stage: deploy
  script:
    - apk_install
    - yarn_install
    - build
    - deploy

.bash: amp;bash |
  function apk_install() {
    apk add jq git curl grep
  }

  function yarn_install() {
     yarn
  }
  function build() {
    echo "Build"

    if [ -f ".gitlab-ci.template.yml" ]; then
       echo "Just a dumb test for more lines"
    fi 
  }

  function deploy() {
    echo "Deploy"
  }

before_script:
  - *bash
  

Я хотел бы взять bash часть и протестировать ее. Я установил shyaml для получения значений из файла YAML, вот так:

 FILE=`cat .gitlab-ci.template.yml | shyaml get-value before_script`
  

Содержимое $FILE было бы:

 - "function apk_install() {n apk add jq git curl grepn}nnfunction yarn_install()  {n yarnn}nfunction build() {n echo "Build"n n if [ -f ".gitlab-ci.template.yml"  ]; thenn echo "Just a dumb test for more lines"n fin}nnfunction deploy()  {n echo "Deploy"n}n"
  

Затем с помощью некоторой следующей команды я снова пытаюсь получить действительный файл:

 echo $FILE | xargs -0 printf '%bn' | sed 's/\[[:space:]]\[[:space:]]/ /g' | sed 's/\"/"/g' | sed 's/\[[:space:]]//g'
  

Теперь я могу удалить некоторые символы из начала и конца. Но мне было интересно, есть ли какой-нибудь лучший / более простой способ?

Ответ №1:

Рассматривали ли вы возможность использования yq?

Вот выражение для извлечения сценария оболочки из вашего файла:

 yq -r '.[".bash"]' .gitlab-ci.template.yml 
  

Результатом является фактический скрипт. Теперь вам просто нужно передать его в компоновщик bash. Я просмотрел этот сайт для вас, но я не смог найти синтаксический анализатор bash, который часто размещается в сообщениях bash (YMMV). Я нашел ShellChecker через Google, но не оценивал тщательно (так что используйте по своему усмотрению).

В конечном счете, ваш код может выглядеть следующим образом:

 yq -r '.[".bash"]' .gitlab-ci.template.yml | ShellChecker # or use your favorite bash linter
  

Ответ №2:

Для того, чтобы вставить скрипт оболочки, встроенный в GitLab CI YAML, комбинация git , yq и shellcheck выполняет трюк, продемонстрированный в этом задании GitLab CI:

 shellcheck:
  image: alpine:3.15.0
  script:
    - |
      # shellcheck shell=sh
      # Check *.sh
      git ls-files --exclude='*.sh' --ignored -c -z | xargs -0r shellcheck -x
      # Check files with a shell shebang
      git ls-files -c | while IFS= read -r file; do
        if head -n1 "${file}" |grep -q "^#\! ?/. (ba|d|k)?sh" ; then
          shellcheck -x "${file}"
        fi
      done
      # Check script embedded in GitLab CI YAML named *.gitlab-ci.yml
      newline="$(printf 'nq')"
      newline=${newline%q}
      git ls-files --exclude='*.gitlab-ci.yml' --ignored -c | while IFS= read -r file; do
        yq eval '.[] | select(tag=="!!map") | (.before_script,.script,.after_script) | select(. != null ) | path | ".[""   join(""].["")   ""]"' "${file}" | while IFS= read -r selector; do
          script=$(yq eval "${selector} | join("${newline}")" "${file}")
          if ! printf '%s' "${script}" | shellcheck -; then
              >amp;2 printf "nError in %s in the script specified in %s:n%sn" "${file}" "${selector}" "${script}"
              exit 1
          fi
        done
      done
  

Задание проверит script , after_script и before_script все места, где сценарий оболочки может появиться в GitLab CI YAML. Он выполняет поиск файлов GitLab CI YAML, соответствующих соглашению об именовании *.gitlab-ci.yml .

Для удобства это задание также проверяет *.sh файлы, которые начинаются с shebang оболочки.

Я также разместил эту информацию на своем сайте по адресуhttps://candrews.integralblue.com/2022/02/shellcheck-scripts-embedded-in-gitlab-ci-yaml

Ответ №3:

Только что заметил, что я должен получить первое сообщение от before_script with shyaml . Итак, я изменил:

 FILE=`cat .gitlab-ci.template.yml | shyaml get-value before_script`
  

Для:

 FILE=`cat .gitlab-ci.template.yml | shyaml get-value before_script.0`
  

Который получит скрипт как есть.