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

Есть еще один метод, который мы используем для управления файлами Makefile:

Dotenv (файлы .env)

Мы любим, любим, любим и используем .env файлы для настройки наших приложений. Если вы не знакомы с ними, суть в том, что они определяют ключи и значения переменных среды в очень простом формате файла. Например, для управления переменной LOG_LEVEL вы можете использовать:

LOG_LEVEL=info

А затем загрузите его при запуске приложения (у большинства языков для этого есть какой-то пакет dotenv).

Хотя наши методы полной настройки — это тема для другого дня, у нас есть несколько правил, которые мы используем во всех наших проектах:

  • Вся конфигурация через переменные среды (не загружать файлы, не обращаться к внешним хранилищам)
  • Всегда используйте файлы .env.
  • Никогда не возвращайте .env файлы.
  • Имейте только один файл .env (без каскадных файлов в зависимости от среды).
  • .env имеет приоритет над значениями в среде.

Некоторые из этих решений, без сомнения, являются спорными, но цель состоит в том, чтобы файлы .env обеспечивали однозначное, каноническое хранение локальных переменных среды, а нелокальные среды использовали любые нативные механизмы для внедрения переменных среды перед запуском процесса (Heroku Config Vars, AWS Parameter Магазин подключен к ECS и т. д.).

Сделать и .env

Это «.env — каноническое хранилище локальной среды» настолько простое и стандартное, что мы даже можем настроить Make для его использования!

Мы помещаем этот блок в начало Makefile — он ищет файл .env и, если он есть, устанавливает из него переменные Make:

ifneq (,$(wildcard ./.env))
    include .env
    export
endif

Где это полезно? Допустим, вы хотите подключиться к базе данных вашего локального приложения. Мы можем поместить этот URL-адрес базы данных в файл .env:

DATABASE_URL=postgres://appuser:pass@localhost:13005/myapp

(Мы всегда запускаем наши базы данных через docker-compose и используем разные порты для разных проектов — вы никогда не вернетесь к :5432, как только начнете делать это таким образом)

Теперь в нашем Makefile мы можем настроить цель для подключения через psql. Обратите внимание на цель cmd-exists-% за прошлую неделю

ifneq (,$(wildcard ./.env))
    include .env
    export
endif
cmd-exists-%:
    @hash $(*) > /dev/null 2>&1 || \
        (echo "ERROR: '$(*)' must be installed and available on your PATH."; exit 1)
psql: cmd-exists-psql
    psql "${DATABASE_URL}"

Теперь запустите его из командной строки:

$ make psql
 psql "postgres://appuser:pass@localhost:13005/myapp"
 psql (12.2, server 11.4 (Debian 11.4-1.pgdg90+1))
 Type "help" for help.

Докер тоже!

Еще одна приятная вещь для этого сверхгибкого файла .env! Docker и docker-compose могут принимать параметр --env-file, и, сохраняя все в одном .env, вы можете использовать одну и ту же конфигурацию между вашим локальным приложением, Make и сборкой Docker.

Вот скорректированный фрагмент Makefile и пример команды Docker:

ifneq (,$(wildcard ./.env))
    include .env
    export
    ENV_FILE_PARAM = --env-file .env
endif
docker-server:
    docker run --rm -it -p $(PORT):$(PORT) $(ENV_FILE_PARAM)

$PORT, разумеется, определяется в файле .env :)

Подробнее в следующий раз

Позже на этой неделе мы поговорим еще об одной полезной вещи, которую мы сделали с Make для еще большей стандартизации. Если вы пишете какой-либо конкретный JavaScript, это меняет вашу жизнь.

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