GitLab CI/CD – Release

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 official release-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’s artifacts.
    • 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 include image: registry.gitlab.com/gitlab-org/release-cli:latest in your release job. This provides the necessary tool for the release 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 your main 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 the release 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

Debjeet Bhowmik

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

Leave a Comment