# Ando Operations
Globals and helpers available in all build.csando scripts.
## Operations
### 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.
```csharp
var output = Root / "dist";
Dotnet.Publish(app, o => o.Output(output));
```
### Temp
Temporary files directory (root/.ando/tmp). Supports path combining with the `/` operator. Use for caches, intermediate files, etc.
```csharp
var cache = Temp / "cache";
var intermediate = Temp / "build-output";
```
### 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.
```csharp
var apiKey = Env("API_KEY");
var optional = Env("OPTIONAL_VAR", required: false);
var lang = Env("SITE_LANG", required: false) ?? "en";
```
### 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.
```csharp
var frontend = Directory("./frontend");
Npm.Ci(frontend);
Cloudflare.PagesDeploy(frontend / "dist", "my-site");
Npm.Ci(Directory(".")); // Use Directory(".") instead of Root
```
### 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.
```csharp
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
Set the Docker image for the current build container. Must be called before build steps execute.
```csharp
Ando.UseImage("ubuntu:24.04");
Ando.UseImage("mcr.microsoft.com/dotnet/sdk:9.0");
Ando.UseImage("node:22");
```
### 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).
```csharp
Ando.CopyArtifactsToHost("dist", "./dist");
Ando.CopyArtifactsToHost("bin/Release", "./output");
```
### 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.
```csharp
Ando.CopyZippedArtifactsToHost("dist", "./output");
Ando.CopyZippedArtifactsToHost("dist", "./dist/binaries.tar.gz");
Ando.CopyZippedArtifactsToHost("dist", "./dist/binaries.zip");
```
### 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.
```csharp
Ando.Build(Directory("./website"));
Ando.Build(Directory("./website") / "deploy.csando");
Ando.Build(Directory("./api"), o => o.WithDind());
```
### 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).
```csharp
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.
```csharp
// 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.
```csharp
// 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`.
```csharp
// 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.
```csharp
// 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.
```csharp
// 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.
```csharp
// 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
| Option | Description |
|--------|-------------|
| `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). |