Skip to content
Read the release manifest

Read the release manifest

This guide covers fetching a release manifest file, reading the module versions out of it, and validating it against the JSON Schema.

For what the data means — the compatibility claim a record makes, why one exact version is named rather than a range, and what neither tier claims — read The release manifest first. This page assumes you have.

Decide which tier to read

The release manifest has two tiers in two projects. Which one you read follows from whether the GitLab version you care about has published.

Your questionTierProjectAccess
Which module versions shipped with a published GitLab version?Immutable recordmanifests/releasedPublic
Which module versions are currently staged for a GitLab version that has not published?Mutable catalogmanifests/unreleasedInternal

If you are installing, reproducing, or pinning an environment, you want the record. The catalog is working state and can change until its GitLab version publishes.

The two tiers hold the same data, laid out differently. For GitLab 19.5.0:

unreleased (catalog)                 released (record)
19/                                  19/
└── 5/                               └── 5/
    └── 0/                               └── 0.json
        ├── artifact-registry.json
        ├── knowledge-graph.json
        └── iam.json

In the catalog the patch number is a directory holding one file per module. In the record it is the filename, and the single file holds every module.

Read the immutable record

1. Construct the path

A record is one file per GitLab release, holding every module:

{major}/{minor}/{patch}.json

GitLab 19.5.0 is therefore 19/5/0.json. Use the major, minor and patch numbers only: a GitLab version string can carry a suffix — 19.2.2-ee on a stable branch, 19.3.0-pre on master — and the path never does.

2. Fetch it

Fetch the record over its raw file URL. The record tier is public, so this needs no token. Save the record to disk, because the later steps read it rather than fetching it again:

export RECORD_URL="https://gitlab.com/gitlab-org/release/manifests/released/-/raw/main/19/5/0.json"

curl --fail --silent --output record.json "${RECORD_URL}"

--fail matters: without it a missing record writes GitLab’s error page to record.json and exits zero, and the failure surfaces later as invalid JSON.

3. Read the module versions

A record names every module that shipped with that GitLab version:

{
  "version": "19.5.0",
  "modules": {
    "artifact-registry": {
      "version": "1.275.1",
      "sha": "6cdaf83c809b7d02c794d5db2dea9e101c662ac7",
      "ref": "v1.275.1",
      "source": { "url": "https://gitlab.com/gitlab-org/ops/artifact-registry" }
    },
    "knowledge-graph": {
      "version": "0.95.3",
      "sha": "51aab3662a8764f47616acefdff8163312bd2bc6",
      "ref": "v0.95.3",
      "source": { "url": "https://gitlab.com/gitlab-org/orbit/knowledge-graph" }
    },
    "iam": {
      "version": "2.14.0",
      "sha": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
      "ref": "v2.14.0",
      "source": { "url": "https://gitlab.com/gitlab-org/auth/iam" }
    },
    "membrane": {
      "version": "0.8.12",
      "sha": "b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3",
      "ref": "v0.8.12",
      "source": { "url": "https://gitlab.com/gitlab-org/cells/membrane" }
    }
  }
}

Each module carries its own version, independent of GitLab’s and of every other module’s. Versions and commit SHAs throughout this page are illustrative.

The version to install for a module is modules.<module-id>.version:

jq -r '.modules["artifact-registry"].version' record.json
FieldMeaning
version (top level)The GitLab version this record describes
modulesMap of module IDs to their entries. Each key is the module’s ID within Release Framework
modules.*.versionThe module version that shipped. This is the one to install
modules.*.shaFull 40-character Git commit SHA the module released from
modules.*.refGit ref for the module release, for example v1.275.1
modules.*.source.urlThe module’s source repository

The keys under modules are module IDs. Read the key as it appears in the file. You cannot derive it from the module’s project path.

Read the mutable catalog

The catalog splits the same data the other way: one file per module, not one file per release.

{major}/{minor}/{patch}/{module-id}.json

Artifact Registry’s entry for the upcoming GitLab 19.6.0 is 19/6/0/artifact-registry.json. One module release writes the same entry to several version directories, so an entry under a version directory does not mean the module was built or tested against that GitLab version.

The file holds the module entry alone, without the surrounding modules map:

{
  "version": "1.276.0",
  "sha": "c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  "ref": "v1.276.0",
  "source": {
    "url": "https://gitlab.com/gitlab-org/ops/artifact-registry"
  }
}

Two consequences for reading it:

  • There is no single file listing every module for an upcoming release. List the directory with the Repository Tree API to see which modules have entries so far, for example path=19/6/0.
  • An entry can be replaced at any time until its GitLab version publishes, so do not cache one as though it were final.

Internal readers only. manifests/unreleased is private. GitLab team members can read it through gitlab-org membership. Automation outside gitlab-org needs a group share with the Reporter role, which the Delivery: Release and Deploy team grants.

Validate a release manifest file

One schema validates both tiers:

export SCHEMA_URL="https://gitlab.com/gitlab-org/release/manifests/schema/-/raw/main/json-schemas/release-manifest.schema.json"

pipx install check-jsonschema
check-jsonschema --schemafile "${SCHEMA_URL}" record.json

The schema resolves the two shapes with oneOf, so a file is valid when it matches exactly one of them — a record or a catalog entry. You do not select a schema per tier, and you do not need to know which shape a file holds before validating it.

Two things to expect when validation fails. Because a file must match exactly one shape, a single missing field is reported against both shapes, so most of the errors you see will be irrelevant. Both shapes also reject unknown keys, so adding a key such as $schema to a release manifest file fails validation.

Both release manifest projects validate every JSON file in CI, on merge requests and on the default branch. The writer commits to the default branch directly, so for a written entry the default-branch pipeline detects an invalid file rather than preventing it.

Handle a missing version or module

Three kinds of absence occur, and they do not mean the same thing:

  • No record for a GitLab version. Versions published before the release manifest existed have no record. The absence says nothing about which module versions those releases shipped with.
  • A record exists, but a module is not in it. That module has no recommended version for that GitLab release. This is not a statement that the module is incompatible with it.
  • The entry was never written. An entry can be missing even though the module released successfully. The write does not run as part of the module’s release, and a write that fails or never runs does not fail that release. So absence does not imply the module published late.

Handle all three as “no answer”, not as an error and not as an implied version. Falling back to a neighbouring release’s record substitutes a version pair that was never published together.

Related

Last updated on