Статический сайт на Gatsby в Yandex Object Storage
Как для сайта на Gatsby автоматизировать его выкладку в Объектное хранилище Яндекс Облака при помощи Github Actions.
Если у вас уже есть сайт на Gatsbyjs можно смело пропускать следующий параграф и переходить к конфигу Terraform.
Если же у вас нет сайта, то можно начать с установки Gatsby:
npm install -g gatsby-cli
Теперь мы можем создать заготовку нашего проекта, чтобы было что деплоить:
gatsby new gatsby-site
cd gatsby-site
Конфиг Terraform
Файл main.tf
содержит полную описание шагов по развертыванию всей инфраструктуры.
// Конфгурируем Yandex.Cloud provider
provider "yandex" {
zone = "ru-central1-a"
}
// Объявляем переменную с названием Организации на гитхабе.
// К сожалению github provider не создает ресурсы `github_actions_secret` в личных репах
// https://github.com/terraform-providers/terraform-provider-github/issues/422
// К счастью базовая функциональность организаций теперь бесплатна.
variable "github_organization" {
type = string
}
// Конфигурируем github provider.
provider "github" {
organization = var.github_organization
}
// Создаем Сервисный аккаунт в нашем облаке.
resource "yandex_iam_service_account" "gatsby" {
name = "gatsby"
description = "service account to publish Gatsby"
}
// Определяем переменную с именем каталога
variable "folder_name" {
type = string
default = "default"
}
data "yandex_resourcemanager_folder" "default" {
name = var.folder_name
}
// Выдаем прав сервисному аккаунту в Облаке
resource "yandex_resourcemanager_cloud_iam_member" "gatsby-iam" {
cloud_id = data.yandex_resourcemanager_folder.default.cloud_id
role = "editor"
member = "serviceAccount:${yandex_iam_service_account.gatsby.id}"
}
// Создаем статический ключ с которым будем ходить в Object Storage
// Для создания бакета, а потом и из Github чтобы заливать готовый сайт
resource "yandex_iam_service_account_static_access_key" "gatsby-static-key" {
service_account_id = yandex_iam_service_account.gatsby.id
description = "static access key for object storage"
}
// Заводим переменную с именем бакета
variable "bucket_name" {
type = string
}
// И созадем сам бакет
resource "yandex_storage_bucket" "gatsby-demo" {
bucket = var.bucket_name
acl = "public-read"
access_key = yandex_iam_service_account_static_access_key.gatsby-static-key.access_key
secret_key = yandex_iam_service_account_static_access_key.gatsby-static-key.secret_key
// В дефолтном примере сгенеренные страницы называются именно та
website {
index_document = "index.html"
error_document = "404.html"
}
// Заодно можно дополнительно указать CORS правила
cors_rule {
allowed_headers = [
"*"]
allowed_methods = [
"GET",
"PUT",
"POST",
"DELETE",
"HEAD"]
allowed_origins = [
"https://${var.bucket_name}.website.yandexcloud.net"]
expose_headers = [
"ETag"]
max_age_seconds = 3000
}
}
// Теперь приступим к созданию нового репозитория в нашей организации
variable "repo_name" {
type = string
}
resource "github_repository" "repo" {
name = var.repo_name
}
// И пропишем секреты, которые мы будем использовать из Github Action
resource "github_actions_secret" "AWS_S3_BUCKET" {
repository = var.repo_name
secret_name = "AWS_S3_BUCKET"
plaintext_value = var.bucket_name
}
resource "github_actions_secret" "AWS_ACCESS_KEY_ID" {
repository = var.repo_name
secret_name = "AWS_ACCESS_KEY_ID"
plaintext_value = yandex_iam_service_account_static_access_key.gatsby-static-key.access_key
}
resource "github_actions_secret" "AWS_SECRET_ACCESS_KEY" {
repository = var.repo_name
secret_name = "AWS_SECRET_ACCESS_KEY"
plaintext_value = yandex_iam_service_account_static_access_key.gatsby-static-key.secret_key
}
// Ну и наконец запишем только что созданный апстрим в наш конфиг локального репозитория
resource "null_resource" "git_origin" {
provisioner "local-exec" {
command = "git remote add origin git@github.com:${var.github_organization}/${var.repo_name}.git"
}
}
Если вы никогда не работали с Terraform, то вот инструкция по его установке.
GitHub Action
Так же нам нужно создать файл .github/workflows/build.yaml
с описанием Action, который при создании нового релиза на GitHub будет пересобирать и разворачивать новую версию сайта.
name: Gatsby Build and Publish
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read --follow-symlinks --delete
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_S3_ENDPOINT: https://storage.yandexcloud.net
AWS_REGION: 'ru-central1'
SOURCE_DIR: 'public'
Собственно почти все. Остается получить токен для гитхаба тут, выставив достаточные права.
Экспортировать его и остальные переменные среды и выполнить рецепт.
export GITHUB_TOKEN=%токен%
export YC_CLOUD_ID=%cloud_id%
export YC_FOLDER_ID=%folder_id%
terraform init
terraform apply
Дальше пушим код в гитхаб. Создаем новый релиз.
Ждем пока соберется и зальется в Object Storage.
Готово.