Search code examples
.netgithub-actionsnuke-build

How do I set a variable with Nuke to use it in a GitHub Actions matrix afterwards?


I am currently working my way into GitHub Actions as well as NUKE.build. My project consists of 2 jobs in GitHub Actions: The first job is responsible for reading the build configurations from a given .csproj file and setting it as a JSON array variable. The second job (which is spread across multiple runners) is then supposed to use this JSON array as the value for the matrix, executing my targets in NUKE, with the respective value as a parameter.

I have managed this so far with the following workflow (shortened):

name: Build Workflow
on:
  ...

jobs:
  get-configurations:
    runs-on: windows-latest

    outputs:
      configurations: ${{ steps.generate-matrix.outputs.configurations }}

    steps:
      ...

      - name: Get Build Configurations
        id: generate-matrix
        run: |
          dotnet NukeComponents --root . --relative-project-file-path "PathToProjectFile" --dotnet --get-configurations

  build:
    needs: get-configurations
    runs-on: windows-latest

    strategy:
      matrix:
        configuration: ${{ fromJson(needs.get-configurations.outputs.configurations) }}

    steps:
      ...
      - name: Build and test
        run: |
          $configuration = "${{ matrix.configuration }}"
          dotnet NukeComponents --root . --relative-project-file-path "PathToProjectFile" --configuration "$configuration"

And in my NUKE "GetConfigurations" target I have the following to set the variable:

var output = string.Join(',', configurations.Select(x => $"\"{x}\""));
Console.WriteLine($"::set-output name=configurations::[{output}]");

As I said, this also works so far. But now it is the case that "::set-output" is deprecated and should not be used anymore. It was said that you should use the following instead:

echo 'KEY=VALUE' >> $GITHUB_OUTPUT

I have tested this and it also works when I define it directly in the workflow:

  - name: Set configurations
    id: set-configurations
    run: echo 'configurations=["20200-Release","20201-Release","20202-Release"]' >> "$env:GITHUB_OUTPUT"

  - name: echo output of previous step for testing
    run: echo ${{ steps.set-configurations.outputs.configurations }}

However, if I now go and try to adjust the line in my NUKE target:

var output = string.Join(',', configurations.Select(x => $"\"{x}\""));
Console.WriteLine($"echo 'configurations=[{output}]' >> '$env:GITHUB_OUTPUT'");

And the workflow file:

- name: Get Build Configurations
  id: generate-matrix
  run: |
    dotnet NukeComponents --root . --relative-project-file-path "PathToProjectFile" --dotnet --get-configurations

 - name: echo output of previous step for testing
   run: echo ${{ steps.generate-matrix.outputs.configurations }}

Then apparently I have the problem that "configurations" remains empty (Get as error message that InputObject in echo command is empty).

I have also tried things like setting the configurations as an environment variable in the NUKE target.

But I can't get it to work. It looks like the echo command is not executed, but just output. But maybe I am wrong and the error is somewhere else.

Can someone help me here?


Solution

  • Thanks to @Azeem's help, I was able to solve the problem.

    My answer is probably not 100% accurate, however the solution works for me and so I am posting it here. If anyone finds an error in my answer, feel free to correct it!

    I removed NUKE from the equation and used a simple console application written in .NET 7.

    I think my guess about GitHub Runner not interpreting the output of my console program and executing commands present in it seems to be correct. In the console program, I ran the following command in the console:

    Console.WriteLine("echo 'configurations=\"[\\\"20200-Release\\\",\\\"20201-Release\\\",\\\"20202-Release\\\"]\"' >> $env:GITHUB_OUTPUT");
    

    However, it seems that the GitHub runner does not execute the echo command, but simply returns it as output, which probably makes sense.

    So what I needed to do is run the echo command in a separate PowerShell:

        static void Main(string[] args)
        {
            ExecuteCommand($"echo 'configurations=\"[\\\"20200-Release\\\",\\\"20201-Release\\\",\\\"20202-Release\\\"]\"' >> $env:GITHUB_OUTPUT");
        }
    
    
        private static void ExecuteCommand(string command)
        {
            var processInfo = new ProcessStartInfo
            {
                FileName = "C:\Windows\System32\\WindowsPowerShell\v1.0\\powershell.exe",
                Arguments = $"/c {command}",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                CreateNoWindow = true
            };
    
    
            Process.Start(processInfo);
        }
    

    The additional "\" in, for example. \\\"20201-Release\\\", are necessary because the array is in quotes and the whole thing, in this case, is interpreted by PowerShell.

    The GitHub workflow job looks like this:

    jobs:
      get-configurations:
        runs-on: windows-latest
    
        outputs:
          configurations: ${{ steps.generate-matrix.outputs.configurations }}
    
        steps:
          ...
    
          - name: Get Build Configurations
            id: generate-matrix
            run: ./NukeComponents/GetConfigurations.exe
    
          - name: echo env of previous step for testing
            run: echo ${{ steps.generate-matrix.outputs.configurations }}