Yesterday, I shared a tip on a two-stage GitHub Action that was running on the "wrong" branch.
The solution involved looking at a different field in the event payload to get the branch that triggered the workflow_run
event,
but I didn't tell the whole story.
In that second workflow, we also had a way to manually trigger the deploy
workflow, which happens with the workflow_dispatch
event.
Because these two events have two different payloads, I needed a more complex if
check to decide whether to deploy to staging or production.
Here's what the first version of the if
check looked like:
- name: Deploy to staging if develop branch
if: |
${{
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/develop') ||
(github.event.name == 'workflow_run' && github.event.workflow_run.head_branch == 'develop')
}}
run: some-deploy-command-here
I then had a similar block after this that would deploy to production if the branch was main
, with the same multi-line if
condition.
But when I tried this out, I noticed that it was always deploying to both staging and production for every run. Clearly something was wrong with my logic, but what was it?
It's a mix of how YAML handles multi-line strings and whitespace, and how GitHub Actions parses expressions.
When you split a string across multiple lines, YAML preserves the line breaks in the resulting string.
Normally this wouldn't matter, but we're also using the ${{ expression }}
syntax that GitHub Actions provides.
Because I had a line break inside the expression, it was evaluating that as a string literal, causing my check which I intended to resolve to true
or false
to actually resolve to a multi-line string 'false\n'
.
And GitHub happily considered this multi-line string to be "truthy", so my if
check was always passing.
The solution was to avoid using the ${{ expression }}
syntax altogether.
In this particular case, GitHub already evaluates the if
condition as an expression.
So by eliminating expression evaluation, I was left with a pure boolean check, and now my logic works as expected.
Here to help,
Joel
P.S. As developers, we run into weird problems like this all the time. That's why it's a good thing we don't charge by the hour when we work with clients.