Variables
Um runner do GitLab recebe diversas variáveis de ambiente que descrevem o contexto da execução da pipeline — como branch atual, tipo de evento (push, merge request, etc.), usuário responsável, entre outros. Essas variáveis permitem criar fluxos inteligentes e personalizados, sendo especialmente úteis na definição de rules, condicionais de execução e comportamentos específicos para cada cenário do CI/CD.
Vamos já de cara criar ver o que temos de variáveis de ambiente em um runner com o que temos até agora.
Em qualquer job coloque um - env
. O comando env imprime todas as variáveis de ambiente direto no shell. Vamos acompanhar no console.
.check: # Template para stage check
stage: check
before_script:
- env # Qualquer job que herde esse template irá imprimir isso.
- npm ci
artifacts:
when: always
expire_in: "3 months"
Abra um MR só para executar a pipeline vamos conferir o log. Algumas variáveis estão masked pois foram criadas para ser se acompanhou o fluxo do estudo.
# Log de um dos jobs.
Skipping Git submodules setup
Executing "step_script" stage of the job script
Using docker image sha256:461edc13e56b039ebc3d898b858ac3acea00c47f31e93ec1258379cae8990522 for node:22-alpine with digest node@sha256:ad1aedbcc1b0575074a91ac146d6956476c1f9985994810e4ee02efd932a68fd ...
$ env
FF_USE_WINDOWS_LEGACY_PROCESS_STRATEGY=false
FF_SCRIPT_SECTIONS=false
FF_POSIXLY_CORRECT_ESCAPES=false
CI_SERVER_VERSION_PATCH=0
CI_SERVER_REVISION=eb738e3a3cd
CI_COMMIT_SHORT_SHA=0f053f0d
GITLAB_USER_LOGIN=davidpuziol
CI_DEPENDENCY_PROXY_PASSWORD=[MASKED]
CI_DEPENDENCY_PROXY_SERVER=gitlab.com:443
FF_USE_DUMB_INIT_WITH_KUBERNETES_EXECUTOR=false
CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED=true
FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY=false
FF_LOG_IMAGES_CONFIGURED_FOR_JOB=false
FF_USE_LEGACY_S3_CACHE_ADAPTER=false
CI=true
CI_SERVER_PROTOCOL=https
CI_PROJECT_NAME=learn-gitlab-app
CI_RUNNER_REVISION=0f67ff19
NODE_VERSION=22.15.0
HOSTNAME=runner-jyvyfkmfg-project-69186599-concurrent-1
CI_JOB_STAGE=check
CI_PROJECT_DESCRIPTION=
CI_COMMIT_DESCRIPTION=
YARN_VERSION=1.22.22
CI_DEPENDENCY_PROXY_USER=gitlab-ci-token
CI_SERVER_VERSION=18.0.0-pre
CI_MERGE_REQUEST_SOURCE_PROJECT_ID=69186599
SHLVL=3
FF_DISABLE_POWERSHELL_STDIN=false
FF_CLEAN_UP_FAILED_CACHE_EXTRACT=false
FF_DISABLE_AUTOMATIC_TOKEN_ROTATION=false
CI_PROJECT_ROOT_NAMESPACE=puziol
HOME=/root
OLDPWD=/
FF_NETWORK_PER_BUILD=false
CI_JOB_ID=9882688551
CI_SERVER_HOST=gitlab.com
CI_COMMIT_REF_NAME=pipe/variables
FF_RESOLVE_FULL_TLS_CHAIN=false
CI_PIPELINE_SOURCE=merge_request_event
CI_MERGE_REQUEST_TARGET_BRANCH_SHA=
CI_RUNNER_VERSION=17.11.0
FF_SKIP_NOOP_BUILD_STAGES=true
FF_USE_FASTZIP=false
FF_USE_WINDOWS_JOB_OBJECT=false
CI_BUILDS_DIR=/builds
CI_SERVER_VERSION_MAJOR=18
CI_DEFAULT_BRANCH=main
CI_MERGE_REQUEST_SOURCE_PROJECT_PATH=puziol/learn-gitlab-app
CI_MERGE_REQUEST_SOURCE_BRANCH_NAME=pipe/variables
CI_REGISTRY_PASSWORD=[MASKED]
CI_SERVER_URL=https://gitlab.com
CI_TEMPLATE_REGISTRY_HOST=registry.gitlab.com
CI_COMMIT_REF_PROTECTED=false
CI_MERGE_REQUEST_DIFF_ID=1343611661
GITLAB_FEATURES=ldap_group_sync,multiple_ldap_servers,seat_link,seat_usage_quotas,pipelines_usage_quotas,transfer_usage_quotas,product_analytics_usage_quotas,zoekt_code_search,repository_size_limit,elastic_search,admin_audit_log,auditor_user,custom_file_templates,custom_project_templates,db_load_balancing,default_branch_protection_restriction_in_groups,extended_audit_events,external_authorization_service_api_management,geo,instance_level_scim,ldap_group_sync_filter,object_storage,pages_size_limit,project_aliases,disable_private_profiles,password_complexity,amazon_q,enterprise_templates,git_abuse_rate_limit,integrations_allow_list,required_ci_templates,runner_maintenance_note,runner_performance_insights,runner_upgrade_management,observability_alerts
CI_PROJECT_ID=69186599
CI_REGISTRY_IMAGE=registry.gitlab.com/puziol/learn-gitlab-app
FF_USE_LEGACY_GCS_CACHE_ADAPTER=false
GITLAB_CI=true
CI_COMMIT_SHA=0f053f0db8b19830a962bde2e22f68ea73239f03
CI_MERGE_REQUEST_SOURCE_BRANCH_PROTECTED=false
FF_RETRIEVE_POD_WARNING_EVENTS=true
CI_CONCURRENT_ID=1
FF_DISABLE_UMASK_FOR_DOCKER_EXECUTOR=false
FF_USE_DOCKER_AUTOSCALER_DIAL_STDIO=true
CI_REGISTRY_USER=gitlab-ci-token
CI_SERVER_PORT=443
CI_MERGE_REQUEST_SQUASH_ON_MERGE=true
CI_PROJECT_DIR=/builds/puziol/learn-gitlab-app
CI_PROJECT_PATH=puziol/learn-gitlab-app
CI_MERGE_REQUEST_PROJECT_URL=https://gitlab.com/puziol/learn-gitlab-app
FF_ENABLE_JOB_CLEANUP=false
FF_WAIT_FOR_POD_TO_BE_REACHABLE=false
CI_PROJECT_NAMESPACE=puziol
CI_COMMIT_TIMESTAMP=2025-04-30T11:27:02-03:00
FF_USE_DIRECT_DOWNLOAD=true
FF_USE_DYNAMIC_TRACE_FORCE_SEND_INTERVAL=false
CI_JOB_TOKEN=[MASKED]
CI_NODE_TOTAL=1
CI_SERVER_NAME=GitLab
CI_MERGE_REQUEST_DESCRIPTION=
CI_PROJECT_NAMESPACE_ID=106089966
CI_PIPELINE_CREATED_AT=2025-04-30T14:27:45Z
CI_MERGE_REQUEST_SOURCE_BRANCH_SHA=
CI_MERGE_REQUEST_DRAFT=false
CI_CONCURRENT_PROJECT_ID=1
CI_JOB_NAME_SLUG=lint-test
CI_MERGE_REQUEST_IID=6
RUNNER_TEMP_PROJECT_DIR=/builds/puziol/learn-gitlab-app.tmp
FF_KUBERNETES_HONOR_ENTRYPOINT=false
CI_PIPELINE_URL=https://gitlab.com/puziol/learn-gitlab-app/-/pipelines/1794394989
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
FF_EXPORT_HIGH_CARDINALITY_METRICS=false
CI_JOB_STARTED_AT=2025-04-30T14:27:50Z
CI_SERVER_VERSION_MINOR=0
CI_RUNNER_DESCRIPTION=general-debian
FF_USE_NEW_BASH_EVAL_STRATEGY=false
FF_DISABLE_UMASK_FOR_KUBERNETES_EXECUTOR=false
FF_MASK_ALL_DEFAULT_TOKENS=true
CI_PROJECT_TITLE=learn-gitlab-app
CI_PROJECT_VISIBILITY=private
CI_COMMIT_TITLE=prints env
GITLAB_USER_EMAIL=[email protected]
FF_USE_GIT_BUNDLE_URIS=true
FF_USE_NATIVE_STEPS=true
FF_USE_FLEETING_ACQUIRE_HEARTBEATS=false
CI_SERVER=yes
CI_JOB_GROUP_NAME=lint-test
CI_MERGE_REQUEST_EVENT_TYPE=detached
FF_TIMESTAMPS=false
CI_PROJECT_REPOSITORY_LANGUAGES=javascript,css,html
CI_MERGE_REQUEST_ID=380143752
CI_PAGES_URL=https://learn-gitlab-app-414996.gitlab.io
FF_SET_PERMISSIONS_BEFORE_CLEANUP=true
FF_PRINT_POD_EVENTS=false
CI_SERVER_FQDN=gitlab.com
CI_COMMIT_AUTHOR=David Puziol <[email protected]>
CI_JOB_IMAGE=node:22-alpine
CI_RUNNER_SHORT_TOKEN=jyvyfkmfg
CI_PAGES_DOMAIN=gitlab.io
CI_JOB_TIMEOUT=3600
CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/puziol/learn-gitlab-app.git
CI_PROJECT_CLASSIFICATION_LABEL=
CI_PIPELINE_NAME=
GITLAB_ENV=/builds/puziol/learn-gitlab-app.tmp/gitlab_runner_env
FF_USE_POWERSHELL_PATH_RESOLVER=false
FF_GIT_URLS_WITHOUT_TOKENS=false
CI_API_GRAPHQL_URL=https://gitlab.com/api/graphql
CI_RUNNER_ID=47096042
CI_REGISTRY=registry.gitlab.com
CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX=gitlab.com:443/puziol/dependency_proxy/containers
CI_API_V4_URL=https://gitlab.com/api/v4
CI_MERGE_REQUEST_SOURCE_PROJECT_URL=https://gitlab.com/puziol/learn-gitlab-app
GITLAB_USER_NAME=David Puziol Prata
CI_PIPELINE_IID=33
CI_MERGE_REQUEST_PROJECT_ID=69186599
FF_USE_POD_ACTIVE_DEADLINE_SECONDS=true
FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=false
CI_JOB_URL=https://gitlab.com/puziol/learn-gitlab-app/-/jobs/9882688551
CI_SERVER_SHELL_SSH_HOST=gitlab.com
CI_MERGE_REQUEST_DESCRIPTION_IS_TRUNCATED=false
CI_RUNNER_EXECUTABLE_ARCH=linux/amd64
FF_TEST_FEATURE=false
FF_USE_INIT_WITH_DOCKER_EXECUTOR=false
CI_MERGE_REQUEST_REF_PATH=refs/merge-requests/6/head
CI_COMMIT_REF_SLUG=pipe-variables
CI_DISPOSABLE_ENVIRONMENT=true
PWD=/builds/puziol/learn-gitlab-app
FF_SECRET_RESOLVING_FAILS_IF_MISSING=true
CI_MERGE_REQUEST_PROJECT_PATH=puziol/learn-gitlab-app
CI_RUNNER_TAGS=["general", "debian"]
CI_SERVER_TLS_CA_FILE=/builds/puziol/learn-gitlab-app.tmp/CI_SERVER_TLS_CA_FILE
CI_PIPELINE_ID=1794394989
CI_PROJECT_PATH_SLUG=puziol-learn-gitlab-app
CI_PROJECT_URL=https://gitlab.com/puziol/learn-gitlab-app
CI_CONFIG_PATH=.gitlab-ci.yml
CI_COMMIT_BEFORE_SHA=0000000000000000000000000000000000000000
CI_MERGE_REQUEST_TITLE=Pipe/variables
CI_PROJECT_NAMESPACE_SLUG=puziol
CI_COMMIT_MESSAGE=prints env
FF_ENABLE_BASH_EXIT_CODE_CHECK=false
CI_PAGES_HOSTNAME=learn-gitlab-app-414996.gitlab.io
CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX=gitlab.com:443/puziol/dependency_proxy/containers
GITLAB_USER_ID=4300841
CI_JOB_STATUS=running
CI_JOB_NAME=lint-test
CI_SERVER_SHELL_SSH_PORT=22
CI_MERGE_REQUEST_DIFF_BASE_SHA=093afcb937eeffbc005998803ace71c2887f1c88
CI_MERGE_REQUEST_TARGET_BRANCH_NAME=main
CI_OPEN_MERGE_REQUESTS=puziol/learn-gitlab-app!6
Claro que ai em cima tem variáveis que são do GitLab e outras que não são. Se observar temos variáveis do runner, do node, e do próprio alpine.
Aqui esta a documentação das variáveis pré definidas do CI/CD.
Variáveis x Contexto
pre-pipeline
: Antes de qualquer job iniciar. Só o GitLab "sabe". ex: CI_PIPELINE_SOURCE, CI_COMMIT_BRANCH.- Variáveis que o GitLab avalia antes de rodar o .gitlab-ci.yml.
- Úteis em rules, only, except (Veremos mais tarde)
pipeline
: Durante toda a execução do pipeline. ex: CI_PIPELINE_ID, CI_PROJECT_NAME- Vivem durante o pipeline inteiro. Estão disponíveis pra todos os jobs e templates.
job-only
: Só dentro de um job. Fora dele, não existe. ex: CI_JOB_NAME, CI_JOB_ID, CI_RUNNER_ID- Só existem quando o job já está rodando. Se tentar acessar numa rule: ou condicional de pipeline, vai dar ruim. Exemplo: CI_RUNNER_DESCRIPTION.
O runner não recebe todas as variáveis de todos os contextos.
pre-pipeline
: Essas variáveis são resolvidas antes do pipeline iniciar. Úteis em rules, workflow, etc, masnão vão pro runner
.pipeline e job-only
: Disponíveis na execução dos jobs e visíveis pro runner.
Apesar dessas serem bem conhecidas, vou marcar aquelas que precisam esta na cabeça.
Variável | Contexto | Descrição |
---|---|---|
CI_PIPELINE_ID | Job-only | ID único da pipeline na instância do GitLab. |
CI_PIPELINE_IID | Pipeline | Único só dentro do projeto |
CI_COMMIT_SHA | Pre-pipeline | SHA completo do commit que disparou a pipeline. |
CI_COMMIT_REF_NAME | Pre-pipeline | Nome da branch ou tag do commit. |
CI_COMMIT_BRANCH | Pre-pipeline | Nome da branch, se for uma pipeline de branch. |
CI_COMMIT_TAG | Pre-pipeline | Nome da tag, se for uma pipeline de tag. |
CI_PROJECT_PATH | Pre-pipeline | Caminho completo do projeto (namespace/projeto). |
CI_PROJECT_DIR | Job-only | Diretório onde o código foi clonado no runner. Nem sempre os runners clonam os projetos no mesmo lugar. |
CI_JOB_NAME | Pipeline | Nome do job atual. Geralmente usado para log e notificações |
CI_JOB_STAGE | Pipeline | Estágio do job no pipeline (build, test, deploy, etc.). Geralmente usado para log e notificações |
CI_JOB_STATUS | Job-only | Status atual do job (sucesso, falha, cancelado). Geralmente usado para log e notificações |
CI_JOB_TOKEN | Job-only | Token usado para autenticação em APIs e artefatos. Esse token tem limitações. |
CI_PIPELINE_SOURCE | Pre-pipeline | Origem da pipeline (push, merge_request_event, trigger, etc). Essa é uma das mais importantes |
CI_COMMIT_MESSAGE | Pre-pipeline | Mensagem completa do commit. É bom para validar se a mensagem do commit esta nos padrões do commitizen por exemplo |
CI_REGISTRY_IMAGE | Pre-pipeline | URL da imagem Docker no registry do projeto. Util se for subir uma imagem no próprio image registry do gitlab. |
CI_ENVIRONMENT_NAME | Pipeline | Nome do ambiente (staging, prod, etc.), se configurado no job. |
CI_ENVIRONMENT_URL | Pipeline | URL do ambiente, se definida. |
CI_COMMIT_AUTHOR | Pre-pipeline | Nome e email do autor do commit. Bom para auditoria e disparar notificação. |
CI_PIPELINE_URL | Job-only | URL para detalhes da pipeline no GitLab. |
GITLAB_USER_LOGIN | Pipeline | Username de quem disparou a pipeline (se aplicável). Nem sempre é igual quem fez o commit. Geralmente quem dispara a pipeline costuma fazer o commit se for automático, mas nem sempre. |
CI_COMMIT_TIMESTAMP | Pre-pipeline | é uma variável pre-pipeline que traz a data e hora exata do commit, no formato ISO 8601 (ex: 2025-04-30T12:45:32+00:00. Bom para incluir em nomes, changelogs, auditoria. |
TRIGGER_PAYLOAD | Pipeline | contém o conteúdo bruto do webhook que disparou a pipeline — em JSON. Só aparece quando a pipeline é iniciada via gatilho externo (como um webhook do GitHub, Jira, outro GitLab, etc). Muito utilizada, inclusive quando utilizamos o gitlab-ci como backend! |
Quando acontece um merge request temos algumas variáveis específicas que também são importantes.
Algumas variáveis vão aparecer como _SLUG. é praticamente a mesma coisa, mas facilita bastante.
- Substitui tudo que não for
a-z
ou0-9
por hífen(-)
- Limita a 63 caracteres (limite comum em DNS/K8s)
- Remove hífens no início/fim, se houver
CI_COMMIT_REF_NAME=feature/Very_Cool-Feature_42
CI_COMMIT_REF_SLUG=feature-very-cool-feature-42
CI_COMMIT_REF_SLUG=pipe/variables
CI_COMMIT_REF_SLUG=pipe-variables
CI_JOB_NAME=lint-test
CI_JOB_NAME_SLUG=lint-test
CI_PROJECT_PATH=puziol/learn-gitlab-app
CI_PROJECT_PATH_SLUG=puziol/learn-gitlab-app
CI_PROJECT_NAMESPACE=puziol
CI_PROJECT_NAMESPACE_SLUG=puziol
Quando você precisa do nome original da branch
, com case e símbolos intactos (ex: validação de padrão, git checkout, logs mais legíveis) não utilize slug
. É bom definir um padrão na equipe.
Use slug quando for criar nomes de ambientes, namespaces no Kubernetes, URLs (ex: review apps), nome de branches em tags Docker (app:${CI_COMMIT_REF_SLUG})
,Labels, diretórios, arquivos gerados automaticamente, etc.
Variável | Contexto | Descrição / Uso Prático |
---|---|---|
CI_MERGE_REQUEST_TITLE | pipeline | Verifica ou exibe o título da MR. Útil pra validar padrões de nomenclatura. |
CI_MERGE_REQUEST_ID | pipeline | ID global da MR. Pode ser usado em logs ou chamadas na API. |
CI_MERGE_REQUEST_IID | pipeline | ID da MR no projeto (aquele número da URL). Útil em scripts ou dashboards. |
CI_MERGE_REQUEST_ASSIGNEES | pipeline | Lista de responsáveis. Dá pra validar se a MR tá atribuída a alguém. |
CI_MERGE_REQUEST_APPROVED | pipeline | Checar se já foi aprovada antes de prosseguir (ex: trava release sem aprovação). |
CI_MERGE_REQUEST_LABELS | pipeline | Muito útil pra lógica condicional baseada em labels (deploy, hotfix...). |
CI_MERGE_REQUEST_DESCRIPTION | pipeline | Pode ser usado pra análise de conteúdo da MR (ex: changelog automatizado). |
CI_MERGE_REQUEST_DRAFT | pipeline | Evita que MRs em draft passem pro ambiente ou sejam deployadas. |
CI_MERGE_REQUEST_SOURCE_BRANCH_NAME | pre-pipeline | Branch de origem da MR (quem quer mergear). |
CI_MERGE_REQUEST_TARGET_BRANCH_NAME | pre-pipeline | Branch de destino da MR (ex: main, develop). Essa é pode fixar na cabeça |
CI_MERGE_REQUEST_EVENT_TYPE | pre-pipeline | Útil pra entender o tipo de pipeline da MR (merge_train, detached, etc). |
CI_MERGE_REQUEST_SQUASH_ON_MERGE | pipeline | Pra aplicar lógica se squash estiver ativado (ex: validar commit único). |
Existem algumas variáveis interessante que é bom conhecer.
As variáveis CHAT_CHANNEL, CHAT_INPUT ,CHAT_USER_ID são específicas de ChatOps no GitLab, ou seja, quando uma pipeline é disparada a partir de um comando enviado por chat (como Slack) usando integração com o GitLab ChatOps.
CI_PIPELINE_SOURCE
Essa variável é muito importante. O que disparou a pipeline pode mudar todo o fluxo. Os possíveis valores são:
Valor | Origem da pipeline |
---|---|
push | Push em uma branch |
web | Criada manualmente via UI |
trigger | Disparada por um trigger token |
schedule | Pipeline agendada |
api | Pipeline criada via API REST |
external | Disparada por integração externa (como webhook de outro sistema) |
pipeline | Pipeline criada por outra pipeline (multi-project ou child pipeline) |
chat | Pipeline iniciada por comando via ChatOps |
webide | Iniciada a partir do Web IDE |
merge_request_event | Pipeline de merge request (tipo antigo) |
external_pull_request_event | Pipeline disparada por pull request externo (ex: GitHub) |
parent_pipeline | Pipeline pai que gerou essa |
ondemand_dast_scan | Pipeline iniciada por um scan DAST sob demanda |
security_orchestration_policy | Disparada por uma política de segurança |
Sei que são muitas variáveis, mas a idéia é criar algo que possamos consultar mais rápido. A documentação oficial sempre esta disponível e conhecer um pouco do que podemos fazer nos dá asas. Agora com os poderes certos podemos começar a criar o fluxo das coisas!
Job Variables
Se a mesma variável (mesma key) for definida no repositório e em nível de job, esta sobreescrerá o valor locamente dentro do job.
Imaginemos que temos MY_VAR definida no repositório como MY_VAR=hello
build:
stage: build
variables:
MY_VAR: my-var # Var em nível de job
script:
- echo $MY_VAR # resultará my-var