They are the three phases of a GitLab CI job: before_script prepares the job, script does the work, and after_script cleans up afterwards.
before_script runs before the main commands and is used for setup. If it fails, the whole job fails.
script holds the main commands, and it is the only one of the three a job must have.
after_script runs after the other two, even when the job fails, so it suits cleanup tasks.
job-example:
before_script:
- echo "Setting up environment"
- apt-get update
script:
- echo "Running main commands"
- npm test
after_script:
- echo "Cleaning up"
- rm -rf temp/
after_script runs in a new, separate shell with its own timeout of 5 minutes by default. It can't see variables that script exported, and it doesn't change the job's exit code. It also doesn't run by default when the job times out, so it is not a guarantee.
Rewriting in plainer words…
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.