Workflow Variables
In complex build workflows, it's often necessary to share data between different targets or even different jobs within a CI/CD pipeline. Atom's Workflow Variable system provides a robust and extensible mechanism for persisting and retrieving these values.
IWorkflowVariableService Interface
IWorkflowVariableService InterfaceThe IWorkflowVariableService is the central component for managing workflow variables. It acts as an abstraction layer over various IWorkflowVariableProvider implementations, allowing you to read and write variables without worrying about the underlying storage mechanism.
When to use it:
When you need to pass a value from one target's execution to another.
When you need to persist a value across different jobs in a CI/CD workflow.
To store dynamic data generated during the build (e.g., a build ID, a generated path, a version number).
Key Methods:
WriteVariable(string variableName, string variableValue, CancellationToken cancellationToken = default): Persists a variable with the given name and value to the workflow context. ThevariableNameshould correspond to a parameter defined in your build definition.ReadVariable(string jobName, string variableName, CancellationToken cancellationToken = default): Retrieves a variable from the workflow context. ThejobNameparameter allows you to specify which job the variable was written from, enabling cross-job data sharing.
IVariablesHelper Interface
IVariablesHelper InterfaceThe IVariablesHelper interface provides a convenient helper method for writing workflow variables. When your build definition interfaces implement IVariablesHelper, you get direct access to the WriteVariable method.
How to use it: Implement IVariablesHelper in your target definition interface. Then, within your target's Executes block, you can call WriteVariable.
// In IMyTargets.cs
[TargetDefinition]
public partial interface IMyTargets : IBuildAccessor, IVariablesHelper
{
Target GenerateBuildId => t => t
.DescribedAs("Generates and writes a unique build ID.")
.Executes(async () =>
{
var buildId = Guid.NewGuid().ToString();
await WriteVariable("BuildId", buildId); // "BuildId" should be a defined parameter
Logger.LogInformation($"Generated Build ID: {buildId}");
});
Target UseBuildId => t => t
.DescribedAs("Consumes the generated Build ID.")
.DependsOn(GenerateBuildId)
.ConsumesVariable(nameof(GenerateBuildId), "BuildId") // Declares dependency on the variable
.Executes(() =>
{
// The BuildId parameter will now be resolved from the workflow variable
Logger.LogInformation($"Using Build ID: {BuildId}");
});
// Assuming BuildId is defined as a parameter in IBuildInfo or another interface
// [ParamDefinition("build-id", "Unique identifier for the build")]
// string BuildId => GetParam(() => BuildId);
}IWorkflowVariableProvider Interface and AtomWorkflowVariableProvider
IWorkflowVariableProvider Interface and AtomWorkflowVariableProviderIWorkflowVariableProvider: This interface defines the contract for concrete implementations that handle the actual storage and retrieval of workflow variables. Atom'sIWorkflowVariableServicedelegates operations to a chain of these providers.AtomWorkflowVariableProvider: This is Atom's defaultIWorkflowVariableProvider. It stores and retrieves variables from a local JSON file within the Atom temporary directory. This is useful for local builds or simple CI/CD setups.
When to use it:
IWorkflowVariableProvider: To integrate with external variable storage systems (e.g., CI/CD platform-specific mechanisms like GitHub Actions outputs, Azure DevOps variables).AtomWorkflowVariableProvider: You typically don't interact with this directly, as it's the default fallback.
How it works: When you call WriteVariable or ReadVariable, the IWorkflowVariableService iterates through all registered IWorkflowVariableProviders. The first provider that successfully handles the operation (returns true) completes the request. This allows you to prioritize custom providers (e.g., a GitHub Actions provider) over the default AtomWorkflowVariableProvider.
By using workflow variables, you can create more dynamic and interconnected build processes, enabling seamless data flow between different stages of your automation.
Last updated
Was this helpful?
