Search code examples
github-actions

difference between "run |" and multiple runs in github actions


what is the difference between

steps:
  - name: npm install, build, and test
    run: |
      npm ci
      npm run build --if-present
      npm test

and

steps:
  - name: npm install, build, and test
  - run: npm ci
  - run: npm run build --if-present
  - run: npm test

in github actions? I tried to read the documentation on steps but it does not mention anything like that


Solution

  • Difference is that first example is executed as single script with three commands, and second example is executed as three different one-line scripts (side note: second example is invalid, as you use step with name without run, i'll ignore that line).


    Let's assume for a second that npm does not create any output when running. In first example, if one of commands fails, it might be a problem to identify which one - you have only one step marked as failed. In second example, you'll know exactly where the problem is, as each command is its own step.


    Let's assume for a second that npm needs to be run in specific subdirectory. We need to remember that each steps always starts in workspace directory / repo's root directory, so we need enter directory where our stuff is first.

    - run: |
           cd my/directory
           npm ci
           npm run build --if-present
           npm test
    
    - run: npm ci
      working-directory: my/directory
    - run: npm run build --if-present
      working-directory: my/directory
    - run: npm test
      working-directory: my/directory
    

    OR

    - run: cd my/directory && npm ci
    - run: cd my/directory && npm run build --if-present
    - run: cd my/directory && npm test
    

    Let's assume for a second npm test needs to be run only on push event, but workflow is configured to run on: [push, pull_request]

    - run:   |
             npm ci
             npm run build --if-present
             if [ "${{ github.event_name }}" == "push" ]; then
                npm test
             fi
      shell: bash
    
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test
      if:  github.event_name == 'push'
    

    Under Actions tab, when processing pull_request event, second example will be displayed as...

    - Run npm ci
    - Run npm run build...
    - Run npm test <-- this one will be grayed out
    

    ...and you need only a quick look to see that npm test step is skipped. In first example you'll have to expand step first and inspect log to notice any difference.


    And so on, and so on, there's dozens of scenarios when it's easier/better to use all-in-one step, and as much scenarios when command-by-command steps are the way to go; it's up to you to decide which one fits you best.

    At the end of the day, both examples do exactly same thing, after all. But if anything goes wrong along the way, picking one way to run commands over another (which also changes how they're displayed) can make a difference how long it gonna take to prepare a fix.