A green pipeline on every push is the first step to reliable merges.
Create .gitlab-ci.yml in the repository root, commit and push. GitLab parses it and creates a pipeline immediately; syntax errors are reported on the pipeline page, and the Pipeline editor (Build, Pipeline editor) validates the file as you type.
A job is a top-level key that is not a reserved keyword. The essentials:
script: one command or a list of commands run by the runner's shell. If any command exits non-zero, the job fails.image: the Docker image the job runs in, such aspython:3.13ornode:22.before_scriptandafter_script: commands run before and afterscript.after_scriptruns even when the job fails, in a separate shell.default:sets keywords likeimageandbefore_scriptfor every job.
Each job starts with the repository already cloned into $CI_PROJECT_DIR, so there is no checkout step to write; GitLab fetches the commit for you (shallow by default, 20 commits).
Keep YAML strings safe: a command containing : (colon and space) or starting with special characters needs quotes, or the line is parsed as a mapping. When in doubt, quote the whole command.
Example
default:
image: python:3.13-slim
stages: [test]
test:
stage: test
before_script:
- pip install -r requirements.txt
script:
- python -m pytest -q # 12 passed in 0.8s
- "echo 'Result: done'" # quoted because of the colon-space
after_script:
- echo "always runs, even on failure" Remember
- Commit .gitlab-ci.yml at the root and push to start a pipeline
- script is required; image picks the container
- Code is already checked out into $CI_PROJECT_DIR
Watch out for
- Unquoted commands containing ': ' break the YAML.