Suppose you have a GitHub Action workflow that does some computation and a possible outcome is that file comes into existence. How do you run a follow-up step based on whether a file was created?

tl;dr


- name: Is file created?
  if: ${{ hashFiles('test.txt') != '' }}
  run: echo "File exists"

The "wrong" way

Technically, there's no wrong way, but an alternative might be to rely on exit codes. This would work.


- name: Check if file was created
  run: |
      if [ -f test.txt ]; then
          echo "File exists"
          exit 1
      else
          echo "File does not exist"
      fi
- name: Did the last step fail?
  if: ${{ failure() }}
  run: echo "Last step failed, so file must have maybe been created"

The problem with this is that not only leaves a red ❌ in the workflow logs, but it could also lead to false positives. For example, if the step that might create a file is non-trivial, you don't want to lump the creation of the file with a possible bug in your code.

A use case

What I needed this for was a complex script that was executed to find broken links in a web app. If there were broken links, only then do I want to file a new issue about that. If the script failed for some reason, you want to know that and work on fixing whatever its bug might be. It looked like this:


  - name: Run broken link check
    run: |
      script/check-links.js broken_links.md

  - name: Create issue from file
    if: ${{ hashFiles('broken_links.md') != '' }}
    uses: peter-evans/create-issue-from-file@433e51abf769039ee20ba1293a088ca19d573b7f
    with:
      token: ${{ env.GITHUB_TOKEN }}
      title: More than one zero broken links found
      content-filepath: ./broken_links.md
      repository: ${{ env.REPORT_REPOSITORY }}
      labels: ${{ env.REPORT_LABEL }}

That script/check-links.js script is given an argument which is the name of the file to write to if it did indeed find any broken links. If there were any, it generates a snippet of Markdown about them which is the body of filed new issue.

Demo

To be confident this works, I created a dummy workflow in a test repo to test. It looks like this: .github/workflows/maybe-fail.yml

Comments

eliezer cazares

How to do it for file contains?
In this case, I run automated tests, if the framework fails, I continue the workflow with continue-on-error.

I am trying to send notifications to Slack only on failure.
I can do it on all cases currently, but I want to send the notification only if test reports contain the word Failed at least once.

Thanks

Peter Bengtsson

In the sample code of this blog post it uses:

  script/check-links.js broken_links.md

And that script will create the file if and only if there *are* broken links.
So you can write something similar yourself.
E.g.

    script/did-it-fail.js it-failed.log

But another option is simpler. If the tests failed, that step of the Actions workflow will exit non-zero.
Example https://github.com/github/docs/blob/44d96b002ba8aeb32a33a8b1d31ef7919b09bd5e/.github/workflows/orphaned-assets-check.yml#L71-L78

Your email will never ever be published.

Related posts