Skip to main content
Înapoi la blog
VercelGitHub ActionsCI/CDDeploymentMonorepo

Deploy pe Vercel din CI când cel care face commit nu e membru al echipei

Muți un repo într-o organizație GitHub și Vercel începe discret să-ți blocheze deploy-urile: commit-ul „nu a putut fi asociat unui membru al echipei”. Iată cum fac deploy din GitHub Actions cu CLI-ul Vercel: commit-urile mele continuă să conteze în propriul graf GitHub, dashboardul arată în continuare cine a dat push, iar eu nu plătesc un loc pentru fiecare contribuitor.

Publicat 10 august 20268 min de citit

Am mutat landee într-o organizație GitHub ca să-mi conteze commit-urile în propriul graf de contribuții. La următorul push, producția a încetat să facă deploy.

Dashboardul Vercel spunea doar atât — la fiecare push. Integrarea Git nativă devenise, discret, o barieră:

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

De ce blochează Vercel deploy-ul

Integrarea Git nativă a Vercel e un deploy prin webhook: GitHub trimite un eveniment de push, Vercel citește autorul commit-ului, verifică dacă e membru al echipei Vercel și blochează deploy-ul dacă nu. E un control de securitate — împiedică un contribuitor oarecare, sau pull request-ul unui fork, să ajungă automat în producție.

E rezonabil — până când cel care scrie codul nu e un membru plătit. Contul meu de GitHub e autorul commit-urilor, dar nu e membru al echipei Vercel. Așa că pentru integrare fiecare deploy vine de la un „non-membru”, și fiecare deploy e blocat.

Fă deploy cu CLI-ul, nu cu integrarea Git

CLI-ul e ieșirea. vercel deploy se autentifică printr-un token, nu prin autorul commit-ului — nu rulează niciodată verificarea de apartenență. Deci deconectează integrarea Git nativă și fă deploy din GitHub Actions: push → rulează workflow-ul → vercel deploy cu un token → Vercel construiește și publică.

.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 }}

Două lucruri fac din asta singura cale de deploy, ca CLI-ul și webhookul să nu se bată: vercel.json dezactivează auto-deploy-ul nativ, iar tu apeși Disconnect pe repo-ul Git din dashboardul Vercel.

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

Păstrează-ți graful de contribuții GitHub

Tot rostul mutării în organizație era ca commit-urile să conteze în graful meu — deci commit-ul de pe GitHub trebuie să rămână scris de mine. Aici deja e așa: deploy-ul prin CLI rulează pe un checkout proaspăt în runner, iar nimic de acolo nu e vreodată împins înapoi în GitHub.

Așa că fac commit în numele meu, dau push, iar pătratele verzi se umplu. Tokenul care autorizează deploy-ul aparține proprietarului contului, nu mie — exact în asta constă un deploy din CI.

Fă dashboardul să arate cine a dat push

Un deploy simplu prin CLI apare în lista Vercel ca un hash gol — fără mesaj, fără ramură, fără autor. Ca să obții un rând în stil git adevărat (mesaj + ramură + avatar), Vercel trebuie să recunoască deploy-ul drept un commit git — iar tocmai această recunoaștere reia verificarea autorului.

Trucul: în runner, rescrie autorul lui HEAD către un membru al echipei, apoi fă deploy. Amend-ul nu e niciodată împins înapoi, așa că pe GitHub commit-ul rămâne al tău. Vercel citește autorul-membru din .git — deploy-ul e recunoscut și neblocat — iar tu pui în mesajul commit-ului pe cel care chiar a dat push, ca rândul să spună tot cine a publicat.

# 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"

Un cont de serviciu prin care fac deploy toți

Generalizează: un cont de serviciu deține echipa Vercel și ține tokenul de deploy. Toți fac commit în numele lor; CI-ul rescrie autorul către contul de serviciu și face deploy cu tokenul acestuia. Rândul din dashboard spune [tu] mesajul tău de commit, iar GitHub păstrează autoratul tău real.

E versiunea plicticoasă și onestă a ceea ce caută multe echipe. Plătești pentru locurile celor care au nevoie de acces la dashboard — nu câte unul de contribuitor. Un token de CI care face deploy la codul tuturor e modelul documentat de Vercel; nu cumperi un loc cuiva doar fiindcă i se publică codul.

Detaliile care mușcă

Câteva lucruri care m-au costat o seară, ca să nu te coste pe tine una:

  • pnpm pe Vercel. Imaginea de build poate fixa un pnpm vechi indiferent de câmpul tău packageManager. Trimite --build-env ENABLE_EXPERIMENTAL_COREPACK=1 către vercel deploy, ca corepack să folosească versiunea pe care chiar ai fixat-o.
  • Commit-uri verificate. Semnarea e separată — configurează semnarea SSH a commit-urilor și înregistrează cheia pe GitHub, iar commit-urile tale (cele reale) capătă insigna verde Verified. Amend-ul de unică folosință din runner nu are nevoie de semnătură.
  • Rulări lizibile. Împarte singurul pas mare de shell în pași denumiți (re-author → deploy → summary), ca interfața Actions să arate etapa dintr-o privire.
  • Teste. Deploy-ul construiește pe Vercel, dar nu-ți rulează niciodată testele — adaugă un workflow CI separat pentru asta și pornește Dependabot cât ești acolo.

Deploy-ul prin CLI e autorizat de un token, nu de cel care a scris commit-ul. În asta stă toată deblocarea — și e o cale documentată, de primă mână, de a publica.

Unde e linia

Să fim sinceri în privința limitei, fiindcă e ușor să te convingi să treci de ea. A face deploy la codul contribuitorilor printr-un token de CI e legitim și e gândit așa. A crea conturi false ca să ocolești plata pe loc nu e — asta e multi-cont, și încalcă termenii oricărei platforme.

Ce faciLegitimPeste linie
Faci deploy la codul contribuitorilor printr-un token de CI✓ documentat
Plătești un loc pentru cel care administrează dashboardul
Faci commit în numele tău; identitatea de serviciu doar în CI✓ statistici oneste
Creezi conturi false/de serviciu ca să nu plătești locuri✗ multi-cont
Împarți un login ca mulți să administreze fără locuri✗ partajare de acreditive

Concluzii

  • Integrarea Git nativă a Vercel blochează deploy-urile al căror autor de commit nu e membru al echipei — o barieră de securitate, nu un bug.
  • vercel deploy cu un token nu verifică niciodată autorul; deconectează integrarea nativă și fă deploy din CI.
  • Fă commit în numele tău și nu împinge niciodată amend-ul din runner, iar graful tău GitHub rămâne intact.
  • Rescrierea autorului lui HEAD către un membru în runner dă un rând real în dashboard fără blocaj — pune-l în mesaj pe cel care a dat push.
  • Plătești pentru locuri de dashboard, nu per contribuitor: un token de CI care face deploy la codul tuturor e modelul gândit.
  • A crea conturi false ca să ocolești plata e multi-cont. Acolo e linia.

Nicio piesă din astea nu e exotică — CLI-ul, un token, un git amend care nu părăsește niciodată runnerul. Declicul e să înțelegi că zidul „non-membru” nu-ți spune să cumperi încă un loc; îți spune să faci deploy așa cum e menit CI-ul. Deconectează webhookul, dă tokenul runnerului — și lasă-l pe cel care a scris codul să rămână cu meritul.

Ai găsit o greșeală?

Un fapt greșit, o traducere stângace, ceva ce sună fals în acest articol? Scrie-mi — în limba ta.