Comparison operations for image tags
Go to file
Comrade Renovate Bot eb3e7758d4
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
chore(deps): update golang docker tag to v1.21
2023-08-09 07:10:31 +00:00
.drone.yml chore(deps): update golang docker tag to v1.21 2023-08-09 07:10:31 +00:00
.gitignore feat: add pin compatibility check 2021-11-01 10:48:22 +01:00
LICENSE chore: godoc badge, drop makefile, clean license 2023-04-14 23:25:05 +02:00
README.md chore: godoc badge, drop makefile, clean license 2023-04-14 23:25:05 +02:00
go.mod Init 2021-08-08 17:48:33 +02:00
renovate.json chore(deps): add renovate.json 2021-11-13 21:30:20 +00:00
tagcmp.go feat: add pin compatibility check 2021-11-01 10:48:22 +01:00
tagcmp_test.go test: pin compatiliby check tests 2021-11-01 10:48:47 +01:00

README.md

tagcmp

Build Status Go Report Card Go Reference

Comparison operations for image tags. Because registries aren't doing this for us 🙄

This library is helpful if you're aiming to use only "stable" and "semver-like" tags and want to be able to do things like compare them, find which tags are more recent, sort them and other types of comparisons. This is a best-effort implementation which follows the wisdom of Renovate.

Docker doesn't really have versioning, instead it supports "tags" and these are usually used by Docker image authors as a form of versioning ... It's pretty "wild west" for tagging and not always compliant with SemVer.

The Renovate implementation allows image tags to be automatically upgraded, is the only show in town, apparently. This library follows that implementation quite closely.

Example

package main

import (
	"fmt"
	"sort"

	"coopcloud.tech/tagcmp"
)

func main() {
	rawTags := []string{
		"1.7.1",
		"1.9.4-linux-arm64",
		"1.14.2-rootless",
		"linux-arm64-rootless",
		"1.14.1-rootless",
		"1.12.4-linux-amd64",
		"1.14.0-rootless",
	}

	tag, err := tagcmp.Parse("1.14.0-rootless")
	if err != nil {
		panic(err)
	}

	var compatible []tagcmp.Tag
	for _, rawTag := range rawTags {
		parsed, _ := tagcmp.Parse(rawTag) // skips unsupported tags
		if tag.IsCompatible(parsed) {
			compatible = append(compatible, parsed)
		}
	}

	sort.Sort(tagcmp.ByTagAsc(compatible))

	fmt.Println(compatible)
}

Output:

[1.14.0-rootless 1.14.1-rootless 1.14.2-rootless]

Types of versions supported

// semver
"5",
"2.6",
"4.3.5",

// semver with 'v'
"v1",
"v2.3",
"v1.0.2",

// semver with suffix
"6-alpine",
"6.2-alpine",
"6.2.1-alpine",

// semver with sufix and 'v'
"v6-alpine",
"v6.2-alpine",
"v6.2.1-alpine",
"v6.2.1-alpine",

// semver with multiple suffix values
"6.2.1-alpine-foo",

// semver with multiple suffix values and 'v'
"v6.2.1-alpine-foo",

Types of versions not supported

Please note, we could support some of these versions if people really need them to be supported. Some tags are using a unique format which we could support by implementing a very specific parser for (e.g. ParseMinioTag, ParseZncTag). For now, this library tries to provide a Parse function which handles more general cases. Please open an issue, change sets are welcome.

// empty
"",

// patametrized
"${MAILU_VERSION:-master}",
"${PHP_VERSION}-fpm-alpine3.13",

// commit hash like
"0a1b2c3d4e5f6a7b8c9d0a1b2c3d4e5f6a7b8c9d",

// numeric
"20191109",
"e02267d",

// not semver
"3.0.6.0",
"r1295",
"version-r1070",

// prerelease
"3.7.0b1",
"3.8.0b1-alpine",

// multiple versions
"5.36-backdrop-php7.4",
"v1.0.5_3.4.0",
"v1.0.5_3.4.0_openid-sso",

// tz based
"RELEASE.2021-04-22T15-44-28Z",

// only text
"alpine",
"latest",
"master",

// multiple - delimters
"apache-debian-1.8-prod",
"version-znc-1.8.2",

License

GPLv3+

Who's using it?