Variables & Secrets
CI/CD Variables
Masked Variables
Protected Variables
File Variables
A complete guide to GitLab CI/CD variables and secrets. Learn CI/CD variables, masked variables, protected variables, file variables, and security best practices.
Variables
Masked
Protected
File Variables
What are CI/CD Variables?
CI/CD variables are dynamic values that are injected into your pipeline at runtime. They're the primary mechanism for configuring pipelines without hardcoding values, and they're absolutely essential for handling secrets like API keys, database passwords, and TLS certificates securely. Every time a job runs, GitLab assembles a set of environment variables from multiple sources and makes them available to your scripts.
Understanding variables is critical because they control almost every aspect of a pipeline's behavior. They determine which Docker registry you push to, which Kubernetes namespace you deploy into, what API endpoints your tests hit, and which credentials your deployment scripts use. A misconfigured variable can break a pipeline, leak a secret, or deploy code to the wrong environment. Getting them right is fundamental to reliable, secure CI/CD.
GitLab provides several types of variables, each with different scoping and security properties. Predefined variables are set by GitLab automatically. Custom variables are defined by you in the .gitlab-ci.yml file or in the GitLab UI. Protected variables are only available on protected branches. Masked variables have their values hidden in job logs. Understanding the distinction between these types is essential for building secure pipelines.
Key Concept: Variables in GitLab CI/CD are environment variables. Your scripts access them the same way they'd access any other shell variable — using $VAR or ${VAR} syntax. The difference is where they come from and how GitLab manages their security.
Types of CI/CD Variables
Predefined Variables
Set automatically by GitLab. Include commit SHA, branch name, pipeline ID, project info, and more.
$CI_COMMIT_SHA
Custom Variables
Defined by you in .gitlab-ci.yml or in GitLab UI. Available at pipeline, stage, or job scope.
variables: { MY_VAR: value }
Masked Variables
Values are hidden in job logs. Essential for secrets that shouldn't appear in CI output.
Value replaced with [MASKED]
Protected Variables
Only available on protected branches and tags. Prevents feature branches from accessing production secrets.
Only on main, release/*
File Variables
Value is stored as a file. The variable contains the path to that file. Perfect for certificates, keys, and config files.
$KUBECONFIG → /path/to/file
Environment Variables
Variables scoped to specific deployment environments. Can be set per environment in GitLab UI.
Production-specific secrets
Predefined Variables
GitLab provides dozens of predefined variables that are automatically available in every pipeline. These variables give you access to information about the commit, branch, pipeline, project, and environment. They're essential for writing dynamic pipelines that adapt to the context in which they run — for example, using the commit SHA as an image tag, or deploying to different environments based on the branch name.
Predefined variables are read-only — you can't overwrite them. They follow a consistent naming convention: they all start with CI_ and use uppercase with underscores. Learning the most common ones will save you significant time and make your pipelines more robust.
# Common Predefined Variables
# Commit-related
$CI_COMMIT_SHA # Full commit SHA
$CI_COMMIT_SHORT_SHA # First 8 characters of SHA
$CI_COMMIT_BRANCH # Branch name
$CI_COMMIT_TAG # Tag name (empty if not a tag)
$CI_COMMIT_REF_NAME # Branch or tag name
$CI_COMMIT_REF_SLUG # Lowercased, slugified ref name
$CI_COMMIT_MESSAGE # Commit message
$CI_COMMIT_TITLE # Commit title (first line)
$CI_COMMIT_DESCRIPTION # Commit description
$CI_COMMIT_AUTHOR # Commit author
$CI_COMMIT_TIMESTAMP # Commit timestamp
# Pipeline-related
$CI_PIPELINE_ID # Pipeline ID
$CI_PIPELINE_IID # Project-level pipeline ID
$CI_PIPELINE_SOURCE # Pipeline trigger source
$CI_PIPELINE_CREATED_AT # Pipeline creation time
$CI_PIPELINE_URL # Pipeline URL
# Job-related
$CI_JOB_ID # Job ID
$CI_JOB_NAME # Job name
$CI_JOB_STAGE # Job stage
$CI_JOB_STATUS # Job status
$CI_JOB_URL # Job URL
$CI_JOB_TOKEN # Job token for API access
$CI_JOB_STARTED_AT # Job start time
$CI_JOB_MANUAL # Whether job is manual
# Project-related
$CI_PROJECT_ID # Project ID
$CI_PROJECT_NAME # Project name
$CI_PROJECT_PATH # Project path (group/project)
$CI_PROJECT_PATH_SLUG # Slugified project path
$CI_PROJECT_NAMESPACE # Project namespace
$CI_PROJECT_URL # Project URL
$CI_PROJECT_DIR # Project directory
$CI_PROJECT_TITLE # Project title
# Registry-related
$CI_REGISTRY # Container registry URL
$CI_REGISTRY_IMAGE # Registry image path
$CI_REGISTRY_USER # Registry username
$CI_REGISTRY_PASSWORD # Registry password
$CI_REGISTRY_IMAGE # Full image path
# Server-related
$CI_SERVER_URL # GitLab server URL
$CI_SERVER_HOST # GitLab server host
$CI_SERVER_PORT # GitLab server port
$CI_SERVER_PROTOCOL # GitLab server protocol
$CI_SERVER_VERSION # GitLab version
$CI_SERVER_REVISION # GitLab revision
# Merge request-related
$CI_MERGE_REQUEST_ID # MR ID
$CI_MERGE_REQUEST_IID # Project-level MR ID
$CI_MERGE_REQUEST_SOURCE_BRANCH # Source branch
$CI_MERGE_REQUEST_TARGET_BRANCH # Target branch
$CI_MERGE_REQUEST_TITLE # MR title
$CI_MERGE_REQUEST_DESCRIPTION # MR description
$CI_MERGE_REQUEST_LABELS # MR labels
# Runner-related
$CI_RUNNER_ID # Runner ID
$CI_RUNNER_DESCRIPTION # Runner description
$CI_RUNNER_TAGS # Runner tags
$CI_RUNNER_EXECUTABLE_ARCH # Runner architecture
# Environment-related
$CI_ENVIRONMENT_NAME # Environment name
$CI_ENVIRONMENT_SLUG # Environment slug
$CI_ENVIRONMENT_URL # Environment URL
$CI_ENVIRONMENT_ACTION # Environment action
# Example: Using predefined variables in a script
build:
script:
- echo "Commit: $CI_COMMIT_SHORT_SHA"
- echo "Branch: $CI_COMMIT_BRANCH"
- echo "Pipeline: $CI_PIPELINE_ID"
- echo "Project: $CI_PROJECT_PATH"
- echo "Registry: $CI_REGISTRY_IMAGE"
| Variable |
Description |
Example Value |
$CI_COMMIT_SHA |
Full commit SHA |
a1b2c3d4e5f6... |
$CI_COMMIT_SHORT_SHA |
Short commit SHA |
a1b2c3d4 |
$CI_COMMIT_BRANCH |
Branch name |
main |
$CI_PIPELINE_ID |
Pipeline ID |
12345 |
$CI_JOB_ID |
Job ID |
67890 |
$CI_PROJECT_PATH |
Project path |
mygroup/myproject |
$CI_REGISTRY_IMAGE |
Registry image path |
registry.gitlab.com/mygroup/myproject |
Custom Variables in .gitlab-ci.yml
Custom variables can be defined directly in your .gitlab-ci.yml file. This is the most common way to define non-sensitive configuration values that don't need to be hidden — things like application names, default versions, or feature flags. Variables defined this way are visible in the repository, so they must never contain secrets.
Variables can be defined at three scopes: pipeline scope (top-level variables keyword), job scope (inside a specific job), and global scope (via default:variables). Job-scoped variables override pipeline-scoped variables with the same name, which gives you fine-grained control over each job's configuration.
Variables can also reference other variables — GitLab expands them at runtime. This lets you build complex values from simple pieces, like combining a registry URL with an image name and version. Just be careful about recursive references, which GitLab will reject.
# Global variables (pipeline scope)
variables:
NODE_VERSION: "18"
APP_NAME: "my-app"
DOCKER_REGISTRY: "registry.gitlab.com"
DOCKER_IMAGE: "$DOCKER_REGISTRY/$CI_PROJECT_PATH"
KUBE_NAMESPACE: "default"
# Job-level variables (override global)
build:
stage: build
variables:
BUILD_ENV: "production"
OPTIMIZE: "true"
script:
- echo "Building $APP_NAME for $BUILD_ENV"
# Variable expansion
variables:
BASE_URL: "https://example.com"
API_URL: "${BASE_URL}/api"
FULL_IMAGE: "${DOCKER_REGISTRY}/${APP_NAME}:${CI_COMMIT_SHORT_SHA}"
# Default variables (all jobs)
default:
variables:
LOG_LEVEL: "info"
before_script:
- echo "Log level: $LOG_LEVEL"
# Using variables in scripts
deploy:
script:
- echo "Deploying $APP_NAME"
- echo "To namespace $KUBE_NAMESPACE"
- echo "Using image $DOCKER_IMAGE"
# Variables with defaults
optional_job:
script:
- echo "${MY_VAR:-default_value}"
# Variables in strings
build_image:
script:
- docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $DOCKER_IMAGE:$CI_COMMIT_SHORT_SHA
# Multiline variables (block scalar)
variables:
MULTILINE_VAR: |
line 1
line 2
line 3
# Variables with special characters
variables:
SPECIAL_VAR: "value with spaces"
JSON_VAR: '{"key": "value"}'
# Variables from command substitution
dynamic_job:
script:
- export TIMESTAMP=$(date +%Y%m%d)
- echo "Today is $TIMESTAMP"
Variable Priority: From highest to lowest:
- Trigger variables (via API)
- Manual pipeline variables (via UI)
- Project variables (via UI)
- Group variables (via UI)
- Instance variables (via UI)
- Job-level variables (in .gitlab-ci.yml)
- Pipeline-level variables (in .gitlab-ci.yml)
- Predefined variables
Masked Variables: Hiding Sensitive Values
Masked variables are the most basic form of secret protection in GitLab. When you mark a variable as masked, GitLab replaces its value with [MASKED] in job logs. This prevents accidental disclosure of secrets through echo statements, error messages, or debug output. It's not a perfect security mechanism — it's a safety net — but it's essential for any value that should never appear in a log.
Masked variables have specific requirements that you must satisfy for the masking to work. The value must be a single line, at least 8 characters long, and must not contain whitespace or certain special characters. These restrictions exist because GitLab uses a pattern-matching approach to mask — it scans job logs for the exact value and replaces matches. If the value is too short or contains unusual characters, the masking might fail or be unreliable.
To configure a masked variable, go to your project's Settings → CI/CD → Variables, click "Add variable," and check the "Masked" option. Alternatively, you can use the GitLab API to create masked variables programmatically. Remember: masking only protects values in job logs. It doesn't encrypt them, doesn't hide them from project maintainers, and doesn't prevent them from being exfiltrated by malicious code in a pipeline.
# Creating a masked variable in GitLab UI
# Settings → CI/CD → Variables → Add Variable
#
# Key: DB_PASSWORD
# Value: supersecretpassword123
# Type: Variable
# Masked: ✓ (checked)
# Protected: (optional)
# Using a masked variable in a script
deploy:
script:
- echo "Connecting to database..." # OK
- echo "$DB_PASSWORD" # Logs show [MASKED]
- mysql -u admin -p$DB_PASSWORD # Password hidden in logs
# What masking looks like in logs:
# Connecting to database...
# [MASKED]
# Warning: Using a password on the command line interface can be insecure.
# Masked variable requirements:
# ✓ Single line (no newlines)
# ✓ At least 8 characters long
# ✓ No whitespace
# ✓ No special characters: @, :, ?, &, etc.
# ✓ No base64 padding (=)
# Valid masked values:
# - mypassword123
# - AbCdEf123456
# - token_ABCdef123456
# Invalid masked values:
# - short (too short)
# - "with spaces" (contains whitespace)
# - "value@with:chars" (special characters)
# - "multiline\nvalue" (newlines)
# Creating masked variables via API
curl --request POST \
--header "PRIVATE-TOKEN: " \
"https://gitlab.com/api/v4/projects/1/variables" \
--form "key=DB_PASSWORD" \
--form "value=supersecret123" \
--form "masked=true" \
--form "protected=true"
# Best practice: Use masked for all secrets
# - API tokens
# - Database passwords
# - Private keys (use file variables instead)
# - OAuth secrets
# - Webhook URLs
Masking Limitations:
- Masking only hides the exact value in logs — it doesn't encrypt or secure the variable
- Project maintainers can still see the value in Settings
- Malicious pipeline code can still exfiltrate the secret
- Masking can fail if the value is transformed (base64, URL-encoded, etc.)
- Not suitable for multi-line values (use file variables instead)
- Combine with protected variables for production secrets
Protected Variables: Environment-Specific Secrets
Protected variables take secret protection to the next level. A protected variable is only available to pipelines running on protected branches or protected tags. This means you can safely store production credentials in a protected variable, knowing that feature branches and merge requests can't access them. It's a fundamental security control for production CI/CD.
The reasoning behind protected variables is straightforward: feature branches are where developers experiment, where unreviewed code runs, and where malicious code could be introduced. If a feature branch could access production database credentials, a compromised developer account could exfiltrate them simply by pushing code that echoes the secret. By marking production secrets as protected, you create a hard boundary: only code that has passed review and merged to a protected branch can access these secrets.
Protected variables work together with protected branches. By default, a new GitLab project has a single protected branch — main (or master, depending on GitLab version). You can add additional protected branches (like release/*) and protected tags. Any branch or tag marked as protected will have access to protected variables; any other branch will see the variable as undefined.
# Configuring protected variables in GitLab UI
# Settings → CI/CD → Variables → Add Variable
#
# Key: PROD_DB_PASSWORD
# Value: production-secret-password
# Type: Variable
# Protected: ✓ (checked)
# Masked: ✓ (checked)
#
# This variable is only available on protected branches
# Configuring protected branches
# Settings → Repository → Protected Branches
# - main (protected by default)
# - release/* (custom pattern)
# - production (custom branch)
# Using protected variables in deploy
deploy_production:
stage: deploy
script:
- echo "Deploying to production..."
- echo "Password: $PROD_DB_PASSWORD" # Only works on protected branches
environment:
name: production
only:
- main
# When a non-protected branch tries to use it:
# The variable is undefined
deploy_feature:
script:
- echo "$PROD_DB_PASSWORD" # Empty on feature branches
# Protected variable behavior:
# - Protected branch → Variable available
# - Non-protected branch → Variable undefined
# - Protected tag → Variable available
# - Non-protected tag → Variable undefined
# - Merge request from fork → Variable undefined
# - Pipeline on fork → Variable undefined
# Best practice: Use protected for production
# - Database credentials
# - Cloud provider API keys
# - Production API tokens
# - SSL certificates
# - Any production secret
# Setting up protected environments
# Settings → CI/CD → Protected Environments
# Allows only specific users/roles to deploy to
# production environments
# Using environment-scoped variables
# Settings → CI/CD → Variables
# Set Environment scope: production
# Variable available only when deploying to production
Protected Variable Best Practices:
- Mark all production secrets as protected
- Combine with masked for defense in depth
- Protect your main branch (and release branches)
- Use protected environments for deployment approval
- Audit protected variable access regularly
- Rotate production secrets periodically
File Variables: Storing Multi-line Secrets
File variables solve a problem that masked variables can't: multi-line secrets. Things like TLS certificates, SSH private keys, JSON service account credentials, and kubeconfig files are inherently multi-line. They can't be masked (masking requires single-line values), and passing them as environment variables is awkward and error-prone. File variables solve this by storing the value as a file on the runner and exposing the file's path through the variable.
When you create a file variable, GitLab writes the value to a temporary file on the runner and sets the environment variable to that file's path. Your script then reads the file with standard file operations. This is elegant because it works naturally with tools that expect file paths — kubectl --kubeconfig=$KUBECONFIG, docker login --password-stdin < $DOCKER_PASSWORD_FILE, and similar patterns.
File variables are perfect for anything that is naturally a file: certificates, keys, configuration files, JSON credentials, and archives. They're also a security best practice for SSH keys — storing an SSH key in a file variable and using it via $SSH_KEY_FILE avoids the common pitfall of echoing the key to disk with echo "$SSH_KEY" > key, which can leak the key into logs.
# Creating a file variable in GitLab UI
# Settings → CI/CD → Variables → Add Variable
#
# Key: KUBECONFIG
# Value: |
# apiVersion: v1
# kind: Config
# clusters:
# - cluster:
# server: https://k8s.example.com
# name: production
# ...
# Type: File
# Protected: ✓
# Using a file variable
deploy_kubernetes:
stage: deploy
script:
# $KUBECONFIG contains the path to the temp file
- echo "Using kubeconfig at $KUBECONFIG"
- kubectl --kubeconfig=$KUBECONFIG get pods
- kubectl --kubeconfig=$KUBECONFIG apply -f deployment.yaml
# SSH key as a file variable
deploy_via_ssh:
stage: deploy
script:
- mkdir -p ~/.ssh
# $SSH_PRIVATE_KEY contains the path to the key file
- cp $SSH_PRIVATE_KEY ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh -o StrictHostKeyChecking=no user@server "deploy.sh"
# Docker registry credentials as file variable
login_docker:
stage: build
script:
# $DOCKER_CONFIG contains path to config.json
- mkdir -p ~/.docker
- cp $DOCKER_CONFIG ~/.docker/config.json
- docker pull myregistry.com/myimage:latest
# TLS certificate as file variable
deploy_with_tls:
stage: deploy
script:
# $TLS_CERT and $TLS_KEY contain paths to cert files
- cp $TLS_CERT /etc/nginx/ssl/cert.pem
- cp $TLS_KEY /etc/nginx/ssl/key.pem
- nginx -s reload
# JSON service account as file variable
deploy_gcp:
stage: deploy
script:
# $GCP_SA_KEY contains path to service account JSON
- gcloud auth activate-service-account --key-file=$GCP_SA_KEY
- gcloud container clusters get-credentials my-cluster
# File variable vs Variable:
#
# Variable (Type: Variable):
# - Value is the literal string
# - $VAR contains the value
# - echo $VAR prints the value
# - Suitable for single-line values
# - Can be masked
#
# File (Type: File):
# - Value is written to a temp file
# - $VAR contains the file path
# - cat $VAR prints the value
# - Suitable for multi-line values
# - Cannot be masked (path is exposed)
# Best practice: use file variables for
# - SSH private keys
# - TLS certificates
# - Kubeconfig files
# - JSON service account keys
# - Multi-line configuration files
File Variables vs Regular Variables:
- Regular Variable:
$VAR contains the actual value
- File Variable:
$VAR contains the path to a temp file
- Use file variables for multi-line content, certificates, and keys
- Use regular variables for single-line values (can be masked)
- File variables can't be masked (the path is visible), but the contents are only in the temp file
Security Best Practices
Never Commit Secrets
Never store secrets in .gitlab-ci.yml or any file in the repository. Use GitLab CI/CD variables or an external secret manager.
Mask All Secrets
Mark every sensitive variable as masked. Even if you don't think the value will be logged, masking prevents accidental disclosure.
Protect Production Secrets
Mark production secrets as protected. This ensures feature branches and forks can't access them.
Use File Variables for Keys
Use file variables for SSH keys, TLS certificates, kubeconfig files, and other multi-line secrets.
Rotate Secrets Regularly
Rotate API keys, database passwords, and tokens on a regular schedule. Automate rotation where possible.
Audit Variable Access
Monitor who accesses variables and when. Set up alerts for suspicious access patterns.
Use External Secret Managers
For high-security environments, integrate with Vault, AWS Secrets Manager, or GCP Secret Manager.
Limit Variable Scope
Use environment-scoped variables to limit secrets to specific environments. Don't give production secrets to staging jobs.
Security Incidents to Avoid:
- Committing a secret to the repository and pushing it
- Logging a secret without masking it
- Allowing feature branches to access production secrets
- Sharing secrets between environments unnecessarily
- Using the same secret across multiple projects
- Failing to rotate secrets after a team member leaves
- Storing secrets in job artifacts or cache
Complete Example: Variables in a Real Pipeline
# Complete example showing all variable types
stages:
- build
- test
- deploy
# Global variables (non-sensitive)
variables:
NODE_VERSION: "18"
APP_NAME: "my-app"
DOCKER_REGISTRY: "$CI_REGISTRY"
DOCKER_IMAGE: "$CI_REGISTRY_IMAGE"
# Global defaults
default:
image: node:$NODE_VERSION
before_script:
- echo "Starting job $CI_JOB_NAME"
- echo "Running in pipeline $CI_PIPELINE_ID"
- echo "On branch $CI_COMMIT_BRANCH"
# Build stage (uses global variables)
build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
# Test stage (uses masked variable for DB password)
test:
stage: test
variables:
TEST_ENV: "ci"
services:
- postgres:15
variables:
POSTGRES_DB: testdb
POSTGRES_USER: testuser
# POSTGRES_PASSWORD is set as a masked variable
# in GitLab UI (Settings → CI/CD → Variables)
script:
- echo "Running tests in $TEST_ENV"
- echo "Database: $POSTGRES_DB"
- echo "Connecting with password..." # Never print the password
- npm test
# Deploy stage (uses protected variables)
deploy_staging:
stage: deploy
environment:
name: staging
url: https://staging.example.com
script:
- echo "Deploying to staging"
- echo "Using API token: $STAGING_API_TOKEN" # Masked
- deploy.sh staging
only:
- develop
deploy_production:
stage: deploy
environment:
name: production
url: https://example.com
script:
# These are protected variables — only on protected branches
- echo "Deploying to production"
- echo "Using API token: $PROD_API_TOKEN" # Masked
- echo "Using kubeconfig: $KUBECONFIG" # File variable
- kubectl --kubeconfig=$KUBECONFIG apply -f k8s/
- deploy.sh production
when: manual
only:
- main
# Variables configured in GitLab UI (not in this file):
#
# Settings → CI/CD → Variables:
# ┌─────────────────────┬────────────┬───────────┬──────────┐
# │ Key │ Type │ Masked │ Protected│
# ├─────────────────────┼────────────┼───────────┼──────────┤
# │ STAGING_API_TOKEN │ Variable │ ✓ │ ✗ │
# │ PROD_API_TOKEN │ Variable │ ✓ │ ✓ │
# │ PROD_DB_PASSWORD │ Variable │ ✓ │ ✓ │
# │ KUBECONFIG │ File │ ✗ │ ✓ │
# │ SSH_PRIVATE_KEY │ File │ ✗ │ ✓ │
# │ DOCKER_AUTH_CONFIG │ File │ ✗ │ ✓ │
# │ SSL_CERT │ File │ ✗ │ ✓ │
# │ SSL_KEY │ File │ ✗ │ ✓ │
# └─────────────────────┴────────────┴───────────┴──────────┘
#
# Behavior:
# - STAGING_API_TOKEN available on develop branch (not protected)
# - PROD_API_TOKEN only available on main (protected)
# - KUBECONFIG file created only on protected branches
# - All masked variables show [MASKED] in logs
What This Example Demonstrates:
- Global variables for non-sensitive config
- Job variables for job-specific overrides
- Masked variables for API tokens and passwords
- Protected variables for production secrets
- File variables for kubeconfig and SSH keys
- Environment-scoped for staging vs production
- Predefined variables used throughout
Frequently Asked Questions
What's the difference between masked and protected variables?
Masked hides the value in job logs. Protected restricts the variable to protected branches and tags. They're independent — you can have a variable that's masked but not protected, protected but not masked, or both.
Can I mask multi-line values?
No. Masked variables must be single-line. For multi-line values like certificates or SSH keys, use file variables instead.
What's the minimum length for a masked variable?
The value must be at least 8 characters long. This prevents masking from interfering with legitimate short strings like "true" or "yes".
Where should I store secrets?
Use GitLab CI/CD variables in the GitLab UI (Settings → CI/CD → Variables). Never commit secrets to the repository. For high-security needs, integrate with Vault, AWS Secrets Manager, or GCP Secret Manager.
Can I override a protected variable?
No. Protected variables are read-only at the pipeline level. You can define a variable with the same name in .gitlab-ci.yml, but the UI variable takes precedence.
How do I access variables in a script?
Use standard shell syntax: $VAR, ${VAR}, or "$VAR". Always quote variables to handle special characters and prevent word splitting.
What's the difference between variables and file variables?
Variables store the literal value — $VAR contains the string. File variables store the value in a temp file — $VAR contains the file path. Use file variables for multi-line content.
How do I pass variables to a child pipeline?
Use the trigger keyword with variables inside the child pipeline trigger. Variables are inherited by default, or you can define new ones.
Variables and secrets are the configuration backbone of your CI/CD pipelines. Master them to build secure, flexible, and maintainable pipelines.