Skip to content
Invex-GamesPublic

About

.NET task and build automation framework

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

Atom

Build NuGet License: MIT .NET

Atom is an opinionated, type-safe build automation framework for .NET. It enables you to define your build logic in C#, debug it like standard code, and automatically generate CI/CD configuration files for GitHub Actions and Azure DevOps.

Packages

Package What it does
Invex.Atom.Build Core framework: build definitions, targets, parameters, hosting.
Invex.Atom.Workflows Workflow definitions, triggers, options, and the Gen target.
Invex.Atom.Module.Dotnet .NET CLI wrappers and build, test, pack, publish, and NuGet helpers.
Invex.Atom.Module.GitHubWorkflows GitHub Actions workflow and Dependabot generation.
Invex.Atom.Module.DevOpsWorkflows Azure DevOps Pipelines workflow generation.
Invex.Atom.Module.AzureKeyVault Azure Key Vault secrets provider.
Invex.Atom.Module.AzureStorage Azure Blob Storage artifact provider.
Invex.Atom.Module.GitVersion GitVersion-based build ID and version.
Invex.Atom.Tool The atom .NET global tool for running builds from any directory.

Features

  • Zero context switching. Write build logic in C# alongside your application code.
  • IntelliSense and debugging. Step through your build process using your IDE.
  • CI/CD agnostic. Define logic once; Atom generates the YAML for GitHub Actions and Azure DevOps.
  • Modular. Pull in capabilities via NuGet packages (GitVersion, Azure Key Vault, and more).
  • Source generators. Targets and parameters are discovered automatically, so there is no registration boilerplate.

Installation

Atom build projects require the .NET 10 SDK. The libraries target net10.0.

Add the core package to your build project (commonly _atom/_atom.csproj):

dotnet add package Invex.Atom.Build

Install the CLI once if you want to invoke builds from any directory:

dotnet tool install --global Invex.Atom.Tool

Quick start

  1. Create a .NET 10 project:

    dotnet new console -n _atom
  2. Replace the contents of _atom.csproj:

    <Project Sdk="Microsoft.NET.Sdk.Worker">
    
      <PropertyGroup>
        <TargetFramework>net10.0</TargetFramework>
        <RootNamespace>Atom</RootNamespace>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Invex.Atom.Build" Version="3.*" />
      </ItemGroup>
    
    </Project>
  3. Replace Program.cs with IBuild.cs:

    using Invex.Atom.Build.Definition;
    using Invex.Atom.Build.Hosting;
    
    namespace Atom;
    
    [BuildDefinition]
    [GenerateEntryPoint]
    internal interface IBuild : IBuildDefinition
    {
        Target HelloWorld =>
            t => t
                .DescribedAs("Prints a hello world message to the console")
                .Executes(() => Logger.LogInformation("Hello, World!"));
    }
  4. Run the target with atom HelloWorld (or dotnet run --project _atom -- HelloWorld):

    26-06-06 +10:00  Invex.Atom.Build.BuildExecutor:
    01:16:47.552 INF Executing build
    
    HelloWorld
    
    Prints a hello world message to the console
    
    26-06-06 +10:00  HelloWorld | Atom.Build:
    01:16:47.616 INF Hello, World!
    
    Build Summary
    
      HelloWorld │ Succeeded │ <0.01s
    

Usage

Parameters and secrets

Declare a parameter with [ParamDefinition] (or a secret with [SecretDefinition], which is masked in logs) and require it on a target:

[ParamDefinition("my-name", "My name")]
string? MyName => GetParam(() => MyName);

[SecretDefinition("my-secret", "My secret")]
string? MySecret => GetParam(() => MySecret);

Target HelloWorld =>
    t => t
        .RequiresParam(nameof(MyName))
        .RequiresParam(nameof(MySecret))
        .Executes(() => Logger.LogInformation("I am {MyName} and my secret is {MySecret}.", MyName, MySecret));

Run it with atom HelloWorld --my-name Frodo --my-secret TheOneRing. See Parameters and Secrets.

Target dependencies

Targets run in dependency order, and parameters only need to be provided once:

Target Goodbye =>
    t => t
        .DescribedAs("Prints a goodbye message to the console")
        .DependsOn(nameof(HelloWorld))
        .Executes(() => Logger.LogInformation("Goodbye!"));

atom Goodbye --my-name Frodo --my-secret TheOneRing runs HelloWorld and then Goodbye. See Targets.

Workflow generation

Reference Invex.Atom.Module.GitHubWorkflows, extend IWorkflowBuildDefinition, and declare a workflow:

using Invex.StructuredText.Expressions;

[BuildDefinition]
[GenerateEntryPoint]
internal interface IBuild : IWorkflowBuildDefinition, IGitHubWorkflows
{
    // targets and parameters as above

    IReadOnlyList<WorkflowDefinition> IWorkflowBuildDefinition.Workflows =>
    [
        new("Hello")
        {
            Triggers = [WorkflowTriggers.PushToMain],
            Targets =
            [
                new(nameof(HelloWorld))
                {
                    Options =
                    [
                        BuildOptions.Inject.Param(nameof(MyName), TextExpressions.GitHub.GitHubRepositoryOwner),
                        BuildOptions.Inject.Secret(nameof(MySecret)),
                    ],
                },
                new(nameof(Goodbye)),
            ],
            Types = [WorkflowTypes.GitHub.Action],
        },
    ];
}

atom Gen writes .github/workflows/Hello.yml, with one job per target and the parameter and secret injected from GitHub. See Workflow Definitions.

File-based apps

A build can also be a single Atom.cs file run with dotnet run Atom.cs HelloWorld:

#:sdk Microsoft.NET.Sdk.Worker
#:package Invex.Atom.Build@3.*

[BuildDefinition]
[GenerateEntryPoint]
internal interface IBuild : IBuildDefinition
{
    Target HelloWorld => t => t.Executes(() => Logger.LogInformation("Hello, World!"));
}

See Your First Build.

Documentation

Full documentation: https://invex-games.github.io/atom/

Guide Contents
Introduction What Atom is, when to use it, and how the packages fit together.
Your First Build Create a project-based or file-based build and run it.
Base vs Workflow Build IBuildDefinition vs IWorkflowBuildDefinition.
Core Concepts Build definitions, targets, parameters, secrets, artifacts, variables, file system, hosting, and more.
Workflows Workflow definitions, triggers, options, variables across jobs, and debugging.
Modules .NET, GitHub Workflows, DevOps Workflows, Azure Key Vault, Azure Storage, and GitVersion.
Built-in Targets SetupBuildInfo, ValidateBuild, and Gen.
Developer Guide Writing modules, custom providers, source generators, and testing.
CLI Reference Command-line options and the atom global tool.
API Reference Key types per package, linked into the generated reference.

Development

The solution is Invex.Atom.slnx and requires the .NET 10 SDK:

dotnet build Invex.Atom.slnx
dotnet test Invex.Atom.slnx

Atom builds itself with the build definition in _atom/. Build or preview the DocFX documentation with:

atom BuildDocs
atom ServeDocs

dotnet run --project _atom -- <target> is equivalent to atom <target>.

AI Disclaimer

The Atom libraries are human-made, however GitHub Copilot completions have been used on a superficial level.

Generative AI was also used to assist in writing tests and documentation.

License

Atom is released under the MIT License.

About

.NET task and build automation framework

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages