Skip to content

Commit 977faa5

Browse files
nfranzeckcesmarvin
authored andcommitted
Merge branch 'release/v0.15.0' into main
2 parents d149212 + 7babff3 commit 977faa5

9 files changed

+195
-83
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
99

10+
## [v0.15.0] - 2024-11-13
11+
### Added
12+
- [#43] add a timestamp to `dogu_v1` and `dogu_v2` which represents the date and time when a dogu was created
13+
- [#50] Add string representation to `core.Version`
14+
1015
## [v0.14.4] - 2024-11-06
1116
### Fixed
1217
- [#48] Map nginx dependency to `nginx-ingress` and `nginx-static`.

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Set these to the desired values
22
ARTIFACT_ID=cesapp-lib
3-
VERSION=0.14.4
3+
VERSION=0.15.0
44

55
GOTAG?=1.18.6
66
MAKEFILES_VERSION=7.4.0

core/dogu_format_manager_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,8 @@ func Test_DoguFormatProvider_WriteDoguToString(t *testing.T) {
645645
{Type: DependencyTypeDogu, Name: "cas"},
646646
}
647647
dogu := Dogu{Name: "jenkins", Version: "1.625.2", DisplayName: "Jenkins CI", Dependencies: expectedDependencies}
648-
expectedRepresentationV1 := "{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[\"cas\"],\"OptionalDependencies\":null}"
649-
expectedRepresentationV2 := "{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[{\"type\":\"dogu\",\"name\":\"cas\",\"version\":\"\"}],\"OptionalDependencies\":null}"
648+
expectedRepresentationV1 := "{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"PublishedAt\":\"0001-01-01T00:00:00Z\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[\"cas\"],\"OptionalDependencies\":null}"
649+
expectedRepresentationV2 := "{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"PublishedAt\":\"0001-01-01T00:00:00Z\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[{\"type\":\"dogu\",\"name\":\"cas\",\"version\":\"\"}],\"OptionalDependencies\":null}"
650650

651651
t.Run("Convert given dogu object into the string representation", func(t *testing.T) {
652652
tests := []formatTest{
@@ -681,8 +681,8 @@ func Test_DoguFormatProvider_WriteDogusToString(t *testing.T) {
681681
dogu1 := Dogu{Name: "jenkins", Version: "1.625.2", DisplayName: "Jenkins CI", Dependencies: expectedDependencies}
682682
dogu2 := Dogu{Name: "scm", Version: "2.625.2", DisplayName: "Scm Manager", Dependencies: expectedDependencies}
683683
dogus := []*Dogu{&dogu1, &dogu2}
684-
expectedRepresentationV1 := "[{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[\"cas\"],\"OptionalDependencies\":null},{\"Name\":\"scm\",\"Version\":\"2.625.2\",\"DisplayName\":\"Scm Manager\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[\"cas\"],\"OptionalDependencies\":null}]"
685-
expectedRepresentationV2 := "[{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[{\"type\":\"dogu\",\"name\":\"cas\",\"version\":\"\"}],\"OptionalDependencies\":null},{\"Name\":\"scm\",\"Version\":\"2.625.2\",\"DisplayName\":\"Scm Manager\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[{\"type\":\"dogu\",\"name\":\"cas\",\"version\":\"\"}],\"OptionalDependencies\":null}]"
684+
expectedRepresentationV1 := "[{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"PublishedAt\":\"0001-01-01T00:00:00Z\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[\"cas\"],\"OptionalDependencies\":null},{\"Name\":\"scm\",\"Version\":\"2.625.2\",\"PublishedAt\":\"0001-01-01T00:00:00Z\",\"DisplayName\":\"Scm Manager\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[\"cas\"],\"OptionalDependencies\":null}]"
685+
expectedRepresentationV2 := "[{\"Name\":\"jenkins\",\"Version\":\"1.625.2\",\"PublishedAt\":\"0001-01-01T00:00:00Z\",\"DisplayName\":\"Jenkins CI\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[{\"type\":\"dogu\",\"name\":\"cas\",\"version\":\"\"}],\"OptionalDependencies\":null},{\"Name\":\"scm\",\"Version\":\"2.625.2\",\"PublishedAt\":\"0001-01-01T00:00:00Z\",\"DisplayName\":\"Scm Manager\",\"Description\":\"\",\"Category\":\"\",\"Tags\":null,\"Logo\":\"\",\"URL\":\"\",\"Image\":\"\",\"ExposedPorts\":null,\"ExposedCommands\":null,\"Volumes\":null,\"HealthCheck\":{\"Type\":\"\",\"State\":\"\",\"Port\":0,\"Path\":\"\",\"Parameters\":null},\"HealthChecks\":null,\"ServiceAccounts\":null,\"Privileged\":false,\"Configuration\":null,\"Properties\":null,\"EnvironmentVariables\":null,\"Dependencies\":[{\"type\":\"dogu\",\"name\":\"cas\",\"version\":\"\"}],\"OptionalDependencies\":null}]"
686686

687687
t.Run("Convert given dogu object into the string representation", func(t *testing.T) {
688688
tests := []formatTest{

core/dogu_v1.go

+24-20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package core
22

33
import (
44
"encoding/json"
5+
"time"
56
)
67

78
// DoguV1 defines an application for the CES. A dogu defines the image and meta information for
@@ -12,6 +13,7 @@ import (
1213
type DoguV1 struct {
1314
Name string
1415
Version string
16+
PublishedAt time.Time
1517
DisplayName string
1618
Description string
1719
Category string
@@ -35,26 +37,28 @@ type DoguV1 struct {
3537

3638
// CreateV2Copy creates a deep DoguV2 copy from an existing DoguV1 object.
3739
func (d *DoguV1) CreateV2Copy() Dogu {
38-
dogu := Dogu{}
39-
dogu.Name = d.Name
40-
dogu.Version = d.Version
41-
dogu.DisplayName = d.DisplayName
42-
dogu.Description = d.Description
43-
dogu.Category = d.Category
44-
dogu.Tags = d.Tags
45-
dogu.Logo = d.Logo
46-
dogu.URL = d.URL
47-
dogu.Image = d.Image
48-
dogu.ExposedPorts = d.ExposedPorts
49-
dogu.ExposedCommands = d.ExposedCommands
50-
dogu.Volumes = d.Volumes
51-
dogu.HealthCheck = d.HealthCheck
52-
dogu.HealthChecks = d.HealthChecks
53-
dogu.ServiceAccounts = d.ServiceAccounts
54-
dogu.Privileged = d.Privileged
55-
dogu.Configuration = d.Configuration
56-
dogu.Properties = d.Properties
57-
dogu.EnvironmentVariables = d.EnvironmentVariables
40+
dogu := Dogu{
41+
Name: d.Name,
42+
Version: d.Version,
43+
PublishedAt: d.PublishedAt,
44+
DisplayName: d.DisplayName,
45+
Description: d.Description,
46+
Category: d.Category,
47+
Tags: d.Tags,
48+
Logo: d.Logo,
49+
URL: d.URL,
50+
Image: d.Image,
51+
ExposedPorts: d.ExposedPorts,
52+
ExposedCommands: d.ExposedCommands,
53+
Volumes: d.Volumes,
54+
HealthCheck: d.HealthCheck,
55+
HealthChecks: d.HealthChecks,
56+
ServiceAccounts: d.ServiceAccounts,
57+
Privileged: d.Privileged,
58+
Configuration: d.Configuration,
59+
Properties: d.Properties,
60+
EnvironmentVariables: d.EnvironmentVariables,
61+
}
5862

5963
// upgrade dependencies to new version
6064
// the old schema only contained dogus as dependencies

core/dogu_v1_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package core
22

33
import (
44
"testing"
5+
"time"
56

67
"github.com/stretchr/testify/assert"
78
)
@@ -12,6 +13,7 @@ func Test_DoguV1_createV2Copy(t *testing.T) {
1213
doguV1 := DoguV1{
1314
Name: "test",
1415
Version: "0.1",
16+
PublishedAt: time.Date(2024, 10, 16, 7, 33, 45, 456, time.UTC),
1517
DisplayName: "displayName",
1618
Description: "description",
1719
Category: "category",
@@ -95,6 +97,7 @@ func Test_DoguV1_createV2Copy(t *testing.T) {
9597
// then
9698
assert.Equal(t, doguV1.Name, doguV2.Name)
9799
assert.Equal(t, doguV1.Version, doguV2.Version)
100+
assert.Equal(t, doguV1.PublishedAt, doguV2.PublishedAt)
98101
assert.Equal(t, doguV1.DisplayName, doguV2.DisplayName)
99102
assert.Equal(t, doguV1.Description, doguV2.Description)
100103
assert.Equal(t, doguV1.Category, doguV2.Category)
@@ -123,6 +126,7 @@ func Test_newDoguV1Object(t *testing.T) {
123126
doguV2 := Dogu{
124127
Name: "test",
125128
Version: "0.1",
129+
PublishedAt: time.Date(2024, 10, 16, 7, 33, 45, 456, time.UTC),
126130
DisplayName: "displayName",
127131
Description: "description",
128132
Category: "category",
@@ -200,6 +204,7 @@ func Test_newDoguV1Object(t *testing.T) {
200204
// then
201205
assert.Equal(t, doguV2.Name, doguV1.Name)
202206
assert.Equal(t, doguV2.Version, doguV1.Version)
207+
assert.Equal(t, doguV2.PublishedAt, doguV1.PublishedAt)
203208
assert.Equal(t, doguV2.DisplayName, doguV1.DisplayName)
204209
assert.Equal(t, doguV2.Description, doguV1.Description)
205210
assert.Equal(t, doguV2.Category, doguV1.Category)

core/dogu_v2.go

+70-57
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package core
33
import (
44
"fmt"
55
"strings"
6+
"time"
67

78
"encoding/json"
89
)
@@ -291,11 +292,11 @@ func (env EnvironmentVariable) String() string {
291292
// ServiceAccount struct can be used to get access to another dogu.
292293
//
293294
// Example:
294-
// {
295-
// "Type": "k8s-dogu-operator",
296-
// "Kind": "k8s"
297-
// }
298295
//
296+
// {
297+
// "Type": "k8s-dogu-operator",
298+
// "Kind": "k8s"
299+
// }
299300
type ServiceAccount struct {
300301
// Type contains the name of the service on which the account should be created. This field is mandatory.
301302
//
@@ -506,41 +507,41 @@ type Dependency struct {
506507
// the [OCI container image], Dogu describes all necessities for automatic container instantiation, f. i. volumes,
507508
// dependencies towards other dogus, and much more.
508509
//
509-
// [OCI container image]: https://opencontainers.org/
510-
//
511510
// Example:
512-
// {
513-
// "Name": "official/newdogu",
514-
// "Version": "1.0.0-1",
515-
// "DisplayName": "My new Dogu",
516-
// "Description": "Newdogu is a test application",
517-
// "Category": "Development Apps",
518-
// "Tags": ["warp"],
519-
// "Url": "https://www.company.com/newdogu",
520-
// "Image": "registry.cloudogu.com/namespace/newdogu",
521-
// "Dependencies": [
522-
// {
523-
// "type":"dogu",
524-
// "name":"nginx"
525-
// }
526-
// ],
527-
// "Volumes": [
528-
// {
529-
// "Name": "temp",
530-
// "Path":"/tmp",
531-
// "Owner":"1000",
532-
// "Group":"1000",
533-
// "NeedsBackup": false
534-
// }
535-
// ],
536-
// "HealthChecks": [
537-
// {
538-
// "Type": "tcp",
539-
// "Port": 8080
540-
// }
541-
// ]
542-
// }
543511
//
512+
// {
513+
// "Name": "official/newdogu",
514+
// "Version": "1.0.0-1",
515+
// "DisplayName": "My new Dogu",
516+
// "Description": "Newdogu is a test application",
517+
// "Category": "Development Apps",
518+
// "Tags": ["warp"],
519+
// "Url": "https://www.company.com/newdogu",
520+
// "Image": "registry.cloudogu.com/namespace/newdogu",
521+
// "Dependencies": [
522+
// {
523+
// "type":"dogu",
524+
// "name":"nginx"
525+
// }
526+
// ],
527+
// "Volumes": [
528+
// {
529+
// "Name": "temp",
530+
// "Path":"/tmp",
531+
// "Owner":"1000",
532+
// "Group":"1000",
533+
// "NeedsBackup": false
534+
// }
535+
// ],
536+
// "HealthChecks": [
537+
// {
538+
// "Type": "tcp",
539+
// "Port": 8080
540+
// }
541+
// ]
542+
// }
543+
//
544+
// [OCI container image]: https://opencontainers.org/
544545
type Dogu struct {
545546
// Name contains the dogu's full qualified name which consists of the dogu namespace and the dogu simple name,
546547
// delimited by a single forward slash "/". This field is mandatory.
@@ -601,6 +602,16 @@ type Dogu struct {
601602
// VERSION="1.23.2-1"
602603
//
603604
Version string
605+
// PublishedAt is the date and time when the dogu was created.
606+
//
607+
// This field does not need to be filled in by the developer. The dogu.cloudogu.com service automatically replaces
608+
// the content with the current time when the new dogu is created.
609+
//
610+
// Examples:
611+
// - 2024-10-16T07:49:34.738Z
612+
// - 2019-05-03T13:31:48.612Z
613+
//
614+
PublishedAt time.Time
604615
// DisplayName is the name of the dogu which is used in UI frontends to represent the dogu. This field is mandatory.
605616
//
606617
// Usages:
@@ -1173,26 +1184,28 @@ func GetNamespace(fullDoguName string) string {
11731184

11741185
// CreateV1Copy converts this dogu object into a deep-copied DoguV1 object (for legacy reasons).
11751186
func (d *Dogu) CreateV1Copy() DoguV1 {
1176-
dogu := DoguV1{}
1177-
dogu.Name = d.Name
1178-
dogu.Version = d.Version
1179-
dogu.DisplayName = d.DisplayName
1180-
dogu.Description = d.Description
1181-
dogu.Category = d.Category
1182-
dogu.Tags = d.Tags
1183-
dogu.Logo = d.Logo
1184-
dogu.URL = d.URL
1185-
dogu.Image = d.Image
1186-
dogu.ExposedPorts = d.ExposedPorts
1187-
dogu.ExposedCommands = d.ExposedCommands
1188-
dogu.Volumes = d.Volumes
1189-
dogu.HealthCheck = d.HealthCheck
1190-
dogu.HealthChecks = d.HealthChecks
1191-
dogu.ServiceAccounts = d.ServiceAccounts
1192-
dogu.Privileged = d.Privileged
1193-
dogu.Configuration = d.Configuration
1194-
dogu.Properties = d.Properties
1195-
dogu.EnvironmentVariables = d.EnvironmentVariables
1187+
dogu := DoguV1{
1188+
Name: d.Name,
1189+
Version: d.Version,
1190+
PublishedAt: d.PublishedAt,
1191+
DisplayName: d.DisplayName,
1192+
Description: d.Description,
1193+
Category: d.Category,
1194+
Tags: d.Tags,
1195+
Logo: d.Logo,
1196+
URL: d.URL,
1197+
Image: d.Image,
1198+
ExposedPorts: d.ExposedPorts,
1199+
ExposedCommands: d.ExposedCommands,
1200+
Volumes: d.Volumes,
1201+
HealthCheck: d.HealthCheck,
1202+
HealthChecks: d.HealthChecks,
1203+
ServiceAccounts: d.ServiceAccounts,
1204+
Privileged: d.Privileged,
1205+
Configuration: d.Configuration,
1206+
Properties: d.Properties,
1207+
EnvironmentVariables: d.EnvironmentVariables,
1208+
}
11961209

11971210
var dependencies []string
11981211
for _, dependency := range d.GetDependenciesOfType(DependencyTypeDogu) {

core/marketing_dogu.go

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package core
22

3+
import "time"
4+
35
// MarketingDogu describes properties of a dogu which can be used to enhance the representation of a dogu in UI frontends.
46
//
57
// Example:
@@ -74,6 +76,27 @@ type MarketingDogu struct {
7476
//
7577
// See also Dogu.Name for how dogu names are constructed.
7678
Name string
79+
// Version defines the actual version of the dogu.
80+
//
81+
// The version follows the format from semantic versioning and additionally is split in two parts.
82+
// The application version and the dogu version.
83+
//
84+
// An example would be 1.7.8-1 or 2.2.0-4. The first part of the version (e.g. 1.7.8) represents the
85+
// version of the application (e.g. the nginx version in the nginx dogu). The second part represents the version
86+
// of the dogu and for an initial release it should start at 1 (e.g. 1.7.8-1).
87+
//
88+
// Example versions in the dogu.json:
89+
// - 1.7.8-1
90+
// - 2.2.0-4
91+
//
92+
Version string
93+
// PublishedAt is the date and time when the dogu was created.
94+
//
95+
// Examples:
96+
// - 2024-10-16T07:49:34.738Z
97+
// - 2019-05-03T13:31:48.612Z
98+
//
99+
PublishedAt time.Time
77100
// DisplayName is the name of the dogu which is used in UI frontends to represent the dogu.
78101
//
79102
// Examples:

core/version.go

+26-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func ParseVersion(raw string) (Version, error) {
6565
}
6666

6767
// Version struct can be used to extract single parts of a version number or to compare version with each other.
68-
// The version struct can with four or less digits, plus an extra version which is divided by a hyphen.
68+
// The version struct can with four or fewer digits, plus an extra version which is divided by a hyphen.
6969
// For example: 4.0.7.11-3 => 4 Major, 0 Minor, 7 Patch, 11 Nano, 3 Extra
7070
type Version struct {
7171
Raw string
@@ -142,6 +142,31 @@ func (v *Version) getParts() []int {
142142
return []int{v.Major, v.Minor, v.Patch, v.Nano, v.Extra}
143143
}
144144

145+
// String returns a string representation of a Version object. The string will be reduced to the format Major.Minor.Patch
146+
// if the values of Extra and/or Nano are equal to zero and thus indicating that they are not set.
147+
func (v *Version) String() string {
148+
if v.Raw != "" {
149+
return v.Raw
150+
}
151+
152+
verBuilder := strings.Builder{}
153+
verBuilder.WriteString(strconv.Itoa(v.Major))
154+
verBuilder.WriteString(".")
155+
verBuilder.WriteString(strconv.Itoa(v.Minor))
156+
verBuilder.WriteString(".")
157+
verBuilder.WriteString(strconv.Itoa(v.Patch))
158+
if v.Nano != 0 || v.Extra != 0 {
159+
verBuilder.WriteString(".")
160+
verBuilder.WriteString(strconv.Itoa(v.Nano))
161+
}
162+
if v.Extra != 0 {
163+
verBuilder.WriteString("-")
164+
verBuilder.WriteString(strconv.Itoa(v.Extra))
165+
}
166+
167+
return verBuilder.String()
168+
}
169+
145170
// ByVersion implements sort.Interface for []Version to sort versions
146171
type ByVersion []Version
147172

0 commit comments

Comments
 (0)