htmlkin.ru
Войти
Блог/Как пользоваться

Как организовать Git-Flow для htmlkin.ru

Сайт в GitHub-репозитории публикуется на htmlkin.ru при каждом merge в main: API-ключ, ID сайта из личного кабинета, workflow GitHub Actions, работа через PR и откат.

 · 6 мин чтения
Седой дирижёр в тёмно-зелёном пиджаке поднимает палочку на терракотовом фоне

Правишь сайт в отдельной ветке, открываешь PR, мержишь в main — GitHub Actions сам выкладывает новую версию на htmlkin.ru. Адрес сайта остаётся прежним, откат делается одним git revert.

Так работает тренажёр устного счёта math.htmlkin.ru. Его репозиторий открыт — github.com/seliseev/math, весь код ниже взят оттуда.

Устройство такое: GitHub Actions упаковывает репозиторий в ZIP и отправляет его в REST API htmlkin запросом PUT /api/v1/pages/{id}. Сайт заменяется целиком.

Что понадобится

  • Тариф «Оптимальный» или «Бизнес» — на них открыт REST API.
  • Репозиторий на GitHub, в корне которого лежит index.html.

Шаг 1. Создай API-ключ

Личный кабинет → «API-ключи» → создай ключ. Ключ показывается один раз — скопируй его сразу.

Шаг 2. Скопируй ID сайта

Workflow обновляет сайт по его ID. ID показан в карточке сайта в личном кабинете, в разделе «Мои сайты», — рядом с ним кнопка копирования.

Сайт уже опубликован — бери его ID. Адрес сохранится. Первый же прогон заменит содержимое сайта файлами из репозитория.

Сайта ещё нет — создай его: «Мои сайты» → «Опубликовать сайт» → перетащи index.html из репозитория. Остальные файлы выложит первый прогон workflow. ID появится в карточке сайта.

Из терминала сайт создаётся запросом POST /api/v1/pages, ID придёт в поле id ответа — пример в документации REST API.

Шаг 3. Положи ключ и ID в настройки репозитория

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

gh secret set HTMLKIN_API_KEY --repo owner/repo
gh variable set HTMLKIN_PAGE_ID --repo owner/repo --body 'abc123'

gh secret set спросит значение — вставь ключ. Через интерфейс то же самое делается в Settings → Secrets and variables → Actions: ключ — на вкладке Secrets, ID — на вкладке Variables.

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

Шаг 4. Добавь workflow

Создай файл .github/workflows/deploy.yml:

name: Deploy to htmlkin.ru

on:
  push:
    branches: [main]
  workflow_dispatch:

# htmlkin заменяет сайт целиком, поэтому два прогона подряд
# могут выложить старую версию поверх новой.
concurrency:
  group: htmlkin-deploy
  cancel-in-progress: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Собрать ZIP сайта
        run: |
          zip -r site.zip . \
            -x '.git/*' '.github/*' '.gitignore' 'README.md' '*.zip'
          unzip -l site.zip

      - name: Обновить сайт на htmlkin.ru
        env:
          HTMLKIN_API_KEY: ${{ secrets.HTMLKIN_API_KEY }}
          PAGE_ID: ${{ vars.HTMLKIN_PAGE_ID }}
        run: |
          set -euo pipefail

          if [ -z "${HTMLKIN_API_KEY}" ]; then
            echo "::error::Не задан секрет HTMLKIN_API_KEY (Settings → Secrets and variables → Actions → Secrets)"
            exit 1
          fi
          if [ -z "${PAGE_ID}" ]; then
            echo "::error::Не задана переменная HTMLKIN_PAGE_ID (Settings → Secrets and variables → Actions → Variables)"
            exit 1
          fi

          code=$(curl -sS -o response.json -w '%{http_code}' \
            -X PUT "https://htmlkin.ru/api/v1/pages/${PAGE_ID}" \
            -H "Authorization: Bearer ${HTMLKIN_API_KEY}" \
            -F "site_archive=@site.zip")

          echo "HTTP ${code}"
          cat response.json
          echo

          if [ "${code}" -lt 200 ] || [ "${code}" -ge 300 ]; then
            echo "::error::htmlkin.ru вернул ${code}: $(jq -r '.message // .error // "неизвестная ошибка"' response.json)"
            exit 1
          fi

          url=$(jq -r '.url' response.json)
          files=$(jq -r '.file_count' response.json)
          echo "Сайт обновлён: ${url} (файлов: ${files})"
          {
            echo "### Сайт обновлён"
            echo ""
            echo "- Адрес: ${url}"
            echo "- Файлов: ${files}"
            echo "- Коммит: \`${GITHUB_SHA}\`"
          } >> "${GITHUB_STEP_SUMMARY}"

Что он делает:

  • Запускается на каждый push в main и вручную — кнопкой Run workflow на вкладке Actions.
  • Упаковывает в ZIP всё содержимое репозитория, кроме перечисленного после -x. Новые страницы и картинки попадут в архив сами. Служебные файлы, которым не место на сайте, допиши в этот список.
  • Отправляет архив в API, и htmlkin заменяет сайт целиком: файл, удалённый из репозитория, исчезнет и с сайта.
  • Отменяет прогон, который ещё идёт, если пришёл новый push. Так старая версия не ляжет поверх новой.
  • Падает с текстом ошибки, если API ответил не 2xx. При успехе пишет в Summary прогона адрес, число файлов и коммит.

Шаг 5. Запушь и проверь

git add .github/workflows/deploy.yml
git commit -m "Публикация на htmlkin.ru"
git push origin main

Открой вкладку Actions → прогон Deploy to htmlkin.ru. В примере прогон занимает 8–12 секунд. В Summary будет адрес — открой его и проверь, что правка на месте.

Как работать дальше: ветка → PR → main

Правило одно: что в main, то и на сайте. Пуши в другие ветки workflow не запускают, поэтому незаконченные правки держи в ветках.

git switch -c page-40
# добавляешь 40.html, правишь ссылки
git add .
git commit -m "Счёт до 40"
git push -u origin page-40
gh pr create --fill

PR открывается и кнопкой Compare & pull request на GitHub. В нём видна каждая изменённая строка — проверь сам или отдай на ревью. Нажимаешь Merge pull request, GitHub делает push в main, и workflow публикует сайт.

Если над сайтом работают несколько человек, включи защиту ветки main в настройках репозитория, в разделе Branches. Тогда в main попадает только то, что прошло через PR.

Как откатить неудачную версию

Сайт повторяет main, поэтому откат — обычный revert. На странице вмерженного PR нажми Revert: GitHub создаст PR, который отменяет изменения. Смержи его — после прогона на сайте окажется прежняя версия.

Из терминала:

git revert -m 1 <sha мерж-коммита>
git push origin main

Ключ -m 1 нужен для мерж-коммита. Обычный коммит откатывается командой git revert <sha>.

Если сайт собирается или лежит в подпапке

Пример публикует репозиторий как есть. Если сайт собирается сборщиком вроде Vite или Astro, упаковывай папку с результатом сборки. Замени шаг «Собрать ZIP сайта»:

      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - run: npm ci && npm run build

      - name: Собрать ZIP сайта
        run: cd dist && zip -r ../site.zip .

dist — папка, куда сборщик кладёт готовый сайт. Для подпапки без сборки хватит последней строки с её именем: cd site && zip -r ../site.zip ..

Если прогон упал

Текст ошибки — в логе шага «Обновить сайт на htmlkin.ru».

HTTP error Что делать
401 invalid_api_key Секрет пустой или ключ скопирован с ошибкой. Создай новый ключ и перезапиши секрет
403 api_not_allowed API работает на «Оптимальном» и «Бизнесе» — перейди на один из них
404 not_found Сверь HTMLKIN_PAGE_ID с ID в карточке сайта в «Мои сайты»
400 missing_entry_file Положи index.html в корень архива
400 too_many_files В сайте больше 500 файлов
413 file_too_large Сайт больше лимита тарифа: 75 МБ на «Оптимальном», 200 МБ на «Бизнесе»
429 rate_limit_exceeded Лимит — 60 запросов в минуту на «Оптимальном», 120 на «Бизнесе». Перезапусти прогон через время из заголовка Retry-After

Все коды и поля запросов — в документации REST API.

Начни с шагов 1–3, затем скопируй workflow из шага 4 и запушь его в main. Следующий merge уже обновит сайт.