Skip to main content
Назад до блогу
VercelGitHub ActionsCI/CDDeploymentMonorepo

Деплой на Vercel із CI, коли автор коміту не член команди

Перенеси репо в GitHub-організацію — і Vercel тихо починає блокувати деплої: коміт «не вдалося зіставити з членом команди». Ось як я деплою через GitHub Actions і Vercel CLI: коміти все одно йдуть у мій GitHub-графік, дашборд показує, хто пушив, і я не купую seat на кожного контриб’ютора.

Опубліковано 10 серпня 2026 р.8 хв читання

Я переніс landee у GitHub-організацію, щоб мої коміти зараховувались у мій графік контриб’ютів. Наступним же пушем продакшн перестав деплоїтись.

Дашборд Vercel писав отаке — на кожен пуш. Нативна Git-інтеграція тихо перетворилась на шлагбаум:

Deployment Blocked
The deployment was blocked because the commit could not be
matched to a team member.

Чому Vercel блокує деплой

Нативна Git-інтеграція Vercel — це деплой по вебхуку: GitHub шле push-подію, Vercel читає автора коміту, перевіряє, чи є він членом команди, і блокує, якщо ні. Це захист: він не дає випадковому контриб’ютору чи форк-PR автоматично викотитись у продакшн.

Це розумно — аж поки той, хто пише код, не є оплаченим членом. Мій GitHub-акаунт авторить коміти, але він не член Vercel-команди. Тож кожен деплой для інтеграції — «не член», і кожен блокується.

Деплой через CLI, а не Git-інтеграцію

Вихід — CLI. vercel deploy авторизується токеном, а не автором коміту — і ніколи не запускає перевірку членства. Тож відключаємо нативну Git-інтеграцію й деплоїмо з GitHub Actions: push → workflow → vercel deploy з токеном → Vercel білдить і котить.

.github/workflows/deploy-production.yml
name: Deploy Production (Vercel CLI)

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
      VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
    steps:
      - uses: actions/checkout@v7
      - run: npm install -g vercel@latest
      - run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
      - run: vercel deploy --prod --token=${{ secrets.VERCEL_TOKEN }}

Дві речі роблять це єдиним шляхом деплою, щоб CLI і вебхук не гонились: vercel.json вимикає нативний авто-деплой, а ти тиснеш Disconnect на Git-репо в дашборді Vercel.

vercel.json
{
  "git": { "deploymentEnabled": false },
  "installCommand": "pnpm install --frozen-lockfile"
}

Зберегти свій GitHub-графік

Увесь сенс переносу в org — щоб коміти йшли у мій графік, тож коміт на GitHub має лишатись за моїм авторством. Тут це вже так: CLI-деплой працює на свіжому чекауті в раннері, і нічого звідти назад у GitHub не пушиться.

Тож я комічу під собою, пушу — і зелені квадратики заповнюються. Токен, який авторизує деплой, належить власнику акаунта, а не мені — це й є суть CI-деплою.

Показати в дашборді, хто пушив

Звичайний CLI-деплой у списку Vercel — це голий хеш: без повідомлення, гілки, автора. Щоб був нормальний git-рядок (повідомлення + гілка + аватар), Vercel має розпізнати деплой як git-коміт — а саме це й запускає перевірку автора.

Трюк: у раннері переписуємо автора HEAD на члена команди, потім деплоїмо. Цей amend ніколи не пушиться назад, тож на GitHub коміт лишається твоїм. Vercel читає автора-члена з .git — деплой розпізнаний і не заблокований — а реального пушера вписуєш у повідомлення коміту.

# In the runner only — this amend is NEVER pushed back, so on GitHub the
# commit stays authored by the real pusher (your contribution graph is intact).
MSG="$(git log -1 --pretty=%s)"
git -c user.name="CI Bot" -c user.email="ci@your-org.dev" \
  commit --amend --author="CI Bot <ci@your-org.dev>" \
  -m "[$GITHUB_ACTOR] $MSG"

# Vercel now reads a team-member author from .git → recognized AND not blocked.
vercel deploy --prod --token="$VERCEL_TOKEN"

Один сервісний акаунт — усі деплоять через нього

Узагальнюємо: один сервісний акаунт володіє Vercel-командою й тримає деплой-токен. Усі комітять під собою; CI переписує автора на сервісний акаунт і деплоїть його токеном. У дашборді рядок — [ти] твоє повідомлення, а GitHub тримає твоє справжнє авторство.

Це нудна, чесна версія того, до чого тягнеться багато команд. Ти платиш за seat-и тих, кому потрібен доступ до дашборду, — а не по одному на контриб’ютора. CI-токен, що деплоїть код усіх, — це модель, яку Vercel сам документує.

Деталі, що кусають

Кілька речей, які забрали в мене вечір — щоб не забрали в тебе:

  • pnpm на Vercel. Білд-образ може взяти старий pnpm, ігноруючи packageManager. Передай --build-env ENABLE_EXPERIMENTAL_COREPACK=1 у vercel deploy — і corepack візьме саме ту версію, яку ти закріпив.
  • Verified-коміти. Підпис — окрема тема: налаштуй SSH-підпис комітів і додай ключ на GitHub — твої (справжні) коміти отримають бейдж Verified. Тимчасовому amend у раннері підпис не потрібен.
  • Читабельні рани. Розбий один великий shell-крок на названі кроки (re-author → deploy → summary), щоб у Actions було видно етап з першого погляду.
  • Тести. Деплой білдить на Vercel, але ніколи не ганяє тести — додай окремий CI-workflow, і заодно увімкни Dependabot.

CLI-деплой авторизує токен, а не той, хто написав коміт. Це й є весь розблок — і це документований, повноцінний спосіб деплою.

Де межа

Будьмо чесні щодо межі, бо її легко проговорити. Деплоїти код контриб’юторів через CI-токен — легітимно й задумано так. Клепати фейкові акаунти, щоб обійти оплату seat-ів, — ні— це multi-accounting, і це проти правил будь-якої платформи.

Що ти робишЛегітимноЗа межею
Деплоїти код контриб’юторів через CI-токен✓ по доках
Один seat для того, хто керує дашбордом
Комітити під собою; сервісна ідентичність лише в CI✓ чесна статистика
Клепати фейкові акаунти, щоб не платити за seat-и✗ multi-accounting
Один логін на багатьох, щоб керувати без seat-ів✗ credential-sharing

Головне

  • Нативна Git-інтеграція Vercel блокує деплої, чий автор коміту не член команди — це захист, а не баг.
  • vercel deploy з токеном не перевіряє автора; відключи нативну інтеграцію й деплой з CI.
  • Коміть під собою й ніколи не пуш amend із раннера — графік лишається твоїм.
  • Amend автора HEAD на члена команди дає нормальний рядок без блоку — впиши реального пушера в повідомлення.
  • Ти платиш за seat-и доступу до дашборду, а не по контриб’ютору: CI-токен для коду всіх — це задумана модель.
  • Клепати фейки заради обходу оплати — це multi-accounting. Отут і межа.

Жоден із цих шматків не екзотичний — CLI, токен, git amend, що ніколи не покидає раннер. Зсув — у тому, що стіна «не член» не каже тобі купувати ще один seat; вона каже деплоїти так, як і має робити CI. Відключи вебхук, віддай токен раннеру — і нехай той, хто написав код, залишиться його автором.

Помітили помилку?

Невірний факт, кривий переклад, щось звучить неправдиво в цій статті? Напишіть мені — своєю мовою.