Читать в телеге. Когда-то там были посты не только от меня.
Резиновый квадрат в CSS
Прогресс не стоит на месте. Когда делал галерею со смешнявками на чистом CSS в далеком 2020 году, у меня был вопрос, на который не могли ответить ни знакомые фронтендеры, ни на StackOverflow: как сделать “резиновый” квадрат, совместимый с другими фичами.
И вот, 5 лет спустя, шальная мысль пришла в голову и решение нашлось за один запрос: примерно с 2021 везде доступно свойство aspect-ratio, которое делает именно то, что нужно. Никаких больше уродских абсолютных значений в пикселях!
Не тестируйте внешние домены
Не раз такое видел, что в тесте по интеграции с внешним API идет обращение к реальному домену. Некоторые даже при этом говорят “ачетаково”.
Основных проблем две: нестабильность теста и безопасность.
С нестабильностью понятно — сервис прилег, проблемы по дороге с сетью/DNS, rate-limiter зарубил вашего разраба, который запускал тесты 100500 раз в секунду, и привет, тест завален (очень сомневаюсь, что там учитываются подобные проблемы). Да, изредка нужно протестировать интеграцию 1-в-1, но это имеет смысл в весьма редких случаях и может быть достигнуто другими средствами (ну и graceful degradation никто не отменял). Опять же, как вы с реальным сервисом будете тестировать обработку всех проблем?
С безопасностью посложнее — между вами и доменом сервиса есть несколько промежуточных узлов, и вряд ли вы проверяете всю цепочку… Ок, домен доверенный, снимаем шапочку из фольги. А если у вас в коде randomserver.org? Конечно, вероятность, что об этом кто-то узнает, довольно мала. Внимательный читатель может догадаться, почему эта вероятность может резко повыситься:) Но если прям очень надо потестировать что-то связанное с реальной сетью (что еще более невероятно), то хотя бы используйте домены из RFC: .test, .example, .invalid.
Хотя о чем это я, простите, в половине инструкций в интернете сейчас curl | sh.
Почему коллеги не хотят
Хороший доклад про разрешение конфликтов и как продвигать “очевидные” изменения.
Начинается с показательных примеров про конфликт интересов (“наши доблестные воины…”.jpg) и кажущиеся полярными точки зрения относительно “очевидно хороших” предложений.
В целом навалено базы:
- Компромисс мало к чему приведет;
- Надо понять своего «оппонента»;
- Надо думать не решениями, а проблемами;
- Зависит от
задапроблемы; - У людей (обычно) нет цели сделать плохо, проблема в системе.
И одна из основных идей — людей ты не поменяешь, поэтому «начни с себя»: лучше погрузись в проблему: какую проблему решаем? действительно ли это проблема? надо ли ее решать сейчас? плюсы/минусы и т.д. При этом признается, что конченные люди все-таки существуют, но не так много как думается, ну и работать с ними не стоит. Дискуссия в кои-то веки тоже полезная.
Правда, в здоровой команде люди достаточно взрослые, чтобы давать обратную связь и конструктивно объяснять, что не так. Ну, мечтать не вредно:)
Об одном нестабильном браузерном тесте
У меня с браузерными тестами и selenium в частности весьма неоднозначные отношения: с одной стороны — автоматическое тестирование — это хорошо, с другой — много видимых пользователю косяков можно легко пропустить (т.е. руками все равно надо будет тестировать) и, по моему опыту, тесты очень хрупкие.
И вот была у меня недавно проблема с частью браузерных тестов уровня “нажми сюда и попадешь на эту страницу”: в CI работает, локально — нет: остается на той же странице. В логах пусто, никаких индикаторов о том, что происходит — нет. Некритично, но неприятно. Потратил кучу времени: может не нажимается? Нажимается, но не работает. Пробовал и так, и сяк (рандомные советы из интернетов) — не работает и все. Я мужественно забил и отложил эту проблему на пару месяцев.
Недавно, после очередного обновления хрома (в котором у нас тестируется) и селениума опять запустил тесты — и, в headless-режиме, который не подразумевает никакого интерфейса, вижу, как мелькает окошко от хрома — твой пароль небезопасен!!1. И правда, в тестах логина, которые локально не работали, использовался p@ssw0rd. Заменил его на “более сильный” (хотя надо было бы генерировать, по-хорошему), и тесты “починились”. Т.е. благодаря багу хрома я смог обнаружить проблему, о которой не сообщал selenium :/
Теги git
Все в курсе, что у git раковый UX, но даже он не перестает удивлять. Вот есть в репозитории теги:
$ git tag
v1
v2
Уже на этом этапе я обычно хочу написать tags, ну да ладно. Вот я хочу посмотреть список коммитов, на которые эти теги указывают. Берем первый ответ из гугла:
$ git show-ref --tags
1baddd8efa7f0afac329e16876d94fa54febef4f refs/tags/v1
24105f5ffeb2c93c8dd6f8f10ce0d1701e67a1cd refs/tags/v2
Вроде все логично, однако если сравнить этот вывод с историей:
$ git log --pretty=format:"%H %s"
0c4bd3ad8d403463fbdd6dda50bfe7834ecd2634 second commit
1baddd8efa7f0afac329e16876d94fa54febef4f first commit
То видна проблема — хэши не совпадают. Тут я должен вспомнить, что в git есть два вида тегов: обычные и аннотированные, в которых есть сообщение, автор и т.п.:
$ git for-each-ref refs/tags --format="%(refname:short) %(objecttype)"
v1 commit
v2 tag
Ладно, но как получить то, что я хотел? Для одного тега проще всего запомнить git show $tag, а вот для всего списка нужно всего лишь
$ git for-each-ref --format='%(if)%(*objectname)%(then)%(*objectname)%(else)%(objectname)%(end) %(refname:short)' refs/tags
1baddd8efa7f0afac329e16876d94fa54febef4f v1
0c4bd3ad8d403463fbdd6dda50bfe7834ecd2634 v2
24105f5ffeb2c93c8dd6f8f10ce0d1701e67a1cd v2.1 # oops!
Но даже этот метод (от мейнтейнера git, между прочим!) — неправильный, потому что аннотированные теги могут быть вложенными. Поэтому надо сделать
git tag | while read tag; do echo "$(git rev-parse $tag^{}) $tag"; done
Перегрузка скриптов в DevTools
Оказывается, в инструментах разработчика можно подправить JS-скрипты, загруженные на странице. По сути скачиваешь скрипт, редактируешь его на компе, перезагружаешь страницу — и используется уже он. В Chrome было давно, в Firefox появилось сравнительно недавно.
Понятно, что если приложение полностью под контролем, проще его пересобрать, а что-то мелкое можно и через консоль протестировать. Однако если код не полностью под контролем (например, он сгеренирован каким-то экзотическим языком) и/или как-то нестандартно связан с другими модулям — так может быть проще.
Постмортемы
Мануал по постмортемам от Гугла. Немного водянисто, но суть достаточно проста: не надо искать козла отпущения, а надо сфокусироваться на том, что случилось, почему и как предотвратить подобное в будущем.
Некоторые хорошие тезисы, на мой взгляд:
- Нельзя “исправить” людей, но можно исправить систему/процессы, чтобы стимулировать правильные решения (и предотвратить человеческие ошибки).
- Должно быть видимое поощрение за улучшение процессов (хотя в оригинальном тексте это звучит как поощрение за тушение пожара, что не очень).
- Нужно шарить результаты с коллегами, чтобы они улучшали свои процессы и системы на вашем опыте (если у вас похожий стек технологий и процессы, что с большой вероятностью правда, если вы в одной компании).
- Нужно делать все вовремя, а не когда-нибудь потом и для бюрократической галочки. Ценность постмортема — не в документе, а в последствиях.
Ping устарел
Когда не грузится сайт, я обычно машинально проверяю, работает ли у меня интернет при помощи ping 1.1.1.1. Недавно коллега упомянул, что ping не нужОн и вообще устарел как средство диагностики сети. Я что-то такое смутно подозревал конечно, но явно не осознавал. Вышел в интернет с вопросом и выяснил, что
- ICMP Echo отключен по умолчанию в большинстве нормальных облаков для защиты от DDoS ping flood, ping sweep и прочих.
- Некоторые провайдеры даже отключают ICMP Echo по тем же причинам.
- В кубере пинг тоже не будет работать, но это скорее для простоты.
- И в Software-Defined Networking (SDN) та же история.
- У большинства роутеров ICMP-траффик имеет низкий приоритет обработки и при нагрузке они могут дропать эти пакеты.
- Поскольку в ICMP можно запихать произвольную нагрузку (можно даже туннель сделать), малварь может использовать его для C&C, поэтому многие режут ICMP файрволлом.
Ping only tests for the ability to respond to pings, so that’s base OS, parts of the IP stack and the physical links - but that’s all, everything else could be down and you’d not know.
Предлагается использовать tcping с конкретным портом, а для более качественной диагностики — traceroute. Хотя кажется в моем сценарии “проверить интернет” — и так сойдет :)
CSS игры
Нет, не контра. На прошлой неделе на HN попал в топ “майнкрафт” на чистом CSS. Если копнуть поглубже — то это скорее грамотная подача — все блоки заранее поставлены, а пространство ограничено кубом со стороной 9. Т.е. в пределе это сводится к задаче вкладок на чистом CSS.
Вообще идея не нова — был и на хабре несколько лет назад период ужимания игры по строкам JS, который в итоге превратился в CSS. Например, была охота на уток, сайд-скроллер и типа старкрафт. Я, когда делал свою галерею на чистом CSS, откапывал даже FPS, который оказался ложью (там есть JS, а сейчас оно еще и поломалось). Вообще такого добра навалом: 1, 2, 3, 4…
Все зависимости Gradle-билда
Недавно опять получил сесурити-алерт от dependabot о том, что в проекте уязвимая зависимость, уровень опасности 100500, пофикси срочно, но где — ищи сам (спойлер: она была в итоге транзитивных зависимостях WireMock).
Чтобы получить дерево зависимостей билда Gradle, можно запустить
./gradlew dependencies
Однако, в этом отчете будут только зависимости одного проекта. И там не будет зависимостей билд-логики (плагины там всякие).
Чтобы получить почти все (потому что более чем уверен, что есть случаи, которые этим не покрыты), я использую вот такую колбасу (которая хранится в баш-профиле):
function deps(){
./gradlew --no-parallel dependencies buildEnvironment $(./gradlew -q projects | grep -Fe "--- Project " | sed -Ee "s/^.+--- Project '([^']+)'.*/\1:dependencies \1:buildEnvironment/" | sort) $([ -d buildSrc ] && echo ":buildSrc:dependencies :buildSrc:buildEnvironment" || echo "")
}
Тут запускается диагностика для вывода списка проектов и для каждого из них выводится дерево зависимостей как для самого билда, так и для его билд-логики. Предполагается сохранить вывод в файл (на больших проектах это может быть 100+ мегабайт текста), искать в нем проблемную зависимость и по дереву идти выше до конкретной зависимости верхнего уровня, конфигурации и проекта.
Если нет жестких ограничений на публичность метаданных проекта, можно запустить
./gradlew build --scan
и получить Build Scan с интерактивным отчетом. Вот пример.
И бонус — не могу не пожаловаться на качество разработки с точки зрения ИБ. Ладно еще вышеупомянутый WireMock, у которого каждая версия на текущий момент имеет какую-то незакрытую уязвимость. Но вот официальная библиотека от официальной организации OWASP для санитайзинга HTML тоже не имеет НИ ЕДИНОЙ версии без уязвимостей. И примерно никакущую реакцию на вопрос трехмесячной давности “а какая версия без уязвимостей?” Добью цитатой из README:
This code was written with security best practices in mind, has an extensive test suite, and has undergone adversarial security review.