Деплой из CI
Вход без хранимых секретов
Задача CI может обменять свой OIDC-токен на краткоживущий токен xvii через правило доверия. В настройках
CI ничего не хранится, а токен нельзя использовать за пределами задачи.
Добавьте правило доверия
В id откройте проект → CI → Добавить правило: издатель (GitLab или GitHub), репозиторий, шаблоны
веток (или только защищённые ссылки), scope (обычно подходит deploy) и срок жизни.
Дайте задаче OIDC-токен
GitLab — запись id_tokens (шаблоны ниже делают это сами). GitHub — permissions: id-token: write.
Запустите CLI
XVII_DOMAIN выбирает инстанс; CLI сам найдёт токен задачи.
Wildcard-репозиторий в правиле сводит на нет границу проекта; держите правила узкими. Защищённые окружения
по-прежнему требуют прав, которые задаёт их защита.
Если OIDC недоступен, создайте узкий токен (xvii tokens create ci --scope deploy --ttl 30d), сохраните его
как замаскированную переменную CI XVII_TOKEN и никогда не выводите.
GitLab CI
include:
- remote: https://pages.xvii.network/ci/preview.yml
build:
stage: build
image: node:24-alpine
script: [corepack enable, pnpm install --frozen-lockfile, pnpm build]
artifacts: { paths: [dist/] }
variables:
PAGES_DIR: dist
Ветка по умолчанию попадает на <проект>.pages.xvii.network, остальные — на
<проект>-<ветка>.pages.xvii.network; слияние или удаление ветки убирает превью.
include:
- remote: https://apps.xvii.network/ci/gitlab.yml
variables:
APPS_APP: api # сначала создайте в apps: xvii apps create api --project shop --port 3000
APPS_PROJECT: shop # если имена приложений повторяются
APPS_ENV: production
APPS_DIR: . # папка с Dockerfile или такая, которую знает Railpack
Ветка по умолчанию деплоится; merge request деплоит превью <app>-mr-<iid>, видимое как его окружение
(включите пайплайны merge request). Закрытие MR останавливает превью, а без деплоев оно уходит само через
APPS_TTL. Задаче не нужен Docker: сборка идёт на ноде. Без правила доверия задайте замаскированный
APPS_TOKEN (токен со scope deploy).
GitHub Actions
name: Deploy
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
id-token: write
concurrency:
group: production
cancel-in-progress: false
env:
XVII_DOMAIN: xvii.network
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
curl -fsSL https://xvii.network/install.sh | XVII_INSTALL_DIR="$HOME/.local/bin" sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- run: xvii apps deploy api --project shop --dir . --dotenv apps.env
- run: cat apps.env >> "$GITHUB_STEP_SUMMARY"
--dotenv записывает APPS_URL=<адрес>, когда релиз стал живым. Готовые workflow:
https://pages.xvii.network/ci/github.yml и https://apps.xvii.network/ci/github.yml (сохраните как
.github/workflows/apps.yml, задайте APPS_APP; pull request получает превью <app>-pr-<номер> и
комментарий).
Секреты в CI
Читайте их из env тем же токеном задачи, а не копируйте в настройки CI:
xvii env run --project shop --env preview -- ./integration-tests.sh
Не пускайте production-секреты в preview-окружения: в превью часто работает код, который ещё никто не
проверил.
Если деплой упал
CLI ждёт живого релиза и при ошибке сборки или проверки здоровья завершается с ненулевым кодом и логом.
| Симптом |
Куда смотреть |
| сборка упала |
лог сборки: путь к Dockerfile, контекст, lock-файл, доступ к реестрам |
| релиз долго в деплое, потом падает |
путь проверки здоровья, миграции при старте, лимит памяти, логи |
401 / 403 |
репозиторий и ветка в правиле доверия, scope, защищённое окружение |
| в CI всё прошло, а в браузере 502 |
порт, который слушает приложение (PORT), состояние ноды в xvii apps nodes |
Не отменяйте деплой посреди миграции данных и помните: откат образа не откатывает схему базы.