Или… Когда вы работаете над статическим сайтом, и GitHub Pages кажется идеальным решением для хостинга, поскольку вам нравится иметь все в одном месте, а затем вы понимаете, что вам нужна дополнительная среда, но вы по-прежнему не хотите использовать ничего, кроме GitHub. … Вот что вы можете сделать.

Это статья об особых потребностях, а также общее введение в GitHub Actions.

По состоянию на 2022 год для участия в партнерской программе на сайте medium.com должно быть не менее 100 подписчиков. На момент написания этой статьи у меня их было 13. Поэтому, пожалуйста, подпишитесь на меня, если вы найдете эту статью полезной или интересной. Спасибо!

С появлением одностраничных приложений требования к хостингу были снижены до минимума. Все, что может обслуживать статический файл HTML, отлично справится с этой задачей, а браузер, засыпанный Javascript, сделает тяжелую работу. Высокая доступность и безопасность — это, конечно, совершенно другая тема, но в этом случае я считаю, что GitHub вам поможет.

Благодаря Страницам GitHub предлагает очень удобный сервис для размещения такого приложения. Вы отправляете в свой репозиторий, и GitHub обновляет развертывание для вас. Вы даже получаете хороший поддомен, такой как username.github.io, или вы можете подключить свой собственный домен. Есть только один минус.

Если ваш проект — это не просто очень статичный веб-сайт, а настоящее «приложение», и вы работаете вместе с другими людьми, вы, вероятно, захотите иметь несколько развертываний, таких как среда разработки и промежуточная среда. Проблема в том, что репозиторий на GitHub может иметь только один экземпляр страницы GitHub, и вы, вероятно, не хотите поддерживать зеркальный репозиторий для каждой из ваших сред, поэтому в конечном итоге вы будете использовать внешний хостинг, а затем начнете задавать вопросы. GitHub Pages в качестве вашего предпочтительного решения для хостинга. В этой статье я покажу вам, что я сделал, чтобы «остаться на GitHub».

Действия и рабочие процессы GitHub

GitHub предлагает не только бесплатный хостинг, но и бесплатную, довольно гибкую и мощную автоматизацию рабочих процессов с помощью GitHub Actions. Если вы еще не знакомы с CI/CD и действиями GitHub, в частности, я рекомендую вам изменить это как можно скорее. Я слишком долго игнорировал эту тему, но теперь я большой поклонник. Это просто дает вам сверхспособности.

Я постараюсь дать вам краткое, но эффективное введение:

GitHub запускает виртуальные машины, которые выполняют роль исполнителей задач для ваших проектов. Эти задачи могут либо выполняться по расписанию, как задание cron, либо инициироваться событиями, происходящими на GitHub, такими как отправка коммитов в ветку, открытие или закрытие задач или их комментирование, если назвать некоторые распространенные. Эти задачи могут состоять из нескольких шагов, которые могут быть объединены в цепочку и зависеть друг от друга, отсюда и термин рабочие процессы. Терминология следующая: рабочие процессы содержат одно или несколько заданий, каждое из которых состоит из одного или нескольких шагов, которые могут использовать действие, которое может иметь входы и выходы.

Действия — это, так сказать, «атомы», из которых состоит рабочий процесс. Действие — это репозиторий на GitHub, содержащий action.yml файл, описывающий его входы и выходы. Это означает, что действие может в основном делать все, что вы хотите. Однако стоит отметить, что на самом деле вам даже не нужно использовать действия в своих рабочих процессах. Вы также можете просто запускать произвольные команды в операционной системе, в которой работает рабочий процесс, и иногда это все, что вам нужно. Вы можете думать о рабочих процессах GitHub просто как о «выполнении чего-то» на виртуальной машине, которую GitHub создает для вас по запросу.

Чтобы добавить новый рабочий процесс, вам нужно добавить файл конфигурации YAML в каталог .github/workflows вашего репозитория. GitHub автоматически подберет это и запустит в соответствии с настроенными вами условиями. Вот hello-world.yml, который показывает, пожалуй, самый простой и бесполезный рабочий процесс:

name: Hello World
on:
  schedule:
    - cron: '0 0 * * *'
jobs:
  hello-world:
    runs-on: ubuntu-latest
    steps:
      - run: echo Hello World!

(Я не буду рассматривать формат YAML в этой статье, но скажу вам, что тире представляют элементы в массиве, и если тире нет, вы имеете дело с ключами объекта. Если есть тире, за которыми следует… нет тире… это массив объектов. В отличие от простого JSON он поддерживает одинарные кавычки и комментарии. Все, что не заключено в кавычки, считается строкой, если только это явно не строка. YAML — это надмножество JSON. просто... в любом случае...)

Один раз в день в 0:00 этот рабочий процесс запускается и печатает «Hello World!» на stdout какой-нибудь виртуальной машины Ubuntu, где-то в сети GitHub. Он не использует никаких действий, а вместо этого запускает команду echo. Один шаг может либо запускать команды ИЛИ использовать действие.

jobs:
  hello-world:
    runs-on: ubuntu-latest
    steps:
      - uses: hello-world/say-action@v1
        with:
          say: Hello World!

Вы устанавливаете входные данные действия, если они есть, с помощью ключевого слова with. Я бы назвал это inputs, но кого это волнует.

Выходы и зависимые задания

Если у действия есть выходные данные, вы можете использовать их в последовательных шагах одного и того же задания. Шагу с выходными данными просто нужен id, на который будут ссылаться другие шаги.

jobs:
  hello-world:
    runs-on: ubuntu-latest
    steps:
      - id: get-name
        uses: hello-world/get-name-action@v1 # has a "name" output
      - uses: hello-world/greet-action@v1        
        with:
          name: ${{ steps.get-name.outputs.name }}

Чтобы сделать задание зависимым от предыдущего и, таким образом, позволить ему использовать свои выходные данные, вы должны указать, какие именно выходные данные сделать доступными, а затем определить массив «потребностей».

jobs:
  get-name:
    runs-on: ubuntu-latest
    outputs:
      name: ${{ steps.get-name.outputs.name }}
    steps:
      - id: get-name
        uses: hello-world/get-name-action@v1 # has a "name" output
  say-name:
    runs-on: ubuntu-latest
    steps:
      - uses: hello-world/greet-action@v1        
        with:
          name: ${{ steps.get-name.outputs.name }}

Секреты и окружение

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

Здесь вы можете определить эти значения и использовать их в своих рабочих процессах.

steps:
  - run: echo ${{ secrets.SECRET_STRING }}

Секреты также можно определить для всей организации на GitHub (перейдите в ее настройки и там Секреты), чтобы они были доступны во всех рабочих процессах во всех репозиториях этой организации. С другой стороны, вы также можете дополнительно ограничить доступ к секретам. Вот для чего нужны среды. Думайте о них как о категориях секретов в определенном хранилище.

Вы можете сказать рабочему процессу, к каким секретам среды он может получить доступ. Допустим, вы создали среду в настройках своего репозитория под названием development.

jobs:
  hello-world:
    runs-on: ubuntu-latest
    environment: development
    steps:
      - run: echo ${{ secrets.DEVELOPMENT_ENV_SECRET }}

В настройках среды вы увидите, что доступ также может быть ограничен определенными ветвями, так что только рабочий процесс, запущенный событием, связанным с соответствующей ветвью, имеет доступ к секретам среды, и вы также можете потребовать, чтобы администратор одобрил эти рабочий процесс запускается до того, как они фактически запускаются.

Мы будем использовать это позже в статье.

После обработки этой очень сжатой информации вы должны почувствовать, насколько мощными и гибкими могут быть эти рабочие процессы и что вы можете делать практически все, что только можете себе представить. Например, я использую их для интеграции криптовалютных платежей в конвейеры развертывания на GitHub, но это совершенно секретный проект, и вам лучше стереть эту информацию из памяти прямо сейчас. Хорошо? Хорошо. Спасибо.

Если вы хотите глубже погрузиться в GitHub Actions самостоятельно, просмотрите документацию, а если вы хотите начать экспериментировать, я рекомендую добавить в закладки Синтаксис рабочего процесса для GitHub Actions и События, запускающие рабочие процессы.

ВНИМАНИЕ: Небольшое примечание по безопасности при использовании секретов с неофициальными/непроверенными действиями!

Как уже упоминалось, действия могут принимать входные данные. Эти входные данные могут быть секретами. Типичный пример — Докер:

jobs:
  build-and-push-docker-image:
    runs-on: ubuntu-latest
    steps:
      - name: Login to DockerHub
        uses: docker/login-action@v1 
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

Здесь используется действие docker/login-action, которое является проверенным действием:

Используемая вами версия действия определяется @v1 в конце, что является именем ветви или тега. Теперь Докер может быть заслуживающим доверия автором, но даже в доверенных организациях время от времени может появляться новый член команды, и иногда новые члены команды оказываются не такими надежными, как остальная часть организации, к которой они только что присоединились, а политики безопасности иногда более важны. теоретическая вещь. В любом случае… Самое позднее при работе с непроверенными действиями вам нужно знать одну вещь (если вы еще этого не сделали):

Код, на который ссылается тег, может измениться!

Это означает: действие, которому вы передаете один из своих секретов, может сегодня быть вашим лучшим другом, а завтра украсть ваши самые сокровенные секреты, даже если вы даже не подозреваете, и раскрыть их вашим злейшим врагам, которые просматривают темную сеть в поисках последние взломы и утечки!

Если есть сомнения, сошлитесь на действие по хэшу коммита, например:

- name: Login to shady service
  uses: trustme/spy-action@172239021f7ba04fe7327647b213799853a9eb89
  with:
    password: ${{ secrets.SUPER_SECURE_PASSWORD }}

Иубедитесь, что код, на который ссылается этот хэш коммита, действительно делает то, о чем говорится в файле readme. Если вы не… ну… тогда просто используйте имя тега. Вас предупредили (в том числе и доками).

Сценарий моих страниц GitHub

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

Мне нужны были три среды, которые ведут себя так:

  • Производство: приложение, которое пользователи будут использовать на самом деле. Обновлено при отправке в основную ветку, требуется одобрение администратора.
  • Разработка: Предварительный просмотр последнего хода разработки. Обновлено при нажатии на ветку разработки.
  • Staging: развертывания «Phoenix», созданные для запросов на вытягивание из веток функций и удаленные при закрытии, включая слияния.

Основной репозиторий, названный просто «app», не имеет собственной страницы GitHub. Вместо этого есть два дополнительных репозитория: «app-prod» и «app-dev». Я упомянул в начале, что вы, конечно же, не хотите поддерживать какие-либо зеркальные репозитории, и поэтому эти репозитории содержат только сборку приложения и включают свою страницу GitHub. Это их единственная цель. Кроме того, каждый запрос на вытягивание в ветке разработки приводит к созданию нового репозитория с именем «app-pr-‹ID запроса на вытягивание›». Визуализация:

Рабочий процесс: разработка, сборка и развертывание

Давайте начнем с развёртывания для разработки, так как это самое прямое, без каких-либо дополнений. Взгляните на этот файл рабочего процесса, а затем я проведу вас шаг за шагом. Суть происходящего в том, что мы извлекаем репозиторий, собираем приложение и отправляем эту сборку в репозиторий app-dev.

1.) Рабочий процесс запускается, когда новые коммиты отправляются в ветку разработки, но не для изменений, которые затрагивают только сами файлы рабочего процесса или любые файлы уценки:
https://github.com /OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L2-L7

2.) Мы устанавливаем URL-адрес, подключенный к странице GitHub репозитория app-dev, в качестве глобальной переменной среды, чтобы использовать ее позже в рабочем процессе:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L8-L9

3.) На самом деле есть только одно задание с большим количеством шагов, которое выполняется на последней версии виртуальной машины с использованием секретов, которые мы настроили для нашей среды разработки в репозитории. настройки:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L11-L16
К вашему сведению: Установка ключа url для среды означает только то, что GitHub будет отображать ссылку на этот URL-адрес в разных местах на github.com, например, в связанном запросе на включение или обзоре развертываний репозитория.

4.) Мы используем официальное действие (действия, предоставленные организацией actions GitHub) для подготовки Node.js на ВМ:
https:/ /github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L18-L19

5.) Мы используем обычные команды Git, чтобы установить бота GitHub Actions в качестве автора фиксации, потому что позже мы зафиксируем и отправим изменения в репозиторий:
https://github.com /OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L22-L25

6.) Мы извлекаем репозиторий в каталог build, используя официальное действие извлечения:
https://github.com/OpenQDev/app /blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L27-L30
К вашему сведению: если вы не передадите определенное имя репозитория в действие проверки, как в шаг 8, он просто извлечет репозиторий, в котором живет рабочий процесс.

7.) Мы переходим в этот каталог build и фактически собираем приложение (кстати, приложение Nuxt.js) после установки некоторых переменных среды. Затем возвращаемся в родительский каталог:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L32-L41
К вашему сведению: экспортированные переменные среды не являются постоянными для заданий/этапов, и их не следует путать с переменными окружения рабочего процесса (строка 9), которые доступны на протяжении всего рабочего процесса.

8.) Теперь мы извлекаем репозиторий app-dev в каталог deploy, на этот раз также предоставляя в качестве секрета токен личного доступа. Это позволяет отправлять изменения в этот репозиторий на следующем шаге:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L43-L48

9.) Затем мы просто копируем файлы из каталога build в каталог deploy, в результате чего в репозитории появляются нужные нам изменения. для фиксации и отправки:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-dev.yml#L50-L58
к вашему сведению: Строки 54 и 55 добавляют файлы, необходимые для правильной работы страницы GitHub. Мы отключаем Jekyll в качестве генератора статических сайтов GitHub по умолчанию (мы позаботимся об этом сами, используя Nuxt) и настраиваем домен, который мы хотим подключить к нашему развертыванию разработки.

Готово!

Разве это не супер просто и интуитивно понятно? :D Я не утверждаю, что это самый умный и эффективный способ сделать это. Но надеюсь достаточно понятно. Перейдем к производственному развертыванию.

Рабочий процесс: производственная сборка и развертывание

Взгляните на файл рабочего процесса, и вы заметите, что он… почти такой же. Единственными отличиями являются ветка, которую «слушает этот рабочий процесс», URL-адрес развертывания, среда, две переменные env, используемые при сборке приложения и репозиторий развертывания. Однако более существенным отличием является конфигурация среды в настройках репозитория. Это позволит запустить этот рабочий процесс только после того, как администратор утвердит его.

И я думаю, что это все, что можно сказать о производственном развертывании, и мы можем взглянуть на самую интересную часть всего этого. Пул-реквесты.

Рабочий процесс: сборка и развертывание запроса на вытягивание

Опять же, сначала просмотрите файл рабочего процесса, попробуйте разобраться в нем самостоятельно, а затем я просто объясню, что здесь отличается.

Самое главное, что для этого развертывания еще нет репозитория. Мы должны создать его из нашего рабочего процесса. Чтобы иметь уникальное имя для репозитория, мы получаем идентификатор GraphQL запроса на включение:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-pr.yml #L9-L10
К сведению: переменная github позволяет получить доступ к контексту запуска рабочего процесса, например событие, вызвавшее его, включая сам объект запроса на вытягивание.

Существует отдельное задание, которое создает репозиторий с помощью созданного мной специального действия:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/deploy-pr.yml#L13- Л21

Вы можете взглянуть на само действие, чтобы увидеть, что происходит на самом деле:
https://github.com/mktcode/create-repository-action/blob/b1dd3b3dcdcc491795ae189db97383a47f04808e/index.js#L6-L29

Следующее задание зависит от создаваемого репозитория и использует среду pr-staging:
https://github.com/OpenQDev/app/blob/715573cd6ceebe87e7e235180510eaacacb7d74a/.github/workflows/ развернуть-pr.yml#L23-L28

С этого момента это почти то же самое, что и рабочий процесс разработки и производства. Единственное, чего не хватает, — это удалить репозиторий после слияния/закрытия запроса на вытягивание. Это обрабатывается в отдельном рабочем процессе. Он использует еще одно специальное действие, которое я создал.

Теперь у вас могут быть запросы на включение такие как этот с их собственными автоматическими развертываниями для проверки изменений перед слиянием.

И это действительно так! Были сделаны. Теперь у нас есть проект статического сайта с несколькими средами, который полностью находится на GitHub. И это только одна из возможных конфигураций, которая, я уверен, далека от совершенства. На самом деле я работаю над некоторыми улучшениями. Так что, возможно, я скоро обновлю эту статью. Но я надеюсь, что вы почувствовали, что возможно с GitHub Actions и Workflows, и теперь вы начинаете экспериментировать и создавать свои собственные для своих индивидуальных целей.

Спасибо, что прочитали!

Вы можете следить за мной в Twitter и GitHub. Если вы планируете стать участником среды, вы можете поддержать меня, используя мою реферальную страницу: https://markus-kottlaender.medium.com/membership