-
Notifications
You must be signed in to change notification settings - Fork 30
fix(test): take the registry keychain from the caller, not the host #283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,9 +21,34 @@ import ( | |
| "net/http" | ||
| "net/http/httptest" | ||
| "net/url" | ||
| "sync/atomic" | ||
| "testing" | ||
|
|
||
| "github.com/google/go-containerregistry/pkg/authn" | ||
| "github.com/google/go-containerregistry/pkg/crane" | ||
| ) | ||
|
|
||
| // anonymousKeychain returns authn.Anonymous for every request, and records that | ||
| // it was asked. The default keychain would consult the host's docker config: if | ||
| // that sets a credsStore, resolving credentials shells out to | ||
| // docker-credential-<store>, which is not on PATH under `nix run .#test` | ||
| // (nix/apps.nix sets inheritPath = false), so the tag lookup fails on a | ||
| // developer machine while passing in CI. internal/project/push_test.go carries | ||
| // the same helper for the push path. | ||
| // | ||
| // The used flag is what keeps this honest: if the option stops being threaded | ||
| // through to crane, this keychain is never consulted and the test fails on any | ||
| // host, with or without a docker config. | ||
| type anonymousKeychain struct { | ||
| used atomic.Bool | ||
| } | ||
|
|
||
| func (k *anonymousKeychain) Resolve(authn.Resource) (authn.Authenticator, error) { | ||
| k.used.Store(true) | ||
|
|
||
| return authn.Anonymous, nil | ||
| } | ||
|
|
||
| func TestFindImageTagForVersionConstraint(t *testing.T) { | ||
| repoName := "ubuntu" | ||
| responseTags := []byte(`{"tags":["1.2.3","4.5.6"]}`) | ||
|
|
@@ -77,6 +102,8 @@ func TestFindImageTagForVersionConstraint(t *testing.T) { | |
| }, | ||
| } | ||
|
|
||
| keychain := &anonymousKeychain{} | ||
|
|
||
| for name, tc := range cases { | ||
| t.Run(name, func(t *testing.T) { | ||
| tagsPath := fmt.Sprintf("/v2/%s/tags/list", repoName) | ||
|
|
@@ -107,20 +134,33 @@ func TestFindImageTagForVersionConstraint(t *testing.T) { | |
| host = tc.host | ||
| } | ||
|
|
||
| image, err := findImageTagForVersionConstraint(fmt.Sprintf("%s/%s:%s", host, repoName, tc.constraint)) | ||
| image, err := findImageTagForVersionConstraint( | ||
| fmt.Sprintf("%s/%s:%s", host, repoName, tc.constraint), | ||
| crane.WithAuthFromKeychain(keychain), | ||
| ) | ||
|
|
||
| expectedImage := "" | ||
| if !tc.expectError { | ||
| expectedImage = fmt.Sprintf("%s/%s", host, tc.expectedImage) | ||
| } | ||
|
|
||
| if tc.expectError && err == nil { | ||
| switch { | ||
| case tc.expectError && err == nil: | ||
| t.Errorf("[%s] expected: error\n", name) | ||
| } else if expectedImage != image { | ||
| case !tc.expectError && err != nil: | ||
| // Report the error rather than only the empty result: a | ||
| // credential lookup that never reached the registry used to | ||
| // read here as an unreachable registry. | ||
| t.Errorf("[%s] unexpected error: %v\n", name, err) | ||
| case expectedImage != image: | ||
| t.Errorf("[%s] expected: %s, got: %s\n", name, expectedImage, image) | ||
| } | ||
|
Comment on lines
+147
to
157
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Align the changed table-driven assertions with the repository test pattern. The new As per path instructions, 🤖 Prompt for AI AgentsSource: Path instructions |
||
| }) | ||
| } | ||
|
|
||
| if !keychain.used.Load() { | ||
| t.Error("tags were listed without the injected keychain; the lookup fell back to the host's docker config") | ||
| } | ||
| } | ||
|
|
||
| func TestIsErrBaseLayerNotFound(t *testing.T) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this mock is overkill, both here and in the
internal/project/functionstests. Using a nil keychain in unit tests would be simpler and the loss of coverage is minimal.