Я самостоятельно размещаю свой сайт martingraham.dev на VPS на Linode. Исходный код размещен на github, и поэтому каждый раз, когда я хотел установить обновления, мне приходилось удаленно подключаться к моему VPS, чтобы получить последнюю версию из репозитория, собрать сайт и перезапустить соответствующие процессы. Что это такое, 1985 год? Появились Github Actions.
Введение в Github actions
Действия Github — это настраиваемые автоматические действия, которые могут быть вызваны различными событиями, связанными с github. В моем случае действие происходит, когда происходит фиксация в моей ветке main
.
Мы определяем наши действия в файле .yml
, расположенном в .github/workflows
. Стоит сразу оговориться — этот файл будет виден в нашем репозитории, поэтому мы хотим быть внимательными к тому, какая информация будет раскрыта. Безопасность превыше всего!
name: Update Linode VPS Action
on:
push:
branches:
- 'main'
jobs:
Push-to-linode:
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Configure SSH
run: |
mkdir -p ~/.ssh/
echo "$SSH_KEY" > ~/.ssh/staging.key
chmod 600 ~/.ssh/staging.key
cat >>~/.ssh/config <<END
Host staging
HostName $SSH_HOST
User $SSH_USER
IdentityFile ~/.ssh/staging.key
StrictHostKeyChecking no
END
env:
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
- name: Run npm run deploy
run: |
ssh staging 'cd ~/martingraham-dot-dev; npm run deploy'
Давайте разделим это на части:
on:
push:
branches:
- 'main'
Этот бит определяет, когда будет выполняться действие. Моя схема очень проста, но события очень настраиваемы для расширенного развертывания.
Рабочий процесс может иметь несколько заданий — у меня только одно, под названием Push-to-linode
.
jobs:
Push-to-linode:
Это условие ничего не делает (из-за моей настройки событий), но я оставил его для будущего использования возможности
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
Я должен упомянуть строку runs-on: ubuntu-latest
. Действия Github запускаются на так называемых бегунах. В нашем случае бегун управляется github. Наши последующие команды будут выполняться из среды runner. Вы можете самостоятельно разместить свой собственный runner, но это потенциально может подвергнуть машину риску выполнения произвольного кода (скажем, у вас есть действие, которое выполняется на PR или форках), поэтому размещение собственного runner не рекомендуется для публичных репозиториев.
jobs:
Push-to-linode:
runs-on: ubuntu-latest
SSH и секреты
Наше задание состоит из нескольких шагов, первым из которых является настройка SSH-соединения с моим VPS. Команда run
выполняет команду в среде runner, поэтому здесь мы создаем файл конфигурации ssh.
run: |
mkdir -p ~/.ssh/
echo "$SSH_KEY" > ~/.ssh/staging.key
chmod 600 ~/.ssh/staging.key
cat >>~/.ssh/config <<END
Host staging
HostName $SSH_HOST
User $SSH_USER
IdentityFile ~/.ssh/staging.key
StrictHostKeyChecking no
END
$SSH_USER
— довольно странная учетная запись пользователя для использования на моем VPS, не так ли? На самом деле, я не хочу, чтобы весь интернет знал имена внутренних учетных записей моих VPS. И уж точно я не хочу, чтобы у них была копия моего приватного SSH-ключа. Вот тут-то и приходит на помощь env:
.
env:
SSH_USER: ${{ secrets.STAGING_SSH_USER }}
SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
Это устанавливает переменную окружения на runner, к которой могут получить доступ мои задания. В нашем репозитории Github мы заходим в настройки и можем определить секреты (SSH ключи, API ключи и т.д.), которые доступны нашим Github Actions. Очевидно, что они также редактируются в журналах, но вы всегда должны быть осторожны, чтобы не записывать такие значения в журнал.
Скрипты NPM
Следующий шаг использует мое только что настроенное SSH-соединение для подключения к моему VPS и запуска команд.
- name: Run npm run deploy
run: |
ssh staging 'cd ~/martingraham-dot-dev; npm run deploy'
Обратите внимание на ssh staging
— если вы посмотрите выше, то увидите, что в конфигурационном файле мы назвали цель, написав HOST staging
, и именно на это ссылаемся здесь.
В моем случае я запускаю приложение для node (точнее, SvelteKit), которое требует шага сборки, после чего процесс pm2
, связанный с приложением, должен быть перезапущен. Я использую скрипт npm
для извлечения последней версии из репозитория, сборки приложения и перезапуска процесса. Мне нравится этот способ, потому что, если мне нужно изменить процесс сборки, мне не нужно возиться с конфигурацией действий на github.
Заключение
Вот такое простое введение в Github Actions — идите и сэкономьте себе несколько шагов!
Фото Alex Knight on Unsplash