Привет, читатели, это третья часть обучающих постов о написании 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 репозиторий, кому нравиться - ставьте звезды, я старался и это лучший способ меня поддержать!
Автор: Олександр