Conditional expressions [[ ... ]] && work if used with yamal block literals "|"

I tried the following:

[[ "${GCC_VER}" == "4.9" ]] && sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 100

And circleci is giving me an error:

Warning: Syntax Error while parsing circle.yml: while scanning an anchor in ‘reader’, line 21, column 35: - [[ “${GCC_VER}” == “4.9” ]] && sudo update-alternatives --in … ^ expected alphabetic or numeric character, but found but found & in ‘reader’, line 21, column 36: - [[ “${GCC_VER}” == “4.9” ]] && sudo update-alternatives --ins … ^

Am I doing something wrong?

1 Like

Try this instead

- if [[ "${GCC_VER}" == "4.9" ]] ; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 100 ; fi

Yes, I know that works, but its more verbose. Why is the conditional expression not supported?

Not sure, it may be a bug in the parser. Will have to see what staff says.

Should I change this to a bug report or is there a better way to report bugs?

I would probably advise it be changed to a bug report. The error doesn’t seem to make sense, since ; isnt alphanumaric either.

Does running your whole circle.yml though http://www.yamllint.com/ thrown any errors? Im going to guess it wont, but doesnt hurt to check.

You’re correct my full file didn’t work. But using block literals does work and is valid yaml according to yamllint.com:

- | # Test multiline yaml support
  if [[ "$GCC_VER" == "5" ]]; then
    echo GCC_VER is 5
  else
    echo GCC_VER is not 5
  fi

- | # Test Conditional expression
  [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9

But I’m surprised this didn’t work which is both legal yaml and legal bash:

- | # Test Conditional expression
  [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9
  [[ "${GCC_VER}" == "5" ]] && echo GCC_VER is 5

I then tried one more combination, but it doesn’t work either:

- | # Test Conditional expression
  { [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9 ; }
  { [[ "${GCC_VER}" == "5" ]] && echo GCC_VER is 5 ; }

And finally this version works with two if statements. So it makes the two conditional expressions failing even more surprising:

- | # Test multiline yaml support
  if [[ "$GCC_VER" == "5" ]]; then
    echo "GCC_VER is 5"
  else
    echo "GCC_VER is not 5"
  fi
  if [[ "$GCC_VER" == "4.9" ]]; then
    echo "GCC_VER is 4.9"
  else
    echo "GCC_VER is not 4.9"
  fi

So my original version wasn’t legal yaml so that seems reasonable it failed, but the two “conditional expressions” versions I would expect to work, especially in light that the two “if expressions” work and one conditional express works.

So I’ve changed it to a bug, do you have any additional thoughts?

You are using multilines without -, could that be it?

Does this work?

- | # Test Conditional expression
- [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9
- [[ "${GCC_VER}" == "5" ]] && echo GCC_VER is 5

That one does not work all of these work:

- | # Test Conditional expression
  [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9


- | # Test multiline yaml support
  if [[ "$GCC_VER" == "5" ]]; then
    echo GCC_VER is 5
  else
    echo GCC_VER is not 5
  fi


- | # Test multiline yaml support
  if [[ "$GCC_VER" == "5" ]]; then
    echo "GCC_VER is 5"
  else
    echo "GCC_VER is not 5"
  fi
  if [[ "$GCC_VER" == "4.9" ]]; then
    echo "GCC_VER is 4.9"
  else
    echo "GCC_VER is not 4.9"
  fi

The only ones that don’t work are the Conditional Expressions with more than one, so these two don’t work:

- | # Test Conditional expression
  [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9
  [[ "${GCC_VER}" == "5" ]] && echo GCC_VER is 5

- | # Test Conditional expression
  { [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9 ; }
  { [[ "${GCC_VER}" == "5" ]] && echo GCC_VER is 5 ; }

Feel free to clone my repo or do some experiments on one of your own. All of these pass www.yamllint.com test and are legal bash script so to my mind they all should work

Legal bash, yes, legal yaml…not so sure.

Yes, they pass yaml lint, but as per http://www.yaml.org/spec/1.1/#id868988 both [] and & have very special meanings when it comes to parsing yaml that I’m not sure that yamllint checks for.

The error you get points exactly to the spec being followed exactly, & starts an anchor and expects a name after it, as defined in http://www.yaml.org/spec/1.1/#anchor/syntax

If staff can share what package ‘reader’ comes from we can check the code and the errorred line numbers to see if there’s a bug in the parser, but I don’t think this is a CircleCi issue, it’s either upstream, or a fluke that those other versions work at all :smile:

As a followup, https://yaml-online-parser.appspot.com/ appears to be a much more precise parser, if you set it to conical yaml and feed it your code it throws the same error.

Lets reset the conversation :slight_smile: and simplify things.

First, as you point out, the code below is NOT legal yamal:

- [[ "B" == "B" ]] && echo "B does equal B"

And the error that yaml-online-parser.appspot.com is as you say the &'s

ERROR:

while scanning an anchor
  in "<unicode string>", line 1, column 20:
    - [[ "B" == "B" ]] && echo "B does equal B"
                       ^
expected alphabetic or numeric character, but found '&'
  in "<unicode string>", line 1, column 21:
    - [[ "B" == "B" ]] && echo "B does equal B"
                        ^

But when you introduce a block literal it is legal yamal and legal bash and circleci works just fine.
Here is the github project and here is the test on circleci:

test:
  pre:
    - |
      [[ "B" == "B" ]] && echo "B does equal B"

So the above obviously works is this expected or not?

C[quote=“winksaville, post:11, topic:670”]

  • |
    [[ “B” == “B” ]] && echo “B does equal B”
    [/quote]

    !!seq [
    !!str “[[ “B” == “B” ]] && echo “B does equal B””,
    ]

I’m gonna have to bow out I think, I’m not even close to a yaml expert, and without seeing the parser’s code my head is going to burst. Sorry I wasn’t more help.
I’m going to say yes, since the act of making it a block sequence tells the parser that { does NOT start a flow sequence and so it’s parsed as a string.

ETA: https://circleci.com/gh/drazisil/circleci-with-block-literals/3 appears to work, if you don’t like the block sequence it should probably be placed into a gcc4-9.sh script or something

Found http://stackoverflow.com/a/22483116. Maybe you want a > instead of a pipe?

OMG I screwed up, the two failing cases in this post are properly failing here is the first one:

- | # Test Conditional expression
  [[ "${GCC_VER}" == "4.9" ]] && echo GCC_VER is 4.9
  [[ "${GCC_VER}" == "5" ]] && echo GCC_VER is 5

The reason its failing has nothing to do with being multiple lines, its because [[ "${GCC_VER} == "5" ]] exit status is not zero thus the test fails. Its exit status is not zero because the expression is in fact false.

So bottom line is using block literal’s in circle.yml files work just fine in all cases I’ve tried.

2 Likes

So, not a bug? :slight_smile:

correct, all is well and multiple lines using block literal “|” working well.

2 Likes