# 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). |