YAML для веб-разработчиков

0
68
views

Перевод статьи «Yaml for Web Developers».

Photo by Vipul Jha on Unsplash

Все чаще и чаще веб-разработчикам, чтобы стать лучшими профессионалами и меньше зависеть от окружающих в каких-то простых вещах из смежных сфер деятельности, приходится самим изучать эти вещи.

Если вы начинаете карьеру в сфере фронтенд-разработки, вам наверняка встречались файлы с расширением .yml. Например, .travis.yml (для Travis Build) или .gitlab-ci.yml (для GitLab CI). Но давайте начистоту: вы хорошо понимаете, что это за чертовщина?

Зачем люди используют файлы такого типа? Каковы преимущества этих файлов? Как эта штука работает?

Цель этой статьи — познакомить вас с со структурой YAML, чтобы вы при необходимости смогли прочитать и понять такой файл и внести нужные изменения.

Ведь все мы чувствуем себя очень неловко и раздражаемся, когда что-то нужно сделать, а мы даже не понимаем, что это такое.

Прежде всего, что такое YAML?

Как написано на официальном сайте,

«YAML (рекурсивный акроним, означающий «YAML это не язык разметки») это дружественный к человеку стандарт сериализации данных для всех языков программирования».

Этот формат часто используется для конфигурационных файлов, а это МНОГОЕ объясняет, верно?

Кучи конфигов, в которых никто не мог разобраться, очень утомляли людей, пока кто-то однажды не сказал:

«А что, если бы можно было писать файлы конфигурации, как кулинарные рецепты? Я имею в виду, с минимальным количеством очень понятного текста».

И — бум! — в мае 2001 года был создан YAML.

YAML vs JSON

Сюрприз! (или нет): YAML это надмножество для нашего хорошего знакомого — JSON.

«Надмножество это язык программирования, содержащий все функции данного языка, но при этом расширенный или улучшенный и включающий также другие функции», — Font.

Если бы мне нужно было провести какие-то аналогии, я бы сказал, что в мире фронтенда YAML это нечто вроде TypeScript, а JSON — вроде JavaScript.

Чтобы лучше понять, как это возможно, давайте рассмотрим пример:

{
  "compilerOptions": {
    "module": "system",
    "noImplicitAny": true,
    "removeComments": true,
    "preserveConstEnums": true,
    "outFile": "../../built/local/tsc.js",
    "sourceMap": false,
    "types": ["node", "lodash", "express"]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}

Это пример файла tsconfig.json. Его очень легко читать, мы легко можем разобраться, что к чему, но… есть и некоторые ограничения. Например:

  • нельзя создавать переменные;
  • нельзя использовать внешние переменные (скажем, переменные окружения);
  • перезапись значений.

Если мы в мире JS можем создать конфигурационный файл .json, мы практически всегда можем создать и файл .js (как .eslintrc и .eslint.js), что позволяет нам смягчить указанные выше недостатки.

Но когда вы используете другой язык программирования, .js-файлы это не вариант. Вот здесь YAML и проявляет себя во всей красе.

Если бы нам нужно было переписать tsconfig.json в синтаксисе YAML, чтобы обеспечить такой же результат, файл выглядел бы следующим образом:

compilerOptions:
  module: system
  noImplicitAny: true
  removeComments: true
  preserveConstEnums: true
  outFile: '../../built/local/tsc.js'
  sourceMap: false
  types:
    - node
    - lodash
    - express
include:
  - src/**/*
exclude:
  - node_modules
  - '**/*.spec.ts'

Примечание: это только пример! tsconfig нельзя писать на YAML!

Надеюсь, эти примеры помогли вам начать понимать саму идею.

Концепции, типы и синтаксис

А теперь давайте углубимся в концепцию языка.

Отступы

В YAML отступы имеют значение. Уровни вложенности здесь определяются пробельными отступами (т. е., tab использовать нельзя).

Если вы, как и я, используете tab повсеместно, установите какой-нибудь плагин в вашей IDE для замены табов на пробелы (например, editorconfig). Благодаря этому вы будете спокойно нажимать tab, а символ табуляции будет заменяться пробелами.

Root

Поскольку отступы имеют значение, если перед первым объявлением нет отступов, YAML будет считать его корнем вашего файла (нулевым уровнем):

person:
  age: 20

Это как первая фигурная скобка в JSON:

{
  "person": {
    "age": 20
  }
}

Ключ/значение

Как и JSON/JS, YAML использует синтаксис key/value. Делать это можно по-разному:

key: value
key_one: value one
key one: value # Это странно, тем не менее работает.
'my key': somekey

Комментарии

Чтобы написать комментарий, перед сообщением нужно просто поставить знак решетки.

#Я - комментарий.
person: # Я - тоже комментарий.
  age: 20

Это очень удобно, когда нужно задокументировать какое-то решение или оставить примечание. К сожалению, в JSON это недоступно.

Списки

Есть два способа писать списки:

Как в JSON: массив из строк

Вы же помните, что YAML это надмножество JSON? Мы можем использовать синтаксис последнего:

people: ['Anne', 'John', 'Max']
Синтаксис с дефисами

Более распространенный вариант (и, пожалуй, рекомендуемый).

people:
  - Anne
  - John
  - Max

Строки

В YAML есть несколько способов объявления строки:

company: Google # Отдельные слова, без кавычек
full_name: John Foo Bar Doe # Полное предложение, без кавычек
name: 'John' # Использование одинарных кавычек
surname: "Christian Meyer" # Использование двойных кавычек

А в JSON есть только один способ — при помощи двойных кавычек:

{
  "company": "Google",
  "full_name": "John Foo Bar Doe",
  "name": "John",
  "surname": "Christian Meyer"
}

Совет: когда используете любые специальные символы (вроде _, @ и т. п.), отдавайте предпочтение двойным кавычкам.

Числа

Как и в языках программирования, здесь есть два вида чисел: Integer (целые числа) и Float (числа с плавающей запятой):

year: 2019 # Integer
nodeVersion: 10.8 # Float

Якоря

Якорь это механизм создания группы данных (объекта), которую можно вставить в другие объекты и расширить за счет других объектов.

Давайте представим, что вам нужно создать конфигурацию для вашей CI. Она будет иметь и продакшен-, и стейджинг-среду. Как вы догадываетесь, настройки там будут практически одинаковые.

В мире JSON нам пришлось бы дублировать эти конфиги:

{
  "production": {
    "node_version": "13.0.0",
    "os": "ubuntu",
    "package_manager": "yarn",
    "run": ["yarn install", "NODE_ENV=${ENVIRONMENT} yarn build"],
    "env": {
      "ENVIRONMENT": "production"
    }
  },
  "staging": {
    "node_version": "13.0.0",
    "os": "ubuntu",
    "package_manager": "yarn",
    "run": ["yarn install", "NODE_ENV=${ENVIRONMENT} yarn build"],
    "env": {
      "ENVIRONMENT": "staging"
    }
  }
}

Но копипаст раздражает, особенно если приходится потом вносить изменения в разных местах.

Якоря решают эту проблему. Мы можем:

1. Создать наш якорь.

# Я называю это "base-config", но это может быть что угодно
# &base будет "именем переменной", которое вы сможете использовать для вставки
base-config: &base
  node_version: 13.0.0
  os: ubuntu
  package_manager: yarn
  run:
    - yarn install
    - NODE_ENV=${ENVIRONMENT} yarn build

2. Вставить созданный якорь на уровне, где мы хотели бы видеть эти значения.

base-config: &base
  node_version: 13.0.0
  os: ubuntu
  package_manager: yarn
  run:
    - yarn install
    - NODE_ENV=${ENVIRONMENT} yarn build

production:
  # Я вставляю все атрибуты "base" в production
  <<: *base
  env:
    - ENVIRONMENT: production

staging:
  # Я вставляю все атрибуты "base" в staging
  <<: *base
  env:
    - ENVIRONMENT: staging

Выглядит проще, правда? И поддерживать легче.

Если вы скопируете этот код и вставите его в онлайн-конвертер «YAML в JSON», вы увидите тот же код, который я показывал в качестве примера на JSON, но внутри дополнения из base config:

{
  "base-config": {
    "node_version": "13.0.0",
    "os": "ubuntu",
    "package_manager": "yarn",
    "run": ["yarn install", "NODE_ENV=${ENVIRONMENT} yarn build"]
  },
  "production": {
    "node_version": "13.0.0",
    "os": "ubuntu",
    "package_manager": "yarn",
    "run": ["yarn install", "NODE_ENV=${ENVIRONMENT} yarn build"],
    "env": [
      {
        "ENVIRONMENT": "production"
      }
    ]
  },
  "staging": {
    "node_version": "13.0.0",
    "os": "ubuntu",
    "package_manager": "yarn",
    "run": ["yarn install", "NODE_ENV=${ENVIRONMENT} yarn build"],
    "env": [
      {
        "ENVIRONMENT": "staging"
      }
    ]
  }
}

JSON-синтаксис (да, JSON)

Как уже объяснялось, надмножество языка это базовый язык ПЛЮС некоторые дополнительные функции. Это означает, что файл YAML можно писать в стиле JSON:

{
  "details": {
    "company": {
      "name": "Google",
      "year": 2019,
      "active": true
    },
    "employees": [
      "Anne",
      "John",
      "Max"
    ]
  }
}

Сомневаетесь? Скопируйте код и вставьте сюда.

Если вы конвертируете этот YAML в JSON, вы получите ту же структуру:

{
  "details": {
    "company": {
      "name": "Google",
      "year": 2019,
      "active": true
    },
    "employees": ["Anne", "John", "Max"]
  }
}

Окружение Shell/Bash

Как я уже говорил в начале статьи, .yml-файлы часто используются в качестве конфигурационных файлов для многих вещей, но особенно для окружений CI/CD.

В этих файлах вам нужно описать, как должна работать машина/docker, что должно быть установлено, запущено и т. д.

Зачастую все эти окружения это Linux, а значит, вы также имеете доступ к самому окружению.

В GitLab CI, например, вы можете определить для глобального окружения переменные, к которым хотите иметь доступ в течение всего процесса:

variables:
  NODE_IMAGE: node:10

stages:
  - build

test:
  image: $NODE_IMAGE
  stage: build

Обратите внимание, что синтаксис для использования переменных при помощи $ — не из YAML, а из shell/bash.

GitLab CI берет все, что вы определили в variables, и создает переменные shell.

Некоторые другие платформы также вводят другие значения, такие как имя ветки, время сборки, автор, а также секретные ключи, определенные вне конфигурации:

variables:
  NODE_IMAGE: node:10

stages:
  - build

test:
  image: $NODE_IMAGE
  stage: build
  artifacts:
    name: $CI_COMMIT_REF_NAME

В приведенном примере мы использовали переменную внешнего окружения $CI_COMMIT_REF_NAME, которую платформа GitLab CI сделала доступной.

Заключение

Надеюсь, теперь вы немного лучше разбираетесь в том, что такое YAML, и сможете более уверенно читать и писать такие файлы.

Имейте в виду, что используемая вами платформа может накладывать собственные ограничения на то, к чему вы можете иметь доступ. Например, конфигурации Travis отличаются от GitLab CI или CircleCI.

Чтобы понять, что возможно, а что — нет, всегда в первую очередь ориентируйтесь на документацию используемой платформы.

Полезные ссылки

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here