Gitlab - 4.4.3 Internship internship in a pipeline

This lesson clarifies two GitLab CI keywords that look alike but mean different things: stage (singular) is declared inside a job to assign that job to a stage, while stages (plural) is declared at the root of the pipeline to define the execution order of those stages. To illustrate, we start from a simple pipeline with three jobs (build_job, test_job, deploy_job), each one just echoing a message. With no stage declared, GitLab silently puts every job in the default test stage and runs all three in parallel, because parallel is the default behavior whenever no explicit order is set.

Defining stages and execution order

To force the expected build → test → deploy order, each job is given a meaningful stage name and the pipeline declares the global stages list at the top:

stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  script: ["echo build"]

test_job:
  stage: test
  script: ["echo test"]

deploy_job:
  stage: deploy
  script: ["echo deploy"]

The order in which stages appear in the stages list is the order in which GitLab runs them, regardless of where the jobs themselves are written in the file. Multiple jobs sharing the same stage name (for example two parallel test jobs) run together, which is commonly used to speed up test suites. A stage only starts once every job from the previous stage has succeeded; if a test job fails, the deploy stage is skipped, but two parallel jobs within the same stage are independent: one failing does not stop the other.

GitLab also ships five default stages running in a fixed sequence: .pre, build, test, deploy, .post. If your jobs use only these default names, you can omit the stages list entirely and GitLab will sort them automatically. You can still override the order of build, test and deploy, but .pre is always first and .post always last. Finally, if you declare a stage on a job that is not listed in stages, GitLab fails the pipeline because it cannot resolve the stage, so always make sure every used stage name (apart from .pre and .post) is present in the global list.