Custom Versioning Schema for custom base images
The Custom Versioning Schema (CVS) is a method for Snyk to understand your company’s container image tag versioning scheme. It enables Snyk to give more accurate base image upgrade recommendations.
A versioning schema is a system of identifying and organizing different versions of a Project. It is used to track changes and updates to the Project over time and to help users identify which version they are using.
A versioning schema typically consists of a series of numbers or labels that are incremented to reflect the progression of versions.
For example, a versioning schema can use a series of numbers, such as "1.0", "1.1", "2.0", and so on, to indicate major and minor releases of a product.
A consistent and well-defined versioning schema helps users and tools understand and track the development of a Project.
CVS is essentially a regular expression that groups the different parts of an image’s tag into comparable sections.
As an example, consider the following image tags:
Because this repository’s image tags do not follow the semantic versioning standard, it is necessary to describe the tags using a custom versioning schema.
snyk/exampletag schema is defined by the following elements, in this order:
- 1.A number whose value has the highest significance (MAJOR part)
- 2.A period
- 3.Another number, whose significance is less than the first number number (MINOR part)
- 4.An underscore followed by the letter "V" (version)
- 5.A number whose value is the least significant.
For Snyk to understand the different parts and their role, it is necessary to define a schema. In this regular expression, named groups represent the significant variables.
The schema below is a translated version of the above example and its elements.
Instead of naming a group "SIGNIFICANT", the name is changed to the letter "C" followed by a number. "C" stands for "compare", and the number represents the significance of that group, where 0 is the most significant.
- Parses all of the tags in a repository using this expression.
- Compares the values in order of significance.
- Generates a set of images ordered by their tags.
Snyk can then use this ordered set to give better recommendations.
The example below expands on the repository in the previous example and includes a small modification to add a slim version of each image.
The schema below ensures that you receive only recommendations for the flavor you are currently using.
This includes a new group M0, where "M" stands for "match." Snyk then uses this group to filter out possible image recommendations where the MATCH group's value is not equal.
The number following "M" differentiates the multiple categories that your tag can have. In this case, there is only one category of things to match against, so there is only one MATCH group.
For example, recommendations for
snyk/example:1.2_V3-slimdo not include images whose M0 group does not equal "slim".
The example below shows how to develop the expression for this registry.
Start with defining the simple SemVer element:
This groups the major, minor, and patch parts of the tag.
Next, there is a section that indicates the underlying OS distribution. Here, there are two options:
- If the OS that the base image is using is not a concern, and only the version's magnitude is a concern, "ignore" this section by not grouping it in the regex:
- To avoid a mismatch between distributions, add a MATCH group:
Now, the expression looks like this:
Next is the date element. Sometimes dates are there only to provide more information and need not be taken into consideration when comparing versions. In this case, skip over it.
If the date element is important, decide how significant each date element is relative to the SemVer. For example, is the year more significant than a major version?
To keep the significance order, use the regex:
Since the date is ordered in such a way that the number produced by concatenating the year, month, day, and hour can be compared to another concatenated date correctly, the long regex above can be replaced with a simpler one:
Now the regex looks like this:
The optional flavor is last. Add another MATCH group here and make it optional:
This avoids getting
slimrecommended if it is not in use and only gets
slimrecommended if it is being used.
The complete custom versioning schema expression looks like this:
In cases where a repository does not have a consistent tagging format, you can use non-capture groups.
The above repository contains an inconsistent number of capture groups. To handle this, use the following expression:
(?:\.(?<C2>\d+))?, the expression optionally includes a COMPARE group.
When there is an inconsistent number of COMPARE groups, Snyk filters out tags that do not contain enough information to compare them accurately. That is, to get a recommendation for
snyk/example:1.2.4, Snyk does not consider
snyk/example:1.2to be a newer version because it is not possible to know whether
1.2is the same as
1.2.0or whether it is a rolling tag that points to
1.3.5are both higher than
1.2.4and are taken into account as a possible recommendation.
1.3.5have the same issue as
1.2.4, the recommendation is either
1.3.5. At this point, the specific version that is recommended depends on undefined internal factors. However, Snyk aims to improve this logic.
- Note that the regular expression string is parsed as an ECMAScript regex and then internally converted to RE2 syntax. For example, use the
(?<name>re)syntax for grouping.
(?P<name>re)will not parse correctly.
The maximum length of the expression is 1,000 characters, with up to 100 COMPARE groups and 100 MATCH groups.
- All named groups must start with either the letter "C" or the letter "M", followed by an index.
- There must be at least one COMPARE group.
- If an unnamed group is required, it must be explicitly marked as non-capturing.
- If a compare group is an unsigned integer, compare its numeric value. Else, it will be treated as a string.
- MATCH groups are case-sensitive.
- If a MATCH group exists on one tag and not the other, due to the use of optional groups, the tags are considered not matching.
Use of unsupported or invalid regex syntax
This error can happen if an expression that does not conform to ECMAScript syntax is passed.
An example is using Python’s named capture group syntax
In the example, change the capture group syntax from
Use of an unsupported regex feature
This error can happen if an expression is passed that contains unsupported regex features such as lookahead assertions and backreferences.
There is no simple fix. The expression must be redesigned to work without such features.
Group name format is incorrect
Custom Versioning Schema uses named groups that follow a specific naming format.
This error can happen if a named group exists that does not follow the format of either a
M, followed by a positive number, such as
Change the group name to fit the format. If you need only a group, you can use non-capture groups.
Operator index is too big
This error can happen if the number in your named group is larger than 100, such as
Use a number between 0 and 100.
Take into consideration that each character does not require its own separate group. If it makes logical sense, bunch the characters together to end up with fewer groups.
If you still require more than 100 groups, CVS might not be a great fit.
Group is missing a name
This error can happen if a group other than a named group or non-capture group is used.
Often the solution is to explicitly define a non-capture group.
No groups were found
CVS uses named groups to categorize the parts of the tag into comparable sections.
This error can happen if no named groups are found, in which case Snyk cannot compare different image tags to each other.
Expression length is not supported
As with every user input, a maximum length must be set. In this case, the limit is 1,000 characters.
If your expression string is longer than 1,000 characters, Snyk is not able to parse it.
If you still require more than 1,000 characters to describe your tags, CVS might not be a great fit.