Привет, читатели, это третья часть обучающих постов о написании Slack App с использованием чистого Ruby (на самом деле не полностью чистого, как оказалось).
Если вы не знакомы со списком частей, то вот он (со ссылками):
Тусовка приложения с таким гостем как Heroku (Мы здесь).
Положение дел таково, что сейчас бот висит на локальном сервере, запускаю вручную. Ребята из моего workspace могут пользоваться функциями бота, когда он включен, с этим нет проблем.
Проблема или недостаток проваляется в том, чтобы бот был доступен 24/7. Как можно пользоваться чем-либо, если оно имеет неоднозначную доступность. Например, ты выходишь утром на маршрутку и не знаешь наверняка будет она или нет. Тогда, вероятно, ты выберешь иной транспорт для передвижения; что-то более надежное.
Максимально переложив ответственность за онлайн своего приложения, ты сможешь сфокусироваться на других задачах, думать больше о новых фичах и новых приложениях. Ведь попробуй просто представить себе, как ты с утречка начинаешь поднимать 20 ботов на своём бедном Lenovo в надежде, что сегодня ни свет, ни интернет не выключится? Представил? А теперь представь если 20 ботов висят на сервере и ты с утра заходишь, смотришь какой у них статус с помощью удобного дашборда. Так и 21е приложение не за горами будет :)
Понимаю, всё звучит так классно, но ты возразишь, а деньги на сервер зачем выбрасывать? Тебе кажется, что твой бот только тебе и интересен, зачем же тратиться. А если я скажу что есть сервис, бесплатный, качественный, функциональный, который в начале кажется сложным, но как всё сложное, его нужно лишь понять и станет простым и отличным помощником.
Выглядит как промо за 50$, но на самом деле я был поражен лишь тем фактом, что если зайти на цены, то там есть раздел Hobby. Это на моей памяти первый случай, когда сервис есть в бесплатном виде, чтобы поддерживать начинания разработчиков, и потом, когда идея окажется работоспособной, тут же можно понемногу увеличивать возможности своего сервиса. Только за это уже можно читать дальше, разве нет?
Шаг 1 : Создание приложения в Heroku
Заходим по адресу. Регистрируемся. Нажимаем New -> Create new app (Рисунок 1).
Вводим название своего приложения (особо не напрягайся как оно будет называется, это просто идентификатор среди других твоих приложений в этом сервисе).
На следующей вкладке нам интересен блок Deployment methods (Рисунок 2), выбираем Heroku Git.
После выбора, внизу загрузиться инструкция к соответствующему методу выгрузки нашего приложения (Рисунок 3):
Собственно, сейчас выполним эти команды.
Шаг 2 : Выгрузка приложения в Heroku
Открываем терминал и переходим по пути к нашему проекту, который собираемся выгружать. В моём случае, я использую RubyMine, так что терминал в IDE уже открыт по адресу проекта.
Собственно, выполняем команды сверху -> вниз.
heroku login
-> у тебя откроется окно в браузере, после авторизации в консоле появится сообщение об этом.Если у тебя ещё не создан git репозиторий в корне проекта - то создай его, у меня он уже есть, так что я пропущу команды по его созданию
Добавляем ссылку на heroku-git-репозиторий
heroku git:remote -a habr-one-love
Добавляем все файлы, делаем коммит и отправляем (push) на этот репозиторий.
Push может занять некоторое время, ведь теперь, для твоего приложения, heroku создал GitHub action, и на каждый push в ветку master будет делать build и run твоего приложения. Чтобы не сидеть и не смотреть в экран, ожидая окончания push - перейдем к знакомству с командами heroku.
Шаг 3 : Основы, которые необходимы для работы с нашим приложением
Для отправки любых изминений на heroku нужно делать push через git. По-другому лучше не будет, это самый удобный из доступных способов. Тестируем на локалке, пушим - видим на дев сервере.
Команды, которые могут быть полезными чаще других :
heroku logs --tail - отобразит лог событий с твоим приложением в терминале (консоли).
Эти события можно посмотреть через Heroku Dashboard на сайте. Для этого - переходим по ссылке к списку приложений и выбираем своё приложение. Нажимаем More->View logs (Рисунок 4).heroku local - для запуска приложения локально, используя список команд указаных в Procfile (создадим ниже).
Опционально можно указать ещё какой именно процесс вы хотите запустить, по-умолчанию этоweb.
Procfile
- это файл-список команд, которые будут выполнены, при старте твоего приложения.`Dyno` - процессы, которые описаны в
Procfile
.`Adds-on` - дополнительное ПО, например - PostgreSQL устанавливается по-умолчанию.
`Buildpacks` - скрипты, которые будут выполняться во время этапа билда приложения, то есть, каждый раз при push, но перед Procfile. Для нас интересно два buildpack - ruby и chrome headless. Так как по-умолчанию ни ruby, ни браузера на сервере нет.
Шаг 4 : Настраиваем Procfile
Добавляем файл в корень проекта, называем его, угадайте как .... Procfile. Записываем туда одну команду :
web rackup config.ru -p ${PORT:-5000}
Этой командой мы запустим наше приложение.
Шаг 5 : Добавляем ENV
heroku config
Эта команда покажет какие сейчас есть переменные окружения для приложения. Нам нужно добавить сюда переменные, которые сейчас находятся в файле `env`. Для этого использовать такую команду :
heroku config:set ключ=значение
Например :
heroku config:set SLACK_CLIENT_ID=123456789000.1123555869121
По такому же процессу добавляем все переменные окружения :
SLACK_CLIENT_ID
SLACK_API_SECRET
SLACK_VERIFICATION_TOKEN
SLACK_REDIRECT_URI
Для получения SLACK_REDIRECT_URI нам нужно узнать адресс приложения. Чтобы узнать его, заходим в Dashboard (Рисунок 4) и нажимаем Open App. В открывшейся вкладке копируем адрес, это и есть адресс приложения. Добавляем /finish_auth
и вот он наш redirect uri.
После заполнения всех ключей, можем удалить `env.rb` (так же удалить require этого файла в коде), теперь наши sensetive данные хранятся безопастно!
Шаг 5 : Обновляем Database данные
Теперь у нас БД будет не локальная, а хранится на Amazon AWS через Heroku. Поменяем данные для доступа в эту БД. Переходим в файл `Database.rb` в функцию init.
Как найти значения новой базы данных ?
Переходим в Dashboard Heroku;
Блок Adds-on;
Выбираем Heroku Postgres;
Нажимаем на:
Откроется Adds-on (Рисунок 5);
Переходим на вкладку Settings;
Нажимаем View Credentials.
У меня, пока писал пост, появилась идея записать эти данные в Heroku Config, чтобы не хранить в коде доступы.
Заменим в фунции init все параметры на :
def init
@db = PG.connect(
host: ENV['HU_POSTGRES_HOST'],
dbname: ENV['HU_POSTGRES_DBNAME'],
user: ENV['HU_USER_USER_ENV'],
password: ENV['HU_POSTGRES_PASS']
)
end
И добавим, по-аналогии с переменными для Slack API, их - испольуя доступы в базу с Heroku.
Шаг 6 : Проверяем деплой и подключаем Slack
Делаем Push изменений на heroku. Смотрим лог, наблюдаем картину как на Рисунке 6. Если всё так, то значит ты, как и я, сделал всё правильно!
Поскльку адрес бота с localhost поменялся, то нужно зайти в настройки приложения в Slack API и там поменять адрес везде, где только можно. Для удобства, выпишу список потенциальных мест :
Напоминаю, адрес вашего приложения можно получить с помощью Heroku Dashboard!
Slash Commands
OAuth & Permissions > Redirect URLs
Interactivity & Shortcuts > Interactivity
Event Subscriptions
Переустанавливаем приложение, чтобы создалась таблица с доступами в новой БД.
Также, я переписал модуль базы данных для своего приложения, что именно поменялось, можно найти по этим коммитам : главный, фикс, фикс.
Теперь снова делаем коммит + пуш в Heroku.
Заходим в слэк и прописываем команду, которую мы создавали ранее :
/who_am_i
Если твой результат частично совпал с результатом на Рисунке 7 - поздравляю! Ты успешно разместил своё приложение на Heroku!
Шаг 7 : Технические нюансы моего приложения
В прошлом уроке я рассматривал как рендерить фронт на сервере, но делал это на локальной машине, где уже есть бинарные файлы для браузера. Что же касаемо реального сервера ? Там их нет по определению, но можно ведь и добавить :)
Я расскажу как это делать с помощью Heroku Buildpacks.
Заходим в панель управления приложением Heroku.
Выбераем вкладку Settings.
Там ищем блок Buildpacks (Рисунок 8)
Клацаем на Add buildpack.
Вписываем URL : https://buildpack-registry.s3.amazonaws.com/buildpacks/heroku/google-chrome.tgz
Всё, теперь, при следующем билде, у нас загрузится новый buildpack, в котором установиться ядро google-chrome.
Теперь нужно немного подправить сам код по рендеру графика, чтобы он нашел файл этого браузера, в файле commands.rb :
browser = Ferrum::Browser.new(
:browser_path => "/app/.apt/usr/bin/google-chrome"
)
в этом же файле поменяем GET запрос на скрин графа, с этого:
get '/graph_image.png' do
send_file 'Components/Graph/result.png'
end
на такой:
get %r{/graph_image/(?<ts>\w+)} do
send_file "/app/#{params[:ts]}_graph.png"
end
Идея в том, чтобы каждый скрин подписывать timestamp-ом, когда он создан, а не перезаписывать один и тот же файл. К тому же, изменился путь к файлу, ведь в Heroku нельзя сохранять файл так, как он сохранялся ранее. Поменяем процесс сохранению скриншота к такому виду :
graph_ts = Time.now.to_i
browser.screenshot(path: "/app/#{graph_ts}_graph.png")
Так же поменяем сам шаблон :
{
"type": "modal",
"title": {
"type": "plain_text",
"text": "Граф"
},
"blocks": [
{
"type": "image",
"image_url": "http://<%= host %>/graph_image/<%= graph_ts %>",
"alt_text": "Сер Граф"
}
]
}
Эти изменения описаны в комитах 1,2 и 3.
Коммитим и пушим на Heroku! Отныне build приложения будет занимать больше времени из-за нового buildpack.
Теперь можно идти в Slack workspace и писать /graph.
Если всё сделали правильно, то и ответ получим тот, который ожидали !
Результаты
После успешного прохождения всех этапов, вы, как и я должны получить :
Выгруженую в Heroku приложуху которая умеет общаться с Slack API, рендерить html и просто быть в онлайне 24/7.
Переменные окружения теперь находятся в более безопастном месте.
Модуль базы данных был переписан в класс и теперь может создавать базы данных основываясь на динамических функциях (звучит как что-то особенное, но я не знаю как ещё назвать это, кто смотрел коммиты тот поймёт).
Функционал получения графиков обновлен.
Можно резюмировать успешное прохождения цикла из 3х статей по разработке Slack Ruby бота на Sinatra, которое успешно работает на Heroku и имеет функционал по работе с Google Chrome Headless, Slack Modals и Slack Slash Commands. Кроме того - умеет добавлять и поддерживать несколько пользоватей.
С текущего момента, вы сами уже будете иметь необходимые навыки для дальнейшего развития этого приложения, но, если у Вас есть интерес к моим статьям и этой теме, я могу и дальше описывать интересные технологии и решения, которые мне встретятся в будущем. Сейчас, к слову, есть материал для написания таких статьей :
Рефакторинг реального приложения на Ruby on Rails, так как Sinatra уже создает больше неудобств, чем удобств по работе с ним.
Добавление и настройка Home Page для Slack App.
Интеграция Slack App с Jira для авто-трекинга времени по задачам.
Ссылка на Git репозиторий, кому нравиться - ставьте звезды, я старался и это лучший способ меня поддержать!