feat(gitlab/release): add age support (#10280) · updatecli/updatecli@abd1d68 · GitHub
Skip to content

Commit abd1d68

Browse files
authored
feat(gitlab/release): add age support (#10280)
* feat(gitlab/release): add age support Signed-off-by: Olblak <me@olblak.com> * chore: add age e2e test Signed-off-by: Olblak <me@olblak.com> * fix(gitlab/release): latest order Signed-off-by: Olblak <me@olblak.com> --------- Signed-off-by: Olblak <me@olblak.com>
1 parent 9c425b4 commit abd1d68

6 files changed

Lines changed: 330 additions & 13 deletions

File tree

‎e2e/updatecli.d/success.d/gitlab/release.yaml‎

Lines changed: 9 additions & 1 deletion
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package release
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/http/httptest"
7+
"strings"
8+
"testing"
9+
"time"
10+
11+
"github.com/stretchr/testify/assert"
12+
"github.com/stretchr/testify/require"
13+
"github.com/updatecli/updatecli/pkg/plugins/utils/age"
14+
gitlab "gitlab.com/gitlab-org/api/client-go"
15+
)
16+
17+
// daysAgo formats a date n days in the past the way the GitLab API reports one.
18+
func daysAgo(n int) string {
19+
return time.Now().Add(-time.Duration(n) * 24 * time.Hour).Format(time.RFC3339)
20+
}
21+
22+
// newReleaseServer serves a single page of releases, so that the age filtering is
23+
// exercised without reaching the real GitLab API.
24+
func newReleaseServer(t *testing.T, releases ...string) *httptest.Server {
25+
t.Helper()
26+
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
27+
w.Header().Set("Content-Type", "application/json")
28+
fmt.Fprintf(w, "[%s]", strings.Join(releases, ","))
29+
}))
30+
}
31+
32+
func releaseJSON(tag, released string, upcoming bool) string {
33+
return fmt.Sprintf(`{"tag_name":%q,"released_at":%q,"created_at":%q,"upcoming_release":%t}`,
34+
tag, released, released, upcoming)
35+
}
36+
37+
func newReleaseResource(t *testing.T, url string, releaseAge age.Spec) *Gitlab {
38+
t.Helper()
39+
resource, err := New(map[string]interface{}{
40+
"url": url,
41+
"owner": "updatecli",
42+
"repository": "updatecli",
43+
"age": map[string]interface{}{"minimum": releaseAge.Minimum, "maximum": releaseAge.Maximum},
44+
})
45+
require.NoError(t, err)
46+
return resource
47+
}
48+
49+
func TestSearchReleasesAge(t *testing.T) {
50+
// GitLab returns the most recent release first and SearchReleases reverses that,
51+
// so the expected values below read oldest first.
52+
releases := []string{
53+
releaseJSON("v3.0.0", daysAgo(1), false),
54+
releaseJSON("v2.0.0", daysAgo(10), false),
55+
releaseJSON("v1.0.0", daysAgo(30), false),
56+
}
57+
58+
tests := []struct {
59+
name string
60+
releaseAge age.Spec
61+
releases []string
62+
want []string
63+
wantSkip bool
64+
}{
65+
{
66+
name: "no age filter keeps every release",
67+
releases: releases,
68+
want: []string{"v1.0.0", "v2.0.0", "v3.0.0"},
69+
},
70+
{
71+
name: "the most recent release is still in cooldown",
72+
releaseAge: age.Spec{Minimum: "7d"},
73+
releases: releases,
74+
want: []string{"v1.0.0", "v2.0.0"},
75+
},
76+
{
77+
name: "releases published too long ago are discarded",
78+
releaseAge: age.Spec{Maximum: "20d"},
79+
releases: releases,
80+
want: []string{"v2.0.0", "v3.0.0"},
81+
},
82+
{
83+
name: "every release still in cooldown reports a running cooldown",
84+
releaseAge: age.Spec{Minimum: "60d"},
85+
releases: releases,
86+
wantSkip: true,
87+
},
88+
{
89+
name: "an upcoming release is not mistaken for a cooling down one",
90+
releaseAge: age.Spec{Minimum: "7d"},
91+
releases: []string{
92+
releaseJSON("v4.0.0", daysAgo(-1), true),
93+
releaseJSON("v1.0.0", daysAgo(30), false),
94+
},
95+
want: []string{"v1.0.0"},
96+
},
97+
}
98+
99+
for _, tt := range tests {
100+
t.Run(tt.name, func(t *testing.T) {
101+
server := newReleaseServer(t, tt.releases...)
102+
defer server.Close()
103+
104+
got, err := newReleaseResource(t, server.URL, tt.releaseAge).SearchReleases(tt.releaseAge)
105+
106+
if tt.wantSkip {
107+
require.Error(t, err)
108+
assert.ErrorIs(t, err, age.ErrNoVersionMatchingAge)
109+
return
110+
}
111+
112+
require.NoError(t, err)
113+
assert.Equal(t, tt.want, got)
114+
})
115+
}
116+
}
117+
118+
func TestReleaseDate(t *testing.T) {
119+
released := time.Now().Add(-24 * time.Hour)
120+
created := time.Now().Add(-48 * time.Hour)
121+
122+
tests := []struct {
123+
name string
124+
release gitlab.Release
125+
want time.Time
126+
wantOk bool
127+
}{
128+
{
129+
name: "the release date wins",
130+
release: gitlab.Release{ReleasedAt: &released, CreatedAt: &created},
131+
want: released,
132+
wantOk: true,
133+
},
134+
{
135+
name: "the creation date is the fallback",
136+
release: gitlab.Release{CreatedAt: &created},
137+
want: created,
138+
wantOk: true,
139+
},
140+
{
141+
name: "a release without any date reports none",
142+
release: gitlab.Release{},
143+
},
144+
}
145+
146+
for _, tt := range tests {
147+
t.Run(tt.name, func(t *testing.T) {
148+
got, ok := releaseDate(&tt.release)
149+
assert.Equal(t, tt.wantOk, ok)
150+
if tt.wantOk {
151+
assert.Equal(t, tt.want, got)
152+
}
153+
})
154+
}
155+
}

‎pkg/plugins/resources/gitlab/release/condition.go‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ import (
66

77
"github.com/sirupsen/logrus"
88
"github.com/updatecli/updatecli/pkg/core/pipeline/scm"
9+
"github.com/updatecli/updatecli/pkg/plugins/utils/age"
910
)
1011

1112
func (g *Gitlab) Condition(_ context.Context, source string, scm scm.ScmHandler) (pass bool, message string, err error) {
1213
if scm != nil {
1314
logrus.Warningf("Condition not supported for the plugin GitLab release")
1415
}
1516

16-
releases, err := g.SearchReleases()
17+
// A condition checks whether a specific release exists, so the age filter, which
18+
// only narrows down which release to pick, doesn't apply here.
19+
releases, err := g.SearchReleases(age.Spec{})
1720
if err != nil {
1821
return false, "", fmt.Errorf("looking for GitLab release: %w", err)
1922
}

‎pkg/plugins/resources/gitlab/release/main.go‎

Lines changed: 73 additions & 10 deletions

0 commit comments

Comments
 (0)