CLI
Deploy with mayura deploy
Write a target's deployment files, plan a release and run it with the tools you already use: Docker, Docker Compose, Kubernetes, or a platform package.
mayura deploy deploys a Mayura application in two steps, each one shown before anything
happens:
mayura deploy init --target <id>writes the files the target needs (aDockerfile, acompose.yaml, Kubernetes manifests) for you to review and commit. It never overwrites a file without your confirmation.mayura deploy --target <id>plans one release: every command, in order, with everything it is given. Run it with--applyand the plan's digest. Each command is one of the tools you already use and are logged in to:docker,kubectlor a platform's own CLI. Mayura reads no credentials and runs no shell.
mayura deploy init --target kubernetes # plan the files
mayura deploy init --target kubernetes --apply # write them; review and commit
mayura deploy --target kubernetes --tag v42 # plan the release and print its digest
mayura deploy --target kubernetes --tag v42 --apply --confirm <digest>Targets
| Target | Writes | A release |
|---|---|---|
docker |
Dockerfile, .dockerignore |
builds the image and pushes it |
compose |
Dockerfile, .dockerignore, compose.yaml (PostgreSQL, migration, server, worker) |
builds, runs the migration once, then starts or updates the server and worker and waits until they are healthy |
kubernetes |
Dockerfile, .dockerignore, deploy/kubernetes/ (migration Job, server Deployment and Service, worker Deployment) |
builds and pushes the image, runs the migration Job and waits for its outcome, then rolls out the server and worker and waits for both |
Platforms come as packages named @mayurajs/deploy-<id>: install one in the project and use its id as the target.
mayura deploy targets lists the built-in targets and the installed packages. Packages are loaded only from the
project's own dependencies.
| Package | Target | Platform |
|---|---|---|
@mayurajs/deploy-agentcore |
agentcore |
Amazon Bedrock AgentCore Runtime: an ARM64 image serving its HTTP contract (/invocations calls your invoke, /ping reports busy while it runs), then the runtime updated and awaited |
@mayurajs/deploy-aws-ecs |
aws-ecs |
Amazon ECS on Fargate: task definitions at the release's image, a one-off migration task whose exit code is checked, then both services rolled out and awaited |
@mayurajs/deploy-aws-lambda |
aws-lambda |
AWS Lambda (experimental): one container image for the API, workflows and migration functions; the migration runs and is checked before the others update |
@mayurajs/deploy-azure |
azure |
Azure Container Apps: a migration job run to success, then the server and worker apps, each new revision awaited |
@mayurajs/deploy-cloudflare |
cloudflare |
Cloudflare: the app in Containers (server containers behind a Worker, a worker container kept awake by a cron), or the serverless module on Workers with a cron advancing workflows |
@mayurajs/deploy-cloudrun |
cloudrun |
Google Cloud Run: a migration job run to completion, then the server and an always-on internal worker as services, secrets from Secret Manager |
@mayurajs/deploy-digitalocean |
digitalocean |
DigitalOcean App Platform: an app spec with the server, a worker, a pre-deploy migration and PostgreSQL; each release pushes the image to the app's tag and waits for the deployment |
@mayurajs/deploy-fly |
fly |
Fly.io: serve and worker process groups, the migration as the release command, built by Fly's builders, your Docker, or pushed to your registry |
@mayurajs/deploy-railway |
railway |
Railway: a server service and a worker service with config-as-code files, each migrating before it goes live |
@mayurajs/deploy-render |
render |
Render: a Blueprint with a web service, a background worker and PostgreSQL, each service migrating first; released with render deploys create --wait |
@mayurajs/deploy-vercel |
vercel |
Vercel Functions: the API behind a /v1 rewrite, workflows advanced by Vercel Cron with CRON_SECRET, storage migrated from your machine before each deploy |
mayura.deploy.json
deploy init writes mayura.deploy.json when the project has none. Everything in it has a default except the image:
{
"format": "mayura.deploy.v1",
"name": "refunds",
"app": "dist/src/app.js",
"image": "registry.example.com/acme/refunds",
"port": 8080,
"probePort": 9090,
"env": ["OPENAI_API_KEY", "MAYURA_OPERATOR_TOKEN_SHA256"],
"targets": {
"kubernetes": { "namespace": "agents", "context": "prod-eu", "serverReplicas": 2, "workerReplicas": 2 }
}
}namenames services, Jobs and Secrets: lowercase letters, digits and hyphens. It defaults to the package name.appis the compiled application module. It defaults todist/app.jswhensrcis the TypeScript root directory, anddist/src/app.jsotherwise.imageis the image repository, without a tag. A release's tag is--tag, or thepackage.jsonversion.envlists the names of the variables the application reads. Their values never appear in a plan.targets.<id>holds each target's settings. Forkubernetes:namespace(default),context(a kubeconfig context; set it, so a release never goes to whichever cluster happens to be current),secret(<name>-env),serverReplicasandworkerReplicas(2), andtimeoutSeconds(600). Forcompose:projectName.
Plans and confirmation
A plan lists each step with its tool and arguments. Steps that apply rendered manifests show them in --json. The
plan's digest covers all of it: the target, the release, every argument and every manifest. --apply runs the
plan only when --confirm gives that digest, so what runs is exactly what you reviewed. If anything changed in
between, such as an edited manifest or a different tag, the digest differs and nothing runs.
During a run, each tool's output goes to standard error, and the result (each step's status and exit code) goes to standard output. A run stops at the first failing step and skips the rest, so a failed migration never rolls out. Ctrl+C stops the running tool and skips the remaining steps.
Credentials and secrets
Mayura reads no credentials. Each tool uses its own login and configuration: docker login, your kubeconfig, or a
platform CLI's own login. The application's secrets stay where the platform keeps them:
- Compose: the project's
.env, whichdeploy initnever writes. - Kubernetes: a Secret, by default
<name>-env, that the manifests load withenvFrom. Create it before the first release, for example withkubectl create secret generic refunds-env --from-env-file=.env.production.
Kubernetes manifests
The manifests under deploy/kubernetes/ are yours to edit: resources, probes, node selectors, annotations. They
contain two placeholders that a release fills in, and that must stay:
mayura-app-image, the image, which becomes<image>:<tag>;mayura-releasein the Job's name, which becomes the tag (lowercase, at most 13 characters), so each release runs its own migration Job.
The rendered manifests are given to kubectl apply -f -; the files on disk stay unchanged. The migration Job has
backoffLimit: 0, and the release waits for its outcome before anything rolls out.
Write a target
A platform package exports a target as its default export:
import { defineDeployTarget, imageSteps } from 'mayura/cli/deploy';
export default defineDeployTarget({
id: 'acme',
description: 'Deploy to Acme Cloud.',
tools: ['docker', 'acme'],
settings: () => ({}),
files: ({ project }) => ({ 'acme.toml': `app = "${project.name}"\n` }),
plan: ({ release }) => [
...imageSteps(release, 'acme'),
{ id: 'deploy', description: 'Deploy the release', tool: 'acme', args: ['deploy', '--image', release.image ?? ''] },
],
});A target may run only the tools it declares, by name; a step naming any other program is refused when the release is planned. Arguments are passed as given, without a shell.
A step can check what its tool prints with output: { match, as }. The tool's standard output, trimmed, must fully
match the regular expression match, or the step fails. Use it for a result the exit code does not carry, such as a
task's exit code. With as, later steps' arguments can use the output as {{name}}, such as the id of a task an
earlier step started. A step may use only names captured before it, and only output that matched its pattern is
passed on.
To wait for something its tool cannot wait for, a step adds retry: { while, attempts, intervalSeconds } to its
output check. While the output matches while, a status still in progress such as Running, the step runs again
after the interval, up to attempts times and at most an hour. Any answer that matches neither pattern fails the
step at once.
Good to know
- On Windows,
.exetools start directly. Tools that are.cmdscripts (gcloud, az, and CLIs installed with npm) start through cmd.exe with each argument quoted. An argument cmd.exe would interpret (" % ! ^ & | < > ( )or a trailing backslash) is refused, not escaped. Ctrl+C stops the tool and everything it started. deploy initwrites files atomically and refuses links and paths outside the project, like mayura init.- Use
--directory <dir>to work on a project other than the current directory.
Related
- Deployment: the targets, roles and production settings behind these files.
- Serve, worker and migrate: the commands each container runs.