Ando

Globals and helpers available in all build.csando scripts.

Operations

Operation Description
Root
The root path of the project (where build.csando is located). Returns BuildPath, not DirectoryRef. Use for path construction and string arguments. For operations requiring DirectoryRef (Npm, Cloudflare, etc.), use Directory(".") instead. Supports path combining with the / operator.
Temp
Temporary files directory (root/.ando/tmp). Supports path combining with the / operator. Use for caches, intermediate files, etc.
Env
Gets an environment variable. Global function — call as Env(), not Ando.Env(). By default throws if not set. Pass required: false to return null. The second parameter is a bool, not a default value — use null-coalescing (??) for defaults.
Directory
Creates a DirectoryRef — required by operations that need a working directory (Npm, Cloudflare, Playwright, Ando.Build). Global function — call as Directory(). Note: Root returns BuildPath, not DirectoryRef. Use Directory(".") when an operation needs a reference to the project root. Supports path combining with the / operator.
DefineProfile
Defines a build profile that can be activated via CLI. Takes a single argument (the profile name). Returns a Profile object with implicit bool conversion — use directly in if statements. There is no HasProfile() or Profile() function. Use -p or --profile CLI flag to activate.
UseImage
Set the Docker image for the current build container. Must be called before build steps execute.
CopyArtifactsToHost
Register files to copy from the container to the host after the build completes. The first parameter is the path inside the container (relative to /workspace or absolute), and the second is the destination on the host (relative to project root or absolute).
CopyZippedArtifactsToHost
Register files to be archived and copied from the container to the host after the build completes. Creates a single archive file for faster transfer of many small files. Supports .tar.gz (default) and .zip formats. If the destination is a directory, creates artifacts.tar.gz in that directory.
Build
Run a nested build script. Accepts a directory (runs build.csando in that directory) or a specific .csando file path. The child build runs in its own isolated container with its own environment file (.env.ando or .env) and context.
Log
Logging operations for outputting messages during the build. Has four methods: Log.Info() (visible at Normal verbosity), Log.Warning() (visible at Minimal+), Log.Error() (always visible), and Log.Debug() (only at Detailed verbosity).

Operation Details

Root source

The root path of the project (where build.csando is located). Returns BuildPath, not DirectoryRef. Use for path construction and string arguments. For operations requiring DirectoryRef (Npm, Cloudflare, etc.), use Directory(".") instead. Supports path combining with the / operator.

var output = Root / "dist";
Dotnet.Publish(app, o => o.Output(output));

Temp source

Temporary files directory (root/.ando/tmp). Supports path combining with the / operator. Use for caches, intermediate files, etc.

var cache = Temp / "cache";
var intermediate = Temp / "build-output";

Env source

Gets an environment variable. Global function — call as Env(), not Ando.Env(). By default throws if not set. Pass required: false to return null. The second parameter is a bool, not a default value — use null-coalescing (??) for defaults.

var apiKey = Env("API_KEY");
var optional = Env("OPTIONAL_VAR", required: false);
var lang = Env("SITE_LANG", required: false) ?? "en";

Directory source

Creates a DirectoryRef — required by operations that need a working directory (Npm, Cloudflare, Playwright, Ando.Build). Global function — call as Directory(). Note: Root returns BuildPath, not DirectoryRef. Use Directory(".") when an operation needs a reference to the project root. Supports path combining with the / operator.

var frontend = Directory("./frontend");
Npm.Ci(frontend);
Cloudflare.PagesDeploy(frontend / "dist", "my-site");
Npm.Ci(Directory(".")); // Use Directory(".") instead of Root

DefineProfile source

Defines a build profile that can be activated via CLI. Takes a single argument (the profile name). Returns a Profile object with implicit bool conversion — use directly in if statements. There is no HasProfile() or Profile() function. Use -p or --profile CLI flag to activate.

var release = DefineProfile("release");
var publish = DefineProfile("publish");

Dotnet.Build(app);

if (release) {
  Git.Tag("v1.0.0");
  GitHub.CreateRelease(o => o.WithTag("v1.0.0"));
}
// CLI usage:
// ando -p release
// ando -p publish,release

UseImage source

Set the Docker image for the current build container. Must be called before build steps execute.

Ando.UseImage("ubuntu:24.04");
Ando.UseImage("mcr.microsoft.com/dotnet/sdk:9.0");
Ando.UseImage("node:22");

CopyArtifactsToHost source

Register files to copy from the container to the host after the build completes. The first parameter is the path inside the container (relative to /workspace or absolute), and the second is the destination on the host (relative to project root or absolute).

Ando.CopyArtifactsToHost("dist", "./dist");
Ando.CopyArtifactsToHost("bin/Release", "./output");

CopyZippedArtifactsToHost source

Register files to be archived and copied from the container to the host after the build completes. Creates a single archive file for faster transfer of many small files. Supports .tar.gz (default) and .zip formats. If the destination is a directory, creates artifacts.tar.gz in that directory.

Ando.CopyZippedArtifactsToHost("dist", "./output");
Ando.CopyZippedArtifactsToHost("dist", "./dist/binaries.tar.gz");
Ando.CopyZippedArtifactsToHost("dist", "./dist/binaries.zip");

Build source

Run a nested build script. Accepts a directory (runs build.csando in that directory) or a specific .csando file path. The child build runs in its own isolated container with its own environment file (.env.ando or .env) and context.

Ando.Build(Directory("./website"));
Ando.Build(Directory("./website") / "deploy.csando");
Ando.Build(Directory("./api"), o => o.WithDind());

Log source

Logging operations for outputting messages during the build. Has four methods: Log.Info() (visible at Normal verbosity), Log.Warning() (visible at Minimal+), Log.Error() (always visible), and Log.Debug() (only at Detailed verbosity).

Log.Info("Starting deployment...");
Log.Warning("Cache is stale, rebuilding");
Log.Error("Failed to connect to server");
Log.Debug("Processing item 5 of 10");

Globals

These globals are available in all build.csando scripts without any prefix or import. Env(), Directory(), and DefineProfile() are global functions — call them directly, not as methods on the Ando object.

// Directory reference (returns DirectoryRef)
var frontend = Directory("./frontend");

// Path construction with / operator (Root returns BuildPath)
var output = Root / "dist";
var cache = Temp / "build-cache";

// Access environment variables (global function, not Ando.Env)
var dbUrl = Env("DATABASE_URL");
var apiKey = Env("API_KEY", required: false);
var lang = Env("SITE_LANG", required: false) ?? "en";

// Use regular C# variables for custom values
var buildNumber = "123";

Environment Variables

The Env() function retrieves environment variables. The second parameter is required: (a bool), NOT a default value string.

// Required (default) - throws if not set
var apiKey = Env("API_KEY");

// Optional - returns null if not set
var optional = Env("OPTIONAL_VAR", required: false);

// Optional with default value - use null-coalescing (??)
var lang = Env("SITE_LANG", required: false) ?? "en";

// WRONG: second parameter is bool, not a default value
// var lang = Env("SITE_LANG", "en");  // Compile error!

There is no SetEnv() function. Set environment variables via .env.ando files, OS environment, or CI/CD configuration.

BuildPath vs DirectoryRef

ANDO has two path types. Operations like Npm.Ci(), Cloudflare.PagesDeploy(), Playwright.Test(), and Ando.Build() require DirectoryRef, not BuildPath.

// Root returns BuildPath - use for path construction
var outputPath = Root / "dist";
Dotnet.Publish(app, o => o.Output(outputPath));  // OK: accepts string/BuildPath

// Directory() returns DirectoryRef - use for operations
var frontend = Directory("./frontend");
Npm.Ci(frontend);  // OK: requires DirectoryRef

// WRONG: Npm.Ci(Root) - BuildPath is not DirectoryRef
// Use Directory(".") to reference the project root as DirectoryRef:
Npm.Ci(Directory("."));  // OK

Profiles

Profiles allow conditional execution of build steps. DefineProfile() takes a single argument (the name) and returns a Profile with implicit bool conversion. There is no HasProfile(), HasAnyProfile(), or Profile() function.

// Define profiles at the top of your build.csando
var release = DefineProfile("release");
var publish = DefineProfile("publish");

// Project references
var app = Dotnet.Project("./src/App/App.csproj");
var tests = Dotnet.Project("./tests/App.Tests/App.Tests.csproj");

// Always run build and tests
Dotnet.Build(app);
Dotnet.Test(tests);

// Only run when "release" profile is active
if (release) {
  Dotnet.Publish(app, o => o.Output(Root / "dist"));
  Git.Tag("v1.0.0");
}

// Only run when "publish" profile is active
if (publish) {
  Nuget.EnsureAuthenticated();
  Nuget.Pack(app);
  Nuget.Push(app, o => o.SkipDuplicate());
}

// CLI usage:
// ando              # Build and test only
// ando -p release   # Build, test, publish, and tag
// ando -p publish      # Build, test, pack, and push to NuGet

Log

Logging operations for outputting messages during the build. Visibility depends on verbosity level.

// Informational messages (visible at Normal verbosity)
Log.Info("Starting build process...");

// Warnings (visible at Minimal verbosity and above)
Log.Warning("Cache directory not found, rebuilding from scratch");

// Errors (always visible)
Log.Error("Build failed: missing dependency");

// Debug messages (only visible at Detailed verbosity)
Log.Debug($"Processing file: {filePath}");

Build Configuration

Build configuration, artifact copying, and nested builds. Use these to set the Docker image, copy outputs to host, and run child build scripts.

// ando-doc-snippet-test
// Set the Docker image for the build container
Ando.UseImage("mcr.microsoft.com/dotnet/sdk:9.0");

// Copy artifacts from container to host after build
Ando.CopyArtifactsToHost("dist", "./dist");

// Copy as compressed archive (faster for many small files)
Ando.CopyZippedArtifactsToHost("dist", "./output");  // Creates ./output/artifacts.tar.gz
Ando.CopyZippedArtifactsToHost("dist", "./dist/binaries.tar.gz");  // Specific filename
Ando.CopyZippedArtifactsToHost("dist", "./dist/binaries.zip");     // Zip format

// Run a child build in a subdirectory
Ando.Build(Directory("./website"));

// Run a specific build file
Ando.Build(Directory("./website") / "deploy.csando");

// Child build with Docker-in-Docker enabled
Ando.Build(Directory("./integration-tests"), o => o.WithDind());

Options Reference

Build Options

OptionDescription
WithVerbosity(string)Set output verbosity level. Values: “Quiet” (errors only), “Minimal” (warnings and errors), “Normal” (default), “Detailed” (debug output).
ColdStart(bool)Force a fresh container for this build, ignoring any warm container cache. Use when you need a clean environment or are debugging container state issues.
WithDind(bool)Enable Docker-in-Docker mode. Required when the child build needs to run Docker commands (e.g., building images, running docker-compose). Mounts the Docker socket into the container.
WithImage(string)Override the Docker image for this child build. Use when the child build requires different tools than the parent (e.g., Node.js build in a .NET project).