Skip to main content

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, mas nã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ávelContextoDescrição
CI_PIPELINE_IDJob-onlyID único da pipeline na instância do GitLab.
CI_PIPELINE_IIDPipelineÚnico só dentro do projeto
CI_COMMIT_SHAPre-pipelineSHA completo do commit que disparou a pipeline.
CI_COMMIT_REF_NAMEPre-pipelineNome da branch ou tag do commit.
CI_COMMIT_BRANCHPre-pipelineNome da branch, se for uma pipeline de branch.
CI_COMMIT_TAGPre-pipelineNome da tag, se for uma pipeline de tag.
CI_PROJECT_PATHPre-pipelineCaminho completo do projeto (namespace/projeto).
CI_PROJECT_DIRJob-onlyDiretório onde o código foi clonado no runner. Nem sempre os runners clonam os projetos no mesmo lugar.
CI_JOB_NAMEPipelineNome do job atual. Geralmente usado para log e notificações
CI_JOB_STAGEPipelineEstágio do job no pipeline (build, test, deploy, etc.). Geralmente usado para log e notificações
CI_JOB_STATUSJob-onlyStatus atual do job (sucesso, falha, cancelado). Geralmente usado para log e notificações
CI_JOB_TOKENJob-onlyToken usado para autenticação em APIs e artefatos. Esse token tem limitações.
CI_PIPELINE_SOURCEPre-pipelineOrigem da pipeline (push, merge_request_event, trigger, etc). Essa é uma das mais importantes
CI_COMMIT_MESSAGEPre-pipelineMensagem completa do commit. É bom para validar se a mensagem do commit esta nos padrões do commitizen por exemplo
CI_REGISTRY_IMAGEPre-pipelineURL da imagem Docker no registry do projeto. Util se for subir uma imagem no próprio image registry do gitlab.
CI_ENVIRONMENT_NAMEPipelineNome do ambiente (staging, prod, etc.), se configurado no job.
CI_ENVIRONMENT_URLPipelineURL do ambiente, se definida.
CI_COMMIT_AUTHORPre-pipelineNome e email do autor do commit. Bom para auditoria e disparar notificação.
CI_PIPELINE_URLJob-onlyURL para detalhes da pipeline no GitLab.
GITLAB_USER_LOGINPipelineUsername 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_TIMESTAMPPre-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_PAYLOADPipelineconté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 ou 0-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ávelContextoDescrição / Uso Prático
CI_MERGE_REQUEST_TITLEpipelineVerifica ou exibe o título da MR. Útil pra validar padrões de nomenclatura.
CI_MERGE_REQUEST_IDpipelineID global da MR. Pode ser usado em logs ou chamadas na API.
CI_MERGE_REQUEST_IIDpipelineID da MR no projeto (aquele número da URL). Útil em scripts ou dashboards.
CI_MERGE_REQUEST_ASSIGNEESpipelineLista de responsáveis. Dá pra validar se a MR tá atribuída a alguém.
CI_MERGE_REQUEST_APPROVEDpipelineChecar se já foi aprovada antes de prosseguir (ex: trava release sem aprovação).
CI_MERGE_REQUEST_LABELSpipelineMuito útil pra lógica condicional baseada em labels (deploy, hotfix...).
CI_MERGE_REQUEST_DESCRIPTIONpipelinePode ser usado pra análise de conteúdo da MR (ex: changelog automatizado).
CI_MERGE_REQUEST_DRAFTpipelineEvita que MRs em draft passem pro ambiente ou sejam deployadas.
CI_MERGE_REQUEST_SOURCE_BRANCH_NAMEpre-pipelineBranch de origem da MR (quem quer mergear).
CI_MERGE_REQUEST_TARGET_BRANCH_NAMEpre-pipelineBranch de destino da MR (ex: main, develop). Essa é pode fixar na cabeça
CI_MERGE_REQUEST_EVENT_TYPEpre-pipelineÚtil pra entender o tipo de pipeline da MR (merge_train, detached, etc).
CI_MERGE_REQUEST_SQUASH_ON_MERGEpipelinePra 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:

ValorOrigem da pipeline
pushPush em uma branch
webCriada manualmente via UI
triggerDisparada por um trigger token
schedulePipeline agendada
apiPipeline criada via API REST
externalDisparada por integração externa (como webhook de outro sistema)
pipelinePipeline criada por outra pipeline (multi-project ou child pipeline)
chatPipeline iniciada por comando via ChatOps
webideIniciada a partir do Web IDE
merge_request_eventPipeline de merge request (tipo antigo)
external_pull_request_eventPipeline disparada por pull request externo (ex: GitHub)
parent_pipelinePipeline pai que gerou essa
ondemand_dast_scanPipeline iniciada por um scan DAST sob demanda
security_orchestration_policyDisparada 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