What Happens After You Push

leed site push looks like git push with a longer name. It is not. A plain git push moves your commits to GitLab and stops there — no deployment record is created, no build is triggered, and your preview site keeps serving whatever it was serving before. The part that matters is the second half of the command: after the commits land, the CLI tells the CMS what you pushed, and that notification is what turns a commit into a site.

This page picks up where the command returns. The command itself — its checks, its refusals, the validate and commit steps that precede it — is documented at validate, commit and push.

The handoff, step by step

A push is two halves — commits to the remote, then the CMS told about them — and both finish before the command writes a single line. Here is the same sequence from the outside and from the inside.

$ leed site push

	Rebased 2 remote commit(s) onto your work.

	Site pushed successfully...

	CMS successfully notified!

The rebase line appears only when the remote had moved since your last fetch. Site pushed successfully... reports git alone. The line that actually matters is the last one: CMS successfully notified! means a deployment record now exists and a build has started. Without it, your commits are on the remote and nothing is happening.

Why the token is always re-checked

Step 4 round-trips your credentials to the server on every push, even when the locally stored token has not expired yet. That looks wasteful and is not: a token can be revoked or rotated server-side while the copy on your disk still looks perfectly good.

The consequence of skipping it is the worst outcome this command has. Git would happily accept the push with your GitLab remote credentials, and then the notification — the half that creates the deployment — would be refused. Your work would be on origin/staging with nothing built from it, and nobody watching the Deploy screen would see a reason to look.

Why the commit id is re-synced after a rebase

A rebase rewrites your commits, so the sha recorded in the change set at leed site commit time no longer exists once step 5 has run. Step 6 re-points the tracked commit id at the actual pushed HEAD before the CMS is told anything.

If it did not, the CMS would create a deployment for an orphaned sha and the build would die at the very first thing Cloudflare does — checking out the commit — with an error that looks like a repository problem and is not.

What the CMS does with it

POST /api/site/pushed is not a webhook you have to configure; it is the command’s own second step. When it arrives, the CMS:

  • creates a deployment row on the branch you pushed, carrying the single reason badge Developer CLI;
  • marks any earlier deployment for the same commit as superseded, so a re-push of an unchanged commit does not leave two live rows competing;
  • starts a build.

Attribution is worth a sentence, because the row shows your name even though the build itself runs on a server with no session. The CLI writes a structured payload into the commit message at leed site commit time, and the CMS reads the initiator out of that, falling back to the owner of the token that made the request. So a push made by CI on your behalf still credits whoever committed.

Why it lands on preview, not live

Every push lands on the preview site. This is not a setting and it is not a mistake.

Pushes go to the staging branch; staging is what builds the preview site; the live site changes only when a person promotes. The rule holds for everything that arrives as a file rather than as a CMS record — a CLI push, a save in the Layouts workspace, a managed-file refresh — and it is fixed in the product, not chosen per push. Why there are two sites at all.

Watching it

Open Deploy in the CMS rail (/deployments). Your row appears in the left-hand Preview site column with the blue Developer CLI badge, the seven-character commit hash, and your name. It moves through Building → Deploying → Active on its own; the screen re-fetches every five seconds while anything is in flight, so there is no reason to reload.

A Developer CLI deployment row in the Preview site history column of the Deploy screen

What each badge means, and why Active is the only one that tells you what visitors are being served, is covered in the blue reason badges and the status table beside it.

The build, from the outside

If you want to know what is actually running while that row says Building: Cloudflare starts a container, checks out your commit, installs the Leed build tooling, runs the site build, and uploads the result as a version of your site’s worker. Then it calls back into the CMS, and the CMS activates that version at 100% of traffic.

sequenceDiagram
    autonumber
    actor Dev as You (leed site push)
    participant Git as GitLab (raw-content)
    participant CMS as Leed CMS
    participant CF as Cloudflare Builds

    Dev->>CMS: re-validate CLI credentials
    CMS-->>Dev: token still good
    Dev->>Git: fetch + rebase onto origin/staging
    Dev->>Git: push origin staging
    Git-->>Dev: accepted
    Dev->>CMS: POST /api/site/pushed (change set + branch)
    CMS->>CMS: create deployment — Developer CLI, staging
    CMS-->>Dev: CMS successfully notified!
    CMS->>CF: trigger a build for that commit
    CF->>Git: clone the commit
    CF->>CF: leed site build
    CF->>CF: wrangler versions upload
    CF->>CMS: POST /api/site/build-result (version id)
    CMS->>CF: activate that version at 100% of traffic
    CF-->>CMS: deployment active
    Note over CMS,CF: the preview site now serves your commit

The one step that surprises people is the last handoff. Uploading a version and activating it are two separate acts, and the CMS owns the second one. The build cannot put anything in front of a visitor by itself; it can only hand the CMS a version and report that it is ready. That separation is what lets a scheduled publish be built minutes early and still go live exactly on the chosen minute, and it is why a build can succeed while the site has not changed yet.

When it goes wrong

Three things can fail, at three different distances from you, and the symptom tells you which.

Where it failedWhat you seeWhere to look
The CLI refused before pushing — wrong branch, nothing committed, a rebase conflict, or expired credentialsAn error in your terminal and a non-zero exit; nothing reached the remoteThe CLI’s own message — it names the remedy
The push landed but the CMS was never toldSite pushed successfully... followed by The CMS was not notified:, and no new row on the Deploy screenRun leed site notify-cms again once the CMS is reachable
The CMS was told and the build failedA red row in the Preview site columnExpand the row — the error block is the build’s own output

The middle case is the one to recognize on sight, because the command reports both halves and it is easy to read the first line and stop. Your commits are on origin/staging and they are safe; what is missing is the deployment record. The recovery is the notification on its own, not another push — there is nothing left to push.

A red row is a build failure, and build failures have their own diagnosis path — the error block, whether the row offers Retry, and the handful of causes worth checking first are all in diagnosing a failed deployment. The exit codes the CLI reports, the branch rule and the exact rebase-conflict message are cataloged at CLI troubleshooting and exit codes.

Getting it live

When the row reads Active, your commit is on the preview site — staging. in front of your domain — and nowhere else. Review it there, on the real build rather than on your local server, because the preview site is the one running the same worker configuration your visitors will get.

Then promote. Push preview live on the Deploy screen releases everything currently on preview as a single live deployment; what promotion moves, and every reason the button is disabled.

ESC