This article covers the release
keyword in GitLab CI/CD, explaining its use in automating the creation of project releases directly from your CI/CD pipeline. We will explore how to define release details like name, tag, description, and asset links, providing practical examples and best practices for streamlining your code release management process.
Understanding the release
Keyword in GitLab CI/CD
The release
keyword in GitLab CI/CD allows you to integrate the creation of a GitLab Release directly into your CI/CD pipeline. A GitLab Release is a snapshot of your project’s code, associated with a Git tag, and often includes release notes and links to compiled binaries or other release assets. By using the release
keyword, you can automate this process, ensuring consistency and reducing manual steps.
Why Use the release
Keyword?
Automating releases with the release
keyword offers several advantages:
- Automation: Eliminates manual steps for creating releases, reducing errors and saving time.
- Consistency: Ensures that every release follows the same procedure, with consistent naming, tagging, and asset inclusion.
- Version Control Integration: Releases are directly tied to Git tags, making it easy to track the exact state of the code for each release.
- Centralized Release Management: GitLab’s “Deployments > Releases” page provides a single source of truth for all your project’s releases.
- Asset Management: Easily attach pre-compiled binaries, documentation, or other files as release assets.
Configuring release
in .gitlab-ci.yml
The release
keyword is defined at the job level. When a job containing release
completes successfully, it automatically creates or updates a GitLab Release.
Basic Release Definition
The simplest form requires a name
and a tag_name
. The tag_name
must correspond to a Git tag created by a previous job or already existing in the repository.
create_release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest # Recommended: Use Release CLI image
script:
- echo "Creating release for tag $CI_COMMIT_TAG"
rules:
- if: '$CI_COMMIT_TAG' # This job only runs when a Git tag is pushed
release:
name: 'Release $CI_COMMIT_TAG' # Name of the release
tag_name: '$CI_COMMIT_TAG' # The Git tag associated with this release
description: 'Release created from pipeline for tag $CI_COMMIT_TAG.'
In this example:
image: registry.gitlab.com/gitlab-org/release-cli:latest
: It is highly recommended to use the officialrelease-cli
image, which provides the necessary tool to interact with the GitLab Releases API.rules: - if: '$CI_COMMIT_TAG'
: This ensures the release job only runs when a Git tag is pushed.name
: The display name of the release. You can use predefined CI/CD variables (like$CI_COMMIT_TAG
).tag_name
: Crucially, this must be an existing Git tag in your repository. This is the tag that the release will be associated with. If the tag doesn’t exist, the release creation will fail.description
: The release notes. This can be a static string or dynamically generated.
Dynamic Release Description
You can populate the release description from a file, which is useful for longer release notes or changelogs generated during the pipeline.
create_release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script:
- echo "## Release Notes for $CI_COMMIT_TAG" > release_notes.md
- echo "- New feature A" >> release_notes.md
- echo "- Bug fix B" >> release_notes.md
- cat release_notes.md # For debugging
rules:
- if: '$CI_COMMIT_TAG'
release:
name: 'Application Release $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
description: './release_notes.md' # Path to a file containing the release description
Attaching Release Assets
You can attach various assets (binaries, documentation, etc.) to your release. Assets can be linked directly by URL or uploaded as a part of the release.
create_release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script:
- echo "Building application assets..."
- mkdir assets
- echo "App_v1.0.0.zip content" > assets/App_v1.0.0.zip # Simulate building an asset
- echo "README.pdf content" > assets/README.pdf # Simulate another asset
artifacts:
paths:
- assets/ # Ensure assets are available as job artifacts
rules:
- if: '$CI_COMMIT_TAG'
release:
name: 'Final App Release $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
description: 'Official release with all assets.'
assets:
links:
- name: 'Application Binary'
url: 'https://example.com/downloads/app-$CI_COMMIT_TAG.zip' # Link to an external URL
filepath: './assets/App_v1.0.0.zip' # Path to an artifact to upload as a direct asset
link_type: 'package' # Optional: 'other', 'package', 'image', 'runbook'
- name: 'Documentation PDF'
filepath: './assets/README.pdf'
link_type: 'other'
assets:links
: A list of assets to include with the release.name
: Display name of the asset.url
: A direct URL to an external asset (e.g., from a CDN or object storage).filepath
: Path to an artifact file (relative to the project root) that will be uploaded directly to the release. The file must be part of the job’sartifacts
.link_type
: (Optional) Categorizes the asset (e.g.,package
,image
,runbook
).
Release milestones
and released_at
You can associate a release with specific GitLab milestones or set a custom release date.
create_release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script:
- echo "Creating release..."
rules:
- if: '$CI_COMMIT_TAG'
release:
name: 'Release $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
description: 'Release for milestone M1.0.'
milestones:
- 'M1.0' # Associate with existing GitLab milestone(s)
- 'Phase 1'
released_at: '2025-07-12T14:30:00Z' # Custom release date/time (ISO 8601 format)
milestones
: A list of existing GitLab milestones to link to this release.released_at
: (Optional) The date and time the release was published. If omitted, it defaults to the time the job completes.
Using release
with extends
You can define a base release job and extend it for different scenarios.
.release_template:
image: registry.gitlab.com/gitlab-org/release-cli:latest
stage: release
rules:
- if: '$CI_COMMIT_TAG'
create_stable_release:
extends: .release_template
script:
- echo "Preparing stable release..."
release:
name: 'Stable App $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
description: 'Release for stable branch.'
create_patch_release:
extends: .release_template
script:
- echo "Preparing patch release..."
release:
name: 'Patch Release $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
description: 'Patch release notes.'
milestones:
- 'Patch-Fixes'
Best Practices for release
Keyword
- Trigger on Tags: Always use
rules: - if: '$CI_COMMIT_TAG'
to ensure your release job only runs when a Git tag is pushed. This is the standard practice for releases. - Use
release-cli
Image: Always includeimage: registry.gitlab.com/gitlab-org/release-cli:latest
in your release job. This provides the necessary tool for therelease
keyword to function correctly. - Ensure Tag Exists: The
tag_name
must correspond to a valid Git tag in your repository. This tag should ideally be created by a preceding job in the pipeline (e.g., a job on yourmain
branch that creates a tag when a merge request is merged) or pushed manually. - Manage Assets with Artifacts: If you want to upload assets directly, ensure they are generated by a previous job and included in the
artifacts:paths
of the release job. This makes them available for therelease
keyword to upload. - Dynamic Descriptions: Generate your release notes dynamically from a
CHANGELOG.md
or other source during the pipeline. - Protect Your Release Branch/Tags: Protect your release branches (e.g.,
main
,release-X.Y
) and Git tags in GitLab settings to prevent unauthorized pushes and ensure release integrity. - Review Releases in UI: After a pipeline runs, navigate to Deployments > Releases in your GitLab project to verify the created release.
FAQs – GitLab CI/CD Release
What is the release
keyword in GitLab CI/CD?
The release
keyword is used in .gitlab-ci.yml
to automate the creation of GitLab Releases. A release is a snapshot of your project tied to a Git tag, and it can include release notes and downloadable assets (artifacts, links). This helps in packaging and distributing versions of your application.
How do I define a release job in GitLab CI/CD?
You define a job with the release
keyword and specify metadata like the tag name, description, and optional assets:
release_job:
stage: release
script: echo "Creating GitLab release"
release:
tag_name: v1.0.0
description: "First stable release"
This job creates a release for the v1.0.0
tag with a description.
Do I need to create the Git tag before using release
?
Yes. The release must be associated with an existing Git tag. You can create the tag manually or automatically in a previous job:
git tag v1.0.0
git push origin v1.0.0
Alternatively, generate the tag dynamically via CI script and push it.
Can I use variables for dynamic release tags and descriptions?
Yes. GitLab supports using predefined or custom variables:
release_job:
stage: release
script: echo "Releasing $CI_COMMIT_TAG"
release:
tag_name: "$CI_COMMIT_TAG"
description: "Release from commit $CI_COMMIT_SHORT_SHA"
This makes the release tag dynamic, tied to the commit being built.
How do I include assets like binaries or documentation in a GitLab release?
You can attach external or internal assets to the release using assets > links
:
release_job:
stage: release
script: echo "Releasing..."
release:
tag_name: v1.0.0
description: "Release with assets"
assets:
links:
- name: "Download binary"
url: "https://mycdn.com/binaries/app-v1.0.0.tar.gz"
- name: "Documentation"
url: "https://docs.example.com/v1.0.0"
These links will appear in the GitLab release page.
Can I use artifacts as release assets?
Yes, but you need to upload artifacts in a previous job and link them via a public URL in the release
job:
build:
stage: build
script:
- make build
artifacts:
paths:
- build/output.zip
expire_in: 1 week
release_job:
stage: release
script: echo "Releasing..."
release:
tag_name: v1.0.0
description: "Download from artifacts"
assets:
links:
- name: "Output"
url: "https://gitlab.com/<namespace>/<project>/-/jobs/$CI_JOB_ID/artifacts/download"
Replace the URL with the actual job URL or set up an automated job to publish assets to an external location.
Can I create releases automatically when a tag is pushed?
Yes. Use rules
to trigger the release job only when a tag is pushed:
release_job:
stage: release
script: echo "Auto-release for tag"
release:
tag_name: "$CI_COMMIT_TAG"
description: "Automatic release for $CI_COMMIT_TAG"
rules:
- if: '$CI_COMMIT_TAG'
This ensures the release job runs only on tag pipelines.
How do I update an existing GitLab release using the release
keyword?
Simply define the same tag_name
. GitLab will update the release instead of creating a new one. This is useful for fixing release notes or adding more assets.
release:
tag_name: v1.0.0
description: "Updated release notes"
The description and asset links will be overwritten in the existing release.
Can I manage GitLab releases outside CI/CD?
Yes. You can create and manage releases via:
- GitLab Web UI → Releases
- GitLab API:
POST /projects/:id/releases
- GitLab CLI (GLab): A CLI wrapper to manage GitLab resources
However, using CI/CD and the release
keyword ensures automation and consistency.
Where do I see releases in GitLab UI?
Go to your repository and click:
Repository → Releases
Here, you will see a list of all releases, their associated tags, descriptions, timestamps, and asset links.
Can I manually trigger a release job in the pipeline?
Yes. Set the job as when: manual
:
release_job:
stage: release
script: echo "Manual release"
when: manual
release:
tag_name: v1.1.0
description: "Triggered by user"
You can then click the “Play” button in the GitLab UI to trigger the release.
Can I create a release without a script?
Yes. The script
section is required syntactically but can be a no-op if you just want to use the release
feature:
release_job:
stage: release
script:
- echo "Creating release only"
release:
tag_name: v2.0.0
description: "Release without artifacts"
Is the release
keyword supported in child pipelines or included templates?
Yes. You can define a release in child pipelines or use include:
to load it from an external .yml
file. Just ensure it is in a job context and follows normal YAML syntax rules.
Author

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com