deploy is the command you run day to day: it compiles every bound component, uploads only the definitions
whose document actually changed, and runs the platform’s own check_definition against each workflow definition
it uploaded. Re-running it with nothing changed uploads nothing and says so.
It is build plus push plus
check, with one difference that matters at each step: it refreshes the import
allowlist live, it skips definitions that would upload identically, and it checks after every upload has
finished rather than between them.
Synopsis
What it does
- Resolves the blob and revision. This is a write: status
ready, phasedraftormanaged. - Refreshes the import allowlist live. Reading it needs an
admin-scoped key. On success the cache under~/.blobhub/cache/allowlist/is rewritten, so a laterbuildverifies against something current. On a403— which is what theread/writekeys the platform recommends for automation get — it falls back to that cache, and with no cache either it raisesALLOWLIST_UNREADABLEand degrades exactly asbuilddoes. - Lists the revision’s definitions in both categories and matches the manifest against them.
- For each entry: compiles every bound component into an in-memory copy of the document, applying the same
remote-edit gate,
--forceand--strict-importsasbuild. - Compares that document against the remote one. Equal means skipped — no upload, and the local file is not rewritten either.
- Otherwise writes the built document to
source, creates the definition if its alias is absent, and uploads. - Once every entry above is done, and not before, runs
check_definitionagainst each workflow-category definition it uploaded.
unchanged line names a bare alias where every other line names category/alias; on a revision where one
alias legitimately names both a workflow and a playground definition, read it together with the lines above it.
Under --json the payload carries created, uploaded, unchanged, planned, skipped_check, checked,
dry_run and drift, alongside the envelope’s schema_version. checked holds the checker’s own events per
definition, not just a status.
Uploads and checks are two passes, on purpose
Every changed definition is uploaded before the first check runs. Compilation and upload do interleave — each definition is compiled and uploaded before the next one is read — but no check runs until the last upload has finished. The obvious alternative, checking each definition right after uploading it, is worse, and the reason is thatdeploy cannot roll back an upload.
Stopping at the first failing check would leave one definition on its new code and its sibling still on the old
one: a half-deployed revision. And it would leave that behind on top of an incomplete report, because the checks
for everything after the failure never ran. Finishing every upload first means a failing check is always
reported against a fully applied deploy.
A CHECK_FAILED from deploy therefore says the upload happened and the result does not pass, never the
upload was refused. The definition is on the revision. Fix it and deploy again.
Within the check pass itself, deploy reports the first failure and stops. To see every failing definition
at once, run blobhub workflow check, which collects them all.
Playgrounds are not checked
check_definition loads the workflow manifest unconditionally, so running it against a playground definition
checks it against the wrong manifest and produces meaningless findings. deploy skips it and says so on its own
output line rather than silently. A playground is still uploaded exactly like a workflow definition; only the
check is skipped.
What counts as unchanged
The comparison is the full serialized document, local against remote — not a hash of the code, not a timestamp. A definition is skipped only when everything about it matches: components, connections, ports, the compiledcontent[], and the attributes the compiler stamps.
Two consequences worth knowing:
- An unchanged definition leaves its local file untouched.
deploywritessourceonly for the definitions it uploads. In the ordinary case the file on disk already equals the built document, so there is nothing to write; if it does not, runbuildto bring the file itself up to date. - Someone else’s browser edit does not stop the upload. The remote-edit gate reads the code port in the
local definition file, which is all
buildhas to work with. A change made in the visual editor and never pulled is simply a document difference, sodeployuploads over it. On a revision other people edit in the browser, rundifffirst — it is the only command that reports the remote’s state.
--dry-run
Reports the intended calls without compiling, uploading, or writing anything — including the allowlist cache,
which a dry run reads offline rather than refreshing:
diff answers both of
those; --dry-run answers which calls would be made.
Errors
IMPORT_UNAVAILABLE reads differently here than under build: deploy holds the live allowlist, so its message
appends what that allowlist currently permits. DEFINITION_SIZE_NEAR_LIMIT fires at 8 MB — 80% of the
platform’s 10 MB payload ceiling — so a definition that is growing tells you before an upload starts failing at
the gateway.
Every code above, with its remediation, is in Error codes.
See also
blobhub workflow diff— the same comparison, reported and never performed.blobhub workflow build— the compile step alone, offline.blobhub workflow check— every failing definition, wheredeployreports the first.- Check Definition — the operation behind the check pass.
- Workflow overview — where
deploysits among the ten commands.

