С некоторых пор Heroku поддерживает сабмодули Git, что позволяет разделить непосредственно код приложения и файлы, необходимые исключительно для деплоя на Heroku. Тогда первый репозиторий можно хранить на гитхабе, а второй — хостить внутри Heroku, где к нему не будет ни у кого доступа.
Например, я использовал примерно такую структуру репозитория для деплоя Django-приложения (уверен, нечто подобное можно придумать и для RoR):
django-application-heroku ┊ ← Рабочая копия репозитория для Heroku.
│ ┊
├── project ┊ ← Сабмодуль с кодом, указывающий на GH.
│ ├── django_application ┊ ← Непосредственно код и данные самого
│ │ ├── locale/ ┊ приложения, которые ничего знать не
│ │ ├── migrations/ ┊ знают о Heroku. Структура файлов и
│ │ ├── templates/ ┊ каталогов, обычная для Django-проекта.
│ │ ├── admin.py ┊
│ │ ├── apps.py ┊
│ │ ├── models.py ┊
│ │ ├── urls.py ┊
│ │ ├── views.py ┊
│ │ └── (...) ┊
│ │ ┊
│ ├── django_project ┊
│ │ ├── settings.py ┊ ← Базовая часть конфигурации, неизменная
│ │ ├── urls.py ┊ при любом способе деплоя.
│ │ ├── wsgi.py ┊
│ │ └── (...) ┊
│ │ ┊
│ ├── manage.py ┊ ← Раннер и конфиг с закреплёнными версиями,
│ └── requirements.txt ┊ используемые на машинах разработчиков.
│ ┊
├── bin ┊
│ └── post_compile ┊ ← Вспомогательный скрипт, который сам
│ ┊ запускает миграции БД при успешном деплое
│ ┊ на Heroku.
│ ┊
├── manage.py ┊ ← Такой же раннер, что и в рабочем репозитории,
│ ┊ но использует heroku-settings.py в качестве
│ ┊ конфигурации приложения вместо settings.py.
├── requirements.txt ┊ ← Закреплённые версии специально для Heroku.
│ ┊ Тот же набор, что и в рабочем репозитории,
│ ┊ плюс дополнительно пакеты gunicorn,
│ ┊ dj-database-url и WhiteNoise.
├── heroku_settings.py ┊ ← Конфигурация приложения специально
│ ┊ для Heroku. Например, приводит DATABASE_URL
│ ┊ к формату, понятному Django.
├── heroku_wsgi.py ┊ ← То же, что и wsgi.py, но с конфигом Heroku.
├── Procfile ┊ ← Запускает gunicorn с нужными параметрами.
└── runtime.txt ┊ ← Используемый рантайм.
Конечно, данный подход не лишён недостатков (наиболее серьёзный из которых — приходится поддерживать набор практически одинаковых файлов
manage.py
,
requirements.txt
,
wgsi.py
), однако он позволяет:
- избавиться от мешанины разрозненных файлов в корне репозитория
(какая религия помещала разработчикам Heroku искать эти файлы в отдельном подкаталоге, а не корне проекта?);
- эффективно разграничить разработку и деплой.