40

I'm using Gitlab CI, and so have been working on a fairly complex .gitlab-ci.yml file. The file has an after_script section which runs when the main task is complete, or the main task has failed somehow. Problem: I need to do different cleanup based on whether the main task succeeded or failed, but I can't find any Gitlab CI variable that indicates the result of the main task.

How can I tell, inside the after_script section, whether the main task has succeeded or failed?

Daniel Griscom
  • 1,834
  • 2
  • 26
  • 50
  • So are you referring to conditional `after_script` or you are referring to result of the main task. You can consider storing the result into a variable. https://docs.gitlab.com/ee/ci/variables/README.html – Arihant Godha Apr 17 '18 at 07:30
  • @ArihantGodha I'm pretty sure that variables set in one phase aren't preserved in another. Worth a test, though; even though I accepted the answer below, this would be my preferred solution. (I'd set a variable `succeeded` to `0`, and then set it to `1` at the very end of the main script; I'd then test it in the `after_script` to see if the process completed.) – Daniel Griscom Apr 18 '18 at 12:44

4 Answers4

55

Since gitlab-runner 13.5, you can use the CI_JOB_STATUS variable.

test_job:
  # ...
  after_script:
    - >
      if [ $CI_JOB_STATUS == 'success' ]; then
        echo 'This will only run on success'
      else
        echo 'This will only run when job failed or is cancelled'
      fi

See GitLab's documentation on predefined_variables: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html

Nepoxx
  • 4,849
  • 5
  • 42
  • 61
  • 9
    In case someone bumps the head on this one, sometimes the status returned by this variable is running instead of success or failed. There is an open ticket here: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27693 – gibertoni Jan 04 '22 at 13:43
  • 2
    My jobs always stay running in Gitlab 14.4 ... – Mikhail_Sam Jul 25 '22 at 13:25
  • @Mikhail_Sam take a look at the link posted by gibertoni, if it is not the same issue, open a new issue over at gitlab.com – Nepoxx Jul 26 '22 at 14:36
  • `CI_JOB_STATUS` works ok for me (Gitlab 13.12, non-Kubernetes runner). – sourcedelica Aug 04 '22 at 19:47
  • 1
    be aware that `after_script` has a [hardcoded timeout of 5 minutes](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716) and that it [is not run on timeout of the job itself](https://gitlab.com/gitlab-org/gitlab/-/issues/15603) – jan-glx Jul 19 '23 at 10:25
42

The accepted answer may apply to most situations, but it doesn't answer the original question and will only work if you only have one job per stage.

Note: There currently a feature request opened (issues/3116) to handle on_failure and on_success in after_script.

It could be possible to use variables to pass the job status to an after_script script, but this also has a feature request (issues/1926) opened to be able to share variables between before_script, script and after_script.

One workaround will be to write to a temporary file that will be accessed during the after_script block.

test_job:
  stage: test
  before_script:
    - echo "FAIL" > .job_status
  script:
    - exit 1
    - echo "SUCCESS" > .job_status
  after_script:
    - echo "$(cat .job_status)"
Carl Bélanger
  • 518
  • 4
  • 4
  • 10
    `exit 1` will stop the script and `echo "SUCCESS" > .job_status` will never run – Arith Apr 24 '20 at 03:57
  • this is the best solution for now – user319862 May 28 '20 at 20:22
  • Wouldn't exporting env variable work equally well ? export JOB_STATUS=FAIL; echo $JOB_STATUS – lucasnomail Aug 02 '21 at 10:07
  • 1
    This does not work for me, because after_script runs on a different context than before_script/script – gibertoni Jan 04 '22 at 13:26
  • 4
    @Arith yeah, and it's exactly what was intended - you got `FAIL` in `.job_status` then. This is only for visualising how to achieve the flow, normally you put your actual code into `script` section and store job status at the end, so you can check against it in `after_script`. – Wirone Mar 07 '22 at 15:51
10

Instead of determining whether or not the task succeeded or failed in the after_script, I would suggest defining another stage, and using the when syntax, where you can use when: on_failure or when: on_success.


Example from the documentation:

stages:
- build
- cleanup_build
- test
- deploy
- cleanup

build_job:
  stage: build
  script:
  - make build

cleanup_build_job:
  stage: cleanup_build
  script:
  - cleanup build when failed
  when: on_failure

test_job:
  stage: test
  script:
  - make test

deploy_job:
  stage: deploy
  script:
  - make deploy
  when: manual

cleanup_job:
  stage: cleanup
  script:
  - cleanup after jobs
  when: always
Rekovni
  • 6,319
  • 3
  • 39
  • 62
  • Unfortunately `cleanup_job` would not if `deploy_job` is retried, and then fails again. – Christoffer Reijer Mar 05 '19 at 19:12
  • 1
    What if you wanted to perform an `after_script` that required the same `CI_JOB_ID`? – Michael Brawn Sep 24 '19 at 15:56
  • Or you want to inspect the docker containers running that failed... =( – user319862 May 28 '20 at 20:20
  • that was not the question he asked and it does not help if I need to execute something in after script only when the job was successful or not – iRaS Aug 15 '21 at 08:56
  • This would normally be my preferred method, but there is no guarantee the subsequent jobs will happen on the same runner if you use a pool of N runners and need the job to clean up the runner. – James Harr Mar 01 '22 at 14:26
1

Just another way to handle this if you want to setup if failure behavior.

scripts:
  - ./script_that_fails.sh > /dev/null 2>&1 || FAILED=true
  - if [ $FAILED ]
    then ./do_something.sh
    fi

Note: Other examples also worked for me, but I find this implementation more faster and suitable for me

697
  • 321
  • 4
  • 16