mirror of
https://github.com/hanzoai/cd.git
synced 2026-10-30 14:56:45 +00:00
go fix applied the modernizers: promoted-field keys in struct literals,
strings.Cut, SplitSeq, new(expr), slices and maps helpers, wg.Go, reflect.TypeFor
and errors.AsType. omitzero is left out, since omitting a zero struct such as
time.Time{} is a per-field wire decision and not a mechanical one.
Two changes the modernizers could not make for themselves. AsType needs its type
argument to be an error, so the git exit-status reader embeds error in the
interface it asks for. And an error built by concatenating a tag list into its
own format string now says so with a verb, which is what vet was pointing at.
Co-authored-by: Hanzo Dev <[email protected]>
231 lines
5.5 KiB
Go
231 lines
5.5 KiB
Go
package webhook
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/sirupsen/logrus/hooks/test"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/hanzoai/cd/pkg/apis/application/v1alpha1"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
kubetesting "k8s.io/client-go/testing"
|
|
)
|
|
|
|
func TestNormalizeOCI(t *testing.T) {
|
|
t.Parallel()
|
|
tests := []struct {
|
|
name string
|
|
url string
|
|
expected string
|
|
}{
|
|
{"strips oci:// prefix and lowercases", "oci://GHCR.IO/USER/REPO", "ghcr.io/user/repo"},
|
|
{"strips oci:// prefix and trailing slash", "oci://ghcr.io/user/repo/", "ghcr.io/user/repo"},
|
|
{"already normalized with prefix", "oci://ghcr.io/user/repo", "ghcr.io/user/repo"},
|
|
{"without oci:// prefix", "ghcr.io/user/repo", "ghcr.io/user/repo"},
|
|
{"uppercase without prefix", "GHCR.IO/USER/REPO", "ghcr.io/user/repo"},
|
|
{"empty", "", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
got := normalizeOCI(tt.url)
|
|
assert.Equal(t, tt.expected, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGHCRHandlerCanHandle(t *testing.T) {
|
|
t.Parallel()
|
|
h := newGHCRParser("")
|
|
|
|
tests := []struct {
|
|
name string
|
|
event string
|
|
expected bool
|
|
}{
|
|
{"package event", "package", true},
|
|
{"registry package event", "registry_package", false},
|
|
{"push event", "push", false},
|
|
{"empty", "", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, "/", http.NoBody)
|
|
req.Header.Set("X-GitHub-Event", tt.event)
|
|
assert.Equal(t, tt.expected, h.CanHandle(req))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRegistryPackageEvent(t *testing.T) {
|
|
hook := test.NewGlobal()
|
|
h := NewMockHandler(nil, []string{})
|
|
req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, "/v1/webhook", http.NoBody)
|
|
req.Header.Set("X-GitHub-Event", "package")
|
|
payload, err := os.ReadFile("testdata/ghcr-package-event.json")
|
|
require.NoError(t, err)
|
|
req.Body = io.NopCloser(bytes.NewReader(payload))
|
|
|
|
w := httptest.NewRecorder()
|
|
h.Handler(w, req)
|
|
h.Shutdown()
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
assertLogContains(t, hook, "Received registry webhook event")
|
|
}
|
|
|
|
func TestHandleRegistryEvent_RefreshMatchingApp(t *testing.T) {
|
|
hook := test.NewGlobal()
|
|
|
|
patchedApps := []string{}
|
|
|
|
reaction := func(action kubetesting.Action) (bool, runtime.Object, error) {
|
|
patch := action.(kubetesting.PatchAction)
|
|
patchedApps = append(patchedApps, patch.GetName())
|
|
return true, nil, nil
|
|
}
|
|
|
|
h := NewMockHandler(
|
|
&reactorDef{"patch", "applications", reaction},
|
|
[]string{},
|
|
&v1alpha1.Application{
|
|
Name: "oci-app",
|
|
Namespace: "cd",
|
|
Spec: v1alpha1.ApplicationSpec{
|
|
Sources: v1alpha1.ApplicationSources{
|
|
{
|
|
RepoURL: "oci://ghcr.io/user/repo",
|
|
TargetRevision: "1.0.0",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
event := &RegistryEvent{
|
|
RegistryURL: "ghcr.io",
|
|
Repository: "user/repo",
|
|
Tag: "1.0.0",
|
|
}
|
|
|
|
h.HandleRegistryEvent(event)
|
|
|
|
assert.Contains(t, patchedApps, "oci-app")
|
|
assert.Contains(t, hook.LastEntry().Message, "Requested app 'oci-app' refresh")
|
|
}
|
|
|
|
func TestHandleRegistryEvent_RepoMismatch(t *testing.T) {
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
hook := test.NewGlobal()
|
|
|
|
h := NewMockHandler(nil, []string{},
|
|
&v1alpha1.Application{
|
|
Name: "oci-app",
|
|
Namespace: "cd",
|
|
Spec: v1alpha1.ApplicationSpec{
|
|
Sources: v1alpha1.ApplicationSources{
|
|
{
|
|
RepoURL: "oci://ghcr.io/other/repo",
|
|
TargetRevision: "1.0.0",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
event := &RegistryEvent{
|
|
RegistryURL: "ghcr.io",
|
|
Repository: "user/repo",
|
|
Tag: "1.0.0",
|
|
}
|
|
|
|
h.HandleRegistryEvent(event)
|
|
assert.Contains(t, hook.LastEntry().Message, "Skipping app: OCI repository URLs do not match")
|
|
}
|
|
|
|
func TestHandleRegistryEvent_RevisionMismatch(t *testing.T) {
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
hook := test.NewGlobal()
|
|
|
|
h := NewMockHandler(
|
|
nil,
|
|
[]string{},
|
|
&v1alpha1.Application{
|
|
Name: "oci-app",
|
|
Namespace: "cd",
|
|
Spec: v1alpha1.ApplicationSpec{
|
|
Sources: v1alpha1.ApplicationSources{
|
|
{
|
|
RepoURL: "oci://ghcr.io/user/repo",
|
|
TargetRevision: "2.0.0",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
event := &RegistryEvent{
|
|
RegistryURL: "ghcr.io",
|
|
Repository: "user/repo",
|
|
Tag: "1.0.0",
|
|
}
|
|
|
|
h.HandleRegistryEvent(event)
|
|
assert.Contains(t, hook.LastEntry().Message, "Skipping app: revision does not match targetRevision")
|
|
}
|
|
|
|
func TestHandleRegistryEvent_NamespaceFiltering(t *testing.T) {
|
|
t.Parallel()
|
|
patched := []string{}
|
|
|
|
reaction := func(action kubetesting.Action) (bool, runtime.Object, error) {
|
|
patch := action.(kubetesting.PatchAction)
|
|
patched = append(patched, patch.GetNamespace())
|
|
return true, nil, nil
|
|
}
|
|
|
|
h := NewMockHandler(
|
|
&reactorDef{"patch", "applications", reaction},
|
|
[]string{"team-*"},
|
|
&v1alpha1.Application{
|
|
Name: "app1",
|
|
Namespace: "team-a",
|
|
Spec: v1alpha1.ApplicationSpec{
|
|
Sources: v1alpha1.ApplicationSources{
|
|
{RepoURL: "oci://ghcr.io/user/repo", TargetRevision: "1.0.0"},
|
|
},
|
|
},
|
|
},
|
|
&v1alpha1.Application{
|
|
Name: "app2",
|
|
Namespace: "kube-system",
|
|
Spec: v1alpha1.ApplicationSpec{
|
|
Sources: v1alpha1.ApplicationSources{
|
|
{RepoURL: "oci://ghcr.io/user/repo", TargetRevision: "1.0.0"},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
event := &RegistryEvent{
|
|
RegistryURL: "ghcr.io",
|
|
Repository: "user/repo",
|
|
Tag: "1.0.0",
|
|
}
|
|
|
|
h.HandleRegistryEvent(event)
|
|
|
|
assert.Contains(t, patched, "team-a")
|
|
assert.NotContains(t, patched, "kube-system")
|
|
}
|