Skip to content

Commit f3a106f

Browse files
committed
Fix check action to comply with concourse resource spec
* now we return a list of versions starting from the requested one, up to the current one * if there is no requested version (eg. this is the first check for this resource) then we return the latest 10 versions.
1 parent 4ae6ce2 commit f3a106f

File tree

1 file changed

+57
-13
lines changed

1 file changed

+57
-13
lines changed

pkg/resource/check.go

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ package resource
66
import (
77
"context"
88
"fmt"
9-
109
"github.com/Masterminds/semver/v3"
1110
"github.com/pkg/errors"
1211
"oras.land/oras-go/v2/registry"
12+
"oras.land/oras-go/v2/registry/remote"
13+
"slices"
1314
)
1415

1516
type (
@@ -31,30 +32,73 @@ func Check(ctx context.Context, request CheckRequest) (*CheckResponse, error) {
3132
return nil, errors.Wrap(err, "failed to create repository client")
3233
}
3334

34-
// Fetching repository tags
35+
// Fetch repository tags
3536
allTags, err := registry.Tags(ctx, repo)
3637
if err != nil {
3738
return nil, errors.Wrap(err, "failed to fetch tags")
3839
}
3940

40-
// Sorting tags.
41-
var latestTag *semver.Version
42-
for _, tag := range allTags {
43-
v, err := semver.NewVersion(tag)
41+
// Sort tags by semver
42+
sortedSemvers, err := sortBySemver(allTags)
43+
if err != nil {
44+
return nil, err
45+
}
46+
47+
// chop the list at the index of the requested version, if there was one
48+
if request.Version != nil {
49+
requestedVersion, err := semver.NewVersion(request.Version.Tag)
4450
if err != nil {
45-
return nil, errors.Wrap(err, fmt.Sprintf("failed to parse semver in tag %q", tag))
51+
return nil, errors.Wrap(err, fmt.Sprintf("failed to parse semver in requested version %q", request.Version.Tag))
52+
}
53+
for i, version := range sortedSemvers {
54+
if version.GreaterThanEqual(requestedVersion) {
55+
sortedSemvers = sortedSemvers[i:]
56+
break
57+
}
4658
}
47-
if latestTag == nil || v.GreaterThan(latestTag) {
48-
latestTag = v
59+
} else {
60+
// if no version was requested, return the latest 10 versions
61+
startIndex := len(sortedSemvers) - 10
62+
if startIndex < 0 {
63+
startIndex = 0
4964
}
65+
sortedSemvers = sortedSemvers[startIndex:]
5066
}
51-
if latestTag == nil {
67+
68+
if len(sortedSemvers) == 0 {
5269
return nil, fmt.Errorf("no latest tag found for source %s", request.Source.String())
5370
}
5471

55-
digest, err := getDigestForTag(ctx, repo, latestTag.Original())
72+
resolvedVersions, err := resolveImageDigests(ctx, sortedSemvers, repo)
5673
if err != nil {
57-
return nil, errors.Wrap(err, fmt.Sprintf("failed to fetch digest for latest tag %q (parsed as %s)", latestTag.Original(), latestTag.String()))
74+
return nil, err
75+
}
76+
return &resolvedVersions, nil
77+
}
78+
79+
func sortBySemver(allTags []string) ([]semver.Version, error) {
80+
allVersions := make([]semver.Version, len(allTags))
81+
for i, tag := range allTags {
82+
v, err := semver.NewVersion(tag)
83+
if err != nil {
84+
return nil, errors.Wrap(err, fmt.Sprintf("failed to parse semver in tag %q", tag))
85+
}
86+
allVersions[i] = *v
87+
}
88+
slices.SortStableFunc(allVersions, func(i, j semver.Version) int {
89+
return i.Compare(&j)
90+
})
91+
return allVersions, nil
92+
}
93+
94+
func resolveImageDigests(ctx context.Context, sortedSemvers []semver.Version, repo *remote.Repository) (CheckResponse, error) {
95+
resolvedVersions := make(CheckResponse, len(sortedSemvers))
96+
for i, version := range sortedSemvers {
97+
digest, err := getDigestForTag(ctx, repo, version.Original())
98+
if err != nil {
99+
return nil, errors.Wrap(err, fmt.Sprintf("failed to fetch digest for latest tag %q (parsed as %s)", version.Original(), version.String()))
100+
}
101+
resolvedVersions[i] = Version{Tag: version.Original(), Digest: digest}
58102
}
59-
return &CheckResponse{{Tag: latestTag.Original(), Digest: digest}}, nil
103+
return resolvedVersions, nil
60104
}

0 commit comments

Comments
 (0)