Развертывайте как Vercel и Netlify с помощью Cloud Run: Live, Preview и Modern Workflow

Развертывайте как Vercel и Netlify с помощью Cloud Run: Live, Preview и Modern Workflow

1 декабря 2022 г.

TL;DR

  • ☁️ Мы научимся развертывать в Google Cloud Run.
  • ✨ Мы научимся проектировать и реализовывать современный рабочий процесс с помощью GitHub Actions.
  • 🤿 Мы увидим фрагменты кода реальных рабочих процессов.

Если вы хотите узнать, как развертывать Vercel или Netlify с помощью Google Cloud, это место для вас.

Vercel и Netlify предлагают плавный переход от разработки к выпуску ваших функций и делают непрерывная доставка доступна из коробки. Сегодня мы рассмотрим, как спроектировать и воссоздать динамическое развертывание, а также предварительный просмотр развертывания с помощью Cloud Run и Действия GitHub.

Поехали.

Современный дизайн рабочего процесса

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

Чтобы спроектировать рабочий процесс, мы можем разбить его на два пути:

  • Производственный рабочий процесс: активируется событиями push в ветке main.
  • Рабочий процесс предварительного просмотра: активируется событиями push и pull_request во всех ветвях, кроме main.

Workflow overview

Сначала рассмотрим рабочий процесс.

Производственный процесс

production workflow overview

Рабочий процесс делает только одну вещь: живое развертывание. Когда запрос на вытягивание объединяется с основным, он запускает рабочий процесс для развертывания рабочей сборки в Cloud Run.

Рабочий процесс выглядит следующим образом:

Настройте Google Cloud

Отправка образа Docker в реестр артефактов

  • Создать тег изображения
  • Создать док-контейнер
  • отправить Docker-контейнер в реестр

Развернуть

  • Развертывание в Cloud Run

Настройка Google Cloud

<цитата>

Если у вас еще нет проекта в Google Cloud, следуйте этому руководству. чтобы создать его. Я назову свой проект awesome-project.

Чтобы аутентифицировать рабочий процесс для доступа к Google Cloud, мы можем использовать авторизацию< /strong> Действие GitHub для создания токена доступа:

env:
  PROJECT_ID: 'awesome-project'
  SERVICE: 'homepage'
  REGION: 'us-west1' # ☘️Low CO2
  REGISTRY: '[YOUR_REGISTRY_ID]'
  IMAGE_NAME: 'live'
  WORKLOAD_IDENTITY_PROVIDER: '[YOUR_WORKLOAD_PROVIDER_ID]'
  SERVICE_ACCOUNT: '[YOUR_SERVICE_ACCOUNT_ID]'

jobs:
  deploy:
    runs-on: ubuntu-20.04

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: 'Authenticate to Google Cloud'
        uses: 'google-github-actions/auth@v0.4.0'
        id: 'auth'
        with:
          token_format: 'access_token'
          workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ env.SERVICE_ACCOUNT }}

Здесь мы выполняем аутентификацию через Workload Identity Federation. Чтобы все заработало, нам понадобится

Поздравляем, вы сделали это! Это самая сложная часть рабочего процесса.

Теперь мы можем настроить Cloud SDK и разрешить рабочему процессу отправлять контейнеры Docker в реестр артефактов:

steps:
  - name: Set up Cloud SDK
    uses: google-github-actions/setup-gcloud@v0

  - name: Authorize Docker push
    run: gcloud auth configure-docker ${{ env.REGISTRY }}

Вы можете следовать этому руководству настроить реестр артефактов для хранения контейнеров Docker.

Отправить образ Docker в реестр артефактов

Теперь мы можем отправлять контейнеры, так что давайте докеризуем ваш проект и пометим ваше изображение:

steps:
  - name: Generate Image Tag
    id: image-tag
    run: |
      image_tag="$REGISTRY/$PROJECT_ID/$SERVICE/$IMAGE_NAME:${GITHUB_SHA::8}"
      echo "tag=$image_tag" >> $GITHUB_OUTPUT

  - name: Build Docker Container
    run: |
      docker build -t ${{ steps.image-tag.outputs.tag }}

  - name: Push Docker Container
    run: |
      docker push ${{ steps.image-tag.outputs.tag }}

Развернуть

Теперь вы готовы к развертыванию в облаке с помощью контейнера Docker:

steps:
  - name: Deploy to Cloud Run
    run: |
      gcloud run deploy ${{ env.SERVICE }} 
        --platform "managed"
        --region ${{ env.REGION }} 
        --image ${{ steps.image-tag.outputs.tag }}

Cloud Run по умолчанию назначит 100 % трафика этому развертыванию, поэтому все посетители будут перенаправлены на эту версию.

В Cloud Console вы найдете URL-адрес развертывания Cloud Run. Это выглядит так: https://homepage-12345abcde-ez.a.run.app< /a>. Он понадобится нам позже для нашего рабочего процесса предварительного просмотра.

Полный рабочий процесс GitHub Actions:

prod-ci.yaml

Предварительный просмотр рабочего процесса

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

Настройте Google Cloud

Отправка образа Docker в реестр артефактов

Развернуть

Давайте посмотрим на различия.

Отправить образ Docker в реестр артефактов

Первое отличие заключается в тегировании образа Docker. В производственном рабочем процессе мы используем константу $IMAGE_NAME в переменных среды, чтобы пометить рабочий образ. Однако для предварительного просмотра мы хотим использовать идентификатор, представляющий запрос на извлечение. Мы используем первые 8 символов имени ветки в качестве идентификатора:

В качестве примера я назову ветку TASK-123-awesome-workflow. Шаг task извлечет идентификатор задачи task-123 из имени ветки.

<цитата>

Если вас интересует синтаксис сценария оболочки, ознакомьтесь с . Расширение параметров оболочки.

Идентификатор должен быть в нижнем регистре, потому что позже мы будем использовать его для пометки редакции Cloud Run. Соглашение об именах тегов Cloud Run следующее: следует:

  • разрешены символы нижнего регистра
  • разрешены числа
  • допускается "-"
  • максимальная длина — 63 символа.

Затем мы можем использовать идентификатор задачи, чтобы пометить образ, создать контейнер и отправить его в реестр:

steps:
  - name: Generate Image Tag
    id: image-tag
    run: |
      image_tag="$REGISTRY/$PROJECT_ID/$SERVICE/${{ steps.task.outputs.id }}:${GITHUB_SHA::8}"
      echo "tag=$image_tag" >> $GITHUB_OUTPUT

  - name: Build Docker Container
    run: |
      docker build -t ${{ steps.image-tag.outputs.tag }}

  - name: Push Docker Container
    run: |
      docker push ${{ steps.image-tag.outputs.tag }}

Развернуть

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

  • В отличие от динамического развертывания, мы хотим назначать 0 % трафика предварительной версии.
  • Мы хотим указать для развертывания URL-адрес, отличный от действующего URL-адреса.

Мы можем использовать параметры --tag и --no-traffic для их достижения:

steps:
  - name: Deploy Revision with Tag
      run: |
        gcloud run deploy ${{ env.SERVICE }} 
          --platform "managed" 
          --region ${{ env.REGION }} 
          --image ${{ steps.image-tag.outputs.tag }} 
          --tag pr-${{ steps.task.outputs.id }} 
          --no-traffic

После успешного выполнения шага вы получите такой URL-адрес предварительного просмотра: https://pr-task-123---homepage-12345abcde-ez.a.run.app.

Наконец, мы можем опубликовать комментарий к URL-адресу предварительного просмотра в запросе на вытягивание:

steps:
  - name: Comment Preview URL in PR
    uses: mshick/add-pr-comment@v2
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    with:
      message: |
        🍿 Successfully deployed preview revision at https://pr-${{ steps.jira.outputs.id }}---homepage-12345abcde-ez.a.run.app
      allow-repeats: false

Полный рабочий процесс GitHub Actions Preview

предварительный просмотр.yaml

name: Preview Workflow

on:
  push:
    branches-ignore:
      - main
  pull_request:
    branches-ignore:
      - main
  workflow_run:
    workflows: ['Dev CI']
    types: [completed]

env:
  PROJECT_ID: 'awesome-project'
  SERVICE: 'homepage'
  REGION: 'us-west1'
  REGISTRY: '[YOUR_REGISTRY_ID]'
  WORKLOAD_IDENTITY_PROVIDER: '[YOUR_WORKLOAD_PROVIDER_ID]'
  SERVICE_ACCOUNT: '[YOUR_SERVICE_ACCOUNT_ID]'

jobs:
  preview:
    runs-on: ubuntu-20.04

    permissions:
      pull-requests: 'write'

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: 'Authenticate to Google Cloud'
        uses: 'google-github-actions/auth@v0.4.0'
        id: 'auth'
        with:
          token_format: 'access_token'
          workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ env.SERVICE_ACCOUNT }}

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v0

      - name: Authorize Docker push
        run: gcloud auth configure-docker ${{ env.REGISTRY }}

      # Get task id in lowercase from branch name for docker image naming convention
      # More detail on base parameter expansion: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
      - name: Get Task Id from Reference
        id: task
        run: |
          name="${{ github.ref_name }}"
          lowercase="${name,,}"
          echo "id=${lowercase:0:8}" >> $GITHUB_OUTPUT

      - name: Generate Image Tag
        id: image-tag
        run: |
          image_tag="$REGISTRY/$PROJECT_ID/$SERVICE/${{ steps.task.outputs.id }}:${GITHUB_SHA::8}"
          echo "tag=$image_tag" >> $GITHUB_OUTPUT

      - name: Build Docker Container
        run: |
          docker build -t ${{ steps.image-tag.outputs.tag }}

      - name: Push Docker Container
        run: |
          docker push ${{ steps.image-tag.outputs.tag }}

      - name: Deploy Revision with Tag
        run: |
          gcloud run deploy ${{ env.SERVICE }} 
            --platform "managed" 
            --region ${{ env.REGION }} 
            --image ${{ steps.image-tag.outputs.tag }} 
            --tag pr-${{ steps.jira.outputs.id }} 
            --no-traffic

      - name: Comment Preview URL in PR
        uses: mshick/add-pr-comment@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          message: |
            🍿 Successfully deployed preview revision at https://pr-${{ steps.jira.outputs.id }}---homepage-12345abcde-ez.a.run.app
          allow-repeats: false

Заключительные мысли

Мы только что воссоздали современный рабочий процесс от Vercel и Netlify! Есть несколько улучшений, делающих рабочий процесс более надежным:

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

Ссылки


Эта статья изначально была опубликована на веб-сайте Daw-Chih. н


Оригинал