Import a Windmill repository
SupaCloud can import a Windmill wmill sync
repository — its flows, raw apps, and scripts — into a workspace as native
workflows. When the repository ships database migrations under db/migrations/,
SupaCloud applies that schema onto a PostgreSQL resource you choose during the
import, so the imported flows have their tables on first run.
This is an admin task: the import endpoint requires a workspace admin.


Before you start
Section titled “Before you start”- You are a workspace admin.
- The repository is reachable: a git URL plus, for a private repository, a git credential configured under Resources.
- If the repository contains a
db/migrations/folder, create (or identify) a PostgreSQL resource under Resources to host the shared schema. For production, prefer a least-privileged role scoped to that schema rather than a superuser.
Run the import
Section titled “Run the import”-
Open the import wizard. Go to Workflows and choose Import → Windmill repository.
-
Point at the repository. Enter the git URL and, for a private repository, select the git credential. SupaCloud clones the repository and scans it into an import plan — the flows, apps, and scripts it found, and any
db/migrations/it will apply. -
Bind the database resource. If the plan includes a database schema, pick the PostgreSQL resource to apply it onto. This binding is the one deployment-specific choice; SupaCloud reads the schema name and isolation from the repository.
-
Review and apply. Confirm the plan. SupaCloud creates the workflows (each keeps its Windmill folder in the name, so
f/blockworx/bank_syncimports asblockworx/bank_sync), records any schedules and HTTP triggers, and applies the database schema onto the resource you bound.
Zero-touch database schemas
Section titled “Zero-touch database schemas”A repository whose db/migrations/ folder carries no SupaCloud
db/namespace.yaml is still imported with no manual setup: SupaCloud infers the
schema name from the CREATE SCHEMA statement and the tenant isolation
from the SQL. A schema whose tables declare an entity column is isolated per
entity; otherwise it is shared with no per-tenant overlay.
The schema is applied find-or-create by name, append-only and
checksum-guarded — re-running the import never re-applies a migration that
already ran. To override the inferred shape, add a db/namespace.yaml to the
repository; it takes precedence.
Resource and variable references
Section titled “Resource and variable references”A Windmill flow module often reads a credential or a setting through a
resource("f/…") or a variable("u/…") reference. SupaCloud imports these as
real bindings on the generated code node — not as dead placeholders.
-
resource("f/…")becomes a resource binding. A code node that binds a resource runs on the credentialed sandbox (Python/TypeScript) with deny-by-default egress: the script can reach only the bound resource’s host, and reads the resolved credential through a host-mediated accessor — it never holds the raw secret. Apostgresqlresource additionally grants a host-mediated guarded database call (read-only by default; see below). The converter maps each reference to a workspace resource by name and emits a warning for any binding you should verify or re-bind — open the node in the builder and confirm the resource it points at exists in this workspace.The name is folder-qualified: the Windmill folder and the resource name are joined with an underscore, so
f/blockworx/imap_infobecomesblockworx_imap_infoandf/c2ost/imap_infobecomesc2ost_imap_info. Two folders that use the same resource name therefore stay two separate resources — they never collapse onto one shared credential. Thef/oru/prefix is dropped; every other path segment is kept, lowercased, with anything other than a letter or digit turned into an underscore.f/shared/anthropicbecomesshared_anthropic— the shared folder is qualified like any other. -
variable("u/…")becomes a workspace env-var injection. The matching workspace environment variable (by key — the last path segment) is resolved host-side at run time and injected into the node, least-authority: only the variables the script actually reads are injected. A secret-typed variable is decrypted host-side and never stored in the workflow definition. Ensure an env var of that key exists under Resources → Environment variables.
A code node that binds no resource stays hermetic (no network, no database) — unchanged from a plain imported snippet. Bindings are a first-party, workspace-owned capability; marketplace-published workflows never carry them.
The step entrypoint
Section titled “The step entrypoint”Windmill calls a step’s main(...) function for you. SupaCloud runs the step’s
file, so the import adds the call itself — you do not rewrite the entrypoint
by hand:
- the arguments come from the flow’s
input_transforms, matched by parameter name (never by position, so a re-ordered input cannot swap two arguments); - an
asyncentrypoint is awaited (TypeScript) or driven to completion (Python), so the step returns a value rather than a pending promise; - the return value becomes the step result the next step reads. A step that returns nothing produces no result — that is a valid outcome, not an error;
- an entrypoint that throws now fails the step with the error and its stack in the log, instead of finishing successfully with nothing to show;
- a result larger than the step-result limit fails with a message naming the limit and the actual size. Nothing is silently cut short.