Зачастую все проблемы идут из-за неправильно выбранных аналогий и абстракций.
Нам свойственно упрощать вещи, чтобы лучше их понимать. Но если мы выбрали изначально не тот подход, который задумывали авторы, то приходится бороться с тулом.
Make задумывался как сборщик программ. И его цель (результат работы, target) - как правило файл. Если мы чётко прописываем, как получить какой-то файл и какие зависимости нужны, то make за нас это всё делает, строит зависимости, умеет собирать "параллельно на нескольких ядрах" и т.п.
В вашем случае, начинаем думать про файлы. Мы хотим что?
`make a-test-report.html an-integration-test-report.xml` - мы хотим получить отчёт по тестам.
`make -j 8 binary-program` - сделай мне нужный бинарник, используй 8 потоков, что бы там ни было. И актуальность make за тебя проверит, и соберёт только то, что нужно.
Да, хочется иметь удобные цели `make check` или `make test`. И это скорее как исключение. Если наша "несуществующая цель, которая как бы есть, но её нет" потенциально совпадает с файлом, мы помечаем её как .PHONY (https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html).
Ниже даже упомянули про трюк с touch. Когда "правило" не производит никакого результата (make upload) мы можем в конце сделать touch file.uploaded и зацепиться за него как за маркер.
Как-то странно. Сначала говорится о том, что миграция сломала прод. А потом - фича-флаги решают проблемы. Но при этом никак не объяснено, как засунуть миграцию под фича-флаг. Да ещё и проверить. Сделать вкл/выкл в случае чего.
Не то, чтобы я супер эксперт в гите, но (я так думаю) гит задумывался не таким. GitHub и концепция merge request/pull request, конечно, много привнесли и упростили. Но такие абстракции «текут» по-своему. Поэтому вечно задаёмся вопросом, какой git workflow выбрать, squash-ить или rebase-ить. Кто-то ругает fast-forward, хотя в нём нет ничего плохого.
Про группировку. Допустим, надо собрать поштучно кучу коммитов «в группу». Для этого уже есть cherry-pick. Создаём ветку в любой точке истории, переключаемся и тащим к себе коммиты. Хотим перетащить сразу кусок истории (aaaaa..bbbbb) — `git rebase --onto` в помощь.
Задача стояла «как поддерживать множество версий, принимать множество патчей во множество версий программы и не умереть». Важная особенность патча — его нельзя применить абы куда. Часто, набор патчей необходимо применить в определённом порядке. Вот и всё. Патчи слали по почте в конкретную ветку(и). А git — это автоматизация этой почты.
И продолжают так делать до сих пор. Git прост и банален. Этим и хорош. После этого по-другому смотришь и на коммиты, и на описание к ним, и на ветки и т.п.
Ради интереса можно посмотреть на историю ядра, увидеть как один и тот-же патч может быть слит в 10ки веток. Или, посмотрите на postgresql. Поддерживается и развивается сразу несколько версий. Посчитайте количество merge commits у postgresql репозитория.
Просто другой подход. Да, он тяжелее для новичков, да надо разбираться. Но и плюсы есть.
Ну и если начинаешь мыслить патчами — мелкими атомарными, логически законченными изменениями, то всё резко становится проще.
А тот же squash commits на ui — это кастыль: «я тут ходил по граблям, fix, fix, fix, revert, fix, bug-123, bug-123, bug-123, works now. всё, покакал. Ой, это в таком виде не хотят мержить в историю. завернём ка всё в один пакетик».
Когда я пытаюсь смотреть внутрь я вообще не вижу попытки обращения к '[' (программе). Возможно, дело в современном баше или я пользуюсь strace-ом неправильно, но
╭─sirex at sirex-notebook in /tmp 21-06-01 - 14:12:35
╰○ cat test.sh
#!/bin/bash
if [ -n "FOO" ]; then echo FOO; fi
/usr/bin/\[ -n FOO \] && echo ok
╭─sirex at sirex-notebook in /tmp 21-06-01 - 14:12:39
╰○ strace bash test.sh 2>&1 | grep stat | grep /bin
stat("/home/sirex/.cargo/bin/bash", 0x7ffd9304a900) = -1 ENOENT (No such file or directory)
stat("/home/sirex/.local/bin/bash", 0x7ffd9304a900) = -1 ENOENT (No such file or directory)
stat("/home/sirex/.cargo/bin/bash", 0x7ffd9304a900) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/bash", 0x7ffd9304a900) = -1 ENOENT (No such file or directory)
stat("/usr/bin/bash", {st_mode=S_IFREG|0755, st_size=1234376, ...}) = 0
stat("/usr/bin/bash", {st_mode=S_IFREG|0755, st_size=1234376, ...}) = 0
stat("/usr/bin/bash", {st_mode=S_IFREG|0755, st_size=1234376, ...}) = 0
stat("/usr/bin/bash", {st_mode=S_IFREG|0755, st_size=1234376, ...}) = 0
stat("/usr/bin/bash", {st_mode=S_IFREG|0755, st_size=1234376, ...}) = 0
stat("/usr/bin/bash", {st_mode=S_IFREG|0755, st_size=1234376, ...}) = 0
╭─sirex at sirex-notebook in /tmp 21-06-01 - 14:13:00
╰○ bash --version
GNU bash, version 5.1.4(1)-release (x86_64-pc-linux-gnu)
Может, Баш неявно и услужливо преобразовывает вызов [ в нативный для себя вариант…
Это, конечно, не отменяет того, что лучше прочитать мануал и сделать наверняка правильно.
Тогда продолжу:
DevOps — это как подростковый секс: не знают что это такое, читали и видели в Интернете, хвастают друзьям, что уже делали девопс и почти лучшие в этом.
С оговоркой на то, что в пределах минорных версиях всё совместимо, но всё же вот что скажу:
Если вы «замораживаете дистрибутив» (зеркало), то у вас есть согласованность и стабильность. Но как же обновления безопасности в ентерпрайзе? правильно. их будут накатывать, т.е. дистр уже незамороженный. ставите какой-нибудь пакет, а он уже собран с другими версиями библиотек. В целом, благодаря semver и аккуратности, оно, как правило, не ломается. но всё же.
Или тот же докер. Вот банальная задача — собрать контейнер с postgresql и 5 extensions. Постгрес нужен определённой версии и лезем на postgresql.org. ставим оттуда. Оно том с какими-то версиями собрано. А поддержка ldap включили? да. ок, openssl/gcc/anything. Ок. ставим extensions. 2 в стоке были, а какой-нибудь сторонний? с чем он там собран? он точно под именно 12.6 постгрес собран? или 12.3? наверное будет работать. но это не точно. а если под 11 собирали. А ещё один придётся собирать самому. Ок, прошло время, разобрались, сделали классный докер файл. Поправили entrypoint.sh в последней инструкции. Вроде бы заново собрать не надо? а на ci ноде может и не быть кэша, а значит пересоберёте. А что вы пересоберёте? точно не то что было, т.к. много воды утекло.
Питон? ставит пакетизированным способом apt|yum install python-pip-whatever или сами pip install. А если native extension который собрать надо?
Это я всё к чему? Современная разработка более хрупкая, чем кажется. И слово «ентерпрайз дистрибутив» вас не сильно спасает. Т.к. чудо не случится. там сидят такие же, ну или немного более опытные разработчики. И они точно так же борются с возникающими проблемами и обещают вам что «ну должно работать, а если что мы быстро поправим». И становится очевидно, что хочешь-не-хочешь, а разбираться в этом всём нужно довольно глубоко.
Я бы поспорил насчёт дизайна гита, но речь не об этом. Это был всего лишь случайный пример, где надпись на кнопке не так однозначна, как может показаться.
GUI часто бывает неоднозначен, запутан. В то время как консольная команда чаще будет иметь однозначное поведение.
Вот надо вам сделать в git-e soft reset на 2 коммита назад. Открываем gitk, лазим по меню, там ничего нет. тыкаем на коммит, ничего нет, догадываемся (как?) что можно нажать правой кнопкой и там выпадет «Reset master branch here». Reset — это hard reset или soft reset? Рискуем? А если мне надо другую ветку? Как выбрать?
Или вот сижу в firefox и думаю поменять страницу по-умолчанию. А где собственно? И надо бегать по меню перебирая все пункты и гадать, куда же это могли «засунуть». Предполагать, что может это в preferences. А где там дальше искать?
Да, может примеры выше — не самые хорошие, кто-то скажет: «А вот у меня в %PROGNAME% всё понятно». Но уверен, каждый не раз сталкивался с тем, что шарил по GUI в поисках нужного действия.
В Windows: правой кнопкой по файлу или папке -> копировать. Ииии… ничего не происходит. Так видит мир тот, кто не знаком с концепцией ctrl+c/ctrl+v. А крестик справа вверху программу не закрывает.
И даже в вашей любимой IDE наверняка есть кнопка «поискать кнопку, чтобы выполнить команду» по тексту этой команды. Только эту «кнопку поиска» надо тоже поискать. Например, сортировка строк.
Тут уже многие высказались, но не смог пройти мимо.
Если правило придумали, значит оно нужно было. Если кому-то кажется, что правило безсполезно, то, он может просто не знает где оно нужно?
В конце каждого файла должен быть перевод строки. А если не будет, то кто умрёт?
Многие Linux дистрибутивы поумирают. И многие программы сломаются. Конфиги часто разбиваются на отдельные файлы и складываются в /etc/что-нибудь.d/ и дальше обычной склейкой генерируется полный конфиг.
Или если есть препроцессинг исходного кода (в случае объединения файлов).
У меня на реальном java-проекте ребята имели 10+ properties файлов, которые объединялись в разных комбинациях. И в каждом файле в конце стояли дурацкие коменты «оставьте здесь пустую строчку». Пустая строка, кстати, не нужна, если бы разобрались в проблемах
Нельзя делать несколько statements на одной строке. Если я напишу $x = 1; $y = 1; $z = 1;, то читабельность ухудшится на 0.00001% и можно закрывать техотдел?
Давайте быть честными. Не «x y z», а
«size_t keyword_scan_len = GetScanKeyword(h, keywords); size_t keyword_scan_index = 1; TYPE *pi = (TYPE *)(void *)(parmi)». А когда прелетит изменение в этой строке, надо ещё всматриваться и искать, что конкретно поменялось? index? pi? len? А еслиGetScanKeyword надо было после поставить? Даже если есть строгая практика отделения объявления от присвоения, всё равно, названия переменных и их типов могут быть многобуквеннымми, а их значение константой " int c = THE_SEVENTY_EIGHT_PRIME_NUMBER".
Declare statements MUST contain no spaces and MUST be exactly declare(strict_types=1). Ох, как всё серьёзно. Ни одного пробела, причем слово MUST капсом, чтобы все понимали степень ответственности. Если вставить где-нибудь пробел, то на код ревью никто код же прочесть не сможет!
Ещё и от языка зависит. Где-то у вас не распарсится просто, а где-то не будет работать на рантайме или того хуже, будет втихую работать неправильно.
— Современные ide оснащены автоформатированием кода и если не будет стандарта во всём, то каждый коммит будет порождать тонны мусора.
— Когда оформление стандартизировано, я могу выполнять массовые исправления кода (по паттерну), рефакторинг в лоб и т.п.
Ну и наконец, вы подменили понятия. Не дресскод с людьми надо сравнивать, а с чем-нибудь таким же массовым или бумажным:
1. Представьте, что все официальные документы пишутся не от шаблона а от балды: заявление, договоры. А вы тут бухгалтер — разбирайтесь.
2. Вы купили 10 гаек на 12 но они все под разные ключи. А у некоторых не та резьба. А вы крутите эти гайки — наслаждайтесь.
3. Деньги печатаются в разных цветах, разных размеров и форм. И с разным расположением надписей. И вы работаете кассиром — добро пожаловать в персональный ад.
При строительстве кирпичного дома вы не хотите знать, что каждый кирпич — индивидуальность, личность и «он так себя видит». Вы обложите процесс изготовления кирпича максимальным набором правил. И неважных правил там не будет. Вы не станете проверять то, что не важно. Если правил слишком много и это доставляет хлопоты — то вы будете стремиться упростить проверку и сделаете процесс таковым, чтоб он легче проходил её.
Не понимаю, за что минусанули человека.
Как раз сам вышел на эту же проблему: cdn.github.com недоступен.
Пару месяцев всё работало и вот опять. Причём traceroute не проходит, а чистый tcp пропускает ack и syn. Остальное нет. И всё на белтелекоме обрывается. ByFly, Beltelecom, Mts.
Ну это я ради объективности. Есть в гитлабе и хорошие стороны. Вон, дебиан же поднял себе salsa. Наверняка они много думали перед таким поворотом.
Меня от геррита останавливает только одно — кроме дженкинса не могу прикрутить никакого вменяемого ci (наподобии gitlab-ci или github actions). Кто бы подсказал как это сделать — уже бы ушёл на него.
Заходят как-то два программиста и один javascript-разработчик в бар...
Зачастую все проблемы идут из-за неправильно выбранных аналогий и абстракций.
Нам свойственно упрощать вещи, чтобы лучше их понимать. Но если мы выбрали изначально не тот подход, который задумывали авторы, то приходится бороться с тулом.
Make задумывался как сборщик программ. И его цель (результат работы, target) - как правило файл. Если мы чётко прописываем, как получить какой-то файл и какие зависимости нужны, то make за нас это всё делает, строит зависимости, умеет собирать "параллельно на нескольких ядрах" и т.п.
В вашем случае, начинаем думать про файлы. Мы хотим что?
`make a-test-report.html an-integration-test-report.xml` - мы хотим получить отчёт по тестам.
`make -j 8 binary-program` - сделай мне нужный бинарник, используй 8 потоков, что бы там ни было. И актуальность make за тебя проверит, и соберёт только то, что нужно.
Да, хочется иметь удобные цели `make check` или `make test`. И это скорее как исключение. Если наша "несуществующая цель, которая как бы есть, но её нет" потенциально совпадает с файлом, мы помечаем её как .PHONY (https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html).
Ниже даже упомянули про трюк с touch. Когда "правило" не производит никакого результата (make upload) мы можем в конце сделать touch file.uploaded и зацепиться за него как за маркер.
Так и не понятно, почему кубик лучше из вашей статьи.
Простота - тот же номад: скачал бинарник, запустил где угодно и что угодно. У кубика много компонентов.
Yaml - https://noyaml.com/
Оркестратор должен уметь "управление секретами" - вот прям должен?
HCL непопулярен? А в terraform на чём пишем?
Лоад балансер для сервисов в кубике вызывает вопросы..
Я не хочу сказать, что кубик плохой или что-то вы этом духе, но чувствуется предвзятость.
Как-то странно. Сначала говорится о том, что миграция сломала прод. А потом - фича-флаги решают проблемы. Но при этом никак не объяснено, как засунуть миграцию под фича-флаг. Да ещё и проверить. Сделать вкл/выкл в случае чего.
Про группировку. Допустим, надо собрать поштучно кучу коммитов «в группу». Для этого уже есть cherry-pick. Создаём ветку в любой точке истории, переключаемся и тащим к себе коммиты. Хотим перетащить сразу кусок истории (aaaaa..bbbbb) — `git rebase --onto` в помощь.
Задача стояла «как поддерживать множество версий, принимать множество патчей во множество версий программы и не умереть». Важная особенность патча — его нельзя применить абы куда. Часто, набор патчей необходимо применить в определённом порядке. Вот и всё. Патчи слали по почте в конкретную ветку(и). А git — это автоматизация этой почты.
И продолжают так делать до сих пор. Git прост и банален. Этим и хорош. После этого по-другому смотришь и на коммиты, и на описание к ним, и на ветки и т.п.
Ради интереса можно посмотреть на историю ядра, увидеть как один и тот-же патч может быть слит в 10ки веток. Или, посмотрите на postgresql. Поддерживается и развивается сразу несколько версий. Посчитайте количество merge commits у postgresql репозитория.
Просто другой подход. Да, он тяжелее для новичков, да надо разбираться. Но и плюсы есть.
Ну и если начинаешь мыслить патчами — мелкими атомарными, логически законченными изменениями, то всё резко становится проще.
А тот же squash commits на ui — это кастыль: «я тут ходил по граблям, fix, fix, fix, revert, fix, bug-123, bug-123, bug-123, works now. всё, покакал. Ой, это в таком виде не хотят мержить в историю. завернём ка всё в один пакетик».
Когда я пытаюсь смотреть внутрь я вообще не вижу попытки обращения к '[' (программе). Возможно, дело в современном баше или я пользуюсь strace-ом неправильно, но
Может, Баш неявно и услужливо преобразовывает вызов [ в нативный для себя вариант…
Это, конечно, не отменяет того, что лучше прочитать мануал и сделать наверняка правильно.
DevOps — это как подростковый секс: не знают что это такое, читали и видели в Интернете, хвастают друзьям, что уже делали девопс и почти лучшие в этом.
Если вы «замораживаете дистрибутив» (зеркало), то у вас есть согласованность и стабильность. Но как же обновления безопасности в ентерпрайзе? правильно. их будут накатывать, т.е. дистр уже незамороженный. ставите какой-нибудь пакет, а он уже собран с другими версиями библиотек. В целом, благодаря semver и аккуратности, оно, как правило, не ломается. но всё же.
Или тот же докер. Вот банальная задача — собрать контейнер с postgresql и 5 extensions. Постгрес нужен определённой версии и лезем на postgresql.org. ставим оттуда. Оно том с какими-то версиями собрано. А поддержка ldap включили? да. ок, openssl/gcc/anything. Ок. ставим extensions. 2 в стоке были, а какой-нибудь сторонний? с чем он там собран? он точно под именно 12.6 постгрес собран? или 12.3? наверное будет работать. но это не точно. а если под 11 собирали. А ещё один придётся собирать самому. Ок, прошло время, разобрались, сделали классный докер файл. Поправили entrypoint.sh в последней инструкции. Вроде бы заново собрать не надо? а на ci ноде может и не быть кэша, а значит пересоберёте. А что вы пересоберёте? точно не то что было, т.к. много воды утекло.
Питон? ставит пакетизированным способом apt|yum install python-pip-whatever или сами pip install. А если native extension который собрать надо?
Это я всё к чему? Современная разработка более хрупкая, чем кажется. И слово «ентерпрайз дистрибутив» вас не сильно спасает. Т.к. чудо не случится. там сидят такие же, ну или немного более опытные разработчики. И они точно так же борются с возникающими проблемами и обещают вам что «ну должно работать, а если что мы быстро поправим». И становится очевидно, что хочешь-не-хочешь, а разбираться в этом всём нужно довольно глубоко.
Пора и мне на хабре написать:
Название: Основы программирования за 5 минут
Текст:
Давайте выведем 2+2:
Ну вот, мы научились. Да, тут есть что улучшить, но купите наши вазелиновые шарики всего за 9.99. первым 100 000 покупателей скидка 2 копейки.
Вот надо вам сделать в git-e soft reset на 2 коммита назад. Открываем gitk, лазим по меню, там ничего нет. тыкаем на коммит, ничего нет, догадываемся (как?) что можно нажать правой кнопкой и там выпадет «Reset master branch here». Reset — это hard reset или soft reset? Рискуем? А если мне надо другую ветку? Как выбрать?
Или вот сижу в firefox и думаю поменять страницу по-умолчанию. А где собственно? И надо бегать по меню перебирая все пункты и гадать, куда же это могли «засунуть». Предполагать, что может это в preferences. А где там дальше искать?
Да, может примеры выше — не самые хорошие, кто-то скажет: «А вот у меня в %PROGNAME% всё понятно». Но уверен, каждый не раз сталкивался с тем, что шарил по GUI в поисках нужного действия.
В Windows: правой кнопкой по файлу или папке -> копировать. Ииии… ничего не происходит. Так видит мир тот, кто не знаком с концепцией ctrl+c/ctrl+v. А крестик справа вверху программу не закрывает.
И даже в вашей любимой IDE наверняка есть кнопка «поискать кнопку, чтобы выполнить команду» по тексту этой команды. Только эту «кнопку поиска» надо тоже поискать. Например, сортировка строк.
Если правило придумали, значит оно нужно было. Если кому-то кажется, что правило безсполезно, то, он может просто не знает где оно нужно?
Многие Linux дистрибутивы поумирают. И многие программы сломаются. Конфиги часто разбиваются на отдельные файлы и складываются в /etc/что-нибудь.d/ и дальше обычной склейкой генерируется полный конфиг.
Или если есть препроцессинг исходного кода (в случае объединения файлов).
У меня на реальном java-проекте ребята имели 10+ properties файлов, которые объединялись в разных комбинациях. И в каждом файле в конце стояли дурацкие коменты «оставьте здесь пустую строчку». Пустая строка, кстати, не нужна, если бы разобрались в проблемах
Давайте быть честными. Не «x y z», а
«size_t keyword_scan_len = GetScanKeyword(h, keywords); size_t keyword_scan_index = 1; TYPE *pi = (TYPE *)(void *)(parmi)». А когда прелетит изменение в этой строке, надо ещё всматриваться и искать, что конкретно поменялось? index? pi? len? А еслиGetScanKeyword надо было после поставить? Даже если есть строгая практика отделения объявления от присвоения, всё равно, названия переменных и их типов могут быть многобуквеннымми, а их значение константой " int c = THE_SEVENTY_EIGHT_PRIME_NUMBER".
Ещё и от языка зависит. Где-то у вас не распарсится просто, а где-то не будет работать на рантайме или того хуже, будет втихую работать неправильно.
— Современные ide оснащены автоформатированием кода и если не будет стандарта во всём, то каждый коммит будет порождать тонны мусора.
— Когда оформление стандартизировано, я могу выполнять массовые исправления кода (по паттерну), рефакторинг в лоб и т.п.
Ну и наконец, вы подменили понятия. Не дресскод с людьми надо сравнивать, а с чем-нибудь таким же массовым или бумажным:
1. Представьте, что все официальные документы пишутся не от шаблона а от балды: заявление, договоры. А вы тут бухгалтер — разбирайтесь.
2. Вы купили 10 гаек на 12 но они все под разные ключи. А у некоторых не та резьба. А вы крутите эти гайки — наслаждайтесь.
3. Деньги печатаются в разных цветах, разных размеров и форм. И с разным расположением надписей. И вы работаете кассиром — добро пожаловать в персональный ад.
При строительстве кирпичного дома вы не хотите знать, что каждый кирпич — индивидуальность, личность и «он так себя видит». Вы обложите процесс изготовления кирпича максимальным набором правил. И неважных правил там не будет. Вы не станете проверять то, что не важно. Если правил слишком много и это доставляет хлопоты — то вы будете стремиться упростить проверку и сделаете процесс таковым, чтоб он легче проходил её.
Как раз сам вышел на эту же проблему: cdn.github.com недоступен.
Пару месяцев всё работало и вот опять. Причём traceroute не проходит, а чистый tcp пропускает ack и syn. Остальное нет. И всё на белтелекоме обрывается. ByFly, Beltelecom, Mts.
Линукс, терминал, курсы!
Ну купи
Ну почти девопс уже ж… ну купи,
ну ннада
Меня от геррита останавливает только одно — кроме дженкинса не могу прикрутить никакого вменяемого ci (наподобии gitlab-ci или github actions). Кто бы подсказал как это сделать — уже бы ушёл на него.