Unable to interpolate string - hyphenated variables
mced opened this issue · comments
I'm facing an issue when I'm trying to reference a steps.<id>.outputs.<variable>
with an id composed with -
.
Run echo ${{ steps.login-ecr.outputs.registry }}
ERRO[0005] Unable to interpolate string 'echo ${{ steps.login-ecr.outputs.registry }}' - [ReferenceError: 'ecr' is not defined]
Workaround; remove all -
in id names.
i was afraid of this :(
Implementing the expression logic in act
was interesting. I noticed that if i squinted enough that the syntax looked like javascript, so i used robertkrimen/otto to process it as javascript. Unfortunately, javascript doesn't allow -
in variable names, but GH expressions does.
Any ideas on how to fix?
From the blogpost I've just read [1] and the releases history, you actually used a parser released by github. Unfortunately actions/workflow-parser is dead. Can you tell me what happened ?
[1] https://github.blog/2019-02-07-an-open-source-parser-for-github-actions/
The first cut of actions was completely different from the GA version. Seems like it was a rewrite to be based on Azure DevOps.
You're right, it was based on HashiCorp HCL. Now GA uses yaml syntax.
Thus I'd say to replace otto by an yaml parser, but I won't :)
The problem here isn't the parsing of the workflow files. I am using yaml parser for those (and previously the lib for HCL from github). However, some of the values in the yaml have a custom GitHub expression: https://help.github.com/en/actions/reference/contexts-and-expression-syntax-for-github-actions
That expression is what needs an evaluator, and what I use Otto for
Hey guys, I'm having the same problem here :(
As @mced pointed out,for a workaround to this, you can switch all variables with -
to _
for example.
The problem is when you have another action that implement output variables, for example: actions/cache
When I check for the steps.yarn_cache.outputs.cache-hit != 'true'
, I receive the following error:
sh ERRO[0017] Error evaluating expression 'steps.yarn_cache.outputs.cache-hit != 'true'' - ReferenceError: 'hit' is not defined
Great work in this package btw.
Hey guys.
I found a new "workaround" for this.
Looking further into the GA expression docs, there are two ways of writing an expression.
From the GA expression docs:
As part of an expression, you may access context information using one of two syntaxes.
Index syntax:github['sha']
Property dereference syntax:github.sha
Since act
uses otto to evaluate all expressions, if we write:
steps.yarn_cache.outputs['cache-hit'] != 'true'
instead of
steps.yarn_cache.outputs.cache-hit != 'true'
GA runner accepts it, otto evaluates it correctly, and we can run it both with act
and GA
@cplee I found another case where this is an issue and the workaround doesn't work;
When your trying to use someone else's action and it has input parameters with -
in them.
name: Test stuff
on:
- push
jobs:
build:
name: Testing Testing
runs-on: ubuntu-latest
steps:
- name: hello
uses: actions/hello-world-docker-action@master
with:
who-to-greet: "World"
which gives the error:
ERRO[0001] Unable to interpolate string '${{ inputs.who-to-greet }}' - [ReferenceError: 'to' is not defined]
Confirmed @torbjornvatn :(
I'm really stumped on this one. I'd really rather not have to implement my own parser for GitHub Actions expression language. Open to suggestions.
@cplee Replace the dot notation with the array notation before evaluate the expression is an option?
While I agree it would be somewhat annoying to port it to Golang, the expression parser for it is at least open source. You can find the lexer here, for example. It really doesn't look too bad.
Great find @eventualbuddha - would love some help with this one!
Dug a little more at that lexer, looks like the right regex for the actual token would be something like \.([a-zA-Z_][a-zA-Z0-9]*(?:-[a-zA-Z0-9]*)+)
(see the legal keyword test for valid keyword contents). Replacing that with .["$1"]
should do the trick.
I'll try and do a PR in the next couple of days.
#286 is quite interesting
Here is the code handling the evaluation of the if-expression at high-level :
Lines 254 to 266 in 7cc6687
With this setup, we have expr == "steps.bincache.outputs.cache-hit != 'true'"
.
This is not properly parsed by Interpolate
as it is missing the ${{...}}
delimiters ( github actions support this feature though ). By default, Interpolate
will return the same output as the input.
So we end up with expr == "Boolean(steps.bincache.outputs.cache-hit != 'true')"
which is the input of Evaluate
And it fails evaluating because of the js reference error, so we enter this block :
Lines 259 to 261 in 7cc6687
So here EvalBool
returns false
.
But if we change just a little bit the if-expression with :
- if: steps.bincache.outputs.cache-hit != 'true'
+ if: ${{ steps.bincache.outputs.cache-hit != 'true' }}
Then Interpolate
can parse its input. It calls Evaluate
, which fails for the same reason as before. But the error is caught by Interpolate
which will return the empty string because of :
Lines 65 to 67 in 7cc6687
So here, we end up with expr == Boolean()
( this is different from the previous case ). It means that we reach :
Lines 262 to 263 in 7cc6687
In particular, we got this debug log line :
DEBU[0003] Expression 'Boolean()' evaluated to 'false'
And EvalBool
also returns false
.
But the reason is different from the previous case, and the fix will likely be sightly different.