githubEdit

Parameters

Parameters are essential for making your Atom builds flexible and configurable. They allow you to pass external inputs into your build targets, controlling their behavior without modifying the underlying code. Atom provides a robust parameter system that can resolve values from various sources, handle secrets securely, and integrate seamlessly with your build logic.

ParamDefinition

ParamDefinition is a record that encapsulates the metadata for a parameter. It describes how a parameter is identified, what it does, and where its value can come from. You don't create ParamDefinition instances directly; they are generated by Atom's source generator based on attributes you apply to your build definition properties.

A ParamDefinition includes:

  • Name: The programmatic (C# property) name of the parameter.

  • ArgName: The name used on the command line (e.g., --my-param).

  • Description: A human-readable explanation for help documentation.

  • Sources: Where Atom should look for the parameter's value (e.g., command line, environment variables, configuration, secrets).

  • IsSecret: Whether the parameter holds sensitive information.

  • ChainedParams: Other parameters that this parameter's resolution might depend on.

ParamDefinitionAttribute

The [ParamDefinition] attribute is how you declare a standard parameter in your Atom build. You apply this attribute to properties within your build definition class or interfaces.

When to use it:

  • To define any non-sensitive input that your targets need.

  • When you want to expose a configurable option for your build.

How to use it: Declare a property of the desired type within your build class or a partial interface (often the same one where you define your targets). Mark this property with [ParamDefinition], providing an argName (for command-line usage) and a description. Use the GetParam helper method to retrieve its value.

Chained Parameters

Chained Parameters allow you to declare that the resolution of one parameter implicitly requires the resolution of other parameters. This is useful for scenarios where a parameter's value might depend on or influence other related parameters. When a parameter with chained parameters is resolved, Atom will also attempt to resolve all its chained parameters.

When to use it:

  • When a parameter's value is part of a larger set of related configurations.

  • To ensure that all necessary parameters for a complex feature are resolved together.

  • To simplify parameter declarations by grouping related inputs.

How to use it: You specify chained parameters using the chainedParams argument in the [ParamDefinition] or [SecretDefinition] attribute. Provide an array of parameter names (the C# property names) that should be resolved alongside the primary parameter.

In this example, whenever DeployEnvironment is resolved, Atom will also attempt to resolve DeployRegion and DeployCredentials. If DeployEnvironment is required by a target, then DeployRegion and DeployCredentials will also be implicitly treated as required for that target.

SecretDefinitionAttribute

The [SecretDefinition] attribute is specifically for declaring sensitive parameters. It inherits from [ParamDefinition] but automatically marks the parameter as a secret. This tells Atom to handle its value with extra care, such as masking it in logs and prioritizing resolution from secure secret providers.

When to use it:

  • For any sensitive data like API keys, passwords, connection strings, or tokens.

How to use it: Similar to [ParamDefinition], but use [SecretDefinition] instead.

IParamService

The IParamService is the central component responsible for resolving parameter values from various sources. While you interact with parameters primarily through the GetParam helper method (available via IBuildAccessor), the IParamService does the heavy lifting behind the scenes.

How it works: The IParamService resolves parameter values in a specific order of precedence:

  1. Cache: If the value has already been resolved and cached (and caching is not suppressed).

  2. Command-line Arguments: Values provided directly when running the Atom application (e.g., atom --build-config Release).

  3. Environment Variables: Values set in the operating system's environment.

  4. Configuration Files: Values from appsettings.json or environment-specific configuration files.

  5. Secret Providers: For parameters marked as secrets, values are fetched from registered ISecretsProvider implementations (e.g., .NET User Secrets, Azure Key Vault).

  6. Interactive Prompts: If the build is running in interactive mode (--interactive), the user might be prompted for missing required values.

  7. Default Value: The default value specified in the GetParam call.

Key functionalities of IParamService:

  • **GetParam<T>(Expression<Func<T?>> paramExpression, T? defaultValue = default, Func<string?, T?>? converter = null) **: The primary method for retrieving parameter values, supporting type conversion and default values.

  • MaskMatchingSecrets(string text): Replaces any known secret values in a given string with *****, ensuring sensitive data is not accidentally logged.

  • CreateNoCacheScope(): Creates a disposable scope where parameter caching is temporarily disabled, forcing re-resolution from original sources.

You typically won't inject IParamService directly into your targets. Instead, you'll use the GetParam extension method provided by IBuildAccessor on your build definition interfaces.

By leveraging Atom's parameter system, you can create highly flexible and secure builds that adapt to different environments and configurations with ease.

Last updated

Was this helpful?