Add semver support for CD version sets

What does this MR do?

Cd::VersionSet names (releases) now must follow SemVer, e.g. 1.2.3 or v1.2.3-rc.1, instead of the previous permissive slug format that rejected dots — releases are versions, so they should look like versions. As a side effect, Cd::Version names (artifact tags) now also allow dots, so tags like v1.7.8 no longer need underscore substitution to be accepted.

Also adds CdApplication.suggestedNextVersionSetName, a computed field that returns the next release name for an application: the patch bump of its most-recently-created release (dropping any pre-release/build identifiers, preserving a leading v), or 0.1.0 if it has no releases yet.

Changes

  • New Gitlab::Regex.cd_version_set_name_regex / message — full SemVer with an optional leading v, used by Cd::VersionSet#name.
  • New Gitlab::Regex.cd_version_name_regex / message — same character set as cd_name_regex plus ., used by Cd::Version#name only (Application/Environment/Service/VersionSet keep the stricter cd_name_regex since those names double as infra-facing identifiers).
  • New Cd::VersionSet.parse_semver, .latest_semver, .next_suggested_name, .prefix class methods, backed by the existing Packages::SemVer parser.
  • New CdApplication.suggestedNextVersionSetName field (experiment, milestone 19.3), delegating to version_sets.next_suggested_name.
  • Regenerated GraphQL reference docs and introspection schema.

Behind the existing ai_native_deploy feature flag; no schema/migration changes. The Cd::Version change is purely additive (previously-rejected tags are now accepted). The Cd::VersionSet name format is stricter than before: names that were valid under the old slug format but aren't valid SemVer (e.g. my-release) will be rejected going forward. Existing rows are unaffected until re-saved.

How to test

1. Seed data (Rails console)
org = Organizations::Organization.first
app = FactoryBot.create(:cd_application, organization: org, name: 'payments-platform')

service = FactoryBot.create(:cd_service, application: app, organization: org)
artifact_source = FactoryBot.create(:cd_artifact_source, service: service, organization: org)
version = FactoryBot.create(:cd_version, artifact_source: artifact_source, organization: org, name: 'v1.7.8')

FactoryBot.create(:cd_version_set, application: app, organization: org, name: '1.0.0')

puts "org GID:     #{org.to_global_id}"
puts "app GID:     #{app.to_global_id}"
puts "version GID: #{version.to_global_id}"

# ensure the flag + membership for your user
Feature.enable(:ai_native_deploy)
Organizations::OrganizationUser.find_or_create_by!(organization: org, user: User.find_by_username('root')) do |ou|
  ou.access_level = Gitlab::Access::OWNER
end
2. Mutation + query (GraphQL Explorer at `/-/graphql-explorer`)
mutation($input: CdVersionSetCreateInput!) {
  cdVersionSetCreate(input: $input) {
    versionSet { id name }
    errors
  }
}

Variables (paste the app GID and version GID printed above):

{
  "input": {
    "applicationId": "gid://gitlab/Cd::Application/47",
    "name": "1.0.1",
    "versionIds": ["gid://gitlab/Cd::Version/29"]
  }
}

Then check the suggestion advances:

query($id: OrganizationsOrganizationID!) {
  organization(id: $id) {
    cdApplication(id: "gid://gitlab/Cd::Application/47") {
      suggestedNextVersionSetName
    }
  }
}

Expected: the mutation succeeds and suggestedNextVersionSetName becomes 1.0.2. Re-running the mutation with an invalid name (e.g. may-release) returns a validation error instead of creating a version set.

Sample response (create mutation):

{
  "data": {
    "cdVersionSetCreate": {
      "versionSet": {
        "id": "gid://gitlab/Cd::VersionSet/43",
        "name": "1.0.1"
      },
      "errors": []
    }
  }
}

Sample response (suggestion query):

{
  "data": {
    "organization": {
      "cdApplication": {
        "suggestedNextVersionSetName": "1.0.2"
      }
    }
  }
}

Sample response (invalid name):

{
  "data": {
    "cdVersionSetCreate": {
      "versionSet": null,
      "errors": [
        "Name should follow SemVer, with an optional leading v (for example, 1.2.3 or v1.2.3-rc.1): https://semver.org"
      ]
    }
  }
}

References

https://gitlab.com/gitlab-org/gitlab/-/work_items/606283 https://gitlab.com/gitlab-org/gitlab/-/work_items/606065

Screenshots or screen recordings

https://gitlab.com/gitlab-org/gitlab/-/work_items/606065

Before After

How to set up and validate locally

  1. In Rails console, seed data and enable the feature flag as shown in the seed step above.
  2. Open GraphQL Explorer at http://gdk.test:3000/-/graphql-explorer.
  3. Run the cdVersionSetCreate mutation with a valid SemVer name (e.g. 1.0.1) and confirm it succeeds.
  4. Query cdApplication.suggestedNextVersionSetName and confirm it reflects the patch bump of the latest release.
  5. Re-run the mutation with an invalid name (e.g. my-release) and confirm it returns a SemVer validation error instead of creating a version set.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by George Koltsov

Merge request reports

Loading
Loading