Автоматический импорт ssh-ключа в ssh-agent в МacOS

Фронтендеры у нас в Эдстере работают с виртуалками, с доступом по ssh. На этих виртуалках мы собираем всю статику и иногда нужно делать полную сборку проекта, включая выкачивание библиотек из приватного гитхаб-репозитория.

Чтобы не заморачиваться с прописыванием ключей к гитхабу на виртуалке — включён проброс ключей. Однако на MacOS загрузка ключа в ssh-agent через `$ ssh-add` почему-то работает только до перезагрузки системы. Потом нужно снова загрузить ключ.

Перезагружаюсь я редко, но всё равно каждый раз раздражался от необходимости этого лишнего действия. Прописывание команды в `~/.zshrc` не давало нужного результата и так я мучаюсь уже больше полугода. Правильнее сказать — мучился.

Сегодня копнул чуть глубже и нашёл простое рабочее решение. Нужно импортировать ключ в Keychain. Для этого достаточно эту команду в терминале:

$ ssh-add -K [path/to/private SSH key]

Перезагрузился, проверил — ключ успешно импортировался в ssh-agent:

$ ssh-add -l
2048 96:0d:e8:f3:ed:c7:a1:b5:39:a7:a8:f7:13:6c:96:62 /Users/h4/.ssh/id_rsa (RSA)

Первый подход к ES6

Спецификация ECMAScript6 уже пару месяцев как перешла в статус ратифицированного стандарта, а я так и не написал на нём ни строчки. Но вот подвернулся шанс.

Суть задачи проста — у сообщества «Веб-стандарты» есть твиттер-аккаунт для текстовых трансляций с конференций, @webstandards_up, и есть репозиторий для логов этой трансляции. Но не было нормального инструмента для создания md-файлов. Я уже делал попытку написать такой инструмент, но он был не доделан и заброшен.

Нужно сделать три простые вещи — выбрать самый старый твит из дня трансляции, получить json с твитами и сохранить их в виде markdown-файла. Первый шаг всё-таки нужно делать руками, заодно формируем файл с мета-информацией — дата конференции, её название и место проведения, всё остальное делает робот.

Самая нудная часть — это работа с api twitter. Но тут мне несказанно повезло, потому что создатели jsunderhood.ru создали модули get-tweets и twitter-tokens, а также tweet.md для парсинга тела твита (к сожалению, он не умеет раскрывать картинки). Собственно большая часть движка нашего робота также позаимствована у jsunderhood.ru, поэтому просто расскажу, какие вещи в ES6 мне понравились, а какие — не очень.

Общая поддержка языка

Мне было лень ставить последний io.js и разбираться, что уже можно использовать, а что нет, поэтому я просто сделал npm install --save babel и запускал скрипты через babel-node.

В WebShtorm/PHPShtorm уже давно есть поддержка синтаксиса ES6, так что с этим тоже не было проблем.

Модульная система

Сама по себе конструкция import мне давно знакома из питона, но в этом маленьком проекте я не увидел реальной разницы между использованием импортов и require(). Хотя, общий стандарт — это, безусловно, хорошо.

Поддержка import в шторме пока что частичная. Если нужный модуль описан в файлах приложения — его можно автоимпортировать через Alt+Click, как это делается для python-модулей и require-зависимостей. Но если модуль находится в node_modules — IDE его почему-то не видит.

var, let, const

В принципе, у меня уже давно не было проблем с областью видимости переменных, правило — «всегда объявляй все переменные в начале функции» и поддержка IDE прекрасно справляются. Однако мысль использовать const для вещей которые не должны меняться в ходе работы приложения мне нравится. Вот только получается что почти всё становится константой, в том числе и лямбда-функции.

Кроме того, я привык к «single var» в кодстайле и множество const меня как-то смущают. Но тут дело привычки. На «single const» я скорее всего никогда не соглашусь, стройность отступов ломается.

Стрелочные функции

Мне нравится функциональный стиль написания кода. Все эти map(), filter(), reduce(). Но меня очень утомляло написание анонимных функций внутри этих методов и необходимость пробрасывать контекст. Тут стрелочные функции однозначно рулят.

Не очень нравится как выглядит присвоение лямбда-функции переменной/константе — const extractImages = (tweet) => tweet.entities.media; — два символа «равно», которые стоят почти рядом затрудняют восприятие кода.

Template strings

Это та вещь, которой мне очень не хватало в JavaScript. Собирать строки конкатенацией — это какое-то издевательство, особенно когда ты знаешь, что есть нормальные варианты типа "Hello, {name}".format(greeting). Теперь у нас наконец-то есть template strings (вот только я так и не нашёл изящного переводя для этого термина).

Однако очень хочется посмотреть в глаза тому человеку, который решил, что для литеральной формы записи стоит использовать символ ` — на клавиатуре он находится в самом неудобном месте. Идеальным для меня было бы наличие метода format() у объекта String(), но такой вариант был скорее всего отвергнут по причине совместимости со сторонними библиотеками (привет, Symbol.iterator!).

Выводы

Код, который у меня получился, выглядит намного стройнее чем аналогичный код на ES5, меньше вложенность, более коротки строки. В целом, мне нравится.

Конечно, это был микроскопический проект и делать какие-либо выводы рано, но в своих «домашних» проектах я постараюсь целиком перейти на ES6. А может и на основной работе тоже получится, во всяком случае, ничто не мешает использовать его на сервере.

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

«Ручная» загрузка треков в Garmin Connect

Сегодня утром у меня «моргнул» WiFi как раз во время синхронизации треков из моего Garmin Forerunner в Garmin Express на MacOS. Вроде бы ничего страшного, но софт у Гармина сильно хуже железок, поэтому треки с часов списались, а в «облако» не улетели. И при повторной синхронизации с работающим WiFi ничего не произошло. В общем, зажал Express мои треки.

Но меня так просто не проведёшь. Открываем Finder и переходим в каталог `~/Library/Application Support/Garmin/Express/Registered Devices/`. Там будет столько каталогов, сколько устройств у вас подключено в Garmin Express. У меня их два, а имена каталогов — это серийный номер железки, поэтому я ориентировался по картинке `device_image.png` внутри папки.

Переходим в каталог `PendingSyncUploads`, а в ней — в `FIT_TYPE_4` (или в `FIT_TYPE_9`, или в ту, которая соответствует типу активности, трек от которой мы ищем. И не спрашивайте меня, какой номер чему соответствует. Не знаю). Ищем нужный файл по его имени, имя — дата и время тренировки.

Теперь копируем этот файл и у копии добавляем расширение `.fit`, в моём случае `2015-08-14 07/09/14 +0000_360` переименовался в `2015-08-14 07/09/14 +0000_360.fit`. Файлы без расширения не получится залить на http://connect.garmin.com/

Теперь открываем http://connect.garmin.com/ и нажимаем кнопку загрузки активностей. Вот эту

2015-08-14 10-55-22 Garmin Connect

В выпавшем списке выбираем «Upload Your Activity» и переходим на вкладку «Manual Upload». Ну а уже там выбираем наш *.fit файл и загружаем его.

Возможно, стоит почистить каталог `PendingSyncUploads`, чтобы не было дубликатов в будущем. Но что-то мне подсказывает, что Garmin Express не особо смотрит в эту папку.

 

Марвин, который час?

Проснувшись сегодня утром, остро захотел узнать, который час, но вылезать из-под одеяла и искать телефон не хотелось. И тут я вспомнил, что в макоси есть распознавание речи… Теперь у меня есть новый персональный помощник:

Из говна и палок собрал себе говорящие часы

A video posted by Mikhail Baranov (@mkhlbrnv) on

Пошаговая инструкция

В первую очередь, нужно включить поддержку распознавания речи. Идём в System Preferences > Dictation & Speech и включаем поддержку диктовки.

Снимок экрана 2015-08-11 в 9.13.39

Конечно, желательно использовать нормальный внешний микрофон. При активации диктовки система предложит скачать дополнительные файлы. Соглашайтесь.

Теперь нужно сделать так, чтобы система реагировала на голос, идём в System Preferences > Accessibility, переходим в раздел «Dictation». Тут включаем активацию диктовки голосом и задаём ключевое слово (Эта функция появилась только в El Capitan). Сначала я хотел чтобы компьютер откликался на имя Джарвис, но что-то не срослось — то ли у меня проблемы с дикцией, то ли макось не хочет брать на себя такую ответственность. В общем, буду общаться с Марвином. Без паники.

Теперь самое главное — как узнать время? К сожалению, встроенных команд в системе для этого нет. Но есть возможность запускать произвольные команды.

Проще всего будет создать shell-скрипт запускаемый из автоматора. Вот этой одной строчкой получаем дату и сразу проговориваем её.

say `date +"%H %M"`

Открываем автоматор. Создаём новую программу, в разделе утилит выбираем запуск shell-скрипта, вставляем туда эту нехитрую команду. Сохраняем программу.

Снимок экрана 2015-08-11 в 9.40.01

Возвращаемся в настройки диктовки, нажимаем «Dictation commands» и добавляем новую команду. Указываем ключевую фразу и выбираем нашу запуск нашей программы. Придётся продираться через два выпадающих меню, да. Всё готово, пробуем общаться с новым другом.

P. S. В видео выше у меня Марвин почему-то говорил женским голосом, ну ничего, я это уже исправил в System Preferences > Dictation & Speech, выбрав другой голос на вкладке настроек речи.

 

Как это будет сказать по-русски?

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

  • Основное назначение коммит-мессаджа и комментариев — рассказать, а что тут происходит не влезая в код. Представьте, что что-то отвалилось, точно известно, что всё было в порядке месяц назад, перед тем, как вы ушли в отпуск и всё, что вам остаётся — это `git bisect`. Будет гораздо лучше, если вы найдёте первый сломанный коммит с текстом «Переписана метод сохранения комментария», чем «Fix comment».
  • Можно использовать гугл-транслейт — плохой аргумент. На то, чтобы сделать перевод нужно время, в самый неподходящий момент его конечно же не будет.
  • Описания тест-кейсов должны помогать понять, что происходит. В идеале это должна быть связная история, которая помогает быстро понять, что отвалилось.
  • Всё выше написанное не означает, что язык учить не надо. Надо, но не стоит смешивать изучение языка и создание комфортных условий для работы.
  • Если вы запилили опенсорсный проект и считаете, что он будет очень полезен сообществу — напишите README на английском и на русском. Про всё остальное можно будет начать беспокоиться когда у проекта появится достаточное количество пользователей, которые не понимают великий и могучий.