Skip to content

alis build

Create a new service version from the product build repo and build its Docker images. Optionally deploy the version once the build succeeds.

Synopsis

alis build [<package-id>] [flags]

Description

By default the command waits for the operation to finish, streaming progress to stderr and printing the result to stdout. The service is addressed by package ID, which may be omitted inside the service's directory.

By default the latest pushed commit for the service folder on the currently checked-out branch is used. Pass --branch to choose another pushed branch, or to require that an explicit --commit is on that branch. Use --retag when only deployment infrastructure changed and the latest previous images should be retagged; retagging an image whose build context changed since the last build prints a warning.

Definition version

Every build carries the service's definition (its compiled proto descriptors). A deploy syncs that definition to the deployment environment's Spanner proto bundle and Pub/Sub event types before Terraform runs. By default a build carries the latest definition, whatever commit it builds, and the result's notes say which one: descriptors: definition 1.81.0.

When you build an older commit, for example a hotfix branched from what production runs, pin the definition that code was built against so the deploy carries no unrelated schema changes: --definition-version <X.Y.Z>, the alis.build/<org>/<product>/<service> version the service's go.mod requires. The platform rebuilds that version's descriptors from its definition tag; types imported from other packages are taken at their current definition. Definitions made before 20 October 2026 were not tagged and cannot be pinned, which the build reports. alis deploy --plan-only shows what a deploy's definition sync would change (protos→Spanner +1 ~8 -17), so an unexpected change there is the cue to pin.

Image detection

Images are auto-detected under the service folder:

File Build context Image
Dockerfile service folder neurons/<neuron>
worker/Dockerfile worker/ neurons/<neuron>/worker
bff.Dockerfile service folder neurons/<neuron>/bff
web/app.Dockerfile web/ neurons/<neuron>/web/app

A named <name>.Dockerfile lets several images share code in one folder. <name> starts with a lowercase letter, uses only lowercase letters, digits and single hyphens, ends with a letter or digit, and has at most 30 characters. Only the exact .Dockerfile suffix counts (bff.dockerfile and Dockerfile.bff print a warning), and two files building one image (bff.Dockerfile and bff/Dockerfile) fail the build. Moving bff/Dockerfile to bff.Dockerfile keeps the image name. A root-level named Dockerfile sees the whole service folder: COPY only what the image needs and add a <name>.Dockerfile.dockerignore beside it. For Go, one go.mod at the service root with a cmd/<image> main per image shares packages.

Terraform references the image as usual:

${var.ALIS_PRODUCT_REGION}-docker.pkg.dev/${var.ALIS_OS_PRODUCT_PROJECT}/neurons/${var.ALIS_OS_NEURON}/bff:${var.ALIS_OS_NEURON_VERSION_COMMIT_SHA}

Local builds

--local builds the images on this machine with Docker instead of on the platform's builder, then registers the version from the pushed images:

  1. The pushed commit is staged in a temporary git worktree; the working tree is never built or touched.
  2. Each selected image is built with docker buildx build --platform linux/amd64 --push from its usual context, with the product's build credentials (the same service-account key the platform build mounts) handed to every RUN as a BuildKit secret, so private Alis packages resolve exactly as they do on the platform. ALIS_OS_VERSION carries the version the platform is expected to assign.
  3. The image is pushed to the product's registry as <region>-docker.pkg.dev/<project>/neurons/<neuron>[/<image>]:<commit> with that key as the registry identity, through a temporary Docker config; your own ~/.docker/config.json is neither used for credentials nor written to.
  4. The version is registered with the platform, which verifies that every tag exists. --deploy chains as usual.

It needs a running Docker with buildx (Docker Desktop, or Docker Engine with the buildx plugin); on an Apple Silicon or other arm64 machine the amd64 build runs under emulation (enable Rosetta in Docker Desktop). It is not available inside agent sandboxes, and conflicts with --retag and --confirm-no-paths. Docker's output streams to stderr (held back under --quiet and shown only on failure); the result gains a local object with the pushed images and their digests. Nothing but Docker's own layer cache stays on the machine.

Build and deploy

--deploy attaches a deployment request to the build, matching the TUI's build & deploy flow. Pass --environment for each target deployment environment; if omitted and the product has exactly one deployment environment, that deployment environment is used. Deploys to a production deployment environment require confirmation.

Flags

Flag Type Default Meaning
--allow-branch-mismatch bool false With --deploy, proceed even when the built branch is not designated for a target deployment environment.
--async bool false Start the operation and print its name without waiting.
--branch <branch> string checked-out branch when --commit is omitted Git branch the built commit must come from.
--build-path <path> strings Image to build, relative to the service folder: a Dockerfile's folder (., worker) or a named <name>.Dockerfile (repeatable).
--commit <sha> string latest pushed commit for the service folder Exact product build-repo commit to build.
--confirm-no-paths bool false Confirm this service has no Docker images to build or retag.
--confirm-production bool false Required to deploy to a production deployment environment; pass only after explicit user approval.
--definition-version <version> string latest definition Definition (package) version whose descriptors the build carries, e.g. 1.79.0. See Definition version.
--deploy bool false Deploy the built version after the build succeeds.
-e, --environment <id> strings With --deploy, deployment environment id to deploy to (repeatable).
--local bool false Build the images on this machine with Docker and push them, then register the version. See Local builds.
--plan-only bool false With --deploy, run only Terraform plan instead of apply.
--poll-interval <duration> duration 2s How often to poll the operation.
--retag bool false Retag the latest previous images instead of building detected Dockerfiles.
--retag-path <path> strings Image to retag, relative to the service folder: a Dockerfile's folder or a named <name>.Dockerfile (repeatable).
--timeout <duration> duration 0 Give up waiting after this duration (0 = wait indefinitely; the operation keeps running).

Plus the global flags.

Examples

Shell
alis build --json
alis build acme.shop.orders.v1 --json --branch main
alis build acme.shop.orders.v1 --json --branch main --deploy -e <env-id>
alis build acme.shop.orders.v1 --json --branch main --retag --deploy -e <env-id>
alis build acme.shop.orders.v1 --json --branch main --async
alis build acme.shop.orders.v1 --json --local

JSON output

The final operation on stdout, pruned to what is actionable; --verbose keeps every field. images[] lists each image by path; deployments[] appears with --deploy; local (platform, registry, versionArg, images[] with image and digest) appears with --local. See Output contract.

Exit codes

Exit 3 with PRODUCTION_CONFIRMATION_REQUIRED when --deploy targets a production deployment environment without --confirm-production; exit 3 with APPROVAL_REQUIRED under the manual automation tier. With --local: LOCAL_BUILD_UNAVAILABLE when Docker cannot be used here (the retry is the same command without --local) and LOCAL_BUILD_FAILED when a docker build fails (details names the image and exit code and lists the images already pushed). See Exit codes.