Toolkit: Possible bug with expressions and steps.<step id>.outputs

Created on 28 Aug 2019  路  15Comments  路  Source: actions/toolkit

I'm not sure where I should be posting this, or how I can report bugs, so I'm starting here. Please point me in the right direction if this isn't the forum


My goal is to eloquently handle running (or NOT running) a step based on the value of an output from a previous step. In this case i want to do custom things IF my semantic-release step actually cut a new version.

1) According to the docs it says the steps context is directly accessible via property name "steps". However when you want to use this in an jobs.<job_id>.steps.if expression, you need to access like job.steps..., i.e. if: job.steps.<step id>.status == failure

2) However the actual steps context as documented (with outputs) is NOT accessible inside an if expression

3) Everywhere else, ${{ steps..outputs }} works fine. In env it works, in run it works. Everything here works as expected:

- run: |
    printenv
    echo ${{ steps.semantic.outputs.semantic_release_version }}
    echo $VERSION
    echo "$OUTPUTS"
  env:
    VERSION: ${{ steps.semantic.outputs.semantic_release_version }}
    OUTPUTS: ${{ toJson(steps.semantic.outputs) }}

4) However, in an if expression if: steps.<step id>.outputs.someOutput == 'foo', it throws an error:

- Your workflow file was invalid: .github/workflows/test.yml (Line: 42, Col: 13): Unrecognized named-value: 'steps'. Located at position 1 within expression: steps.semantic.outputs.semantic_release_version

Here's a full example

name: testing outputs

on: push

jobs:
  tester:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-node@v1

      - uses: codfish/semantic-release-action@testing
        id: semantic
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: test outputs

        # printenv shows OUTPUTS object but NOT JOB_OUTPUTS
        # echo ${{ steps.semantic.outputs.semantic_release_version }} works as expected
        # echo $VERSION works as expected
        run: |
          printenv
          echo ${{ steps.semantic.outputs.semantic_release_version }}
          echo $VERSION # this works
        env:
          VERSION: ${{ steps.semantic.outputs.semantic_release_version }}
          OUTPUTS: ${{ toJson(steps.semantic.outputs) }}
          JOB_OUTPUTS: ${{ toJson(job.steps.semantic.outputs) }}

      # this does NOT work, whether using true or 'true'
      - if: job.steps.semantic.outputs.semantic_release_bool == 'true'
        run: |
          echo "steps.semantic.outputs.semantic_release_bool is true"

      # this actually throws the above error
      - if: steps.semantic.outputs.semantic_release_bool == 'true'
        run: |
          echo "steps.semantic.outputs.semantic_release_bool is true"

      # this does NOT work
      - if: contains(job.steps.semantic.outputs.semantic_release_version, '.')
        run: |
          echo "steps.semantic.outputs.semantic_release_bool is true"

I'm using https://github.com/codfish/semantic-release-action/compare/testing-outputs?expand=1 for testing (tagged with testing).

Most helpful comment

Hey everyone, I have been watching this thread real-time and tested these changes and I can confirm it all works as of right now. Below is an example yaml file:

name: test

on: push

jobs:

  build:
    runs-on: ubuntu-latest

    steps:
    - name: Step 1
      id: step1
      run: echo "::set-output name=VAR1::Hamel"

    - name: Step 2
      id: step2
      run: echo "::set-env name=VAR2::Husain"

    - name: emit env
      run: |
       echo $VAR2
       echo $VAR1

      env:
        VAR1: ${{ steps.step1.outputs.VAR1 }}

    - name: this should not run
      run: echo "This should not run"
      if: steps.step1.outputs.VAR1 == 'Lucy'

This will give you the following output:

image

All 15 comments

I'm not sure where I should be posting this, or how I can report bugs, so I'm starting here. Please point me in the right direction if this isn't the forum

This isn't super well defined right now, we're working on clarifying that. Since this isn't an issue with the toolkit, it probably belongs here for now - with that said, we should have better avenues for feedback like this soon. For now, we can take this here.

Concerning the issue itself, I _think_ that if: job.steps.semantic.outputs.semantic_release_bool == 'true' should work, but I'm not totally sure. @ericsciple or @thboop do you know what the correct syntax is here? Are we plumbing all of this through yet?

@damccorm thanks for the quick reply!

I've confirmed if: job.steps.semantic.outputs.semantic_release_bool == 'true' does not work. Let me know if you want me to set up another test for you guys. You should also be able to use the full snippet in the issue description to recreate.

IMO, it would make sense to be able to access the steps context normally in an if expression, same way we're able to access github context for instance. Maybe there's a reason this isn't possible at the moment though.

That being said if I have to workaround that by accessing via the job context that's not bad at all, but it seems as though only the status is made available to us, i.e. if: job.steps.<step id>.status == failure and not the outputs.

FYI @ericsciple @thboop

Thanks for the write-up and detailed example @codfish!

We are working on making the steps context and their associated outputs(accessible via steps.<step id>.outputs.<output name>) available inside a step's if statement. We'll make sure the docs reflect this as well, but this behavior isn't currently available.

@dakale, FYI, this is related to the steps context if statement behavior you were looking into.

@thboop awesome, thanks for the update!

Just to give some more context, the step with id second step in the below yaml doesn't run even though it should, so I think there is a bug

```name: practice outputs
on: push

jobs:
test-outputs:
name: Test Outputs Actions
runs-on: ubuntu-latest
steps:

- id: first_step
  name: "This step will run no matter what."
  run: echo 'the first step'

- name: Only run this step if another step succeeds
  id: second_step
  if: job.steps.first_step.status == success()
  run: echo "Hello"

```

Also, I don't think the status is made available either as job.steps.<id>.status consistently returns an empty/null value for me

@codfish the pr is merged for the outputs issue. the fix will roll out with the next runner update. @TingluoHuang do you know when?

@hamelsmu steps.foo.status is not a thing today. i'll open a pr to remove that from the docs.

later this week or really next week.

Awesome, thanks for the update!

@TingluoHuang @thboop @ericsciple wondering if you could answer a related question I have.

The only way I've found to properly set an environment variable (and an output var) is via @actions/core library. I cannot figure out how to set one outside of js and have it persist. For instance, appending export SOME_VAR=foo; to the runners' .bashrc doesn't work.

I see you're using commands, i.e. set-env here, but I'm not sure how that's working under the hood.

So is there a way to set and persist an env/output var from a host action or any other way without using the core package?

@codfish I actually have a PR to doc this right now - https://github.com/actions/toolkit/pull/105

To persist an output variable you can do echo ::set-output name=FOO::BAR, to persist an env variable you can do echo ::set-env name=FOO::BAR

@damccorm awesome, thank you!

@ericsciple

@codfish the pr is merged for the outputs issue. the fix will roll out with the next runner update.

To clarify, will this PR include the ability to reference steps context & outputs in the if property as well?

@codfish That functionality is fixed in a separate PR, as mentioned above by Eric:

@codfish the pr is merged for the outputs issue. the fix will roll out with the next runner update. @TingluoHuang do you know when?

And should be released by end of week, maybe trickling into next week if there are issues duringthe release/rollout, per Ting:

later this week or really next week.

Hey everyone, I have been watching this thread real-time and tested these changes and I can confirm it all works as of right now. Below is an example yaml file:

name: test

on: push

jobs:

  build:
    runs-on: ubuntu-latest

    steps:
    - name: Step 1
      id: step1
      run: echo "::set-output name=VAR1::Hamel"

    - name: Step 2
      id: step2
      run: echo "::set-env name=VAR2::Husain"

    - name: emit env
      run: |
       echo $VAR2
       echo $VAR1

      env:
        VAR1: ${{ steps.step1.outputs.VAR1 }}

    - name: this should not run
      run: echo "This should not run"
      if: steps.step1.outputs.VAR1 == 'Lucy'

This will give you the following output:

image

Thanks @damccorm @thboop @ericsciple @dakale

Can confirm this is now working for me as well. https://github.com/codfish/actions-playground/blob/master/.github/workflows/release.yml#L48

much appreciated! You can close if you want

I am trying to do something similar but instead of using constants 'Hamel' and 'Hussain' for var1 and var2, I want an expression to be evaluated. Concretely, the line looks as such -
echo "::set-env name=WEBSITE_BUCKET_ARN::$(terraform output website_bucket_arn)"

And when I echo the env variable in another step, I get "$WEBSITE_BUCKET_ARN" as a result. Any idea, leads or direction on how to store the result of an expression in an output/env variable. I have not been able to find anything related to this

When I try to access the environment variable WEBSITE_BUCKET, and just echo it in another step, it does not work!

Hey everyone, I have been watching this thread real-time and tested these changes and I can confirm it all works as of right now. Below is an example yaml file:

name: test

on: push

jobs:

  build:
    runs-on: ubuntu-latest

    steps:
    - name: Step 1
      id: step1
      run: echo "::set-output name=VAR1::Hamel"

    - name: Step 2
      id: step2
      run: echo "::set-env name=VAR2::Husain"

    - name: emit env
      run: |
       echo $VAR2
       echo $VAR1

      env:
        VAR1: ${{ steps.step1.outputs.VAR1 }}

    - name: this should not run
      run: echo "This should not run"
      if: steps.step1.outputs.VAR1 == 'Lucy'

This will give you the following output:

image

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andrewdhazlett picture andrewdhazlett  路  5Comments

warrenbuckley picture warrenbuckley  路  6Comments

josephperrott picture josephperrott  路  6Comments

JamesIves picture JamesIves  路  5Comments

kcgen picture kcgen  路  6Comments