Handling versions in Kumori manifests

CUE imposes no structure in versioning CUE modules. However Kumori modules are strongly versioned, and prepared for distribution.

This situation calls for Kumori to establish a convention on how to handle versioning of Kumori modules.

As we explained, CUE modules are recognized by the folder/file structure: cue.mod/module.cue, where module.cue acts as a a metadata file for the module.

CUE only imposes a field in that file: module. Kumori adds an extra requirement for redistributable modules: kumori modules MUST also contain a kmodule.cue file at the root, with the following structure

package kmodule
{
	domain: "kumori.systems"
	module: "examples/hello-world"
	version: [
		1,
		0,
		0,
	]
  prerelease: ""
  buildmetadata: ""
	cue: "v0.4.2"
	spec: [
		1,
		0,
	]
	dependencies: "kumori.systems/kumori": {
		query:  "latest"
		target: "kumori.systems/kumori/@1.0.1-rc.3"
	}
	sums: "kumori.systems/kumori/@1.0.1-rc.3": "isjRqBXCj+LLyg6LDlWSziHHGl65QPUPCL3K9b2uu3g="
	artifacts: {
		frontend: "component"
		hellos:   "service"
	}
}

This file contains the version for all artifacts that are distributed with the module. With this extra requirement, imports of packages from files in a different module must include the semver version string after the module name prefix, followed by the path leading to the package folder. Later on we show how using xref-deprecated:developers:index.adoc[kam] can facilitate authoring kumori modules, without losing the ability to precisely refer to dependency versions.

package server
import (
  k "kumori.systems/kumori/@1.0.0:kumori"
)

The above import statement imports package kumori from version 1.0.0 of module kumori.systems/kumori

In order for the import to succeed, developers must properly declare their dependencies, and use Kumori’s xref-deprecated:developers:index.adoc[dependency resolving tools] to find the actual modules and make them available to CUE resolution algorithm.

Importing packages from the same module

When a file within a module wants to import another package from the same module, it is also necessary to include the version component in the package path. Again, using kumori’s xref-deprecated:developers:kam.adoc[tooling] facilitates such inner references.

Declaring dependencies

Dependencies are declared at the module level, within the kmodule.cue file (as shown in the example above). A dependency declaration consists of four elements:

  • The alias (e.g., in the aboge, kumori.systems/kumori). This is the module prefix of the import path for any package within the module, without needing to refer to the version within the import path.

  • The query string (e.g., latest in the above example). This string is used to find a version of the module that satisfies the "query" for a version.

  • The target (e.g., "kumori.systems/kumori/@1.0.1-rc.3"), that is, the complete module name, including domain and version, that was found when resolving the query

  • The chacksum of the target found, used to guarantee the integrity of the dependency.

See the xref-deprecated:developers:index.adoc[developers] section for details on how to declare dependencies and install them within the development context of the user, using the kam tool.

Pre-1.0.0 dependency resolution scheme

This feature is deprecated, and will be phased out in the 1.1.0 release of the platform.

Kumori still supports through the kumorictl CLI resolving dependencies from GIT repos

When developing a Kumori CUE module where some of its packages import packages from other modules, it is necessary to declare the dependencies on those other modules.

Dependency declaration is carried out within the module.cue metadata file, within the dependencies field.

The following is a simplified example:

dependencies: {
  "kumori.systems/kumori": {
    repository: " https://gitlab.com/kumori/cuemodules/kumori"
    tag: "1.0.0"
    version: "1.0.0"
  },
  "kumori.systems/integrations/hazelcast": {
    repository: "https://gitlab.com/kumori/cuemodules/hazelcast"
    srcpath: "v3"
  }
}

In this example we see two module dependencies. The first, on module "kumori.systems/kumori", references a git repo, and a tag within that repo. Furthermore, it specifies the version of the module that should be found at that location.

Kumori’s dependency resolution machinery verifies that indeed a module with that name and version exists at that location. If the verification fails, the dependency fetching/resolution machinery will issue an error.

The second dependency mentions no tag nor version, it, however, specifies a srcpath. When no tag field is provided, the resolution process assumes that the master branch of the repo must be used. If no srcpath is used, the root of the repo is used as the root of the module. In our second example, the root of the module is expected to reside within the v3 folder.

Also, in our second example, no version field is provided. What this means is that the resolution will accept whatever version is found at the location. When not providing a version in the dependency spec, import statements should take care of either not using a version component in the path, or using the correct one to be found at the target destination mentioned in the dependency specification. We advised that, in this case no version component be used in import statements.