Von der CI aus auf Vercel deployen, wenn der Committer kein Teammitglied ist
Verschiebe ein Repo in eine GitHub-Organisation, und Vercel blockiert klammheimlich deine Deploys: Der Commit „konnte keinem Teammitglied zugeordnet werden“. So deploye ich stattdessen aus GitHub Actions mit der Vercel-CLI — meine Commits zählen weiterhin für meinen eigenen GitHub-Graphen, das Dashboard zeigt weiterhin, wer gepusht hat, und ich kaufe nicht für jeden Mitwirkenden einen Seat.
Ich habe landee in eine GitHub-Organisation verschoben, damit meine Commits für meinen eigenen Beitragsgraphen zählen. Beim allernächsten Push deployte die Produktion nicht mehr.
Das Vercel-Dashboard sagte nur das — bei jedem Push. Die native Git-Integration war leise zur Schranke geworden:
Deployment Blocked
The deployment was blocked because the commit could not be
matched to a team member.Warum Vercel das Deploy blockiert
Die native Git-Integration von Vercel ist ein Webhook-Deploy: GitHub schickt ein Push-Event, Vercel liest den Commit-Autor, prüft, ob dieser Mitglied des Vercel-Teams ist, und blockiert das Deploy, falls nicht. Das ist eine Sicherheitskontrolle — sie verhindert, dass ein beliebiger Mitwirkender oder ein Fork-Pull-Request automatisch in die Produktion ausliefert.
Das ist sinnvoll — bis die Person, die den Code schreibt, kein bezahlter Seat-Inhaber ist. Mein GitHub-Konto verfasst die Commits, ist aber kein Mitglied des Vercel-Teams. Also ist jedes Deploy für die Integration „kein Mitglied“, und jedes Deploy wird blockiert.
Mit der CLI deployen, nicht mit der Git-Integration
Die CLI ist der Ausweg. vercel deploy authentifiziert sich mit einem Token, nicht mit dem Commit-Autor — es führt die Mitgliedschaftsprüfung nie aus. Also: die native Git-Integration trennen und stattdessen aus GitHub Actions deployen: Push → der Workflow läuft → vercel deploy mit einem Token → Vercel baut und liefert aus.
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 }}Zwei Dinge machen das zum einzigen Deploy-Weg, damit CLI und Webhook sich nicht ins Gehege kommen: vercel.json deaktiviert das native Auto-Deploy, und du klickst im Vercel-Dashboard auf Disconnect beim Git-Repo.
{
"git": { "deploymentEnabled": false },
"installCommand": "pnpm install --frozen-lockfile"
}Deinen GitHub-Beitragsgraphen bewahren
Der ganze Sinn des Org-Umzugs war, dass Commits für meinen Graphen zählen — also muss der Commit auf GitHub von mir verfasst bleiben. Das ist hier bereits der Fall: Das CLI-Deploy läuft auf einem frischen Checkout im Runner, und nichts davon wird je zu GitHub zurückgepusht.
Also committe ich als ich selbst, pushe, und die grünen Kacheln füllen sich. Das Token, das das Deploy autorisiert, gehört dem Kontoinhaber, nicht mir — genau das ist der Sinn eines CI-Deploys.
Das Dashboard soll zeigen, wer gepusht hat
Ein einfaches CLI-Deploy erscheint in Vercels Liste als nackter Hash — keine Nachricht, kein Branch, kein Autor. Für eine echte git-artige Zeile (Nachricht + Branch + Avatar) muss Vercel das Deploy als Git-Commit erkennen — und genau diese Erkennung löst die Autorenprüfung erneut aus.
Der Trick: Im Runner den Autor von HEAD auf ein Teammitglied umschreiben, dann deployen. Das Amend wird nie zurückgepusht, also bleibt der Commit auf GitHub deiner. Vercel liest den Teammitglied-Autor aus .git — das Deploy wird erkannt und nicht blockiert — und du schreibst den echten Pusher in die Commit-Nachricht, damit die Zeile weiterhin nennt, wer ausgeliefert hat.
# 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"Ein Service-Konto, über das alle deployen
Verallgemeinere es: Ein Service-Konto besitzt das Vercel-Team und hält das Deploy-Token. Alle committen als sie selbst; die CI schreibt den Autor auf das Service-Konto um und deployt mit dessen Token. Die Dashboard-Zeile liest [du] deine Commit-Nachricht, und GitHub behält deine echte Autorschaft.
Das ist die langweilige, ehrliche Variante dessen, wonach viele Teams greifen. Du bezahlst für die Seats derjenigen, die Dashboard-Zugriff brauchen — nicht einen pro Mitwirkendem. Ein CI-Token, das den Code aller deployt, ist das von Vercel dokumentierte Modell; du kaufst niemandem einen Seat, nur weil sein Code ausgeliefert wird.
Die Details, die beißen
Ein paar Dinge, die mich einen Abend gekostet haben — damit sie dich keinen kosten:
- pnpm auf Vercel. Das Build-Image kann ein altes pnpm festlegen, unabhängig von deinem
packageManager-Feld. Übergib--build-env ENABLE_EXPERIMENTAL_COREPACK=1anvercel deploy, damit Corepack die Version nutzt, die du tatsächlich festgelegt hast. - Verifizierte Commits. Das Signieren ist davon getrennt — richte SSH-Commit-Signierung ein und registriere den Schlüssel bei GitHub, dann bekommen deine (echten) Commits das grüne Verified-Abzeichen. Das Wegwerf-Amend im Runner braucht keine Signatur.
- Lesbare Runs. Teile den einen großen Shell-Schritt in benannte Schritte auf (re-author → deploy → summary), damit die Actions-Oberfläche die Phase auf einen Blick zeigt.
- Tests. Das Deploy baut auf Vercel, führt aber nie deine Tests aus — füge dafür einen eigenen CI-Workflow hinzu und schalte gleich Dependabot ein.
Das CLI-Deploy wird von einem Token autorisiert, nicht davon, wer den Commit geschrieben hat. Das ist der ganze Kniff — und ein dokumentierter, vollwertiger Weg zum Ausliefern.
Wo die Grenze liegt
Seien wir ehrlich zur Grenze, denn man redet sich leicht darüber hinweg. Den Code von Mitwirkenden über ein CI-Token zu deployen, ist legitim und so gedacht. Fake-Konten hochzuziehen, um die Seat-Abrechnung zu umgehen, ist es nicht — das ist Multi-Accounting und verstößt gegen die Bedingungen jeder Plattform.
| Was du tust | Legitim | Über der Grenze |
|---|---|---|
| Code von Mitwirkenden über ein CI-Token deployen | ✓ dokumentiert | |
| Einen Seat für die Person mit Dashboard-Verwaltung zahlen | ✓ | |
| Als du selbst committen; Service-Identität nur in der CI | ✓ ehrliche Statistik | |
| Fake-/Service-Konten anlegen, um Seats zu sparen | ✗ Multi-Accounting | |
| Ein Login teilen, damit viele ohne Seats verwalten | ✗ Zugangsdaten-Teilen |
Fazit
- Vercels native Git-Integration blockiert Deploys, deren Commit-Autor kein Teammitglied ist — eine Sicherheitsschranke, kein Bug.
vercel deploymit einem Token prüft den Autor nie; trenne die native Integration und deploye aus der CI.- Committe als du selbst und pushe das Runner-Amend nie — dein GitHub-Graph bleibt intakt.
- Den Autor von
HEADim Runner auf ein Teammitglied umzuschreiben, ergibt eine echte Dashboard-Zeile ohne Block — schreib den echten Pusher in die Nachricht. - Du zahlst für Dashboard-Seats, nicht pro Mitwirkendem: Ein CI-Token, das den Code aller deployt, ist das vorgesehene Modell.
- Fake-Konten anzulegen, um die Abrechnung zu umgehen, ist Multi-Accounting. Da liegt die Grenze.
Keines dieser Teile ist exotisch — die CLI, ein Token, ein git amend, das den Runner nie verlässt. Der Aha-Moment ist die Erkenntnis, dass die „kein Mitglied“-Wand dir nicht sagt, einen weiteren Seat zu kaufen; sie sagt dir, so zu deployen, wie CI gemeint ist. Trenne den Webhook, gib dem Runner das Token — und lass die Person, die den Code geschrieben hat, die Anerkennung dafür behalten.
Einen Fehler entdeckt?
Ein falscher Fakt, eine schiefe Übersetzung, etwas, das in diesem Artikel falsch klingt? Schreib mir — in deiner eigenen Sprache.