Search code examples
githubcontinuous-integrationyamlworkflowgithub-actions

How to run a script at the end of a job, even if the job was cancelled?


This is the workflow I'm currently using on GitHub

name: Windows10 - CI
on: [ push ]
jobs:
  run-test:
    runs-on: [ self-hosted, windows, DO ]
    steps:
      - uses: actions/checkout@v2
        with:
          clean: false

      - name: Run nds2 CI - Sanity Test
        if: github.ref == 'refs/heads/master'
        run: cd c:\actions-runner\_work\nds2\nds2 ; python3 ci_host.py --master

      - name: Run nds2 CI - Build Installer
        if: github.ref != 'refs/heads/master'
        run: cd c:\actions-runner\_work\nds2\nds2 ; python3 ci_host.py

I have a windows 10 computer which listens for an incoming job by using the GitHub runner. Upon an incoming job, if a push is being made to the master branch the script ci_host.py is being run with the '--master' flag which spins up a VM and runs multiple tests on it. Eventually, at the end of the tests, the script restores the VM to a pre-configured snap shot.

So basically what I'm trying to achieve is, when the job is being canceled through the GitHub actions web interface then the script which handles the test is being canceled mid-job and doesn't have the chance to restore the VM to its prior clean state (snapshot).

How can I run a script which will be run at the end of the workflow even if the job was canceled? So no matter what happens my VM could be restored to its clean state

Thanks in advance for your help :)


Solution

  • You can use status check functions to execute a step depending on what happened on the job before it (or not):

    • success: Returns true when none of the previous steps have failed or been canceled.

    • always: Always returns true, even when canceled. A job or step will not run when a critical failure prevents the task from running. For example, if getting sources failed.

    • cancelled: Returns true if the workflow was canceled.

    • failure: Returns true when any previous step of a job fails.

    Example of use:

    steps:
      - name: Execute if the job succeeded
        if: ${{ success() }}
      
      - name: Execute if the job failed
        if: ${{ failure() }}
      
      - name: Execute if the job was cancelled
        if: ${{ cancelled() }}
      
      - name: Always execute
        if: ${{ always() }}