docs icon indicating copy to clipboard operation
docs copied to clipboard

Add explanation of ordinal comparison of strings using the `<` and `>` operators

Open norwd opened this issue 1 year ago • 11 comments

The < and > operators, and by extension the <= and >= operators, will behave unexpectedly when evaluating steps.*.outputs.* values, because these values will be compared as strings. So for example '10000' > '2' evaluates to false. This can lead to unexpected behaviour when used in if: ${{ ... }} conditional steps and should be documented.

Why:

The <, >, <=, and >= operators work in an unexpected way (because they evaluate steps.*.outputs.* as strings using JS comparison rules). I can't change how JavaScript defines these operators, and I can't change what language the GitHub Actions backend is written in, but I can document this behaviour and help others avoid falling into the same trap I fell into this morning.

Closes: https://github.com/orgs/community/discussions/57480

What's being changed (if available, include any code snippets, screenshots, or gifs):

image

##[debug]Expanded: (true && ('15' < '9'))
##[debug]Result: true

Check off the following:

  • [x] I have reviewed my changes in staging, available via the View deployment link in this PR's timeline.

    • For content changes, you will also see an automatically generated comment with links directly to pages you've modified. The comment won't appear if your PR only edits files in the data directory.
  • [x] For content changes, I have completed the self-review checklist.

norwd avatar Jun 07 '23 22:06 norwd

Automatically generated comment ℹ️

This comment is automatically generated and will be overwritten every time changes are committed to this branch.

The table contains an overview of files in the content directory that have been changed in this pull request. It's provided to make it easy to review your changes on the staging site. Please note that changes to the data directory will not show up in this table.


Content directory changes

You may find it useful to copy this table into the pull request summary. There you can edit it to share links to important articles or changes and to give a high-level overview of how the changes in your pull request support the overall goals of the pull request.

Source Preview Production What Changed
actions/learn-github-actions/expressions.md fpt
ghec
ghes@ 3.9 3.8 3.7 3.6 3.5
ghae
fpt
ghec
ghes@ 3.9 3.8 3.7 3.6 3.5
ghae

fpt: Free, Pro, Team ghec: GitHub Enterprise Cloud ghes: GitHub Enterprise Server ghae: GitHub AE

github-actions[bot] avatar Jun 07 '23 22:06 github-actions[bot]

@norwd Thanks for submitting a PR! We appreciate the link to the community post and the extra context there ✨

I'll get this triaged for review! :zap:

cmwilson21 avatar Jun 08 '23 14:06 cmwilson21

Also, just a heads up, looking at the local preview link above, the table submitted appears broken. I can't pinpoint where the break is happening, as I copied and pasted the table in a test and it worked there. It's breaking somewhere in my rendering, is it the same for you? 👀

cmwilson21 avatar Jun 08 '23 14:06 cmwilson21

Also, just a heads up, looking at the local preview link above, the table submitted appears broken. I can't pinpoint where the break is happening, as I copied and pasted the table in a test and it worked there. It's breaking somewhere in my rendering, is it the same for you? 👀

@cmwilson21, thanks for catching that, I've pushed a fix. Try again now?

norwd avatar Jun 08 '23 18:06 norwd

@norwd yep! That fixed it! Great catch. Thanks! I missed that line break. 👍

It's up for review so someone will have eyes on it soon 👀

cmwilson21 avatar Jun 09 '23 15:06 cmwilson21

👋 Hello @norwd! Thank you for catching this and for writing this pull request. I'll be happy to review this and help publish some of these updates for our docs as I suspect you're not the only one who has experienced this issue.

I'm wondering if you can provide some workflow runs and outputs that illustrate the ordinal comparison confusions you're referencing. Seeing these in action will help us expedite this review.

Thank you in advance! ✨

jc-clark avatar Jun 13 '23 20:06 jc-clark

👋 Hello @norwd! Thank you for catching this and for writing this pull request. I'll be happy to review this and help publish some of these updates for our docs as I suspect you're not the only one who has experienced this issue.

I'm wondering if you can provide some workflow runs and outputs that illustrate the ordinal comparison confusions you're referencing. Seeing these in action will help us expedite this review.

Thank you in advance! ✨

Hi @jc-clark!

Sure thing, no problem. I've created a test workflow file in my norwd/norwd repo to illustrate both the problem and the workaround.

Here is the workflow file, full text included below: https://github.com/norwd/norwd/blob/eaca46c2674e4d25a6528a9578aed32fdde8d9ac/.github/workflows/github_docs_pull_25870.yml

---

name: "Example Workflow for https://github.com/github/docs/pull/25870"
on: workflow_dispatch
jobs:
  ordinal_comparison:
    runs-on: ubuntu-latest
    steps:
      - id: a
        run: echo "result=5" >> "${GITHUB_OUTPUT}"
      - id: b
        run: echo "result=10" >> "${GITHUB_OUTPUT}"
      - if: steps.a.outputs.result > steps.b.outputs.result
        run: echo "${{ steps.a.outputs.result }} is greater than ${{ steps.b.outputs.result }} (as strings)"
      - if: steps.a.outputs.result < steps.b.outputs.result
        run: echo "${{ steps.a.outputs.result }} is less than ${{ steps.b.outputs.result }} (as strings)"
      - if: fromJSON(steps.a.outputs.result) > fromJSON(steps.b.outputs.result)
        run: echo "${{ steps.a.outputs.result }} is greater than ${{ steps.b.outputs.result }} (as numbers)"
      - if: fromJSON(steps.a.outputs.result) < fromJSON(steps.b.outputs.result)
        run: echo "${{ steps.a.outputs.result }} is less than ${{ steps.b.outputs.result }} (as numbers)"

Here is an example run of this workflow, including a screenshot of the steps that were run and which were skipped: https://github.com/norwd/norwd/actions/runs/5260508350/jobs/9507497069

image

Note that the steps that compare the results directly are comparing strings (as indicated with single quotes, Expanded: (true && ('5' > '10'))) and that using the fromJSON() function is comparing objects (in this case the objects are numeric, Expanded: (true && (5 > 10))). This can be seen in the raw debug logs (included below).

Raw logs
2023-06-13T21:28:37.1826019Z Requested labels: ubuntu-latest
2023-06-13T21:28:37.1826316Z Job defined at: norwd/norwd/.github/workflows/github_docs_pull_25870.yml@refs/heads/main
2023-06-13T21:28:37.1826423Z Waiting for a runner to pick up this job...
2023-06-13T21:28:37.3379429Z Job is waiting for a hosted runner to come online.
2023-06-13T21:28:40.5864127Z Job is about to start running on the hosted runner: GitHub Actions 2 (hosted)
2023-06-13T21:28:43.1946814Z ##[debug]Starting: ordinal_comparison
2023-06-13T21:28:43.1972126Z ##[debug]Cleaning runner temp folder: /home/runner/work/_temp
2023-06-13T21:28:43.2268917Z ##[debug]Starting: Set up job
2023-06-13T21:28:43.2269285Z Current runner version: '2.304.0'
2023-06-13T21:28:43.2291231Z ##[group]Operating System
2023-06-13T21:28:43.2291658Z Ubuntu
2023-06-13T21:28:43.2291872Z 22.04.2
2023-06-13T21:28:43.2292198Z LTS
2023-06-13T21:28:43.2292459Z ##[endgroup]
2023-06-13T21:28:43.2292705Z ##[group]Runner Image
2023-06-13T21:28:43.2293025Z Image: ubuntu-22.04
2023-06-13T21:28:43.2293309Z Version: 20230517.1
2023-06-13T21:28:43.2293741Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20230517.1/images/linux/Ubuntu2204-Readme.md
2023-06-13T21:28:43.2294302Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20230517.1
2023-06-13T21:28:43.2294709Z ##[endgroup]
2023-06-13T21:28:43.2295009Z ##[group]Runner Image Provisioner
2023-06-13T21:28:43.2295264Z 2.0.236.1
2023-06-13T21:28:43.2295741Z ##[endgroup]
2023-06-13T21:28:43.2296604Z ##[group]GITHUB_TOKEN Permissions
2023-06-13T21:28:43.2297749Z Actions: write
2023-06-13T21:28:43.2298044Z Checks: write
2023-06-13T21:28:43.2298364Z Contents: write
2023-06-13T21:28:43.2298696Z Deployments: write
2023-06-13T21:28:43.2299034Z Discussions: write
2023-06-13T21:28:43.2299363Z Issues: write
2023-06-13T21:28:43.2299629Z Metadata: read
2023-06-13T21:28:43.2299943Z Packages: write
2023-06-13T21:28:43.2300255Z Pages: write
2023-06-13T21:28:43.2300651Z PullRequests: write
2023-06-13T21:28:43.2300970Z RepositoryProjects: write
2023-06-13T21:28:43.2301284Z SecurityEvents: write
2023-06-13T21:28:43.2301533Z Statuses: write
2023-06-13T21:28:43.2301819Z ##[endgroup]
2023-06-13T21:28:43.2305237Z Secret source: Actions
2023-06-13T21:28:43.2305703Z ##[debug]Primary repository: norwd/norwd
2023-06-13T21:28:43.2306510Z Prepare workflow directory
2023-06-13T21:28:43.2380207Z ##[debug]Creating pipeline directory: '/home/runner/work/norwd'
2023-06-13T21:28:43.2383007Z ##[debug]Creating workspace directory: '/home/runner/work/norwd/norwd'
2023-06-13T21:28:43.2384475Z ##[debug]Update context data
2023-06-13T21:28:43.2387319Z ##[debug]Evaluating job-level environment variables
2023-06-13T21:28:43.2930594Z ##[debug]Evaluating job container
2023-06-13T21:28:43.2934313Z ##[debug]Evaluating job service containers
2023-06-13T21:28:43.2936837Z ##[debug]Evaluating job defaults
2023-06-13T21:28:43.3011419Z Prepare all required actions
2023-06-13T21:28:43.3270433Z ##[debug]Set step 'a' display name to: 'Run echo "result=5" >> "${GITHUB_OUTPUT}"'
2023-06-13T21:28:43.3272668Z ##[debug]Set step 'b' display name to: 'Run echo "result=10" >> "${GITHUB_OUTPUT}"'
2023-06-13T21:28:43.3453693Z ##[debug]Set step '__run' display name to: 'Run echo "${{ steps.a.outputs.result }} is greater than ${{ steps.b.outputs.result }} (as strings)"'
2023-06-13T21:28:43.3456413Z ##[debug]Set step '__run_2' display name to: 'Run echo "${{ steps.a.outputs.result }} is less than ${{ steps.b.outputs.result }} (as strings)"'
2023-06-13T21:28:43.3458637Z ##[debug]Set step '__run_3' display name to: 'Run echo "${{ steps.a.outputs.result }} is greater than ${{ steps.b.outputs.result }} (as numbers)"'
2023-06-13T21:28:43.3460543Z ##[debug]Set step '__run_4' display name to: 'Run echo "${{ steps.a.outputs.result }} is less than ${{ steps.b.outputs.result }} (as numbers)"'
2023-06-13T21:28:43.3462225Z Complete job name: ordinal_comparison
2023-06-13T21:28:43.3485395Z ##[debug]Collect running processes for tracking orphan processes.
2023-06-13T21:28:43.3698835Z ##[debug]Finishing: Set up job
2023-06-13T21:28:43.3924002Z ##[debug]Evaluating condition for step: 'Run echo "result=5" >> "${GITHUB_OUTPUT}"'
2023-06-13T21:28:43.3964342Z ##[debug]Evaluating: success()
2023-06-13T21:28:43.3971995Z ##[debug]Evaluating success:
2023-06-13T21:28:43.4002797Z ##[debug]=> true
2023-06-13T21:28:43.4011117Z ##[debug]Result: true
2023-06-13T21:28:43.4057337Z ##[debug]Starting: Run echo "result=5" >> "${GITHUB_OUTPUT}"
2023-06-13T21:28:43.4387044Z ##[debug]Loading inputs
2023-06-13T21:28:43.4422083Z ##[debug]Loading env
2023-06-13T21:28:43.4516649Z ##[group]Run echo "result=5" >> "${GITHUB_OUTPUT}"
2023-06-13T21:28:43.4517030Z [36;1mecho "result=5" >> "${GITHUB_OUTPUT}"[0m
2023-06-13T21:28:43.5191700Z shell: /usr/bin/bash -e {0}
2023-06-13T21:28:43.5192100Z ##[endgroup]
2023-06-13T21:28:43.5346053Z ##[debug]/usr/bin/bash -e /home/runner/work/_temp/fa0ddde8-01ba-46c2-a151-236b17fc845f.sh
2023-06-13T21:28:43.5844918Z ##[debug]Set output result = 5
2023-06-13T21:28:43.5859330Z ##[debug]Finishing: Run echo "result=5" >> "${GITHUB_OUTPUT}"
2023-06-13T21:28:43.5872804Z ##[debug]Evaluating condition for step: 'Run echo "result=10" >> "${GITHUB_OUTPUT}"'
2023-06-13T21:28:43.5875193Z ##[debug]Evaluating: success()
2023-06-13T21:28:43.5875746Z ##[debug]Evaluating success:
2023-06-13T21:28:43.5876401Z ##[debug]=> true
2023-06-13T21:28:43.5876940Z ##[debug]Result: true
2023-06-13T21:28:43.5877862Z ##[debug]Starting: Run echo "result=10" >> "${GITHUB_OUTPUT}"
2023-06-13T21:28:43.5887687Z ##[debug]Loading inputs
2023-06-13T21:28:43.5888734Z ##[debug]Loading env
2023-06-13T21:28:43.5895441Z ##[group]Run echo "result=10" >> "${GITHUB_OUTPUT}"
2023-06-13T21:28:43.5895940Z [36;1mecho "result=10" >> "${GITHUB_OUTPUT}"[0m
2023-06-13T21:28:43.6076475Z shell: /usr/bin/bash -e {0}
2023-06-13T21:28:43.6076811Z ##[endgroup]
2023-06-13T21:28:43.6127451Z ##[debug]/usr/bin/bash -e /home/runner/work/_temp/3f7d53ef-8480-4122-b3e8-fa6a61451333.sh
2023-06-13T21:28:43.6338325Z ##[debug]Set output result = 10
2023-06-13T21:28:43.6339870Z ##[debug]Finishing: Run echo "result=10" >> "${GITHUB_OUTPUT}"
2023-06-13T21:28:43.6350106Z ##[debug]Evaluating condition for step: 'Run echo "${{ steps.a.outputs.result }} is greater than ${{ steps.b.outputs.result }} (as strings)"'
2023-06-13T21:28:43.6361517Z ##[debug]Evaluating: format('echo "{0} is greater than {1} (as strings)"', steps.a.outputs.result, steps.b.outputs.result)
2023-06-13T21:28:43.6363713Z ##[debug]Evaluating format:
2023-06-13T21:28:43.6396820Z ##[debug]..Evaluating String:
2023-06-13T21:28:43.6397849Z ##[debug]..=> 'echo "{0} is greater than {1} (as strings)"'
2023-06-13T21:28:43.6426536Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6428305Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6428582Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6428844Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6429674Z ##[debug]........=> Object
2023-06-13T21:28:43.6441759Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6442039Z ##[debug]........=> 'a'
2023-06-13T21:28:43.6444173Z ##[debug]......=> Object
2023-06-13T21:28:43.6444667Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6444934Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6445216Z ##[debug]....=> Object
2023-06-13T21:28:43.6445464Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6445700Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6446140Z ##[debug]..=> '5'
2023-06-13T21:28:43.6447039Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6447316Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6447572Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6447814Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6448062Z ##[debug]........=> Object
2023-06-13T21:28:43.6448308Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6448547Z ##[debug]........=> 'b'
2023-06-13T21:28:43.6448771Z ##[debug]......=> Object
2023-06-13T21:28:43.6449011Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6449251Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6449469Z ##[debug]....=> Object
2023-06-13T21:28:43.6449695Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6449930Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6450197Z ##[debug]..=> '10'
2023-06-13T21:28:43.6450555Z ##[debug]=> 'echo "5 is greater than 10 (as strings)"'
2023-06-13T21:28:43.6450937Z ##[debug]Result: 'echo "5 is greater than 10 (as strings)"'
2023-06-13T21:28:43.6451511Z ##[debug]Set step '__run' display name to: 'Run echo "5 is greater than 10 (as strings)"'
2023-06-13T21:28:43.6468260Z ##[debug]Evaluating: (success() && (steps.a.outputs.result > steps.b.outputs.result))
2023-06-13T21:28:43.6468839Z ##[debug]Evaluating And:
2023-06-13T21:28:43.6473656Z ##[debug]..Evaluating success:
2023-06-13T21:28:43.6474494Z ##[debug]..=> true
2023-06-13T21:28:43.6475044Z ##[debug]..Evaluating GreaterThan:
2023-06-13T21:28:43.6476830Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6477303Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6477779Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6478251Z ##[debug]..........Evaluating steps:
2023-06-13T21:28:43.6478743Z ##[debug]..........=> Object
2023-06-13T21:28:43.6479208Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6479638Z ##[debug]..........=> 'a'
2023-06-13T21:28:43.6480062Z ##[debug]........=> Object
2023-06-13T21:28:43.6480513Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6480962Z ##[debug]........=> 'outputs'
2023-06-13T21:28:43.6481367Z ##[debug]......=> Object
2023-06-13T21:28:43.6481851Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6482269Z ##[debug]......=> 'result'
2023-06-13T21:28:43.6482680Z ##[debug]....=> '5'
2023-06-13T21:28:43.6483127Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6483598Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6484063Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6484520Z ##[debug]..........Evaluating steps:
2023-06-13T21:28:43.6484956Z ##[debug]..........=> Object
2023-06-13T21:28:43.6485403Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6485825Z ##[debug]..........=> 'b'
2023-06-13T21:28:43.6486227Z ##[debug]........=> Object
2023-06-13T21:28:43.6486996Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6487443Z ##[debug]........=> 'outputs'
2023-06-13T21:28:43.6487855Z ##[debug]......=> Object
2023-06-13T21:28:43.6488302Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6488723Z ##[debug]......=> 'result'
2023-06-13T21:28:43.6489123Z ##[debug]....=> '10'
2023-06-13T21:28:43.6493997Z ##[debug]..=> true
2023-06-13T21:28:43.6494659Z ##[debug]=> true
2023-06-13T21:28:43.6499909Z ##[debug]Expanded: (true && ('5' > '10'))
2023-06-13T21:28:43.6500382Z ##[debug]Result: true
2023-06-13T21:28:43.6501009Z ##[debug]Starting: Run echo "5 is greater than 10 (as strings)"
2023-06-13T21:28:43.6508537Z ##[debug]Loading inputs
2023-06-13T21:28:43.6512596Z ##[debug]Evaluating: format('echo "{0} is greater than {1} (as strings)"', steps.a.outputs.result, steps.b.outputs.result)
2023-06-13T21:28:43.6513164Z ##[debug]Evaluating format:
2023-06-13T21:28:43.6513498Z ##[debug]..Evaluating String:
2023-06-13T21:28:43.6513918Z ##[debug]..=> 'echo "{0} is greater than {1} (as strings)"'
2023-06-13T21:28:43.6514359Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6514703Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6515029Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6515383Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6515736Z ##[debug]........=> Object
2023-06-13T21:28:43.6516086Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6516398Z ##[debug]........=> 'a'
2023-06-13T21:28:43.6516712Z ##[debug]......=> Object
2023-06-13T21:28:43.6517039Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6517358Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6517649Z ##[debug]....=> Object
2023-06-13T21:28:43.6517963Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6518276Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6518565Z ##[debug]..=> '5'
2023-06-13T21:28:43.6518870Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6519191Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6519517Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6519850Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6520161Z ##[debug]........=> Object
2023-06-13T21:28:43.6520486Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6520808Z ##[debug]........=> 'b'
2023-06-13T21:28:43.6521104Z ##[debug]......=> Object
2023-06-13T21:28:43.6521414Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6522068Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6522341Z ##[debug]....=> Object
2023-06-13T21:28:43.6522627Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6522895Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6523261Z ##[debug]..=> '10'
2023-06-13T21:28:43.6523549Z ##[debug]=> 'echo "5 is greater than 10 (as strings)"'
2023-06-13T21:28:43.6523881Z ##[debug]Result: 'echo "5 is greater than 10 (as strings)"'
2023-06-13T21:28:43.6524262Z ##[debug]Loading env
2023-06-13T21:28:43.6528426Z ##[group]Run echo "5 is greater than 10 (as strings)"
2023-06-13T21:28:43.6528734Z [36;1mecho "5 is greater than 10 (as strings)"[0m
2023-06-13T21:28:43.6569953Z shell: /usr/bin/bash -e {0}
2023-06-13T21:28:43.6570238Z ##[endgroup]
2023-06-13T21:28:43.6622822Z ##[debug]/usr/bin/bash -e /home/runner/work/_temp/7a79b1bf-656f-4371-806a-c65fd2413df7.sh
2023-06-13T21:28:43.6710090Z 5 is greater than 10 (as strings)
2023-06-13T21:28:43.6712695Z ##[debug]Finishing: Run echo "5 is greater than 10 (as strings)"
2023-06-13T21:28:43.6717942Z ##[debug]Evaluating condition for step: 'Run echo "${{ steps.a.outputs.result }} is less than ${{ steps.b.outputs.result }} (as strings)"'
2023-06-13T21:28:43.6719514Z ##[debug]Evaluating: format('echo "{0} is less than {1} (as strings)"', steps.a.outputs.result, steps.b.outputs.result)
2023-06-13T21:28:43.6719977Z ##[debug]Evaluating format:
2023-06-13T21:28:43.6720275Z ##[debug]..Evaluating String:
2023-06-13T21:28:43.6720615Z ##[debug]..=> 'echo "{0} is less than {1} (as strings)"'
2023-06-13T21:28:43.6720984Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6721355Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6721614Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6721878Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6722121Z ##[debug]........=> Object
2023-06-13T21:28:43.6722378Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6722624Z ##[debug]........=> 'a'
2023-06-13T21:28:43.6722860Z ##[debug]......=> Object
2023-06-13T21:28:43.6723144Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6723401Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6723622Z ##[debug]....=> Object
2023-06-13T21:28:43.6723867Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6724108Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6724325Z ##[debug]..=> '5'
2023-06-13T21:28:43.6724576Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6724838Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6725092Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6725341Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6725590Z ##[debug]........=> Object
2023-06-13T21:28:43.6725842Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6726093Z ##[debug]........=> 'b'
2023-06-13T21:28:43.6726312Z ##[debug]......=> Object
2023-06-13T21:28:43.6726560Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6726803Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6727034Z ##[debug]....=> Object
2023-06-13T21:28:43.6727265Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6727516Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6727744Z ##[debug]..=> '10'
2023-06-13T21:28:43.6728024Z ##[debug]=> 'echo "5 is less than 10 (as strings)"'
2023-06-13T21:28:43.6728338Z ##[debug]Result: 'echo "5 is less than 10 (as strings)"'
2023-06-13T21:28:43.6728878Z ##[debug]Set step '__run_2' display name to: 'Run echo "5 is less than 10 (as strings)"'
2023-06-13T21:28:43.6732389Z ##[debug]Evaluating: (success() && (steps.a.outputs.result  true
2023-06-13T21:28:43.6734187Z ##[debug]..Evaluating LessThan:
2023-06-13T21:28:43.6735749Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6736161Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6736554Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6737162Z ##[debug]..........Evaluating steps:
2023-06-13T21:28:43.6737558Z ##[debug]..........=> Object
2023-06-13T21:28:43.6738191Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6738571Z ##[debug]..........=> 'a'
2023-06-13T21:28:43.6738922Z ##[debug]........=> Object
2023-06-13T21:28:43.6739309Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6739666Z ##[debug]........=> 'outputs'
2023-06-13T21:28:43.6740020Z ##[debug]......=> Object
2023-06-13T21:28:43.6740426Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6740772Z ##[debug]......=> 'result'
2023-06-13T21:28:43.6741113Z ##[debug]....=> '5'
2023-06-13T21:28:43.6741488Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6741881Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6742264Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6742668Z ##[debug]..........Evaluating steps:
2023-06-13T21:28:43.6743111Z ##[debug]..........=> Object
2023-06-13T21:28:43.6743434Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6743755Z ##[debug]..........=> 'b'
2023-06-13T21:28:43.6744042Z ##[debug]........=> Object
2023-06-13T21:28:43.6744532Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6744848Z ##[debug]........=> 'outputs'
2023-06-13T21:28:43.6745155Z ##[debug]......=> Object
2023-06-13T21:28:43.6745480Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6745795Z ##[debug]......=> 'result'
2023-06-13T21:28:43.6746094Z ##[debug]....=> '10'
2023-06-13T21:28:43.6748101Z ##[debug]..=> false
2023-06-13T21:28:43.6748591Z ##[debug]=> false
2023-06-13T21:28:43.6750571Z ##[debug]Expanded: (true && ('5'  'echo "{0} is greater than {1} (as numbers)"'
2023-06-13T21:28:43.6757943Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6758257Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6758557Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6758860Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6759163Z ##[debug]........=> Object
2023-06-13T21:28:43.6759447Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6759733Z ##[debug]........=> 'a'
2023-06-13T21:28:43.6760002Z ##[debug]......=> Object
2023-06-13T21:28:43.6760321Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6760699Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6760926Z ##[debug]....=> Object
2023-06-13T21:28:43.6761168Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6761410Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6761624Z ##[debug]..=> '5'
2023-06-13T21:28:43.6761872Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6762132Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6762386Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6762639Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6762885Z ##[debug]........=> Object
2023-06-13T21:28:43.6763134Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6763378Z ##[debug]........=> 'b'
2023-06-13T21:28:43.6763596Z ##[debug]......=> Object
2023-06-13T21:28:43.6763843Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6764090Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6764335Z ##[debug]....=> Object
2023-06-13T21:28:43.6764717Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6764983Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6765213Z ##[debug]..=> '10'
2023-06-13T21:28:43.6765501Z ##[debug]=> 'echo "5 is greater than 10 (as numbers)"'
2023-06-13T21:28:43.6765838Z ##[debug]Result: 'echo "5 is greater than 10 (as numbers)"'
2023-06-13T21:28:43.6766393Z ##[debug]Set step '__run_3' display name to: 'Run echo "5 is greater than 10 (as numbers)"'
2023-06-13T21:28:43.6768899Z ##[debug]Evaluating: (success() && (fromJSON(steps.a.outputs.result) > fromJSON(steps.b.outputs.result)))
2023-06-13T21:28:43.6769526Z ##[debug]Evaluating And:
2023-06-13T21:28:43.6769867Z ##[debug]..Evaluating success:
2023-06-13T21:28:43.6770225Z ##[debug]..=> true
2023-06-13T21:28:43.6770581Z ##[debug]..Evaluating GreaterThan:
2023-06-13T21:28:43.6770951Z ##[debug]....Evaluating fromJSON:
2023-06-13T21:28:43.6773210Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6773581Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6773922Z ##[debug]..........Evaluating Index:
2023-06-13T21:28:43.6774300Z ##[debug]............Evaluating steps:
2023-06-13T21:28:43.6774647Z ##[debug]............=> Object
2023-06-13T21:28:43.6775010Z ##[debug]............Evaluating String:
2023-06-13T21:28:43.6775322Z ##[debug]............=> 'a'
2023-06-13T21:28:43.6775652Z ##[debug]..........=> Object
2023-06-13T21:28:43.6776001Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6776320Z ##[debug]..........=> 'outputs'
2023-06-13T21:28:43.6776632Z ##[debug]........=> Object
2023-06-13T21:28:43.6777131Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6777461Z ##[debug]........=> 'result'
2023-06-13T21:28:43.6777760Z ##[debug]......=> '5'
2023-06-13T21:28:43.6796426Z ##[debug]....=> 5
2023-06-13T21:28:43.6796817Z ##[debug]....Evaluating fromJSON:
2023-06-13T21:28:43.6797175Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6797530Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6798020Z ##[debug]..........Evaluating Index:
2023-06-13T21:28:43.6798474Z ##[debug]............Evaluating steps:
2023-06-13T21:28:43.6799050Z ##[debug]............=> Object
2023-06-13T21:28:43.6799416Z ##[debug]............Evaluating String:
2023-06-13T21:28:43.6799740Z ##[debug]............=> 'b'
2023-06-13T21:28:43.6800048Z ##[debug]..........=> Object
2023-06-13T21:28:43.6800384Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6800689Z ##[debug]..........=> 'outputs'
2023-06-13T21:28:43.6800985Z ##[debug]........=> Object
2023-06-13T21:28:43.6801303Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6801623Z ##[debug]........=> 'result'
2023-06-13T21:28:43.6801911Z ##[debug]......=> '10'
2023-06-13T21:28:43.6802444Z ##[debug]....=> 10
2023-06-13T21:28:43.6802733Z ##[debug]..=> false
2023-06-13T21:28:43.6803001Z ##[debug]=> false
2023-06-13T21:28:43.6803516Z ##[debug]Expanded: (true && (5 > 10))
2023-06-13T21:28:43.6803889Z ##[debug]Result: false
2023-06-13T21:28:43.6808541Z ##[debug]Evaluating condition for step: 'Run echo "${{ steps.a.outputs.result }} is less than ${{ steps.b.outputs.result }} (as numbers)"'
2023-06-13T21:28:43.6810290Z ##[debug]Evaluating: format('echo "{0} is less than {1} (as numbers)"', steps.a.outputs.result, steps.b.outputs.result)
2023-06-13T21:28:43.6810846Z ##[debug]Evaluating format:
2023-06-13T21:28:43.6811198Z ##[debug]..Evaluating String:
2023-06-13T21:28:43.6811598Z ##[debug]..=> 'echo "{0} is less than {1} (as numbers)"'
2023-06-13T21:28:43.6812040Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6812394Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6812765Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6813115Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6813470Z ##[debug]........=> Object
2023-06-13T21:28:43.6813825Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6814169Z ##[debug]........=> 'a'
2023-06-13T21:28:43.6814484Z ##[debug]......=> Object
2023-06-13T21:28:43.6814877Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6815221Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6815536Z ##[debug]....=> Object
2023-06-13T21:28:43.6815866Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6816193Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6816490Z ##[debug]..=> '5'
2023-06-13T21:28:43.6816825Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6817756Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6818003Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6818249Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6818503Z ##[debug]........=> Object
2023-06-13T21:28:43.6818755Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6819181Z ##[debug]........=> 'b'
2023-06-13T21:28:43.6819401Z ##[debug]......=> Object
2023-06-13T21:28:43.6819645Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6819884Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6820114Z ##[debug]....=> Object
2023-06-13T21:28:43.6820344Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6820588Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6820812Z ##[debug]..=> '10'
2023-06-13T21:28:43.6821099Z ##[debug]=> 'echo "5 is less than 10 (as numbers)"'
2023-06-13T21:28:43.6821411Z ##[debug]Result: 'echo "5 is less than 10 (as numbers)"'
2023-06-13T21:28:43.6821957Z ##[debug]Set step '__run_4' display name to: 'Run echo "5 is less than 10 (as numbers)"'
2023-06-13T21:28:43.6823582Z ##[debug]Evaluating: (success() && (fromJSON(steps.a.outputs.result)  true
2023-06-13T21:28:43.6825038Z ##[debug]..Evaluating LessThan:
2023-06-13T21:28:43.6825394Z ##[debug]....Evaluating fromJSON:
2023-06-13T21:28:43.6825737Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6826086Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6826424Z ##[debug]..........Evaluating Index:
2023-06-13T21:28:43.6826786Z ##[debug]............Evaluating steps:
2023-06-13T21:28:43.6827106Z ##[debug]............=> Object
2023-06-13T21:28:43.6827448Z ##[debug]............Evaluating String:
2023-06-13T21:28:43.6827756Z ##[debug]............=> 'a'
2023-06-13T21:28:43.6828059Z ##[debug]..........=> Object
2023-06-13T21:28:43.6828386Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6828702Z ##[debug]..........=> 'outputs'
2023-06-13T21:28:43.6828994Z ##[debug]........=> Object
2023-06-13T21:28:43.6829311Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6829617Z ##[debug]........=> 'result'
2023-06-13T21:28:43.6829896Z ##[debug]......=> '5'
2023-06-13T21:28:43.6830253Z ##[debug]....=> 5
2023-06-13T21:28:43.6830583Z ##[debug]....Evaluating fromJSON:
2023-06-13T21:28:43.6830960Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6831296Z ##[debug]........Evaluating Index:
2023-06-13T21:28:43.6831627Z ##[debug]..........Evaluating Index:
2023-06-13T21:28:43.6831979Z ##[debug]............Evaluating steps:
2023-06-13T21:28:43.6832465Z ##[debug]............=> Object
2023-06-13T21:28:43.6832817Z ##[debug]............Evaluating String:
2023-06-13T21:28:43.6833127Z ##[debug]............=> 'b'
2023-06-13T21:28:43.6833432Z ##[debug]..........=> Object
2023-06-13T21:28:43.6833762Z ##[debug]..........Evaluating String:
2023-06-13T21:28:43.6834089Z ##[debug]..........=> 'outputs'
2023-06-13T21:28:43.6834395Z ##[debug]........=> Object
2023-06-13T21:28:43.6834716Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6835034Z ##[debug]........=> 'result'
2023-06-13T21:28:43.6835319Z ##[debug]......=> '10'
2023-06-13T21:28:43.6835648Z ##[debug]....=> 10
2023-06-13T21:28:43.6835947Z ##[debug]..=> true
2023-06-13T21:28:43.6836218Z ##[debug]=> true
2023-06-13T21:28:43.6836690Z ##[debug]Expanded: (true && (5  'echo "{0} is less than {1} (as numbers)"'
2023-06-13T21:28:43.6847203Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6847541Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6847866Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6848211Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6848541Z ##[debug]........=> Object
2023-06-13T21:28:43.6848879Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6849357Z ##[debug]........=> 'a'
2023-06-13T21:28:43.6849665Z ##[debug]......=> Object
2023-06-13T21:28:43.6849989Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6850312Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6850605Z ##[debug]....=> Object
2023-06-13T21:28:43.6850922Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6851243Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6851539Z ##[debug]..=> '5'
2023-06-13T21:28:43.6851854Z ##[debug]..Evaluating Index:
2023-06-13T21:28:43.6852190Z ##[debug]....Evaluating Index:
2023-06-13T21:28:43.6852521Z ##[debug]......Evaluating Index:
2023-06-13T21:28:43.6852846Z ##[debug]........Evaluating steps:
2023-06-13T21:28:43.6853171Z ##[debug]........=> Object
2023-06-13T21:28:43.6853496Z ##[debug]........Evaluating String:
2023-06-13T21:28:43.6853814Z ##[debug]........=> 'b'
2023-06-13T21:28:43.6854096Z ##[debug]......=> Object
2023-06-13T21:28:43.6854421Z ##[debug]......Evaluating String:
2023-06-13T21:28:43.6854745Z ##[debug]......=> 'outputs'
2023-06-13T21:28:43.6855047Z ##[debug]....=> Object
2023-06-13T21:28:43.6855346Z ##[debug]....Evaluating String:
2023-06-13T21:28:43.6855747Z ##[debug]....=> 'result'
2023-06-13T21:28:43.6856006Z ##[debug]..=> '10'
2023-06-13T21:28:43.6856326Z ##[debug]=> 'echo "5 is less than 10 (as numbers)"'
2023-06-13T21:28:43.6856700Z ##[debug]Result: 'echo "5 is less than 10 (as numbers)"'
2023-06-13T21:28:43.6857549Z ##[debug]Loading env
2023-06-13T21:28:43.6861850Z ##[group]Run echo "5 is less than 10 (as numbers)"
2023-06-13T21:28:43.6862145Z [36;1mecho "5 is less than 10 (as numbers)"[0m
2023-06-13T21:28:43.6906441Z shell: /usr/bin/bash -e {0}
2023-06-13T21:28:43.6906685Z ##[endgroup]
2023-06-13T21:28:43.6951087Z ##[debug]/usr/bin/bash -e /home/runner/work/_temp/103aa898-3783-4d28-a142-3507d54934df.sh
2023-06-13T21:28:43.6974924Z 5 is less than 10 (as numbers)
2023-06-13T21:28:43.6979456Z ##[debug]Finishing: Run echo "5 is less than 10 (as numbers)"
2023-06-13T21:28:43.7084915Z ##[debug]Starting: Complete job
2023-06-13T21:28:43.7087101Z Uploading runner diagnostic logs
2023-06-13T21:28:43.7140512Z ##[debug]Starting diagnostic file upload.
2023-06-13T21:28:43.7140853Z ##[debug]Setting up diagnostic log folders.
2023-06-13T21:28:43.7142669Z ##[debug]Creating diagnostic log files folder.
2023-06-13T21:28:43.7159645Z ##[debug]Copying 1 worker diagnostic logs.
2023-06-13T21:28:43.7180515Z ##[debug]Copying 1 runner diagnostic logs.
2023-06-13T21:28:43.7182160Z ##[debug]Zipping diagnostic files.
2023-06-13T21:28:43.7226092Z ##[debug]Uploading diagnostic metadata file.
2023-06-13T21:28:43.7251378Z ##[debug]Diagnostic file upload complete.
2023-06-13T21:28:43.7252280Z Completed runner diagnostic log upload
2023-06-13T21:28:43.7252640Z Cleaning up orphan processes
2023-06-13T21:28:43.7473788Z ##[debug]Finishing: Complete job
2023-06-13T21:28:43.7607933Z ##[debug]Finishing: ordinal_comparison

norwd avatar Jun 13 '23 21:06 norwd

Thanks for all the context @norwd! This is super helpful.

I have a couple follow up questions. Will the comparison operators only behave unexpectedly when evaluating steps.*.outputs.* values using the outputs context? Or is this something that only happens in the scenario you described?

This can lead to unexpected behaviour when used in if: ${{ ... }} conditional steps and should be documented.

jc-clark avatar Jun 16 '23 23:06 jc-clark

Thanks for all the context @norwd! This is super helpful.

I have a couple follow up questions. Will the comparison operators only behave unexpectedly when evaluating steps.*.outputs.* values using the outputs context? Or is this something that only happens in the scenario you described?

This can lead to unexpected behaviour when used in if: ${{ ... }} conditional steps and should be documented.

I've also noticed that composite actions will convert their outputs to strings even if using the fromJSON() when setting the output. Same goes for job outputs, it looks like all data being passed around in ${{ ... }} contexts are evaluated as strings even if they were converted to numbers previously.

norwd avatar Jun 16 '23 23:06 norwd

Hi @jc-clark, do you need any more information or is there anything I can add to the documentation itself?

norwd avatar Jun 23 '23 02:06 norwd

Hey @norwd thank you for your patience on this one. We're currently working out the best direction based on what you said.

Same goes for job outputs, it looks like all data being passed around in ${{ ... }} contexts are evaluated as strings even if they were converted to numbers previously.

This is helpful and gives us some good information to work with. I'll be able to help address this one as soon as I can.

jc-clark avatar Jun 23 '23 19:06 jc-clark

Taking a closer look at this one @norwd. As I've been studying contexts a bit more, I see that we do document how contexts are evaluated within the ${{ ... }} brackets.

The steps context for example, lists that steps.<step_id>.outputs.<output_name> evaluates as a string. However steps.<step_id>.outputs evaluates as an object. The docs list various contexts and the data types they evaluate to.

And over in, About expressions mentions:

You need to use specific syntax to tell GitHub to evaluate an expression rather than treat it as a string.

${{ <expression> }}

When you use expressions in an if conditional, you may omit the expression syntax (${{ }}) because GitHub automatically evaluates the if conditional as an expression. For more information about if conditionals, see "Workflow syntax for GitHub Actions."

So I think the right information is documented, but I also think it's a a bit too easy to overlook especially when seeking information on operators specifically. There's nothing within the operators headers that might indicate string evaluation for expressions.

I think it's easy to miss this information, especially if you jump right into the operators documentation. We've found a lot of folks who read the docs jump right to the section they need and it can be easy to miss information further up in an "About" header.

With all this in mind, I'm wondering if we just need to make this information more visible in the docs using a note callout.

What do you think about, instead of diving into the nitty-gritty of the way GitHub would evaluate ASCII hex representations of strings, we figure out a way to make it much more apparent in the relevant sections of the docs that specific syntax is needed to avoid evaluating expressions as strings?

jc-clark avatar Jun 26 '23 23:06 jc-clark

The steps context for example, lists that steps.<step_id>.outputs.<output_name> evaluates as a string. However steps.<step_id>.outputs evaluates as an object. The docs list various contexts and the data types they evaluate to.

Thanks for the reply @jc-clark 🙂, I'm glad that this behaviour is not only known but documented.

What would be a good approach here then? You're right that a table giving examples with the ASCII values is a little too dense, do you think that a simple footnote would suffice here? I think it is quite important to also provide an indication of how to access the actual values directly, i.e. using the fromJSON(...) function, if there's only a footnote I'm worried that the information might not be obvious enough and that readers won't see this information unless they know to click on a little [1] supertext.

Maybe instead of adding an entire new table, the existing table can have a new row added at the bottom that describes the behaviour?

  • GitHub ignores case when comparing strings.
  • Objects and arrays are only considered equal when they are the same instance.
  • ${{ steps.<step_id>.outputs.<output_name> }} values are treated as strings, for numerical comparison, the fromJSON(...) function can be used to convert the string '5' to the number 5.

norwd avatar Jun 27 '23 01:06 norwd

Great questions, @norwd! And I'm glad you agree. This has been a good learning project for me to understand how expressions in Actions get evaluated. So thank you for working with me here.

I think we could get more visibility to the important information here using a note callout. What do you think about the following changes?

(These steps will move existing content into a reusable file so it can be repeated throughout the docs wherever the information is appropriate)

  • [ ] Cut "You need to use specific syntax to tell {% data variables.product.prodname_dotcom %} to evaluate an expression rather than treat it as a string." from the beginning of "Expressions" and paste that content into a new reusable file in /data/reusables/actions called expressions-syntax-evaluation.md. The full file path would be https://github.com/github/docs/tree/main/data/reusables/actions/expressions-syntax-evaluation.md

  • [ ] In "Expressions," add this tag under the "About expressions" header where the content used to be: {% data reusables.actions.expressions-syntax-evaluation %}

  • [ ] In "Expressions" replace the ASCII table you're currently suggesting with the following note callout.

{% note %}

**Notes:**
- {% data variables.product.company_short %} ignores case when comparing strings.
- `steps.<step_id>.outputs.<output_name>` evaluates as a string. {% data reusables.actions.expressions-syntax-evaluation %} For more information, see "[AUTOTITLE](/actions/learn-github-actions/contexts#steps-context)."
- {% data reusables.actions.expression-syntax-if %} For more information about `if` conditionals, see "[AUTOTITLE](/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idif)."
- For numerical comparison, the `fromJSON()` function can be used to convert a string to a number. For more information on the `fromJSON()` function, see "[fromJSON](#fromjson)."

{% endnote %}

jc-clark avatar Jun 27 '23 21:06 jc-clark

I've gone ahead and made your suggested changes, @jc-clark, thanks for walking me through the reusable content steps!

norwd avatar Jun 27 '23 22:06 norwd

Sorry @jc-clark, I missed that last note, I've applied your suggestion 👍

norwd avatar Jun 28 '23 00:06 norwd

Thanks very much for contributing! Your pull request has been merged 🎉 You should see your changes appear on the site in approximately 24 hours. If you're looking for your next contribution, check out our help wanted issues :zap:

github-actions[bot] avatar Jun 28 '23 19:06 github-actions[bot]