Gitlab Pipeline – after_script – What is after_script in GitLab CI/CD?

DevOps

MOTOSHARE 🚗🏍️
Turning Idle Vehicles into Shared Rides & Earnings

From Idle to Income. From Parked to Purpose.
Earn by Sharing, Ride by Renting.
Where Owners Earn, Riders Move.
Owners Earn. Riders Move. Motoshare Connects.

With Motoshare, every parked vehicle finds a purpose. Owners earn. Renters ride.
🚀 Everyone wins.

Start Your Journey with Motoshare

The after_script keyword in GitLab CI/CD allows you to define a list of shell commands that should be executed after the main script commands of a job. A crucial characteristic of after_script is that its commands are executed regardless of the success or failure of the job’s script or before_script sections.

This makes after_script ideal for tasks like:

  • Cleaning up temporary files or resources.
  • Logging final status or collecting diagnostic information.
  • De-authenticating from services.
  • Uploading artifacts even if the job failed.

You can define after_script at two main levels:

  1. Globally (as a default): Using default:after_script:. These commands will run after every job unless a job overrides it.
  2. Job-level: Defined within a specific job. This overrides any global after_script for that particular job.

Example .gitlab-ci.yml with after_script:

YAML

# .gitlab-ci.yml

# 1. Default after_script: Applied to all jobs unless overridden
default:
  image: alpine:latest # Using a common default image
  after_script:
    - echo "--- Default after_script (Global) ---"
    - echo "Job finished at: $(date)"
    - echo "Job status was: $CI_JOB_STATUS" # CI_JOB_STATUS reflects the script's outcome
    - echo "Cleaning up default resources..."

stages:
  - build
  - test
  - cleanup_test

# Job 1: Successful job that uses the default after_script
successful_job:
  stage: build
  before_script:
    - echo "Before script for successful_job"
  script:
    - echo "--- Main script for successful_job ---"
    - echo "This job will succeed."
    - exit 0 # Explicitly succeed

# Job 2: Failing job that also uses the default after_script
failing_job:
  stage: test
  before_script:
    - echo "Before script for failing_job"
  script:
    - echo "--- Main script for failing_job ---"
    - echo "This job will intentionally fail."
    - exit 1 # Explicitly fail

# Job 3: Job with a custom after_script (overrides the default)
job_with_custom_after_script:
  stage: cleanup_test
  after_script: # Job-level after_script overrides the default one
    - echo "--- Custom after_script for job_with_custom_after_script ---"
    - echo "Performing specific cleanup for this job."
    - echo "Job status was: $CI_JOB_STATUS"
  script:
    - echo "--- Main script for job_with_custom_after_script ---"
    - echo "This job uses its own custom after_script."

# Job 4: Job that disables after_script (even the default one)
job_without_any_after_script:
  stage: cleanup_test
  after_script: [] # Explicitly set to an empty array to disable
  # You could also use `after_script: null` in some GitLab versions.
  script:
    - echo "--- Main script for job_without_any_after_script ---"
    - echo "No after_script (neither default nor custom) will be executed for this job."

Code language: PHP (php)

Explanation:

  1. default:after_script:
    • The default: block allows setting default configurations.
    • after_script: within default: defines commands that execute after every job, regardless of whether the job passed or failed (unless the job has its own after_script or disables it).
    • In this example:
      • It prints introductory lines and the finish time.
      • It prints the CI_JOB_STATUS (a predefined variable indicating if the job’s main script succeeded, failed, etc.).
      • It simulates a default cleanup.
  2. successful_job:
    • This job completes its script section successfully (exit 0).
    • It does not have its own after_script.
    • Therefore, it inherits and executes the commands from the default:after_script: section after its script block. The CI_JOB_STATUS will likely be success.
  3. failing_job:
    • This job intentionally fails in its script section (exit 1).
    • It also does not have its own after_script.
    • Despite the failure, it will still inherit and execute the commands from the default:after_script: section. This demonstrates the key behavior of after_script. The CI_JOB_STATUS will likely be failed.
  4. job_with_custom_after_script:
    • This job defines its own after_script: block.
    • This job-level after_script completely overrides (replaces) the default:after_script:. The commands from default:after_script: will not run for this job.
    • Only the commands listed in this job’s after_script will execute after its main script, regardless of the main script’s outcome.
  5. job_without_any_after_script:
    • This job explicitly sets after_script: [] (an empty array).
    • This tells GitLab CI not to run any after_script commands for this job, not even the ones defined in the default:after_script: section.

Key Concepts and Behavior:

  • Purpose: after_script is intended for cleanup, final logging, or any actions that must occur regardless of the job’s outcome.
  • Execution Order: For any given job:
    1. before_script (if any) runs.
    2. Main script runs.
    3. after_script (if any) runs.
  • Runs on Success or Failure: This is the most important characteristic. Commands in after_script are executed even if the before_script or script sections fail.
  • Failure Handling in after_script:
    • The exit code of commands in after_script does not affect the overall job status. The job’s status is determined by the before_script and script sections.
    • However, if a command in after_script fails, you might see errors in the job log for the after_script phase.
  • Array of Commands: after_script takes an array of strings, where each string is a shell command executed sequentially.
  • Inheritance and Overriding:
    • Job-level after_script overrides default:after_script.
    • To prevent any after_script (including a global one) from running for a specific job, set after_script: [] or after_script: null.
  • Execution Context:
    • after_script commands run on the same GitLab Runner that executed the job.
    • They generally have access to the same environment variables, files in the workspace (unless cleaned up by the job’s script), and services as the main script.
    • The CI_JOB_STATUS predefined variable is particularly useful in after_script to know the outcome of the job’s main execution.
  • Timeout: after_script has its own separate timeout, which is configured by the GitLab administrator (usually shorter than the main job timeout).
  • Common Use Cases:
    • Removing temporary files or directories.
    • Stopping services started during the job.
    • Logging out from authenticated sessions.
    • Uploading test reports or logs, especially if the job failed and artifacts wouldn’t be uploaded otherwise (though artifacts:when:always is often preferred for artifact uploading).
    • Sending notifications.

Using after_script ensures that critical cleanup and finalization steps are performed consistently, contributing to a more robust and manageable CI/CD pipeline.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x