Pull to refresh

Comments 50

Мы используем простую самописную утилиту, которая вносит изменения во все конфиги проекта (Java). В каждом новом проекте от человека, ответственного за сборку, требуется один раз научить эту утилиту новым кофигам (добавить в её собственный конфиг относительные пути к файлам, xpath'ы или regexp'ы), а от разработчика (или того, кто поднимает приложение на сервере) — один раз указать настройки проекта во втором конфиге утилиты.
Дальше конфигурационные файлы проекта поддерживаются в актуальном для инстанса состоянии автоматически.

Для xml-конфигов можно также воспользоваться включением файла (<!ENTITY myConfig SYSTEM ...>, <root>&myConfig;</root>). Файл с индивидуальными для окружения данными (включаемой частью) — не коммитить. Но это уже близко к понятию извращения.
А я по своему скудоумию сделал облако на xen и у меня везде настройки одинаковые независимо от ОС.
>>> Делайте конфиги, которые не надо часто править.

Сам по себе конфигурационный файл как задумка вообще-то и предназначен для того, чтобы ваш проект мог адекватно вписаться в любое окружение. И его правка — такая же часть разработки, как и все остальные. Другое дело, что разработчики друг другу мешают — но это уже их лечить надо, а не придумывать велосипед для конфигурационных файлов.

ИМХО коммитить не-шаблонные (читай — исправленные под окружение разработчика) конфиги — моветон.

Да и чтобы не возникало вопросов с адаптацией приложения под разные платформы — нужно сесть и продумать, что и как может повлиять на работу вашего приложения в зависимости от системы, отразить это в конфиге, снабдить соусом из объяснительных комментариев и дальше уповать на вменяемость читающего ваш конфиг. Иначе каши не будет.

Снова же, ИМХО, проблемма слегка надуманна.
Точно так!

Надо, чтобы были разные окружения — в репозитории сохраняется шаблон конфигурационного файла типа: «conf.template.py». А сам конфигурационный файл ставим игнор для системы контроля версий, что бы никто случайно не закинул файл в репозиторий.

Каждый разработчик для себя переименовывает файл, задно подставляя свои настройки.

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

PS Единственное неудобство — при добавлении новых строк в конфигурационном файле каждый разработчик должен будет поправить свою версию конфига руками.
Рабочая база данных по умолчанию — разве это хорошо? Появится новый разработчик, которому, как потом окажется, забыли сообщить о настройках переменных окружения, заберет проект из репозитория, и… запоганит вам рабочую базу.
У нас большой проект и сервера распределены по ролям. Мы используем файл whoami.txt, в котором находится просто строка с идентификатором хоста, а в конфиге уже находятся параметры для всех хостов. whoami не находится в репозитории специально. Таким образом мы можем на одной машине содержать разные хосты в разных директориях, в репозитории мы содержим конфиг с перечислением всех хостов. Файл whoami создаётся каждый раз при выгрузке кода.
А не проще когда у каждого разработчика свой конфиг?
А не использует ли кто-нибудь вариант с терминальным доступом к серверу. Т.е. когда одна конфигурация среды на сервере и к нему девелоперы подключаются через терминал или «Удалённый стол» и работают в более-менее одинаковых условиях… Чую, что будут проблемы, но в небольших рабочих группах должно получится…
Используем, очень удобно. Для тех же, кто привык к всяким IDE — есть CVS или SVN и файлики типа .cvs_ignore куда вписываем конфиги.
У меня вот например полная синхронизация — сервер-localhost-localhost2(другой комп, на котором порой пишу) — доступы в базу, во всяком случае, не было проблемой сделать одинаковыми только для локалхоста.
Я вот еще подумал, что проблемы не вижу, — даже если у каждого будут свои доступы — что проще может быть использования локальных отдельных конфигов? Или же привязка к хосту (localhost/site.ru/site.local).

Короч, ни о чём, по-моему=)
>что проще может быть использования локальных отдельных конфигов
используем первый метод (через файл host.conf)

[mysql_host]
mysql_user = medved
mysql_password = preved
mysql_host = 192.168.1.240
mysql_port = 3306
mysql_db = test

и подключаем этот конфиг через стандартную php-функцию parse_ini_file()

$host=parse_ini_file('host.conf');
define('MYSQL_USER',$host['mysql_user']);
define('MYSQL_PASSWORD',$host['mysql_password']);
define('MYSQL_HOST',$host['mysql_host']);
define('MYSQL_PORT',$host['mysql_port']);
define('MYSQL_DB',$host['mysql_db'])
> у разных разработчиков (с разными параметрами окружения) может быть одинаковый хост — скажем, localhost;

ну что за детский сад? =)

касательно хостов — деления на дев/прод мало, ибо есть всякие ключи для внешних апи, которые привязываются к имени хоста.
Чем городить огород с переменными окружения проще поправить /etc/hosts в соответствии с соглашением по разработке и все дела.
Если честно, не задумывался раньше какая это все-таки проблема: локальная разработка и «терминальный» билд :)
У нас для сборки Java приложения, работающего на Jboss'e используется Bamboo — он собирает проект, беря его из репозитория. При этом файлы конфигурации в билд не входят — они свои для каждого участника проекта ( и для стенда на котором проект в итоге собирается).
А что вы делаете, если в конфиг надо внести новый параметр?
Если не лукавить — никак.
При правильной иерархии такое навряд ли случается. Все базовые настройки правятся руками но таких могу назвать только две: какой-нибудь path и параметры коннекта к базе. Все остальное — уже производное от них и такие конфиги входят в сборку.
По-крайне мере в моем случае.
Я думаю, не проблема игнорировать локальные конфиги при коммите. Проблема, что не все фреймворки/библиотеки позволяют разбивать конфиги на части.

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

И, кстати, зачем разработчикам разные версии MySQL? Значительно проще, когда версия одна на всех.
Спасибо. Ценные замечания.

Про сервер, на котором запускаются тесты и проч. У нас используется такое правило: запуск тестов (кроме того, ещё вывод ошибок прямо на экран, помимо логирования) разрешён с определённых IP-адресов. При этом окружение — серверное. При запуске тестов тестовая база сменяется автоматически на *_test (это «кодинг стайл», если хотите). При наших размерах проектов это нормальное решение — хотя, возможно, какой-нибудь хакер и сможет инициировать прогон тестов, подменив IP, я не очень глубоко разбираюсь в сетевых протоколах.

>И, кстати, зачем разработчикам разные версии MySQL? Значительно проще, когда версия одна на всех.
Просто иногда приходится работать с фрилансерами. Поэтому база на localhost, не из интернета же тягать данные.
Понятно. У вас фрилансеры накладывают стиль работы. У нас все в одном офисе, потому и БД разделяемая, и тесты может запускать любой сотрудник. Есть в этом определённые плюсы всё-таки. :)
>Я думаю, не проблема игнорировать локальные конфиги при коммите.

Бывает такое, что конфиг правится. У нас это норма — нет-нет, да добавится какой-нибудь параметр, раз в несколько недель. Проще поправить конфиг всем сразу, чем рассказывать каждому, что именно надо заменить в том файле, который не апдейтится из репозитория. Да, можно сказать, что конфиги надо хранить в БД, а в файле — только доступ к ней… но это на любителя, мне не всегда нравится такой подход.
Вот для таких случаев как раз надо, чтобы конфиги можно было разделять на отдельные файлы. Разработчикам нужно править абсолютные локальные пути, параметры доступа к ресурсам (sql, smtp), адреса электронной почты (чтобы именно на их ящик приходили уведомления с тестовой копии сайта). А вот всякие параметры, относящиеся к бизнес-логике можно хранить в другом конфиг-файле.

Тогда, по идее, будет всё правильно. К сожалению, если речь идёт о фреймворках, то сложно предсказать, есть там возможность разделять конфиги, или нет. Например, ASP.NET версий 1.0/1.1 загружал только web.config, но со 2-й версии любой раздел конфига можно вынести в отдельный файл и править отдельно.
мы делаем следующим образом — при создании виртуального хоста в апаче каждый девелопер прописывает ServerAdmin по своему нику — например

ServerAdmin spirit@project
ServerAdmin user@project и тд.

Следующий preg_match в php получает этот ник
сорри, отправил случайно
*Следующий preg_match в php получает этот ник
preg_match( '~^(.*)\@~Ui', $_SERVER['SERVER_ADMIN'], $section );

А вот уже конфиг database.ini
[default]
host = localhost
username = defaultUser
password = defaultPass
dbname = databaseName
driver = mysql

[spirit: default]
username = spirit
password = mypass
dbname = dbname

[user: default]
host = 192.168.1.100
Раз уж предложили использвать bat файл для запуска скриптов, то можно воспользоваться командой set, в этом случае bat файл будет выглядеть примерно так:

cd "E:\myproject\utils"
set DEV_HOST=DM9
php clean_something.php localhost
pause
Спасибо, действиельно. :)
Я, наверное, что-то невнимательно прочитал. То есть при деплойменте вы заказчику отдаете полный файл? Со своими внутренними паролями?
p.s.
кстати, сам пост хороший, проблема есть, она обозначена, есть пример решения. возможно, комментарии подскажут лучший ;-)
Да, именно так. Хотите я Вам расскажу свой пароль от БД? 123. Логин — root. :)

А production server у нас как раз от заказчика (ну или наш, если фактический заказчик — своя же компания).
не с нашей топологией… :-)
не проще ли виртуалками пользоваться?
Поясните, пожалуйста, что Вы подразумеваете.
виртуалка с единообразным environment, набором сервисов и инструментов у каждого разработчика. настройки девелоперской машины и личные предпочтения на саму среду не влияют.
Хм… Мы уже второй год пользуемся Symfony Framework и такие проблемы отпали сами собой. В среднем у нас на проект есть около 5 разных серверов (prod, test, dev1-3).
Создается environment и используется.

Более подробно можно почитать тут: www.symfony-project.org/book/1_1/05-Configuring-Symfony#Project%20Configuration
А мы в своем «велосипедном» фрэймворке. Мреджим конфиги.
То есть их три уровня
1. framework
2. project
3. production, dev,test,…
Каждый последующий конфиг просто переписывает настройки предыдущих.
При каждом развертываниии нужно создать хитрый файлик который определяет имя конфига третьего уровня. После апдейта из репозитарии конфиги мержатся и кэшируется до следующего обновления или редактирования.
1-й конфиг одинаков для всех сайтов написанных с использованием данного фрэймворка, и лежит в папке фрэймворка.
2-й лежит в отдельной папке с файлами проекта.
3-й располагается рядом со вторым, но под уникальным именем.
Все это лежит в одном репозитарии и никакак не конфликтует.
При желании каждый разработчик может подсмотреть что-нибуть у соседа.
PS: все правки конфига через редактор в админке.
По ссылке на ZF (выше):.
Это круто. Тоже хочу.

А насчёт многоуровневых конфигов — это только дополняет тему поста. Статья как раз про самый высокий уровень конфига: production, dev, test.
*По ссылке: <staging extends="production">.
Вопрос не совсем по теме:
Каким планировщиком вы пользуетесь?
Что-то стандартное типа cron + скрипты, сторонний софт или самописная прога?

Мне нужен планировщик задач, чтобы умел обрабатывать зависимости (запускать зачаду А каждую ночь или один раз. если задача А завершилась успешно, выполнить последовательно задачи Б, В и Г, в противном случае Д и т.п.)
Сейчас используем cron, но с зависимостями у него туго (совсем никак, или я просто не в курсе), писать вручную скрипты на bash лень и не каждый умеет (задачи в планировщике выставляют разные люди).
Хотелось бы чего-нибудь c понятной логикой и удобным интерфейсом (как пользовательским, так и программным, чтобы другие программы могли самостоятельно выставлять задачи)

Уже почти начал писать сам, но вдруг уже есть что-то удобное?
Заинтересовали задачей :) Я ниже ответил, не на ту кнопку нажал.
Если это вопрос к автору топика (то есть мне), то мы используем Крон, который запускает раз в N минут наш собственный простенький планировщик. Последний умеет запускать задачи через (или в) какое-то время, сохраняя время последнего запуска и логируя всё это. Пока хватало :)

С зависимостями я напрямую не сталкивался. Были многошаговые задачи: 1) скачать — 2) распарсить и сложить в базу — 3) докачать зависимости. Можно было делать как говорите Вы, но я предпочёл сделать такую архитектуру блоков, чтобы те не зависели друг от друга. Все три скрипта запускаются независимо со своей частотой и просто по какому-то признаку проверяют, есть ли им работа. Если есть — выполняют её. Потенциально это, кстати, означает, что я могу распараллелить нагрузку, вынеся каждый из блоков на отдельную машину.

Если же есть жёсткая логика — я выношу её всю в один cron-скрипт.

А не поделитесь поподробнее, что у Вас за задача такая?
да задач куча разных — разная текучка, типа обновления сайта каждую ночь, рассылка новостных писем, составление разных репортов для маркетинга и для разных чужих сервисов, получение репортов с чужих сервисов, составление репортов на базе репортов (в определённом порядке, но с неопределённой длительностью выполнения) и т.п. например, ньюслеттерс нельзя рассылать, пока сайт не обновился (а обновление может занять часов семь :), иначе подписчик зайдёт по ссылке в письме на сайт и не увидит обещанных нештяков.
А я примерно так делаю:
if (file_exists('/file_name.txt'))
{
// локальная конфигурация
}
else
{
// серверная конфигурация
}
Работает всегда и везде.
Провожу разделение средствами PHP.
Сервера в основном чужие, доступа к конфигам баз данных и веб-серверов нет.

< ?php
class projectname_db_config {
/* поскипано */
/* Autoload */
public function __construct()
{
/* Database settings */
$this->a('db_host', ''mysql1064.domain.tld');
$this->a('db_name', 'dbqwerty');
$this->a('db_user', 'qwerty');
$this->a('db_pass', '1234');
$this->a('table_prefix', 'my_');
$this->a('db_driver', 'mysqli');
/* поскипано */
$this->_switch_cfg_profile();
}
/* Switch between configuration profiles */
private function _switch_cfg_profile()
{
/* Alternative settings */
if ($_SERVER['HTTP_HOST'] == '127.0.0.1')
{
/* Database settings */
$this->a('db_host', 'localhost');
$this->a('db_name', 'dbasdfg');
$this->a('db_user', 'asdfg');
$this->a('db_pass', '5678');
$this->a('table_prefix', '');
$this->a('db_driver', 'mysql');
/* поскипано */
}
/* поскипано */
}
/* поскипано */
}
? >
Автор, объясните, пожалуйста, почему в первом варианте править конфиг — это «ай-яй-яй», а во втором — вполне нормально? ИМХО, первый вариант, как раз, удачнее (за исключением того, что это XML). В своих проектах я имею отдельно файлик с «глобальной» конфигурацией (драйвер БД, пути, етс.) и «хостозависимой» (имена, явки, пароли).
Извините, не понял вопроса. В обоих приведённых случаях я правлю конфиг только для добавления новых настроек или для того чтобы сменить текущие настройки, если они поменялись. Разница только в том, что я в одном случае привязываюсь к имени домена, а во втором — к переменной окружения.
>> Недостатков у этого метода было 2:
>> — у разных разработчиков (с разными параметрами окружения) может быть одинаковый хост — скажем, localhost;
>> — кроме того, при смене или добавлении хоста приходится править файл.

Вот последний недостаток — почему он недостаток, если он в обоих случаях присутствует? :)
Фактически, я под именем хоста подразумевал имя домена, что кого-то ввело в заблуждение. Я слишком подно понял свою ошибку.

Если домен меняется — во втором случае менять в настройках либо ничего не приходится, либо приходится меньше. При добавлении же хоста — да, вопрос корректный, я с Вами согласен.
Sign up to leave a comment.

Articles