Deploying Jobs
Deploying Jobs
A Trilogy Cloud job is a project directory with a [cloud] block in its trilogy.toml. The block says how the job runs: which command, on what schedule, with which secrets. trilogy cloud sync finds every such directory and creates or updates one job for each.
The project you deploy is the same one you run locally with trilogy run or trilogy refresh. Nothing about the models changes.
Install and Sign In
The cloud commands ship with the standard CLI:
pip install pytrilogy
trilogy cloud login
trilogy cloud whoami
login opens a browser to sign in and stores an API token for this machine. whoami prints your user and the orgs you belong to.
Declare a Job
Add a [cloud] block to the project's trilogy.toml:
[engine]
dialect = "duck_db"
[engine.config]
enable_gcs = true
[cloud]
org = "acme"
name = "daily-sales"
operation = "refresh"
schedule = "0 0 6 * * *"
timeout_seconds = 1800
secret_env = ["GOOGLE_HMAC_KEY", "GOOGLE_HMAC_SECRET"]
This deploys the whole directory as one job named daily-sales. Every day at 06:00 UTC it runs trilogy refresh, which rebuilds only the datasources that are stale. The two org secrets are injected as environment variables.
Preview the change, then apply it:
trilogy cloud sync . --dry-run
trilogy cloud sync .
A trilogy.toml whose [cloud] block names only org or api_url is configuration, not a job, and is never deployed.
Settings
Every setting is optional. An unset setting keeps whatever the job already has.
| Key | Description |
|---|---|
org | The org to deploy into. Only read from the trilogy.toml at or above the working directory; pass --org otherwise. |
name | The job's display name. Defaults to the directory's path under the sync root, joined with -. Renaming is safe at any time. |
operation | run (default), refresh, plan or state. |
entrypoint | The file or directory the job runs, relative to the project. Defaults to the whole directory. |
schedule | A six-field cron expression in UTC, seconds first: 0 0 6 * * * is daily at 06:00. |
timeout_seconds | The run's time limit. Defaults to 300; the maximum is 5 hours. |
memory_mb | Memory for the run, up to 16384. |
cpus | CPUs for the run, up to 4. |
secret_env | Org secrets to expose to the run as environment variables of the same name. |
vm_class | shared packs small jobs onto one worker; exclusive gives each run its own. Cannot be combined with memory_mb or cpus. |
priority | 0 (realtime) to 4 (background). Defaults to 2. |
deadline_seconds | Raises a queued run's priority as the deadline approaches. Never fails a run. |
include | Globs for the files to upload. Replaces the default set (*.preql, *.py, *.sql, *.toml, *.json, *.csv). |
exclude | Globs to leave out. Adds to the defaults (tests/, test_*, .venv/, __pycache__/, *.pyc, *.parquet). |
A refresh that finds every datasource already fresh finishes as up to date, which counts as a success.
Job Identity
A job's identity is the repository and subdirectory it lives in, not its name. Sync updates the job whose source matches, so its run history and schedule survive every deploy.
Moving a directory deploys a new job and leaves the old one behind. trilogy cloud sync --prune deletes jobs whose directory no longer exists.
Jobs created by hand in the UI, or with trilogy cloud jobs push, have no source. Sync does not adopt them by name; it creates a new job beside them.
Secrets
Credentials are org secrets, never files in the project. Set them once per org:
trilogy cloud secrets set GOOGLE_HMAC_KEY
trilogy cloud secrets set GOOGLE_HMAC_SECRET
trilogy cloud secrets list
set prompts for the value. list shows names and timestamps; values are never returned.
A job can use a secret two ways. secret_env exposes it as an environment variable. A ${secret:NAME} reference in a config or script is replaced with the value when the run starts. A run that references a missing secret fails before it executes, naming the secret.
Several Jobs in One Project
A project can declare several jobs over one shared tree with [[cloud.job]] entries. The [cloud] block holds the shared defaults, and each entry states only what differs:
[cloud]
org = "acme"
workspace = "sales-models"
secret_env = ["GOOGLE_HMAC_KEY", "GOOGLE_HMAC_SECRET"]
schedule = "0 0 6 * * *"
operation = "refresh"
[[cloud.job]]
key = "raw"
name = "sales-raw"
entrypoint = "raw"
timeout_seconds = 1800
[[cloud.job]]
key = "rollups"
name = "sales-rollups"
entrypoint = "reporting/rollups.preql"
[[cloud.job]]
key = "validate"
name = "sales-validate"
entrypoint = "reporting/validate.preql"
operation = "run"
Each entry requires a key, a name and an entrypoint. The key is the job's identity: changing it deploys a new job. The files upload once, to the workspace named by workspace.
Ordering
Jobs from one trilogy.toml that share a schedule fire together, and run in dependency order. Trilogy Cloud reads each job's files to find which datasources it builds and which it reads. In the example above, sales-rollups waits for sales-raw when it reads a datasource that sales-raw builds.
A job whose upstream fails is skipped, with the upstream named. A job whose upstreams were all already up to date is skipped too, since there is nothing new to process.
When the order cannot be read from the files, declare it in a [dependencies] table:
[dependencies]
"reporting/validate.preql" = { after = ["reporting/rollups.preql"], when = "always" }
Keys and after entries are entrypoints. when is completed (the default), failed or always: a failed edge runs the job only when its upstream failed, which suits a repair step. The table also orders the same scripts when you run the directory locally.
Branch Environments
Sync picks its target from the current git branch. From main or master it deploys to production. From any other branch it deploys into an environment named after the branch, created on first use. An environment's jobs write to their own namespaced tables and files, so a branch never builds over production. Its jobs carry no schedules.
trilogy cloud env label # the environment this branch maps to
trilogy cloud sync . # from a feature branch: deploys to that environment
trilogy cloud env delete my_branch --with-jobs # tear it down after merging
--production deploys to production from any branch. --environment NAME targets a named environment.
Next Steps
- Deploy from GitHub Actions keeps a repository in sync on every merge.
- The cloud CLI reference lists every command.