v2.31.0-dev19 35467d7

push_integration_test.go RawHistoryFolder

1package cli
2
3import (
4	"context"
5	"fmt"
6	"net/http"
7	"net/http/httptest"
8	"strings"
9	"testing"
10
11	climocks "github.com/bnema/gordon/internal/adapters/in/cli/mocks"
12	"github.com/bnema/zerowrap"
13	v1 "github.com/google/go-containerregistry/pkg/v1"
14	"github.com/google/go-containerregistry/pkg/v1/random"
15	"github.com/stretchr/testify/assert"
16	"github.com/stretchr/testify/mock"
17	"github.com/stretchr/testify/require"
18
19	registryhttp "github.com/bnema/gordon/internal/adapters/in/http/registry"
20	"github.com/bnema/gordon/internal/adapters/out/filesystem"
21	"github.com/bnema/gordon/internal/domain"
22	registrysvc "github.com/bnema/gordon/internal/usecase/registry"
23	"github.com/bnema/gordon/pkg/registrypush"
24)
25
26func TestIntegration_TagAndPush_NativeRegistry(t *testing.T) {
27	t.Parallel()
28
29	ctx := context.Background()
30	harness := newCLITestRegistry(t, 95*1024*1024)
31	defer harness.Close()
32
33	img, err := random.Image(512, 1)
34	require.NoError(t, err)
35
36	ops := climocks.NewMockpushImageOps(t)
37	ops.On("Tag", mock.Anything, mock.Anything, mock.Anything).Return(nil)
38	ops.On("Exists", mock.Anything, mock.Anything).Return(true, nil)
39	ops.EXPECT().Push(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, ref string) error {
40		pusher := registrypush.New(
41			registrypush.WithChunkSize(256),
42			registrypush.WithTransport(harness.server.Client().Transport),
43			registrypush.WithImageSource(func(context.Context, string) (v1.Image, error) {
44				return img, nil
45			}),
46		)
47		return pusher.Push(ctx, ref)
48	})
49
50	registry := strings.TrimPrefix(harness.server.URL, "http://")
51	versionRef := registry + "/testapp:v1.0.0"
52	latestRef := registry + "/testapp:latest"
53
54	err = tagAndPush(ctx, ops, imagePush{
55		Registry:   registry,
56		ImageName:  "testapp",
57		Version:    "v1.0.0",
58		VersionRef: versionRef,
59		LatestRef:  latestRef,
60	})
61	require.NoError(t, err)
62
63	harness.RequireManifest(t, "v1.0.0")
64	harness.RequireManifest(t, "latest")
65	harness.RequireBlobs(ctx, t, img)
66}
67
68type cliTestRegistry struct {
69	server *httptest.Server
70}
71
72func newCLITestRegistry(t *testing.T, maxBlobChunkSize int64) *cliTestRegistry {
73	t.Helper()
74
75	log := zerowrap.Default()
76	rootDir := t.TempDir()
77
78	blobStore, err := filesystem.NewBlobStorage(rootDir, log)
79	require.NoError(t, err)
80
81	manifestStore, err := filesystem.NewManifestStorage(rootDir, log)
82	require.NoError(t, err)
83
84	svc := registrysvc.NewService(blobStore, manifestStore, cliNoopEventPublisher{})
85	handler := registryhttp.NewHandler(svc, log, maxBlobChunkSize)
86
87	return &cliTestRegistry{server: httptest.NewServer(handler)}
88}
89
90func (h *cliTestRegistry) Close() {
91	h.server.Close()
92}
93
94func (h *cliTestRegistry) RequireManifest(t *testing.T, tag string) {
95	t.Helper()
96
97	req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/testapp/manifests/%s", h.server.URL, tag), nil)
98	require.NoError(t, err)
99
100	resp, err := h.server.Client().Do(req)
101	require.NoError(t, err)
102	defer resp.Body.Close()
103
104	assert.Equal(t, http.StatusOK, resp.StatusCode)
105}
106
107func (h *cliTestRegistry) RequireBlobs(ctx context.Context, t *testing.T, img v1.Image) {
108	t.Helper()
109
110	layers, err := img.Layers()
111	require.NoError(t, err)
112
113	for _, layer := range layers {
114		digest, digestErr := layer.Digest()
115		require.NoError(t, digestErr)
116
117		req, reqErr := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v2/testapp/blobs/%s", h.server.URL, digest.String()), nil)
118		require.NoError(t, reqErr)
119
120		resp, respErr := h.server.Client().Do(req)
121		require.NoError(t, respErr)
122		assert.Equal(t, http.StatusOK, resp.StatusCode)
123		require.NoError(t, resp.Body.Close())
124	}
125}
126
127type cliNoopEventPublisher struct{}
128
129func (cliNoopEventPublisher) Publish(domain.EventType, any) error {
130	return nil
131}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close