How to create a simple IaC workflow with C# for GitHub actions

Time is moving fast and a lot of things happing within the Software Development and DevOps world. You have properly heart a lot about Infrastructure As Code (IaC). IMO the idea behind Infrastructure as code is to ensure that we can at any time recreate and redeploy our environment in the same way so that we do not forget steps or have a concern about how to re-do it again.

There are of course different ways and frameworks for IaC, like Microsoft Bicep, Terraform, and Pulumi. You can of course also do it without having a specific framework, in Azure you can make IaC using Arm Template, PowerShell, etc.

In this article, I am going to build a very simple YAML workflow for GitHub actions for continuous integration that I already use in my open-source CryptoNet project. And I will later convert it to IaC as C# code using ADotNet a new and lightweight open-source library developed by Hassan Rezk Habib.

Let’s go for it.

My requirement for my continuous integration workflow file was as described below:

  1. To trigger actions on main and feature branches but exclude feature branches start with ci.
  2. To trigger actions on pull request to main branch.
  3. To build and test my code on 3 different platforms, windows, ubuntu and mac os.
  4. To time out after 15 min if things fails or did not went well.
  5. To build and test my code using dotnet 6.

With all that mentioned requirements, I come up with the following YAML file solution:

on:
  # following triggers described in 1 and 2 in requirement
  push:
    branches:
      - main
      - "feature/*"
      - "!feature/ci*"
    paths-ignore:
      - "**/README.md"
  pull_request:
    branches:
      - main

jobs:
  build:
    # following matrix build described in 3 in requirement
    strategy:
      fail-fast: false
      matrix:
        os: [windows-latest, ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    # following timeout described in 4 in requirement
    timeout-minutes: 15
    # following steps refer to 5 in requirement
    steps:
    - name: Checkout
      uses: actions/[email protected]
    - name: Setup .NET
      uses: actions/[email protected]
      with:
        dotnet-version: 6.0.x
    - name: Build
      run: dotnet build --configuration Release
    - name: Test
      run: dotnet test --configuration Release --no-build

Now, if I need to create a C# code that can generate the above YAML file, I have to use ADotNet open source library. I create a console project and add ADotNet NuGet to it, calling it CryptoNetIaC. In my Program class I add the following methods:

public static void CiYamlGenerator(string workflowName = "ci.yaml")
{
    var adoClient = new ADotNetClient();

    var aspNetPipeline = new GithubPipeline()
    {
        Name = ".NET",
        
        OnEvents = new Events()
        {
            Push = new PushEvent()
            {
                Branches = new[]
                {
                    "main",
                    "feature/*",
                    "!feature/ci*"
                }
            },
            PullRequest = new PullRequestEvent()
            {
                Branches = new[]
                {
                    "main"
                }
            }
        },

        Jobs = new Jobs()
        {
            Build = new BuildJob()
            {
                RunsOn = "ubuntu-latest",
                TimeoutInMinutes = 15,
                Steps = new List<GithubTask>()
                {
                    new CheckoutTaskV2()
                    {
                        Name = "Checkout",
                        Uses = "actions/[email protected]"
                    },
                    new SetupDotNetTaskV1()
                    {
                        Name = "Setup .NET",
                        Uses = "actions/[email protected]",
                        TargetDotNetVersion = new TargetDotNetVersion()
                        {
                            DotNetVersion = "6.0.x"
                        }
                    },
                    new DotNetBuildTask()
                    {
                        Name = "Build",
                        Run = "dotnet build --configuration Release"
                    },
                    new TestTask()
                    {
                        Name = "Test",
                        Run = "dotnet test --configuration Release --no-build"
                    }
                }
            }
        }
    };

    CreateWorkFlowFile(adoClient, aspNetPipeline, workflowName);
}

private static void CreateWorkFlowFile(ADotNetClient adoClient, GithubPipeline githubPipeline, string workflowName)
{
    var solutionRoot = Directory.GetParent(Directory.GetCurrentDirectory())?.Parent?.Parent?.Parent?.FullName;
    var workflowPath = $"{solutionRoot}\\.github\\workflows";
    string workflowFile = Path.Combine(workflowPath, workflowName);
    adoClient.SerializeAndWriteToFile(githubPipeline, workflowFile);
}

I followed the same structure in my YAML file for creating a C# IaC, that can automatically create the same pipeline. This gives me flexibility for adding some dynamic generated variables names and an easy way to maintain my pipeline using C# syntax for those developers that might have issues with YAML 😜.

Now when I run this code, it will create ci.yaml under .github/workflows folder.

I have also created CreateWorkFlowFile a method so I can reuse it for creating other YAML files.

That is it for this time 😃.

Conclusion

As you can see it was straightforward for me to create a YAML workflow pipeline as IaC in C# for GitHub using the ADotNet library. As you can see in my YAML file, there are keys like paths-ignore and matrix os, they are not supported yet in ADotNet but as time goes a lot of updates add to it. For example, I asked for the timeout-minutes feature, and it took 2 days and it was implemented. With the same library, you can also use it to create an Azure DevOps pipeline as well. You can of course also use a framework or combine it with other solutions as well. As it is a DevOps solution, there are no limits or rules on how to do it as long as it is well documented and delivers the results for your business. I will cover other ways of IaC in the future. Keep tuned.

1 thought on “How to create a simple IaC workflow with C# for GitHub actions”

  1. Impressive blog with lovely information. Really a very useful article for us thanks for sharing such a wonderful blog.

    Reply

Leave a Comment