skip to content

GitLab CI/CD

2 roadmaps30 questionsupdated

GitLab's integrated pipelines defined in .gitlab-ci.yml: stages and jobs, runners with their executors, and tight coupling to merge requests and the built-in registry. Interviewers ask when a shop self-hosts GitLab, and as a contrast to GitHub Actions on runner and configuration model.

on this pageshow

guide

overview

~1 min

GitLab CI/CD is the pipeline engine built into GitLab. A `.gitlab-ci.yml` at the repository root declares jobs, GitLab turns a push, merge request, tag or schedule into a pipeline of them, and separate runner processes pick the jobs up and execute them. Interviewers reach for it when a team self-hosts GitLab, or as a contrast with GitHub Actions, and the questions move quickly past syntax to control: which jobs exist, where they run, and what they can reach. The hub splits five ways. [Pipeline YAML & Rules](/topics/cloud-gitlab-ci-pipeline-yaml-rules) is the configuration model and `rules`, the logic that decides whether a job is created at all. [Runners & Executors](/topics/cloud-gitlab-ci-runners-executors) is the agent, the executor that builds each job's environment, and how jobs reach machines. [Variables & Secrets](/topics/cloud-gitlab-ci-variables-secrets) asks how values reach a job and which are safe. [Environments & Review Apps](/topics/cloud-gitlab-ci-environments-review-apps) is GitLab's deployment tracking, from per-merge-request previews to gated production. [Includes, Templates & Components](/topics/cloud-gitlab-ci-includes-templates) is how a platform team keeps many repositories on one pipeline. Junior rounds check the vocabulary: stages, artifacts, tags, `include`. Senior and principal rounds become debugging and governance stories — a job that runs when it should not, a job stuck pending, a secret in a log, a mandated scan a project quietly removed. Learn the YAML and its rules first, then runners; every other section assumes both.

primer

### A pipeline is decided when it is created GitLab merges the configuration once, when the pipeline is created, and settles then which jobs exist. `workflow:rules` decide whether there is a pipeline at all; each job's `rules` decide whether that job joins it, judged against the pipeline's source, ref, variables and changed files. Most "why did this job run" and "why is it missing" questions trace back to that moment. ### Stages order jobs; needs rewires them Jobs in one stage can run in parallel, and a stage waits for the one before it. `needs` lets a job start as soon as the specific jobs it names are done, turning a row of stages into a graph. Artifacts follow whichever ordering you chose. ### GitLab schedules, runners execute The GitLab server holds the queue; runners are separate agents, installed wherever work should happen, that ask it for jobs. A runner's **executor** decides what a job's environment is — the host shell, a fresh container, a pod — and that single choice sets isolation, cache behaviour and how awkward building container images becomes. Tags and runner scope decide which machine may take which job, which makes routing a trust decision as much as a capacity one. ### Variables have owners and a ranking A value can come from the YAML, from project, group or instance settings, from a trigger or manual run, or from GitLab itself. When names collide a fixed precedence picks the winner, and the order surprises many candidates. **Protected**, **masked** and **file** are separate controls answering separate risks. The strongest answers avoid stored credentials entirely, using short-lived tokens that a cloud provider or Vault exchanges for access. ### A deployment is a record, not just a job Attaching an environment to a job makes GitLab keep a history of what went where, show it on merge requests, and let you protect, approve, stop or roll back that target. Review apps are the per-branch form of the same idea. The history is only as trustworthy as the deploy job is reproducible. ### Reuse is merging, and merging has rules `include` pulls configuration in, `extends` and `!reference` combine pieces of it, and components add typed inputs and versions. Each merges differently, and each carries a trust question: whose file is it, pinned to what, and can the project remove it?

rules
A job keyword holding ordered conditions evaluated at pipeline creation; the first match decides whether and how the job is added.
workflow:rules
Rules for the pipeline as a whole, deciding whether a pipeline is created for a given push, merge request, tag or schedule.
needs
A job keyword naming the jobs it depends on, so it can start before its stage is reached and fetch artifacts only from them.
Artifact
Files a job uploads to GitLab when it finishes, available to later jobs and for download, kept for a configured time.
Runner
The GitLab Runner agent that asks GitLab for jobs and executes them; it is registered to an instance, a group or a project.
Executor
The runner setting that decides how each job's environment is created, for example directly in a host shell, in a Docker container or in a Kubernetes pod.
Protected variable
A CI/CD variable passed only to jobs running on protected branches or tags.
Masked variable
A CI/CD variable whose literal value is replaced in job logs; it is still present in the job's environment.
ID token
A short-lived JWT GitLab issues to a job on request, which an external system can verify and exchange for credentials.
Environment
A named deployment target GitLab tracks, such as production or a review app, with a history of the deployments made to it.
CI/CD component
A reusable, versioned unit of pipeline configuration with declared inputs, published from a project and included by reference.

Follow one push. GitLab first assembles the configuration — the project's file plus everything it includes, with `extends` resolved — then evaluates `workflow:rules` and every job's `rules` against this push. The jobs that survive form the pipeline and wait in a queue. A runner whose scope covers the project and whose tags cover the job asks for work and receives it; its executor builds the job's environment, GitLab hands over the variables that apply to this ref, the script runs, and artifacts and cache are uploaded. If the job declares an environment, GitLab records a deployment against it and links it from the merge request. One deploy job touches every section of the hub: ```yaml deploy-review: stage: deploy needs: [build] tags: [k8s] rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" id_tokens: CLOUD_TOKEN: aud: https://vault.example.com environment: name: review/$CI_COMMIT_REF_SLUG on_stop: stop-review script: ./deploy.sh ``` The lines act at different moments: `rules` when the pipeline is created, `needs` while it runs, `tags` when a runner claims the job, `id_tokens` as the job starts, and `environment` once it deploys. Debugging mostly means finding which moment went wrong. The teardown job named by `on_stop` has to pass its own rules in the same pipeline, or GitLab has no job to run when the environment is stopped.

  1. Pipeline YAML & Rules →

    The configuration model every section assumes: stages, jobs, artifacts, needs, and the rules that decide which jobs exist.

  2. Runners & Executors →

    Where jobs actually run: executors, tags, runner scope and cache, and why image builds need special care.

  3. Variables & Secrets →

    How values reach a job, which one wins a name clash, and how to reach the cloud without a stored key.

  4. Environments & Review Apps →

    Deployment tracking, review apps, approvals and rollback, which build on rules and variables.

  5. Includes, Templates & Components →

    Sharing and enforcing pipelines across many projects; it makes sense once a single project's pipeline is familiar.

  • Reading rules as a list of filters that all apply: evaluation stops at the first matching entry, and a job with no matching rule is not created.

  • Trusting rules:changes on tag, scheduled or new-branch pipelines — see Why rules:changes keeps matching.

  • Calling a masked variable safe: masking only rewrites exact matches in the log; which jobs receive the value at all is what protection controls.

  • Enabling privileged mode for Docker-in-Docker on a widely shared runner without naming the cost: a privileged job can reach far beyond its container.

  • Expecting extends to append a template's script to the job's own: lists are replaced, not merged, so the template's commands silently disappear.

  • Claiming a shared include enforces a mandatory scan: maintainers own the file and can delete the line, so enforcement has to sit above the project.

  • Promising the rollback button restores the old build: it re-runs the old deploy job, which can rebuild or pull a tag that has since moved.

GitLab CI usually arrives with the decision to host code in GitLab, and interviewers expect you to place it against the alternatives. Against **GitHub Actions**, the practical difference is the model: Actions assembles automation from event-triggered workflow files and a marketplace of reusable steps, while GitLab builds a pipeline per trigger from one root configuration plus includes, and ties it closely to merge requests, environments and its built-in container registry. Against **Jenkins**, GitLab CI trades a plugin-extensible, separately run server for a pipeline engine that ships inside the code host. Around it sit tools that take over one stage. A GitOps controller such as **Argo CD** or **Flux** often handles deployment: the pipeline builds, tests and pushes an image, then updates the manifests the controller reconciles. **HashiCorp Vault** or a cloud secret manager holds secrets that jobs fetch at run time instead of storing them as variables. A good design answer says where GitLab stops and the neighbouring tool starts.

explore

report an issue with this guide →

questions

30

In a GitLab CI job, what does the `environment:` keyword do, and what do its `name` and `url` fields control?

level: juniorimportance: must knowfreq 74%

answer

  1. metadata, not a deploy action
  2. GitLab records what is live where
  3. name identifies, slash makes folders
  4. url becomes the View app link
  5. CI_ENVIRONMENT_NAME / _SLUG / _URL

basics

~20 s

The environment: keyword marks a GitLab CI job as a deployment, so GitLab records what is deployed where. The name identifies the tracked environment; the url is the address GitLab links to from that environment, the job, and the merge request.

solid answer

~50 s

`environment:` is metadata you attach to a job. It does not deploy anything — your `script:` still does the work — but when the job runs, GitLab creates or updates an **Environment** record with that `name` and appends a **Deployment** to its history pointing at the commit and the job. That is what powers the Environments page: which commit is live on staging, when it got there, a link to open it, and the re-deploy/rollback buttons. `name` is the identifier, and a slash groups environments into folders in the UI, so `review/$CI_COMMIT_REF_SLUG` collapses hundreds of review apps under one `review` folder. `url` is where the app can be reached; GitLab turns it into an "Open live environment" link on the environment and a "View app" button in the merge request widget. Without `environment:`, a deploy job still works — GitLab just has no idea it happened.

code

yaml · 8 lines
yaml
deploy_staging:
  stage: deploy
  script:
    - ./deploy.sh staging
    - curl --fail "$CI_ENVIRONMENT_URL/health"
  environment:
    name: staging
    url: https://staging.example.com

go deeper

for a junior

Be able to write a deploy job with environment: name and url and say plainly that the script deploys while the keyword records the deployment for GitLab to display.

for a middle

Explain what GitLab stores — an environment plus a deployment tied to a commit and job — and name CI_ENVIRONMENT_NAME, CI_ENVIRONMENT_SLUG and CI_ENVIRONMENT_URL along with what a slash in the name does.

for a senior

Show why the record matters in production: without it there is no deployment history, no rollback button and no way to answer "what commit is live" during an incident. Mention action: prepare for non-deploying jobs.

for a principal

Own the naming scheme across many projects — stable names for fixed environments, folder prefixes for ephemeral ones — because environment names are what dashboards, DORA metrics and protected-environment rules key on.

## What the keyword is, and what it is not `environment:` is **job-level metadata** in `.gitlab-ci.yml`. Adding it does not make GitLab deploy anything, and removing it does not stop a deployment: the job's `script:` is what runs `kubectl`, `helm`, `scp`, `aws s3 sync` or whatever else. What the keyword changes is GitLab's *bookkeeping*. When a job carrying `environment:` starts, GitLab creates the named environment if it does not exist, and records a **deployment** — an entry tying that environment to the commit SHA, the pipeline, the job, the user who triggered it, and a status (running, success, failed). That record is the whole point. Everything GitLab offers around delivery is built on it: the Environments page listing what is currently live where, per-environment deployment history, the re-deploy and rollback buttons, the merge request widget showing that this branch is deployed, environment-scoped CI/CD variables, and protected environments. ```yaml deploy_staging: stage: deploy script: - ./deploy.sh staging environment: name: staging url: https://staging.example.com ``` ## `name` `name` is the identifier, and it is unique per project: two jobs using `name: staging` update the *same* environment, which is exactly what you want — the second deployment appends to the first one's history rather than creating a rival entry. The name may contain CI/CD variables, which is how dynamic environments work (`name: review/$CI_COMMIT_REF_SLUG`). A slash in the name has one extra meaning: GitLab groups environments whose names share a prefix before the slash into a **folder** in the UI. With hundreds of merge requests open, `review/add-login`, `review/fix-navbar` and friends appear as one collapsible `review` folder rather than hundreds of top-level rows. Inside the job, GitLab exposes `CI_ENVIRONMENT_NAME` (the name as written, after variable expansion) and `CI_ENVIRONMENT_SLUG` — a shortened, lowercased, DNS-safe version of the name that is safe to use as a hostname label or a Kubernetes namespace. ## `url` `url` is the address at which the deployed application can be reached. GitLab does not check it, ping it, or route to it; it renders it as a link. That link appears in three useful places: an "Open live environment" button on the environment, a link on the job page, and — for an environment attached to a merge request's branch — a "View app" button in the merge request widget, which is what makes review apps usable by a reviewer who has never opened a terminal. The value may be built from variables (`url: https://$CI_COMMIT_REF_SLUG.review.example.com`), and it is exposed to the job as `CI_ENVIRONMENT_URL`, so a smoke-test step can curl the thing it just deployed without repeating the hostname. When the URL is only known *after* the job runs — a platform that hands you a generated hostname — you can leave `url` out of the static config and have the script write the value into a `dotenv` report artifact, which GitLab reads back and attaches to the deployment. ## `action` `environment:action` says what this job does to the environment. The default is `start`, which is the recording behaviour described above. `stop` marks the environment stopped (see teardown of review apps). `prepare` attaches the job to the environment — making environment-scoped variables available — **without** recording a deployment, which is what you want for a plan or dry-run job that must read production credentials but is not deploying. `verify` and `access` are similar non-deploying variants used for verification and access-only jobs. ## Where teams get this wrong The most common mistake is simply never adding `environment:`, so deploys are invisible: GitLab's Environments page is empty, nobody can tell which commit is on staging, and there is no rollback button to press during an incident. The second is expecting the keyword to *perform* something — candidates sometimes claim `url` makes GitLab route traffic or health-check the app. It does neither. The third is giving each pipeline a unique environment name for a fixed environment (`staging-$CI_PIPELINE_ID`), which destroys the deployment history the feature exists to give you.

  • If two different jobs in different pipelines both use `environment: name: staging`, what does GitLab do?
    They update the same environment. Environment names are unique per project, so the second job appends a new deployment to `staging`'s history and that deployment becomes the current one. That is the intended behaviour — it is how the Environments page can say which commit is live and offer a rollback to the previous entry.
  • When would you set `environment:action: prepare` instead of the default?
    When a job must be associated with an environment without counting as a deployment — for example a plan, dry-run or verification job that needs the environment's scoped CI/CD variables. `prepare` attaches the job to the environment so those variables resolve, but records no deployment, so the environment's history and "what is live" state stay accurate.
  • How do you set the environment URL when the hostname is only known once the job has run?
    Have the script write the value into a `dotenv` report artifact and reference that variable from `environment:url`. GitLab reads the report after the job finishes and attaches the resolved URL to the deployment, so the "View app" link points at the address the platform actually allocated.

saying these in an interview costs you the question

  • Claims environment: performs the deployment itself
  • Thinks url makes GitLab route or health-check traffic
  • Gives a fixed environment a unique name per pipeline
  • Believes environments must be created in the UI first
  • Confuses environment:name with the job name

context

open as a page

In a GitLab CI .gitlab-ci.yml, what does the include: keyword pull in, and how do its local, project, remote and template forms differ?

level: juniorimportance: must knowfreq 68%

basics

~20 s

GitLab CI's include merges other YAML configuration into your pipeline when the pipeline is created. local reads a file from the same repository and commit, project a file from another project on the same instance, remote a publicly reachable URL, and template a file GitLab ships with the instance.

open as a page

In GitLab CI, how do you pass a file produced by one job to a job in a later stage, and what controls which artifacts a job downloads?

level: juniorimportance: must knowfreq 68%

basics

~10 s

Declare the file under artifacts:paths in the producing job; GitLab uploads it and later-stage jobs download artifacts from all earlier-stage jobs automatically. Narrow that with dependencies: (an empty list downloads nothing) or with needs:.

open as a page

In GitLab CI, how does a job's `tags:` keyword decide which runner picks the job up, and why can a job sit pending forever?

level: juniorimportance: must knowfreq 70%

basics

~20 s

A GitLab CI job runs only on a runner that carries every tag listed in its tags: keyword. If no online, permitted runner has all of them, the job stays pending until such a runner appears or GitLab drops it as stuck.

open as a page

In GitLab CI, how do you give every merge request its own review app environment, and where does the environment name come from?

level: middleimportance: must knowfreq 62%

basics

~20 s

Put a CI/CD variable in the environment name so each branch creates its own environment — typically name: review/$CI_COMMIT_REF_SLUG with a matching url. GitLab expands the variable per pipeline, so every merge request gets a separately tracked deployment and a View app link.

open as a page

In GitLab CI, how does extends: combine a hidden .template job with the job that extends it, and why can a YAML anchor not do the same thing across included files?

level: middleimportance: must knowfreq 58%

basics

~20 s

extends performs a recursive merge of the template job's keys into the extending job, with the extending job's own values winning. YAML anchors are resolved by the YAML parser inside a single file, so they cannot reference a node defined in an included file; extends can, because GitLab merges all included files first.

open as a page

In a GitLab CI job's `rules:` list, how does GitLab decide whether the job is added to the pipeline, and what does a rule with `when: never` do?

level: middleimportance: must knowfreq 80%

basics

~20 s

GitLab evaluates a job's rules top to bottom when the pipeline is created and stops at the first rule that matches, using that rule's when. A matching rule with when: never drops the job, and if no rule matches the job is never created.

open as a page

In GitLab Runner's config.toml, what does the `executor` setting control, and how do the shell, docker, and kubernetes executors differ?

level: middleimportance: must knowfreq 72%

basics

~20 s

The executor decides how GitLab Runner creates the environment a job's script runs in. Shell runs commands directly on the runner host, docker starts a fresh container per job from the job's image, and kubernetes schedules a pod per job in a cluster.

open as a page

In GitLab CI/CD, the same variable name is set both in the project's CI/CD settings and in .gitlab-ci.yml. Which value does the job get, and what is the overall precedence order?

level: middleimportance: must knowfreq 70%

basics

~20 s

The project setting wins. GitLab ranks variables defined outside the repository above ones defined inside it: manual, trigger and schedule values first, then project, then group, then instance, then the values in .gitlab-ci.yml, with predefined variables last.

open as a page

In GitLab CI/CD, what is the difference between a protected variable, a masked variable, and a file-type variable?

level: middleimportance: must knowfreq 72%

basics

~20 s

They solve three unrelated problems. Protected controls which jobs receive the value at all — only jobs on protected branches or tags. Masked redacts the value if it is printed to the job log. File type writes the value to a temporary file and sets the variable to that file's path.

open as a page

In GitLab CI/CD, what are the predefined CI_* variables, and how does CI_COMMIT_REF_SLUG differ from CI_COMMIT_REF_NAME?

level: juniorimportance: should knowfreq 62%

basics

~20 s

GitLab injects predefined CI_* variables into every job, describing the commit, pipeline, project, job and runner. CI_COMMIT_REF_NAME is the raw branch or tag name; CI_COMMIT_REF_SLUG lowercases it, replaces every non-alphanumeric character with a hyphen and truncates it.

open as a page

A GitLab CI job extends a template whose script: has three commands, but the job defines its own script: and the template's commands stop running. Why, and how do you keep both?

level: middleimportance: should knowfreq 38%

basics

~20 s

GitLab's extends merges hash maps but replaces arrays, and script: is an array, so the job's own list overwrites the template's entirely. Splice the template's commands back in with the !reference tag, or move the shared commands into before_script.

open as a page

In GitLab CI, what does adding `needs:` to a job change about when it starts and which artifacts it receives?

level: middleimportance: should knowfreq 62%

basics

~20 s

needs: turns stage-ordered execution into a DAG: the job starts as soon as the jobs it lists have finished, even if its own stage has not been reached, and it downloads artifacts only from those jobs instead of from all earlier stages.

open as a page

In GitLab, how do shared, group, and project runners differ, and what does that choice mean for trust and queueing?

level: middleimportance: should knowfreq 50%

basics

~20 s

Shared runners serve every project on the instance, group runners serve one group and its subgroups, and project runners are attached to specific projects. Narrowing the scope narrows who can send code to that machine, at the cost of queueing and idle capacity.

open as a page

What does the id_tokens: keyword do in a GitLab CI job, and what does the job actually receive?

level: middleimportance: should knowfreq 42%

basics

~20 s

id_tokens: asks GitLab to mint one or more short-lived JWTs for the job, each with an audience you specify. Each token appears as an environment variable of the name you chose, so the job can exchange it for cloud or Vault credentials without any stored key.

open as a page

In GitLab, what actually happens when you use the rollback button on an older deployment in an environment's deployment history, and why might it not restore the previous version?

level: seniorimportance: should knowfreq 38%

basics

~20 s

GitLab re-runs that older pipeline's deployment job against the old commit and records it as a new deployment. It restores the previous version only if that job is reproducible — if it rebuilds from source, depends on expired artifacts, or pulls a mutable tag, you can get something else entirely.

open as a page

Review apps created by your GitLab CI pipeline are never cleaned up after branches merge. Which environment keywords are supposed to stop them, and why does the stop job so often fail to run?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Teardown comes from environment:on_stop, which names a job with action: stop, plus environment:auto_stop_in for an expiry. Stop jobs fail most often because the job was never created in the original pipeline, or because it tries to check out a branch that has since been deleted.

open as a page

In GitLab, how do you require human approval before a pipeline job deploys to production, and what happens to that job while it waits?

level: seniorimportance: should knowfreq 40%

basics

~20 s

You protect the environment in the project's CI/CD settings, not in .gitlab-ci.yml: a protected environment lists who is allowed to deploy and how many approvals a deployment needs. A job targeting it is created and then blocked, waiting for approval before the runner picks it up.

open as a page

What is the risk of using include: remote: in a GitLab CI configuration, and what would you use instead?

level: seniorimportance: should knowfreq 42%

basics

~20 s

GitLab fetches the URL with an unauthenticated GET at pipeline creation and runs whatever it returns as part of your configuration, on your runners, with your CI/CD variables. Nothing is pinned or verified, so whoever controls that URL can inject jobs. Prefer include:project at a pinned ref, or a versioned component.

open as a page

A GitLab CI job guarded by `rules:changes` keeps running even when none of the listed paths were modified. What are the usual causes?

level: seniorimportance: should knowfreq 45%

basics

~20 s

rules:changes needs a diff to compare against. When there is none — a new branch, a tag pipeline, a scheduled or manual run — GitLab treats the paths as changed and the rule evaluates true. On branch pipelines it also compares the whole push, not just the last commit.

open as a page

In GitLab CI, why can a single push create two pipelines for a branch that has an open merge request, and how do `workflow:rules` stop it?

level: seniorimportance: should knowfreq 58%

basics

~20 s

GitLab can create both a branch pipeline and a merge request pipeline for the same commit when job rules accept both sources. workflow:rules decide whether a pipeline is created at all, so one entry keeps merge request pipelines and another rejects branch pipelines while a merge request is open.

open as a page

In GitLab Runner's config.toml, what is the difference between the global `concurrent` setting and a runner entry's `limit`?

level: seniorimportance: should knowfreq 38%

basics

~20 s

concurrent is a process-wide ceiling on jobs running across every runner entry in that config.toml, while limit caps how many jobs one specific [[runners]] entry may run at once. The effective parallelism is the smaller of the two.

open as a page

A GitLab CI job on a docker-executor runner needs to build a container image. Why does the docker:dind service require privileged mode, and what are the alternatives?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Docker-in-Docker starts a second Docker daemon inside the job's container, and a daemon needs kernel capabilities that ordinary containers lack, so the runner must be configured with privileged mode. Daemonless builders such as Buildah or rootless BuildKit avoid that by building images without a daemon.

open as a page

A GitLab CI job printed a secret into its log even though the variable was marked Masked. What are the ways masking fails to protect you?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Masking replaces only exact, literal occurrences of the value in the log stream. Any transformation defeats it — base64, URL encoding, JSON escaping, line splitting — and it does not touch artifacts, reports or anything the job sends elsewhere.

open as a page

Project maintainers control their own .gitlab-ci.yml, but security requires a scan job in every pipeline. How do you actually enforce that in GitLab, and what does that cost the teams?

level: principalimportance: should knowfreq 28%

basics

~20 s

An include the project can delete is a convention, not a control. GitLab enforces mandated jobs above the project: a compliance framework applied to the project supplies the pipeline's root configuration, which then includes the project's own file. Newer GitLab moves this to pipeline execution policies.

open as a page

In a GitLab CI job's `environment:` configuration, what does `deployment_tier` tell GitLab that the environment's name does not?

level: middleimportance: nice to knowfreq 22%

basics

~20 s

deployment_tier classifies an environment as production, staging, testing, development or other, independently of what it is called. GitLab otherwise guesses the tier from the name, so an unconventionally named environment is miscounted in reporting such as DORA deployment metrics.

open as a page

In a GitLab CI/CD component, what does a spec:inputs header give you that configuring an included template through global variables does not?

level: middleimportance: nice to knowfreq 34%

basics

~20 s

spec:inputs declares typed, validated parameters with defaults and allowed values, interpolated into the template as $[[ inputs.name ]] before the configuration is parsed. Invalid or missing values fail at pipeline creation, and the values are scoped to that one include rather than leaking into every job.

open as a page

GitLab CI jobs on an autoscaled runner fleet almost never get a cache hit, even though `cache:` is configured correctly. Why, and what fixes it?

level: seniorimportance: nice to knowfreq 32%

basics

~20 s

By default GitLab Runner stores caches locally on the machine that ran the job, so a fleet that creates a fresh instance or pod per job never finds the previous cache. Configuring distributed cache storage in [runners.cache] with Shared enabled puts caches in object storage instead.

open as a page

In GitLab CI, what does the secrets: keyword do, and why might your application receive a file path instead of the secret value?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

secrets: tells GitLab Runner to fetch a value from an external secret manager before the script runs and expose it as a CI/CD variable. By default the value is delivered as a file variable, so the variable holds a temporary file's path rather than the secret itself.

open as a page

When would you split a GitLab CI configuration into parent and child pipelines with `trigger:include`, and what do you give up by doing it?

level: principalimportance: nice to knowfreq 32%

basics

~20 s

Split when one configuration has grown past what a team can reason about, or when the job set must be decided at runtime — a trigger job with include generates a separate child pipeline. The cost is a fragmented view, no cross-pipeline needs ordering, explicit status and variable propagation.

open as a page