Search code examples
powershellgithubenvironment-variablesgithub-actionsstrsplit

split string line by line and variablize i.e assign it to GITHUB_OUTPUT - workflow


Github action run invokes a powershell that returns as below:

Powershell return function:

return "$($psitem.Key)=$($psitem.Value)"

The return is assigned to a github action variable returnvalue

The return contains a list of key=value pairs separated by ' ' [single spacebar]

I wish to assign each returned key-value pair as github variable=value and then print it.

I use the below workflow run logic to achieve this:

  - name: Powershell to split

    run: |
      "${{ needs.READ_VARS_FROM_XML.outputs.key_value_x }}" -split " " | ForEach-Object {
        echo $_
        echo "$_" >>  $env:GITHUB_OUTPUT 
        }

       
  - name: Print single key-value attemp 2
    run: |
      echo "PORT NUMBER: ${{ env.port }} and {{ port }}"            

     

Output:

Powershell to split

Run "deploy_path=C:\\inetpub\\wwwroot\\tss.qa port=8814 app_name=Signup-qa debug=true deploy_password=password deploy_user=" -split " " | ForEach-Object {
deploy_path=C:\\inetpub\\wwwroot\\tss.qa
port=8814
app_name=Signup-qa
debug=true
deploy_password=password
deploy_user=

Print single key-value attemp 2

Run echo "PORT NUMBER:  and {{ port }}"            
PORT NUMBER:  and {{ port }}

I was expecting Port number 8814 to be printed for variable port but it doesn’t seem to hold any value.

Update: Post answer as suggested I printed the environment variables

steps:
  - name: Print Environment Variables
    run: |
      Get-ChildItem Env:

Unfortunately, I don't see any of the key=value i.e port=8814 in the output of environment variables. Please suggest what could be wrong?

Can you please suggest what did I miss?


Solution

  • You're creating output variables, not environment variables by appending to $env:GITHUB_OUTPUT. You'll need to make a few changes to work with the env. scope and the shell's environment.

    1. Instead of $env:GITHUB_OUTPUT, use $env:GITHUB_ENV.
    2. Pass the env. scope to the environment of the PowerShell task
    3. (optional) mask passwords

    A workflow that works for me is the following:

    jobs:
      init:
        env:
          key_value: "deploy_path=C:\\inetpub\\wwwroot\\tss.qa port=8814 app_name=Signup-qa debug=true deploy_password=FHSGDSJJD deploy_user="    
        runs-on: ubuntu-latest
        steps:
        - run: |
             $values = $env:key_value -split " "
             foreach ($value in $values)
             {
               if ($value -like "*password*")
               {
                 $secret = ($value.split("=",2))[1]
                 echo "::add-mask::$secret"
               }
               echo $value
               echo $value >> $env:GITHUB_ENV
             }
          id: split
          shell: pwsh
          env:
            key_value: ${{ env.key_value }}
    
        - run: |
              echo "PORT NUMBER: ${{ env.port }} and $($env:port)"    
          shell: pwsh
          env: ${{ env }}
    

    For outputs, the steps are very similar:

    1. Add an id: to the step that generates the output variable.
    2. Store the output variables in $env:GITHUB_OUTPUT
    3. Pass the previous step's outputs to the env: section of the next step.
    4. Again, optionally mask the passwords
    jobs:
      init:
        env:
          key_value: "deploy_path=C:\\inetpub\\wwwroot\\tss.qa port=8814 app_name=Signup-qa debug=true deploy_password=FHSGDSJJD deploy_user="    
        runs-on: ubuntu-latest
        steps:
        - run: |
             $values = $env:key_value -split " "
             foreach ($value in $values)
             {
               if ($value -like "*password*")
               {
                 $secret = ($value.split("=",2))[1]
                 echo "::add-mask::$secret"
               }
               echo $value
               echo $value >> $env:GITHUB_OUTPUT
             }
          id: split
          shell: pwsh
          env:
            key_value: ${{ env.key_value }}
        - run: |
              echo "PORT NUMBER: ${{ steps.split.outputs.port }} and $($env:port)"    
          shell: pwsh
          env: ${{ steps.split.outputs }}
    

    To dump the contents of a scope to the log, you can use:

        - name: Dump the env scope
          run: |
              echo $env:scope
          env:
            scope: ${{ toJson(env) }}
          shell: pwsh
    

    You can pass vars, env, github, matrix, steps.X.outputs, etc to the toJson function to dump the context to the console.