From 5194c2ec798ec013b164dbdff62ac17ca01aa228 Mon Sep 17 00:00:00 2001 From: Anurag <81210977+kranurag7@users.noreply.github.com> Date: Tue, 11 Jul 2023 18:35:14 +0530 Subject: [PATCH 01/22] chore: fix lint warning (#1001) Signed-off-by: Anurag --- cmd/oras/internal/display/print.go | 5 +++-- cmd/oras/internal/option/applier.go | 2 +- cmd/oras/internal/option/packer_test.go | 16 ++++++++++------ cmd/oras/internal/option/remote.go | 4 +++- cmd/oras/internal/option/remote_test.go | 9 +++++++-- cmd/oras/root/attach.go | 2 +- cmd/oras/root/discover.go | 9 ++++++--- internal/cache/target_test.go | 4 +++- internal/graph/graph_test.go | 19 ++++++++++++------- 9 files changed, 46 insertions(+), 24 deletions(-) diff --git a/cmd/oras/internal/display/print.go b/cmd/oras/internal/display/print.go index 35de4ec5a..48374a327 100644 --- a/cmd/oras/internal/display/print.go +++ b/cmd/oras/internal/display/print.go @@ -116,7 +116,7 @@ func (p *tagManifestStatusForRepo) PushReference(ctx context.Context, expected o if p.printHint != nil { p.printHint.Do(func() { ref := p.refPrefix + "@" + expected.Digest.String() - Print("Tagging", ref) + _ = Print("Tagging", ref) }) } if err := p.Repository.PushReference(ctx, expected, content, reference); err != nil { @@ -136,9 +136,10 @@ func (p *tagManifestStatusForTarget) Tag(ctx context.Context, desc ocispec.Descr if p.printHint != nil { p.printHint.Do(func() { ref := p.refPrefix + "@" + desc.Digest.String() - Print("Tagging", ref) + _ = Print("Tagging", ref) }) } + if err := p.Target.Tag(ctx, desc, reference); err != nil { return err } diff --git a/cmd/oras/internal/option/applier.go b/cmd/oras/internal/option/applier.go index f47aba14b..1d177e96e 100644 --- a/cmd/oras/internal/option/applier.go +++ b/cmd/oras/internal/option/applier.go @@ -29,7 +29,7 @@ type FlagApplier interface { // NOTE: The option argument need to be a pointer to the options, so its value // becomes addressable. func ApplyFlags(optsPtr interface{}, target *pflag.FlagSet) { - rangeFields(optsPtr, func(fa FlagApplier) error { + _ = rangeFields(optsPtr, func(fa FlagApplier) error { fa.ApplyFlags(target) return nil }) diff --git a/cmd/oras/internal/option/packer_test.go b/cmd/oras/internal/option/packer_test.go index 5c7470ee5..e0cd51339 100644 --- a/cmd/oras/internal/option/packer_test.go +++ b/cmd/oras/internal/option/packer_test.go @@ -70,7 +70,10 @@ func TestPacker_LoadManifestAnnotations_err(t *testing.T) { func TestPacker_LoadManifestAnnotations_annotationFile(t *testing.T) { testFile := filepath.Join(t.TempDir(), "testAnnotationFile") - os.WriteFile(testFile, []byte(testContent), fs.ModePerm) + err := os.WriteFile(testFile, []byte(testContent), fs.ModePerm) + if err != nil { + t.Fatalf("Error writing %s: %v", testFile, err) + } opts := Packer{AnnotationFilePath: testFile} anno, err := opts.LoadManifestAnnotations() @@ -120,11 +123,12 @@ func TestPacker_LoadManifestAnnotations_annotationFlag(t *testing.T) { t.Fatalf("unexpected error: failed when looking for '$manifest' in annotations") } if !reflect.DeepEqual(annotations, - map[string]map[string]string{"$manifest": { - "Key0": "", - "Key1": "Val", - "Key2": "${env:USERNAME}", - }, + map[string]map[string]string{ + "$manifest": { + "Key0": "", + "Key1": "Val", + "Key2": "${env:USERNAME}", + }, }) { t.Fatalf("unexpected error: %v", errors.New("content not match")) } diff --git a/cmd/oras/internal/option/remote.go b/cmd/oras/internal/option/remote.go index c4261a880..efd4e054a 100644 --- a/cmd/oras/internal/option/remote.go +++ b/cmd/oras/internal/option/remote.go @@ -273,7 +273,9 @@ func (opts *Remote) NewRepository(reference string, common Common) (repo *remote return nil, err } if opts.distributionSpec.referrersAPI != nil { - repo.SetReferrersCapability(*opts.distributionSpec.referrersAPI) + if err := repo.SetReferrersCapability(*opts.distributionSpec.referrersAPI); err != nil { + return nil, err + } } return } diff --git a/cmd/oras/internal/option/remote_test.go b/cmd/oras/internal/option/remote_test.go index efca51cc2..abd1c3029 100644 --- a/cmd/oras/internal/option/remote_test.go +++ b/cmd/oras/internal/option/remote_test.go @@ -51,7 +51,9 @@ func TestMain(m *testing.M) { case p == "/v2/" && m == "GET": w.WriteHeader(http.StatusOK) case p == fmt.Sprintf("/v2/%s/tags/list", testRepo) && m == "GET": - json.NewEncoder(w).Encode(testTagList) + if err := json.NewEncoder(w).Encode(testTagList); err != nil { + http.Error(w, "error encoding", http.StatusBadRequest) + } } })) defer ts.Close() @@ -233,7 +235,10 @@ func TestRemote_NewRepository_Retry(t *testing.T) { http.Error(w, "error", http.StatusTooManyRequests) return } - json.NewEncoder(w).Encode(testTagList) + err := json.NewEncoder(w).Encode(testTagList) + if err != nil { + http.Error(w, "error encoding", http.StatusBadRequest) + } })) defer ts.Close() opts := struct { diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index 99ed8ba14..d0a84dd13 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -94,7 +94,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI image layout folder cmd.Flags().StringVarP(&opts.artifactType, "artifact-type", "", "", "artifact type") cmd.Flags().IntVarP(&opts.concurrency, "concurrency", "", 5, "concurrency level") - cmd.MarkFlagRequired("artifact-type") + _ = cmd.MarkFlagRequired("artifact-type") opts.EnableDistributionSpecFlag() option.ApplyFlags(&opts, cmd.Flags()) return cmd diff --git a/cmd/oras/root/discover.go b/cmd/oras/root/discover.go index d853e77d2..b7dd372ae 100644 --- a/cmd/oras/root/discover.go +++ b/cmd/oras/root/discover.go @@ -133,7 +133,7 @@ func runDiscover(ctx context.Context, opts discoverOptions) error { fmt.Println("Digest:", desc.Digest) if len(refs) > 0 { fmt.Println() - printDiscoveredReferrersTable(refs, opts.Verbose) + _ = printDiscoveredReferrersTable(refs, opts.Verbose) } return nil } @@ -171,7 +171,7 @@ func fetchAllReferrers(ctx context.Context, repo oras.ReadOnlyGraphTarget, desc return nil } -func printDiscoveredReferrersTable(refs []ocispec.Descriptor, verbose bool) { +func printDiscoveredReferrersTable(refs []ocispec.Descriptor, verbose bool) error { typeNameTitle := "Artifact Type" typeNameLength := len(typeNameTitle) for _, ref := range refs { @@ -188,9 +188,12 @@ func printDiscoveredReferrersTable(refs []ocispec.Descriptor, verbose bool) { for _, ref := range refs { print(ref.ArtifactType, ref.Digest) if verbose { - printJSON(ref) + if err := printJSON(ref); err != nil { + return fmt.Errorf("Error printing JSON: %w", err) + } } } + return nil } // printDiscoveredReferrersJSON prints referrer list in JSON equivalent to the diff --git a/internal/cache/target_test.go b/internal/cache/target_test.go index cbc7cd0b0..508116774 100644 --- a/internal/cache/target_test.go +++ b/internal/cache/target_test.go @@ -177,7 +177,9 @@ func TestProxy_fetchReference(t *testing.T) { w.WriteHeader(http.StatusOK) // write data to the response if this is the first request if requestCount == 1 { - w.Write(blob) + if _, err := w.Write(blob); err != nil { + t.Errorf("Error writing blobs: %v", err) + } } atomic.AddInt64(&successCount, 1) return diff --git a/internal/graph/graph_test.go b/internal/graph/graph_test.go index 50eb0e8e0..599307fa2 100644 --- a/internal/graph/graph_test.go +++ b/internal/graph/graph_test.go @@ -121,7 +121,7 @@ func TestReferrers(t *testing.T) { index ) anno := map[string]string{"test": "foo"} - appendBlob(ocispec.MediaTypeArtifactManifest, []byte("subject content")) + appendBlob(ocispec.MediaTypeArtifactManifest, []byte(`{"name":"subject content"}`)) imageType := "test.image" appendBlob(imageType, []byte("config content")) generateImage(nil, nil, descs[imgConfig], descs[blob]) @@ -139,7 +139,9 @@ func TestReferrers(t *testing.T) { referrers := []ocispec.Descriptor{descs[image], descs[image]} memory := memory.New() for i := range descs { - memory.Push(ctx, descs[i], bytes.NewReader(blobs[i])) + if err := memory.Push(ctx, descs[i], bytes.NewReader(blobs[i])); err != nil { + t.Errorf("Error pushing %v\n", err) + } } finder := &predecessorFinder{Store: memory} @@ -244,7 +246,7 @@ func TestSuccessors(t *testing.T) { artifact index ) - appendBlob(ocispec.MediaTypeArtifactManifest, []byte("subject content")) + appendBlob(ocispec.MediaTypeArtifactManifest, []byte(`{"name":"subject content"}`)) imageType := "test.image" appendBlob(imageType, []byte("config content")) generateImage(&descs[subject], ocispec.MediaTypeImageManifest, descs[config]) @@ -255,7 +257,9 @@ func TestSuccessors(t *testing.T) { memory := memory.New() ctx := context.Background() for i := range descs { - memory.Push(ctx, descs[i], bytes.NewReader(blobs[i])) + if err := memory.Push(ctx, descs[i], bytes.NewReader(blobs[i])); err != nil { + t.Errorf("Error pushing %v\n", err) + } } fetcher := &fetcher{Fetcher: memory} @@ -341,7 +345,7 @@ func TestFindReferrerPredecessors(t *testing.T) { image ) var anno map[string]string - appendBlob(ocispec.MediaTypeArtifactManifest, []byte("subject content")) + appendBlob(ocispec.MediaTypeArtifactManifest, []byte(`{"name":"subject content"}`)) imageType := "test.image" appendBlob(imageType, []byte("config content")) generateImage(&descs[subject], anno, descs[imgConfig]) @@ -353,7 +357,9 @@ func TestFindReferrerPredecessors(t *testing.T) { referrers := []ocispec.Descriptor{descs[image], descs[image]} memory := memory.New() for i := range descs { - memory.Push(ctx, descs[i], bytes.NewReader(blobs[i])) + if err := memory.Push(ctx, descs[i], bytes.NewReader(blobs[i])); err != nil { + t.Errorf("Error pushing %v\n", err) + } } finder := &predecessorFinder{Store: memory} type args struct { @@ -367,7 +373,6 @@ func TestFindReferrerPredecessors(t *testing.T) { want []ocispec.Descriptor wantErr bool }{ - {"should failed to get referrers", args{ctx, &errLister{}, ocispec.Descriptor{}}, nil, true}, {"should failed to get predecessor", args{ctx, &errFinder{}, ocispec.Descriptor{}}, nil, true}, {"should return referrers when target is a referrer lister", args{ctx, &refLister{referrers: referrers}, ocispec.Descriptor{}}, referrers, false}, From 46780e700bf62ccb0c046726ebd217a4c4e966aa Mon Sep 17 00:00:00 2001 From: Aman <136564604+amands98@users.noreply.github.com> Date: Wed, 12 Jul 2023 06:03:47 +0530 Subject: [PATCH 02/22] chore: fix the links in project readme (#1012) Signed-off-by: Aman <136564604+amands98@users.noreply.github.com> Co-authored-by: Terry Howe --- CONTRIBUTING.md | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 95d6182fe..f0bcf8e35 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ # Contributing -Please refer to the [ORAS Contributing guide](https://oras.land/docs/contributing). +Please refer to the [ORAS Contributing guide](https://oras.land/docs/community/contributing_guide). diff --git a/README.md b/README.md index cf9831a3f..8059c4785 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,11 @@ ## Docs Documentation for the ORAS CLI is located on -the project website: [oras.land/cli](https://oras.land/docs/category/cli) +the project website: [oras.land/cli](https://oras.land/docs/category/oras-commands) ## Development Environment Setup -Refer to the [development guide](https://oras.land/docs/CLI/developer_guide) to get started [contributing to ORAS](https://oras.land/docs/contributing). +Refer to the [development guide](https://oras.land/docs/community/developer_guide) to get started [contributing to ORAS](https://oras.land/docs/community/contributing_guide). ## Code of Conduct From ed3fbcc19f7a75aba248e626c5930b509f408ded Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 12 Jul 2023 08:47:20 +0800 Subject: [PATCH 03/22] chore: update container build prepare job output in Github Actions (#1019) Signed-off-by: Billy Zha --- .github/workflows/release-ghcr.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release-ghcr.yml b/.github/workflows/release-ghcr.yml index d9ba9575b..e39ae4ae4 100644 --- a/.github/workflows/release-ghcr.yml +++ b/.github/workflows/release-ghcr.yml @@ -35,8 +35,7 @@ jobs: if [[ "${VERSION}" == "${BRANCH_NAME}" ]]; then VERSION=$(git rev-parse --short HEAD) fi - echo ::set-output name=version::${VERSION} - echo ::set-output name=ref::ghcr.io/${{ github.repository }}:${VERSION} + echo "ref=ghcr.io/${{ github.repository }}:${VERSION}" >> $GITHUB_OUTPUT - name: docker login uses: docker/login-action@v2 with: From 21d0b71c2737f0c533cf682b5fc25ae39801cb22 Mon Sep 17 00:00:00 2001 From: Akanksha Gahalot Date: Wed, 12 Jul 2023 06:26:56 +0530 Subject: [PATCH 04/22] test: add unit test for error scenario in `internal/credential/store.go` (#982) Signed-off-by: Akanksha Gahalot --- internal/credential/store_test.go | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 internal/credential/store_test.go diff --git a/internal/credential/store_test.go b/internal/credential/store_test.go new file mode 100644 index 000000000..c7f94569b --- /dev/null +++ b/internal/credential/store_test.go @@ -0,0 +1,48 @@ +/* +Copyright The ORAS Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package credential + +import ( + "os" + "path" + "reflect" + "strings" + "testing" +) + +func TestNewStoreError(t *testing.T) { + tmpDir := t.TempDir() + filename := path.Join(tmpDir, "testfile.txt") + _, err := os.Create(filename) + if err != nil { + t.Errorf("error: cannot create file : %v", err) + } + err = os.Chmod(filename, 000) + if err != nil { + t.Errorf("error: cannot change file permissions: %v", err) + } + credStore, err := NewStore(filename) + if credStore != nil { + t.Errorf("Expected NewStore to return nil but actually returned %v ", credStore) + } + if err != nil { + ok := strings.Contains(err.Error(), "failed to open config file") + reflect.DeepEqual(ok, true) + + } else { + t.Errorf("Expected err to be not nil") + } +} From 309265617a1e1f912815bc19d207464c35aec200 Mon Sep 17 00:00:00 2001 From: Anurag <81210977+kranurag7@users.noreply.github.com> Date: Thu, 13 Jul 2023 11:58:21 +0530 Subject: [PATCH 05/22] chore: use golangci lint (#986) Signed-off-by: Anurag --- .github/workflows/golangci-lint.yml | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/golangci-lint.yml diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 000000000..fe2f952c1 --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,41 @@ +# Copyright The ORAS Authors. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: golangci-lint + +on: + pull_request: + paths-ignore: + - 'docs/**' + +permissions: + contents: read + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + strategy: + matrix: + go-version: ['1.20'] + fail-fast: true + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Go ${{ matrix.go-version }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go-version }} + check-latest: true + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 From a1d076409970ad5e0c02a63e927bd18e2ce51420 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 18 Jul 2023 20:52:31 +0800 Subject: [PATCH 06/22] fix: correct e2e specs and CI check configuration (#1023) Signed-off-by: Billy Zha --- Makefile | 3 +-- test/e2e/suite/command/attach.go | 2 +- test/e2e/suite/command/cp.go | 2 +- test/e2e/suite/command/manifest.go | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index cbf8181c4..df548f223 100644 --- a/Makefile +++ b/Makefile @@ -134,8 +134,7 @@ teste2e-covdata: ## test e2e coverage export GOCOVERDIR=$(CURDIR)/test/e2e/.cover; \ rm -rf $$GOCOVERDIR; \ mkdir -p $$GOCOVERDIR; \ - $(MAKE) teste2e; \ - $(GO_EXE) tool covdata textfmt -i=$$GOCOVERDIR -o "$(CURDIR)/test/e2e/coverage.txt" + $(MAKE) teste2e && $(GO_EXE) tool covdata textfmt -i=$$GOCOVERDIR -o "$(CURDIR)/test/e2e/coverage.txt" .PHONY: help help: ## Display this help diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index 499a613da..883ab2fed 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -293,7 +293,7 @@ var _ = Describe("OCI image layout users:", func() { root := PrepareTempFiles() subjectRef := LayoutRef(root, foobar.Tag) prepare(root) - ORAS("attach", "--artifact-type", "test.attach", "-v", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test.attach", "-v", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--skip-delete-referrers"). MatchErrKeyWords("referrers deletion can only be enforced upon registry\n"). WithWorkDir(root). Exec() diff --git a/test/e2e/suite/command/cp.go b/test/e2e/suite/command/cp.go index 5865ba0cb..3064c9977 100644 --- a/test/e2e/suite/command/cp.go +++ b/test/e2e/suite/command/cp.go @@ -364,7 +364,7 @@ var _ = Describe("OCI layout users:", func() { }) It("should copy and output verbosed warning for Feferrers deletion by default", func() { - ORAS("cp", RegistryRef(Host, ArtifactRepo, foobar.Tag), GinkgoT().TempDir(), Flags.ToLayout, "-v"). + ORAS("cp", RegistryRef(Host, ArtifactRepo, foobar.Tag), GinkgoT().TempDir(), Flags.ToLayout, "-v", "--skip-delete-referrers"). MatchErrKeyWords("referrers deletion can only be enforced upon registry\n"). Exec() }) diff --git a/test/e2e/suite/command/manifest.go b/test/e2e/suite/command/manifest.go index 36d30bf0c..51235314e 100644 --- a/test/e2e/suite/command/manifest.go +++ b/test/e2e/suite/command/manifest.go @@ -549,7 +549,7 @@ var _ = Describe("OCI image layout users:", func() { manifestPath := WriteTempFile("manifest.json", manifest) root := filepath.Dir(manifestPath) prepare(root) - ORAS("manifest", "push", root, Flags.Layout, manifestPath, "--skip-delete-referrers=false"). + ORAS("manifest", "push", root, Flags.Layout, manifestPath, "--skip-delete-referrers"). WithWorkDir(root). MatchErrKeyWords("referrers deletion can only be enforced upon registry\n").Exec() }) From 4b9ffea43ff9982f17a0533dab687f5eb01c4d43 Mon Sep 17 00:00:00 2001 From: Sajay Antony Date: Thu, 20 Jul 2023 04:49:31 -0700 Subject: [PATCH 07/22] workflow: add github stale action (#1024) Signed-off-by: Sajay Antony --- .github/stale.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 000000000..8d0b9f879 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,32 @@ +# Copyright The ORAS Authors. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: "Close stale issues and PRs" +on: + schedule: + - cron: "30 1 * * *" + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v8 + with: + stale-issue-message: "This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days." + stale-pr-message: "This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 30 days." + close-issue-message: "This issue was closed because it has been stalled for 30 days with no activity." + close-pr-message: "This PR was closed because it has been stalled for 30 days with no activity." + days-before-issue-stale: 60 + days-before-pr-stale: 45 + days-before-issue-close: 30 + days-before-pr-close: 30 From 92602099b926bef6836323ee76465e544b5b2ba9 Mon Sep 17 00:00:00 2001 From: Sajay Antony Date: Sat, 22 Jul 2023 11:53:02 -0700 Subject: [PATCH 08/22] fix: move stale into .github/workflows (#1031) Signed-off-by: Sajay Antony --- .github/{ => workflows}/stale.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{ => workflows}/stale.yml (100%) diff --git a/.github/stale.yml b/.github/workflows/stale.yml similarity index 100% rename from .github/stale.yml rename to .github/workflows/stale.yml From 41cb0c8b422a1492fa77afbfdbb9b3b13539b0cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 07:56:53 -0700 Subject: [PATCH 09/22] build(deps): bump github.com/onsi/gomega from 1.27.8 to 1.27.10 in /test/e2e (#1037) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/e2e/go.mod | 8 ++++---- test/e2e/go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index ef6a4cc4f..09b86ff2c 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/onsi/ginkgo/v2 v2.11.0 - github.com/onsi/gomega v1.27.8 + github.com/onsi/gomega v1.27.10 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc2 gopkg.in/yaml.v2 v2.4.0 @@ -16,10 +16,10 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect - golang.org/x/net v0.10.0 // indirect + golang.org/x/net v0.12.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect golang.org/x/tools v0.9.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/test/e2e/go.sum b/test/e2e/go.sum index c0cd2933f..bac81e704 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -16,8 +16,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= -github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= @@ -28,15 +28,15 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= From 0b6651ab310cd4e03a016537d214f7a1ff59f4f3 Mon Sep 17 00:00:00 2001 From: Shubham Singh <116020663+1Shubham7@users.noreply.github.com> Date: Thu, 27 Jul 2023 09:05:11 +0530 Subject: [PATCH 10/22] chore: improving error log for `oras push` and `oras attach` when the annotation file is invalid (#1026) Signed-off-by: Shubham Singh --- cmd/oras/internal/option/packer.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/oras/internal/option/packer.go b/cmd/oras/internal/option/packer.go index d32fa62de..ad633dd65 100644 --- a/cmd/oras/internal/option/packer.go +++ b/cmd/oras/internal/option/packer.go @@ -99,7 +99,13 @@ func (opts *Packer) LoadManifestAnnotations() (annotations map[string]map[string } if opts.AnnotationFilePath != "" { if err = decodeJSON(opts.AnnotationFilePath, &annotations); err != nil { - return nil, err + errStr := err.Error() + docLink := " Please refer to the document at https://oras.land/docs/how_to_guides/manifest_annotations." + if !strings.HasSuffix(errStr, ".") { + docLink = "."+docLink + } + return nil, fmt.Errorf("failed to load annotations from %s: %w" + + docLink, opts.AnnotationFilePath, err) } } if len(opts.ManifestAnnotations) != 0 { From e6b9a44c0ecbb2b705fb5ec57e9eeb5cb20c1e0f Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Thu, 27 Jul 2023 11:45:36 +0800 Subject: [PATCH 11/22] chore: exempt stale if milestone is set (#1036) Signed-off-by: Billy Zha --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 8d0b9f879..62f5ff723 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -30,3 +30,4 @@ jobs: days-before-pr-stale: 45 days-before-issue-close: 30 days-before-pr-close: 30 + exempt-all-milestones: true From dcc112b1c057cf6ca494214b66561f6c1d78c5eb Mon Sep 17 00:00:00 2001 From: Feynman Zhou Date: Tue, 8 Aug 2023 18:48:32 +0800 Subject: [PATCH 12/22] chore: add triage labels (#1055) Signed-off-by: Feynman Zhou --- .github/ISSUE_TEMPLATE/bug-report.yaml | 2 +- .github/ISSUE_TEMPLATE/feature-request.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index c4e40abc6..2cbee8fc9 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -13,7 +13,7 @@ name: Bug Report description: File a bug report -labels: [bug] +labels: [bug, triage] body: - type: markdown id: preface diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml index 13603c30c..d6656579e 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -13,7 +13,7 @@ name: Feature Request description: File a feature request -labels: [enhancement] +labels: [enhancement, triage] body: - type: markdown id: preface From ceb56f8b077f49d642187c5c3be15876b4830daf Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 9 Aug 2023 11:49:17 +0800 Subject: [PATCH 13/22] chore: make error returned by `oras tag` more readable (#1058) Signed-off-by: Billy Zha --- cmd/oras/root/tag.go | 4 ++++ test/e2e/suite/command/tag.go | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cmd/oras/root/tag.go b/cmd/oras/root/tag.go index 35475fec6..a6540ea80 100644 --- a/cmd/oras/root/tag.go +++ b/cmd/oras/root/tag.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "oras.land/oras-go/v2" + "oras.land/oras-go/v2/registry" "oras.land/oras/cmd/oras/internal/display" "oras.land/oras/cmd/oras/internal/option" ) @@ -58,6 +59,9 @@ Example - Tag the manifest 'v1.0.1' to 'v1.0.2' in an OCI image layout folder 'l Args: cobra.MinimumNArgs(2), PreRunE: func(cmd *cobra.Command, args []string) error { opts.RawReference = args[0] + if _, err := registry.ParseReference(opts.RawReference); err != nil { + return fmt.Errorf("unable to add tag for '%s': %w", opts.RawReference, err) + } opts.targetRefs = args[1:] return option.Parse(&opts) }, diff --git a/test/e2e/suite/command/tag.go b/test/e2e/suite/command/tag.go index 0878a7d7f..d5836ee26 100644 --- a/test/e2e/suite/command/tag.go +++ b/test/e2e/suite/command/tag.go @@ -33,7 +33,11 @@ var _ = Describe("ORAS beginners:", func() { }) It("should fail when provided manifest reference is not found", func() { - ORAS("tag", RegistryRef(Host, ImageRepo, "i-dont-think-this-tag-exists")).ExpectFailure().MatchErrKeyWords("Error:").Exec() + ORAS("tag", RegistryRef(Host, ImageRepo, "i-dont-think-this-tag-exists"), "tagged").ExpectFailure().MatchErrKeyWords("Error:").Exec() + }) + + It("should fail when provided invalid reference", func() { + ORAS("tag", "list", "tagged").ExpectFailure().MatchErrKeyWords("Error:", "'list'").Exec() }) }) }) From 91db0182fefed22811670f88a1882ba17d1cc740 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 9 Aug 2023 16:50:38 +0800 Subject: [PATCH 14/22] revert: "feat: add flag to skip deleting obsolete referrers index" (#1060) Signed-off-by: Billy Zha --- cmd/oras/internal/errors/errors.go | 8 --- cmd/oras/internal/option/referrers.go | 42 --------------- cmd/oras/root/attach.go | 10 +--- cmd/oras/root/cp.go | 9 +--- cmd/oras/root/manifest/push.go | 8 +-- test/e2e/README.md | 2 +- test/e2e/internal/testdata/foobar/const.go | 4 -- test/e2e/scripts/common.sh | 5 +- test/e2e/scripts/e2e.sh | 6 +-- test/e2e/suite/command/attach.go | 60 +--------------------- test/e2e/suite/command/cp.go | 36 ------------- test/e2e/suite/command/manifest.go | 49 +----------------- 12 files changed, 11 insertions(+), 228 deletions(-) delete mode 100644 cmd/oras/internal/option/referrers.go diff --git a/cmd/oras/internal/errors/errors.go b/cmd/oras/internal/errors/errors.go index 631403ac6..e3c6e4c43 100644 --- a/cmd/oras/internal/errors/errors.go +++ b/cmd/oras/internal/errors/errors.go @@ -16,11 +16,9 @@ limitations under the License. package errors import ( - "errors" "fmt" "oras.land/oras-go/v2/registry" - "oras.land/oras-go/v2/registry/remote" ) // NewErrInvalidReference creates a new error based on the reference string. @@ -32,9 +30,3 @@ func NewErrInvalidReference(ref registry.Reference) error { func NewErrInvalidReferenceStr(ref string) error { return fmt.Errorf("%s: invalid image reference, expecting ", ref) } - -// IsReferrersIndexDelete checks if err is a referrers index delete error. -func IsReferrersIndexDelete(err error) bool { - var re *remote.ReferrersError - return errors.As(err, &re) && re.IsReferrersIndexDelete() -} diff --git a/cmd/oras/internal/option/referrers.go b/cmd/oras/internal/option/referrers.go deleted file mode 100644 index 4920c29d0..000000000 --- a/cmd/oras/internal/option/referrers.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright The ORAS Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package option - -import ( - "github.com/sirupsen/logrus" - "github.com/spf13/pflag" - "oras.land/oras-go/v2/registry/remote" -) - -// Referrers option struct. -type Referrers struct { - SkipDeleteReferrers bool -} - -// ApplyFlags applies flags to a command flag set. -func (opts *Referrers) ApplyFlags(fs *pflag.FlagSet) { - fs.BoolVarP(&opts.SkipDeleteReferrers, "skip-delete-referrers", "", false, "skip deleting old referrers index, only work on registry when referrers API is not supported") -} - -// SetReferrersGC sets the referrers GC option for the passed-in target. -func (opts *Referrers) SetReferrersGC(target any, logger logrus.FieldLogger) { - if repo, ok := target.(*remote.Repository); ok { - repo.SkipReferrersGC = opts.SkipDeleteReferrers - } else if opts.SkipDeleteReferrers { - // not a registry, can't skip referrers deletion - logger.Warnln("referrers deletion can only be enforced upon registry") - } -} diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index d0a84dd13..f49c5e4b9 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -19,7 +19,6 @@ import ( "context" "errors" "fmt" - "os" "strings" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -27,7 +26,6 @@ import ( "oras.land/oras-go/v2" "oras.land/oras-go/v2/content" "oras.land/oras-go/v2/content/file" - oerr "oras.land/oras/cmd/oras/internal/errors" "oras.land/oras/cmd/oras/internal/option" "oras.land/oras/internal/graph" ) @@ -37,7 +35,6 @@ type attachOptions struct { option.Packer option.ImageSpec option.Target - option.Referrers artifactType string concurrency int @@ -101,7 +98,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI image layout folder } func runAttach(ctx context.Context, opts attachOptions) error { - ctx, logger := opts.WithContext(ctx) + ctx, _ = opts.WithContext(ctx) annotations, err := opts.LoadManifestAnnotations() if err != nil { return err @@ -124,8 +121,6 @@ func runAttach(ctx context.Context, opts attachOptions) error { if err := opts.EnsureReferenceNotEmpty(); err != nil { return err } - opts.SetReferrersGC(dst, logger) - subject, err := dst.Resolve(ctx, opts.Reference) if err != nil { return err @@ -168,9 +163,6 @@ func runAttach(ctx context.Context, opts attachOptions) error { root, err := pushArtifact(dst, pack, copy) if err != nil { - if oerr.IsReferrersIndexDelete(err) { - fmt.Fprintln(os.Stderr, "attached successfully but failed to remove the outdated referrers index, please use `--skip-delete-referrers` if you want to skip the deletion") - } return err } diff --git a/cmd/oras/root/cp.go b/cmd/oras/root/cp.go index 20cc2a753..f8a953b39 100644 --- a/cmd/oras/root/cp.go +++ b/cmd/oras/root/cp.go @@ -18,7 +18,6 @@ package root import ( "context" "fmt" - "os" "strings" "sync" @@ -27,7 +26,6 @@ import ( "github.com/spf13/cobra" "oras.land/oras-go/v2" "oras.land/oras/cmd/oras/internal/display" - oerr "oras.land/oras/cmd/oras/internal/errors" "oras.land/oras/cmd/oras/internal/option" "oras.land/oras/internal/graph" ) @@ -36,7 +34,6 @@ type copyOptions struct { option.Common option.Platform option.BinaryTarget - option.Referrers recursive bool concurrency int @@ -99,7 +96,7 @@ Example - Copy an artifact with multiple tags with concurrency tuned: } func runCopy(ctx context.Context, opts copyOptions) error { - ctx, logger := opts.WithContext(ctx) + ctx, _ = opts.WithContext(ctx) // Prepare source src, err := opts.From.NewReadonlyTarget(ctx, opts.Common) @@ -115,7 +112,6 @@ func runCopy(ctx context.Context, opts copyOptions) error { if err != nil { return err } - opts.SetReferrersGC(dst, logger) // Prepare copy options committed := &sync.Map{} @@ -171,9 +167,6 @@ func runCopy(ctx context.Context, opts copyOptions) error { } } if err != nil { - if oerr.IsReferrersIndexDelete(err) { - fmt.Fprintln(os.Stderr, "failed to remove the outdated referrers index, please use `--skip-delete-referrers` if you want to skip the deletion") - } return err } diff --git a/cmd/oras/root/manifest/push.go b/cmd/oras/root/manifest/push.go index f6391c939..c932e8e3f 100644 --- a/cmd/oras/root/manifest/push.go +++ b/cmd/oras/root/manifest/push.go @@ -29,7 +29,6 @@ import ( "oras.land/oras-go/v2/errdef" "oras.land/oras-go/v2/registry/remote" "oras.land/oras/cmd/oras/internal/display" - oerr "oras.land/oras/cmd/oras/internal/errors" "oras.land/oras/cmd/oras/internal/option" "oras.land/oras/internal/file" ) @@ -39,7 +38,6 @@ type pushOptions struct { option.Descriptor option.Pretty option.Target - option.Referrers concurrency int extraRefs []string @@ -106,14 +104,13 @@ Example - Push a manifest to an OCI image layout folder 'layout-dir' and tag wit } func pushManifest(ctx context.Context, opts pushOptions) error { - ctx, logger := opts.WithContext(ctx) + ctx, _ = opts.WithContext(ctx) var target oras.Target var err error target, err = opts.NewTarget(opts.Common) if err != nil { return err } - opts.SetReferrersGC(target, logger) if repo, ok := target.(*remote.Repository); ok { target = repo.Manifests() } @@ -154,9 +151,6 @@ func pushManifest(ctx context.Context, opts pushOptions) error { return err } if _, err := oras.TagBytes(ctx, target, mediaType, contentBytes, ref); err != nil { - if oerr.IsReferrersIndexDelete(err) { - fmt.Fprintln(os.Stderr, "pushed successfully but failed to remove the outdated referrers index, please use `--skip-delete-referrers` if you want to skip the deletion") - } return err } if err = display.PrintStatus(desc, "Uploaded ", verbose); err != nil { diff --git a/test/e2e/README.md b/test/e2e/README.md index f3fa24672..26e7332a8 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -30,7 +30,7 @@ go test oras.land/oras/test/e2e/suite/${suite_name} This is super handy when you want to do step-by-step debugging from command-line or via an IDE. If you need to debug certain specs, use [focused specs](https://onsi.github.io/ginkgo/#focused-specs) but don't check it in. ### 4. Testing Registry Services -The backend of E2E tests are two registry services: [oras-distribution](https://github.com/oras-project/distribution) and [upstream distribution](https://github.com/distribution/distribution). The former is expected to support image and artifact media types and referrer API; The latter is expected to only support image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema), with deletion disabled. +The backend of E2E tests are two registry services: [oras-distribution](https://github.com/oras-project/distribution) and [upstream distribution](https://github.com/distribution/distribution). The former is expected to support image and artifact media types and referrer API; The latter is expected to only support image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema). You can run scenario test suite against your own registry services via setting `ORAS_REGISTRY_HOST` or `ORAS_REGISTRY_FALLBACK_HOST` environmental variables. diff --git a/test/e2e/internal/testdata/foobar/const.go b/test/e2e/internal/testdata/foobar/const.go index 66a0591f8..0ea5471f0 100644 --- a/test/e2e/internal/testdata/foobar/const.go +++ b/test/e2e/internal/testdata/foobar/const.go @@ -16,8 +16,6 @@ limitations under the License. package foobar import ( - "fmt" - "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "oras.land/oras/test/e2e/internal/utils/match" @@ -26,8 +24,6 @@ import ( var ( Tag = "foobar" Digest = "sha256:fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb" - Size = 851 - DescriptorStr = fmt.Sprintf(`{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"%s","size":%d}`, Digest, Size) ManifestStateKey = match.StateKey{Digest: "fd6ed2f36b54", Name: "application/vnd.oci.image.manifest.v1+json"} FileLayerNames = []string{ diff --git a/test/e2e/scripts/common.sh b/test/e2e/scripts/common.sh index e1d40f919..7760a6578 100755 --- a/test/e2e/scripts/common.sh +++ b/test/e2e/scripts/common.sh @@ -15,14 +15,13 @@ help () { echo "Usage" - echo " run-registry " + echo " run-registry " echo "" echo "Arguments" echo " mount-root root mounting directory for pre-baked registry storage files." echo " image-name image name of the registry." echo " container-name container name of the registry service." echo " container-port port to export the registry service." - echo " delete-enabled if set to true, the registry service will be configured to allow deletion." } # run registry service for testing @@ -62,7 +61,7 @@ run_registry () { try_clean_up $ctr_name docker run --pull always -d -p $ctr_port:5000 --rm --name $ctr_name \ -u $(id -u $(whoami)) \ - --env REGISTRY_STORAGE_DELETE_ENABLED=$5 \ + --env REGISTRY_STORAGE_DELETE_ENABLED=true \ --env REGISTRY_AUTH_HTPASSWD_REALM=test-basic \ --env REGISTRY_AUTH_HTPASSWD_PATH=/etc/docker/registry/passwd \ --mount type=bind,source=$mnt_root/docker,target=/var/lib/registry/docker \ diff --git a/test/e2e/scripts/e2e.sh b/test/e2e/scripts/e2e.sh index 08d555a77..b110e38c6 100755 --- a/test/e2e/scripts/e2e.sh +++ b/test/e2e/scripts/e2e.sh @@ -49,16 +49,14 @@ run_registry \ ${e2e_root}/testdata/distribution/mount \ ghcr.io/oras-project/registry:v1.0.0-rc.4 \ $oras_container_name \ - $ORAS_REGISTRY_PORT \ - true + $ORAS_REGISTRY_PORT echo " === preparing upstream distribution === " run_registry \ ${e2e_root}/testdata/distribution/mount_fallback \ registry:2.8.1 \ $upstream_container_name \ - $ORAS_REGISTRY_FALLBACK_PORT \ - false + $ORAS_REGISTRY_FALLBACK_PORT echo " === run tests === " if ! ginkgo -r -p --succinct suite; then diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index 883ab2fed..a3083e86b 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -195,7 +195,7 @@ var _ = Describe("Fallback registry users:", func() { subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image"). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -207,53 +207,6 @@ var _ = Describe("Fallback registry users:", func() { Expect(index.Manifests[0].MediaType).To(Equal("application/vnd.oci.image.manifest.v1+json")) }) - It("should fail to attach again when cleaning referrers index", func() { - testRepo := attachTestRepo("fallback/fail-gc") - tempDir := PrepareTempFiles() - subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) - prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) - // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). - WithWorkDir(tempDir). - MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - - // validate - var index ocispec.Index - bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents() - Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred()) - Expect(len(index.Manifests)).To(Equal(1)) - Expect(index.Manifests[0].MediaType).To(Equal(ocispec.MediaTypeImageManifest)) - // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "-a", "test.type=another.image"). - WithWorkDir(tempDir). - MatchErrKeyWords("Error: failed to delete dangling referrers index"). - ExpectFailure().Exec() - }) - - It("should attach again and skip cleanning index", func() { - testRepo := attachTestRepo("fallback/skip-gc") - tempDir := PrepareTempFiles() - subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) - prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) - // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). - WithWorkDir(tempDir). - MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - // validate - var index ocispec.Index - bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents() - Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred()) - Expect(len(index.Manifests)).To(Equal(1)) - // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "-a", "test.type=another.image", "--skip-delete-referrers"). - WithWorkDir(tempDir). - MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - // validate - bytes = ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents() - Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred()) - Expect(len(index.Manifests)).To(Equal(2)) - }) - It("should attach a file via a OCI Image and generate referrer via tag schema", func() { testRepo := attachTestRepo("fallback/tag_schema") tempDir := PrepareTempFiles() @@ -279,7 +232,6 @@ var _ = Describe("OCI image layout users:", func() { prepare := func(root string) { ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Tag), Flags.ToLayout, LayoutRef(root, foobar.Tag)).Exec() } - It("should attach a file to a subject", func() { root := PrepareTempFiles() subjectRef := LayoutRef(root, foobar.Tag) @@ -289,16 +241,6 @@ var _ = Describe("OCI image layout users:", func() { MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() }) - It("should attach and output warning for referrers deletion by default", func() { - root := PrepareTempFiles() - subjectRef := LayoutRef(root, foobar.Tag) - prepare(root) - ORAS("attach", "--artifact-type", "test.attach", "-v", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--skip-delete-referrers"). - MatchErrKeyWords("referrers deletion can only be enforced upon registry\n"). - WithWorkDir(root). - Exec() - }) - It("should attach a file to a subject and export the built manifest", func() { // prepare root := PrepareTempFiles() diff --git a/test/e2e/suite/command/cp.go b/test/e2e/suite/command/cp.go index 3064c9977..4b49187fa 100644 --- a/test/e2e/suite/command/cp.go +++ b/test/e2e/suite/command/cp.go @@ -31,7 +31,6 @@ import ( "oras.land/oras/test/e2e/internal/testdata/foobar" ma "oras.land/oras/test/e2e/internal/testdata/multi_arch" . "oras.land/oras/test/e2e/internal/utils" - "oras.land/oras/test/e2e/internal/utils/match" ) func cpTestRepo(text string) string { @@ -246,34 +245,6 @@ var _ = Describe("Common registry users:", func() { var _ = Describe("OCI spec 1.0 registry users:", func() { When("running `cp`", func() { - It("should fail to copy when cleaning referrers index", func() { - testRepo := cpTestRepo("fallback/fail-gc") - tempDir := PrepareTempFiles() - subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) - // prepare - prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). - WithWorkDir(tempDir). - MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - // test - ORAS("cp", "-r", RegistryRef(FallbackHost, ArtifactRepo, foobar.FallbackSBOMImageReferrer.Digest.String()), RegistryRef(FallbackHost, testRepo, ""), "-v"). - MatchErrKeyWords("Error: failed to delete dangling referrers index"). - ExpectFailure().Exec() - }) - - It("should copy and skip cleaning referrers index", func() { - testRepo := cpTestRepo("fallback/skip-gc") - tempDir := PrepareTempFiles() - subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) - // prepare - prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). - WithWorkDir(tempDir). - MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - // test - ORAS("cp", "-r", RegistryRef(FallbackHost, ArtifactRepo, foobar.FallbackSBOMImageReferrer.Digest.String()), RegistryRef(FallbackHost, testRepo, ""), "--skip-delete-referrers").Exec() - }) - It("should copy an image artifact and its referrers from a registry to a fallback registry", func() { repo := cpTestRepo("to-fallback") stateKeys := append(append(foobarStates, foobar.ImageReferrersStateKeys...), foobar.ImageReferrerConfigStateKeys...) @@ -284,7 +255,6 @@ var _ = Describe("OCI spec 1.0 registry users:", func() { ORAS("discover", "-o", "tree", RegistryRef(FallbackHost, repo, foobar.Digest)). WithDescription("discover referrer via subject").MatchKeyWords(foobar.SignatureImageReferrer.Digest.String(), foobar.SBOMImageReferrer.Digest.String()).Exec() }) - It("should copy an image artifact and its referrers from a fallback registry to a registry", func() { repo := cpTestRepo("from-fallback") stateKeys := append(append(foobarStates, foobar.FallbackImageReferrersStateKeys...), foobar.ImageReferrerConfigStateKeys...) @@ -363,12 +333,6 @@ var _ = Describe("OCI layout users:", func() { Expect(srcManifest).To(Equal(dstManifest)) }) - It("should copy and output verbosed warning for Feferrers deletion by default", func() { - ORAS("cp", RegistryRef(Host, ArtifactRepo, foobar.Tag), GinkgoT().TempDir(), Flags.ToLayout, "-v", "--skip-delete-referrers"). - MatchErrKeyWords("referrers deletion can only be enforced upon registry\n"). - Exec() - }) - It("should copy an image from an OCI image layout to a registry via tag", func() { layoutDir := GinkgoT().TempDir() src := LayoutRef(layoutDir, "copied") diff --git a/test/e2e/suite/command/manifest.go b/test/e2e/suite/command/manifest.go index 51235314e..109e4ecc3 100644 --- a/test/e2e/suite/command/manifest.go +++ b/test/e2e/suite/command/manifest.go @@ -518,7 +518,9 @@ var _ = Describe("OCI image layout users:", func() { ORAS("manifest", "fetch-config", Flags.Layout, root).ExpectFailure().MatchErrKeyWords("Error:", "invalid image reference").Exec() }) }) +}) +var _ = Describe("OCI image layout users:", func() { When("running `manifest push`", func() { scratchSize := 2 scratchDigest := "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" @@ -545,15 +547,6 @@ var _ = Describe("OCI image layout users:", func() { } descriptor := "{\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"digest\":\"sha256:f20c43161d73848408ef247f0ec7111b19fe58ffebc0cbcaa0d2c8bda4967268\",\"size\":246}" - It("should push and output verbosed warning for Feferrers deletion by default", func() { - manifestPath := WriteTempFile("manifest.json", manifest) - root := filepath.Dir(manifestPath) - prepare(root) - ORAS("manifest", "push", root, Flags.Layout, manifestPath, "--skip-delete-referrers"). - WithWorkDir(root). - MatchErrKeyWords("referrers deletion can only be enforced upon registry\n").Exec() - }) - It("should push a manifest from stdin", func() { root := GinkgoT().TempDir() prepare(root) @@ -562,7 +555,6 @@ var _ = Describe("OCI image layout users:", func() { WithInput(strings.NewReader(manifest)).Exec() validate(root, manifestDigest, "") }) - It("should push a manifest from stdin and tag", func() { tag := "from-stdin" root := GinkgoT().TempDir() @@ -614,40 +606,3 @@ var _ = Describe("OCI image layout users:", func() { }) }) }) - -func pushTestRepo(text string) string { - return fmt.Sprintf("command/push/%d/%s", GinkgoRandomSeed(), text) -} - -var _ = Describe("Fallback registry users:", func() { - When("running `manifest push`", func() { - manifest := fmt.Sprintf(`{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"oras.test","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2},"subject":%s,"layers":[]}`, foobar.DescriptorStr) - It("should fail to push manifest when cleaning referrers index", func() { - testRepo := pushTestRepo("fallback/fail-gc") - subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) - // prepare - ORAS("cp", RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef, "-r").Exec() - // test - ORAS("manifest", "push", RegistryRef(FallbackHost, testRepo, ""), "-"). - WithInput(strings.NewReader(manifest)). - ExpectFailure(). - MatchErrKeyWords("failed to delete dangling referrers index"). - Exec() - }) - It("should push manifest and skip cleaning referrers index", func() { - testRepo := pushTestRepo("fallback/skip-gc") - subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) - // prepare - ORAS("cp", RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef, "-r").Exec() - // test - ORAS("manifest", "push", RegistryRef(FallbackHost, testRepo, ""), "-", "--skip-delete-referrers"). - WithInput(strings.NewReader(manifest)). - Exec() - // validate - var index ocispec.Index - bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents() - Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred()) - Expect(len(index.Manifests)).To(Equal(2)) - }) - }) -}) From fda8425c7bf8712eec8c948a11c9304ef128d17e Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 9 Aug 2023 19:00:46 +0800 Subject: [PATCH 15/22] feat: disable referrers index GC by default (#1059) Signed-off-by: Billy Zha --- cmd/oras/internal/option/remote.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/oras/internal/option/remote.go b/cmd/oras/internal/option/remote.go index efd4e054a..0f9e3fe42 100644 --- a/cmd/oras/internal/option/remote.go +++ b/cmd/oras/internal/option/remote.go @@ -269,6 +269,7 @@ func (opts *Remote) NewRepository(reference string, common Common) (repo *remote } hostname := repo.Reference.Registry repo.PlainHTTP = opts.isPlainHttp(hostname) + repo.SkipReferrersGC = true if repo.Client, err = opts.authClient(hostname, common.Debug); err != nil { return nil, err } From 0e2e0f3b4e0c7afce66cff90a6183a55a663f20d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 01:23:29 +0000 Subject: [PATCH 16/22] build(deps): bump golang.org/x/term from 0.10.0 to 0.11.0 (#1051) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d76346c6e..34e1ab8fb 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - golang.org/x/term v0.10.0 + golang.org/x/term v0.11.0 gopkg.in/yaml.v3 v3.0.1 oras.land/oras-go/v2 v2.2.1-0.20230627113607-6b5bd4b4372b ) @@ -17,5 +17,5 @@ require ( require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.10.0 // indirect + golang.org/x/sys v0.11.0 // indirect ) diff --git a/go.sum b/go.sum index ef1f32966..9b03d46b4 100644 --- a/go.sum +++ b/go.sum @@ -25,10 +25,10 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 30abae3156f9a4f0a9056bb01f3a111317503881 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Fri, 18 Aug 2023 13:37:30 +0800 Subject: [PATCH 17/22] feat: pack OCI image spec v1.1 manifests (#1054) Signed-off-by: Billy Zha --- cmd/oras/internal/option/spec.go | 30 +++--- cmd/oras/root/attach.go | 7 +- cmd/oras/root/cp.go | 5 +- cmd/oras/root/push.go | 27 +++--- go.mod | 4 +- go.sum | 8 +- internal/graph/graph.go | 98 ++++++++++++------- internal/graph/graph_test.go | 145 +---------------------------- test/e2e/go.mod | 4 +- test/e2e/go.sum | 8 +- test/e2e/suite/command/attach.go | 51 +--------- test/e2e/suite/command/discover.go | 2 +- test/e2e/suite/command/push.go | 4 +- 13 files changed, 125 insertions(+), 268 deletions(-) diff --git a/cmd/oras/internal/option/spec.go b/cmd/oras/internal/option/spec.go index ccbb204fb..aa08fcae6 100644 --- a/cmd/oras/internal/option/spec.go +++ b/cmd/oras/internal/option/spec.go @@ -18,35 +18,39 @@ package option import ( "fmt" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/pflag" + "oras.land/oras-go/v2" +) + +const ( + ImageSpecV1_1 = "v1.1" + ImageSpecV1_0 = "v1.0" + // TODO: pending on https://github.com/oras-project/oras-go/issues/568 + PackManifestTypeImageV1_0 = 0 ) // ImageSpec option struct. type ImageSpec struct { - // Manifest type for building artifact - ManifestMediaType string - - // specFlag should be provided in form of `-` - specFlag string + flag string + PackType oras.PackManifestType } // Parse parses flags into the option. func (opts *ImageSpec) Parse() error { - switch opts.specFlag { - case "v1.1-image": - opts.ManifestMediaType = ocispec.MediaTypeImageManifest - case "v1.1-artifact": - opts.ManifestMediaType = ocispec.MediaTypeArtifactManifest + switch opts.flag { + case ImageSpecV1_1: + opts.PackType = oras.PackManifestTypeImageV1_1_0_RC4 + case ImageSpecV1_0: + opts.PackType = PackManifestTypeImageV1_0 default: - return fmt.Errorf("unknown image specification flag: %q", opts.specFlag) + return fmt.Errorf("unknown image specification flag: %q", opts.flag) } return nil } // ApplyFlags applies flags to a command flag set. func (opts *ImageSpec) ApplyFlags(fs *pflag.FlagSet) { - fs.StringVar(&opts.specFlag, "image-spec", "v1.1-image", "[Experimental] specify manifest type for building artifact. options: v1.1-image, v1.1-artifact") + fs.StringVar(&opts.flag, "image-spec", ImageSpecV1_1, fmt.Sprintf("[Experimental] specify manifest type for building artifact. options: %s, %s", ImageSpecV1_1, ImageSpecV1_0)) } // distributionSpec option struct. diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index f49c5e4b9..540de3a1c 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -33,7 +33,6 @@ import ( type attachOptions struct { option.Common option.Packer - option.ImageSpec option.Target artifactType string @@ -52,10 +51,6 @@ func attachCmd() *cobra.Command { Example - Attach file 'hi.txt' with type 'doc/example' to manifest 'hello:v1' in registry 'localhost:5000': oras attach --artifact-type doc/example localhost:5000/hello:v1 hi.txt -Example - Attach file "hi.txt" with specific media type when building the manifest: - oras attach --artifact-type doc/example --image-spec v1.1-image localhost:5000/hello:v1 hi.txt # OCI image - oras attach --artifact-type doc/example --image-spec v1.1-artifact localhost:5000/hello:v1 hi.txt # OCI artifact - Example - Attach file "hi.txt" using a specific method for the Referrers API: oras attach --artifact-type doc/example --distribution-spec v1.1-referrers-api localhost:5000/hello:v1 hi.txt # via API oras attach --artifact-type doc/example --distribution-spec v1.1-referrers-tag localhost:5000/hello:v1 hi.txt # via tag scheme @@ -134,7 +129,7 @@ func runAttach(ctx context.Context, opts attachOptions) error { packOpts := oras.PackOptions{ Subject: &subject, ManifestAnnotations: annotations[option.AnnotationManifest], - PackImageManifest: opts.ManifestMediaType == ocispec.MediaTypeImageManifest, + PackImageManifest: true, } pack := func() (ocispec.Descriptor, error) { return oras.Pack(ctx, store, opts.artifactType, descs, packOpts) diff --git a/cmd/oras/root/cp.go b/cmd/oras/root/cp.go index f8a953b39..224de53f7 100644 --- a/cmd/oras/root/cp.go +++ b/cmd/oras/root/cp.go @@ -25,6 +25,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/spf13/cobra" "oras.land/oras-go/v2" + "oras.land/oras-go/v2/content" "oras.land/oras/cmd/oras/internal/display" "oras.land/oras/cmd/oras/internal/option" "oras.land/oras/internal/graph" @@ -117,7 +118,9 @@ func runCopy(ctx context.Context, opts copyOptions) error { committed := &sync.Map{} extendedCopyOptions := oras.DefaultExtendedCopyOptions extendedCopyOptions.Concurrency = opts.concurrency - extendedCopyOptions.FindPredecessors = graph.FindReferrerPredecessors + extendedCopyOptions.FindPredecessors = func(ctx context.Context, src content.ReadOnlyGraphStorage, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + return graph.Referrers(ctx, src, desc, "") + } extendedCopyOptions.PreCopy = display.StatusPrinter("Copying", opts.Verbose) extendedCopyOptions.PostCopy = func(ctx context.Context, desc ocispec.Descriptor) error { committed.Store(desc.Digest.String(), desc.Annotations[ocispec.AnnotationTitle]) diff --git a/cmd/oras/root/push.go b/cmd/oras/root/push.go index 0423df717..206a742b7 100644 --- a/cmd/oras/root/push.go +++ b/cmd/oras/root/push.go @@ -71,10 +71,6 @@ Example - Push file "hi.txt" with config type "application/vnd.me.config": Example - Push file "hi.txt" with the custom manifest config "config.json" of the custom media type "application/vnd.me.config": oras push --config config.json:application/vnd.me.config localhost:5000/hello:v1 hi.txt -Example - Push file "hi.txt" with specific media type when building the manifest: - oras push --image-spec v1.1-image localhost:5000/hello:v1 hi.txt # OCI image - oras push --image-spec v1.1-artifact localhost:5000/hello:v1 hi.txt # OCI artifact - Example - Push file to the insecure registry: oras push --insecure localhost:5000/hello:v1 hi.txt @@ -102,15 +98,20 @@ Example - Push file "hi.txt" into an OCI image layout folder 'layout-dir' with t opts.RawReference = refs[0] opts.extraRefs = refs[1:] opts.FileRefs = args[1:] - if opts.manifestConfigRef != "" { - if opts.artifactType != "" { - return errors.New("--artifact-type and --config cannot both be provided") + if err := option.Parse(&opts); err != nil { + return err + } + switch opts.PackType { + case option.PackManifestTypeImageV1_0: + if opts.manifestConfigRef != "" && opts.artifactType != "" { + return errors.New("--artifact-type and --config cannot both be provided for 1.0 OCI image") } - if opts.ManifestMediaType == ocispec.MediaTypeArtifactManifest { - return errors.New("cannot build an OCI artifact with manifest config") + case oras.PackManifestTypeImageV1_1_0_RC4: + if opts.manifestConfigRef == "" && opts.artifactType == "" { + opts.artifactType = oras.MediaTypeUnknownArtifact } } - return option.Parse(&opts) + return nil }, RunE: func(cmd *cobra.Command, args []string) error { return runPush(cmd.Context(), opts) @@ -135,6 +136,8 @@ func runPush(ctx context.Context, opts pushOptions) error { packOpts := oras.PackOptions{ ConfigAnnotations: annotations[option.AnnotationConfig], ManifestAnnotations: annotations[option.AnnotationManifest], + PackImageManifest: true, + PackManifestType: opts.ImageSpec.PackType, } store, err := file.New("") if err != nil { @@ -152,10 +155,6 @@ func runPush(ctx context.Context, opts pushOptions) error { } desc.Annotations = packOpts.ConfigAnnotations packOpts.ConfigDescriptor = &desc - packOpts.PackImageManifest = true - } - if opts.ManifestMediaType == ocispec.MediaTypeImageManifest { - packOpts.PackImageManifest = true } descs, err := loadFiles(ctx, store, annotations, opts.FileRefs, opts.Verbose) if err != nil { diff --git a/go.mod b/go.mod index 34e1ab8fb..63a6ecf28 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,14 @@ go 1.20 require ( github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc2 + github.com/opencontainers/image-spec v1.1.0-rc4 github.com/oras-project/oras-credentials-go v0.2.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 golang.org/x/term v0.11.0 gopkg.in/yaml.v3 v3.0.1 - oras.land/oras-go/v2 v2.2.1-0.20230627113607-6b5bd4b4372b + oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 ) require ( diff --git a/go.sum b/go.sum index 9b03d46b4..7134a6c8b 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= +github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/oras-project/oras-credentials-go v0.2.0 h1:BvWAXo0e5unWR6Hfxyb0K04mHNHreQz/Zclw6IzCYJo= github.com/oras-project/oras-credentials-go v0.2.0/go.mod h1:JVdg7a5k7hzTrEeeouwag0aCv7OLrS77r7/6w3gVirU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -34,5 +34,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -oras.land/oras-go/v2 v2.2.1-0.20230627113607-6b5bd4b4372b h1:NYynybpqtG3lLTZMWNlrvUlcyGakCke57tg4TX6w2kA= -oras.land/oras-go/v2 v2.2.1-0.20230627113607-6b5bd4b4372b/go.mod h1:goptA58HogB/6sLN7KV6FgoiurcVxd5QBqv8wMVB0as= +oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 h1:lK/VtXN9+dzSD3EMuCXu0D28OJadBxB9yUpaJBDIABM= +oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ= diff --git a/internal/graph/graph.go b/internal/graph/graph.go index bcefdd43d..4269d36df 100644 --- a/internal/graph/graph.go +++ b/internal/graph/graph.go @@ -25,6 +25,34 @@ import ( "oras.land/oras/internal/docker" ) +// MediaTypeArtifactManifest specifies the media type for a content descriptor. +const MediaTypeArtifactManifest = "application/vnd.oci.artifact.manifest.v1+json" + +// Artifact describes an artifact manifest. +// This structure provides `application/vnd.oci.artifact.manifest.v1+json` mediatype when marshalled to JSON. +// +// This manifest type was introduced in image-spec v1.1.0-rc1 and was removed in +// image-spec v1.1.0-rc3. It is not part of the current image-spec and is kept +// here for Go compatibility. +// +// Reference: https://github.com/opencontainers/image-spec/pull/999 +type Artifact struct { + // MediaType is the media type of the object this schema refers to. + MediaType string `json:"mediaType"` + + // ArtifactType is the IANA media type of the artifact this schema refers to. + ArtifactType string `json:"artifactType"` + + // Blobs is a collection of blobs referenced by this manifest. + Blobs []ocispec.Descriptor `json:"blobs,omitempty"` + + // Subject (reference) is an optional link from the artifact to another manifest forming an association between the artifact and the other manifest. + Subject *ocispec.Descriptor `json:"subject,omitempty"` + + // Annotations contains arbitrary metadata for the artifact manifest. + Annotations map[string]string `json:"annotations,omitempty"` +} + // Successors returns the nodes directly pointed by the current node, picking // out subject and config descriptor if applicable. // Returning nil when no subject and config found. @@ -43,18 +71,30 @@ func Successors(ctx context.Context, fetcher content.Fetcher, node ocispec.Descr nodes = manifest.Layers subject = manifest.Subject config = &manifest.Config - case ocispec.MediaTypeArtifactManifest: + case MediaTypeArtifactManifest: var fetched []byte fetched, err = content.FetchAll(ctx, fetcher, node) if err != nil { return } - var manifest ocispec.Artifact + var manifest Artifact if err = json.Unmarshal(fetched, &manifest); err != nil { return } nodes = manifest.Blobs subject = manifest.Subject + case ocispec.MediaTypeImageIndex: + var fetched []byte + fetched, err = content.FetchAll(ctx, fetcher, node) + if err != nil { + return + } + var index ocispec.Index + if err = json.Unmarshal(fetched, &index); err != nil { + return + } + nodes = index.Manifests + subject = index.Subject default: nodes, err = content.Successors(ctx, fetcher, node) } @@ -83,12 +123,12 @@ func Referrers(ctx context.Context, target content.ReadOnlyGraphStorage, desc oc } for _, node := range predecessors { switch node.MediaType { - case ocispec.MediaTypeArtifactManifest: + case MediaTypeArtifactManifest: fetched, err := fetchBytes(ctx, target, node) if err != nil { return nil, err } - var artifact ocispec.Artifact + var artifact Artifact if err := json.Unmarshal(fetched, &artifact); err != nil { return nil, err } @@ -109,39 +149,31 @@ func Referrers(ctx context.Context, target content.ReadOnlyGraphStorage, desc oc if image.Subject == nil || !content.Equal(*image.Subject, desc) { continue } - node.ArtifactType = image.Config.MediaType + node.ArtifactType = image.ArtifactType + if node.ArtifactType == "" { + node.ArtifactType = image.Config.MediaType + } node.Annotations = image.Annotations + case ocispec.MediaTypeImageIndex: + fetched, err := fetchBytes(ctx, target, node) + if err != nil { + return nil, err + } + var index ocispec.Index + if err := json.Unmarshal(fetched, &index); err != nil { + return nil, err + } + if index.Subject == nil || !content.Equal(*index.Subject, desc) { + continue + } + node.ArtifactType = index.ArtifactType + node.Annotations = index.Annotations default: continue } - if node.ArtifactType != "" && (artifactType == "" || artifactType == node.ArtifactType) { - results = append(results, node) - } - } - return results, nil -} - -// FindReferrerPredecessors returns referrer nodes of desc in target. -func FindReferrerPredecessors(ctx context.Context, src content.ReadOnlyGraphStorage, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { - var results []ocispec.Descriptor - if repo, ok := src.(registry.ReferrerLister); ok { - // get referrers directly - err := repo.Referrers(ctx, desc, "", func(referrers []ocispec.Descriptor) error { - results = append(results, referrers...) - return nil - }) - if err != nil { - return nil, err - } - return results, nil - } - predecessors, err := src.Predecessors(ctx, desc) - if err != nil { - return nil, err - } - for _, node := range predecessors { - switch node.MediaType { - case ocispec.MediaTypeArtifactManifest, ocispec.MediaTypeImageManifest: + if artifactType == "" || artifactType == node.ArtifactType { + // the field artifactType in referrers descriptor is allowed to be empty + // https://github.com/opencontainers/distribution-spec/issues/458 results = append(results, node) } } diff --git a/internal/graph/graph_test.go b/internal/graph/graph_test.go index 599307fa2..d33c4ad8c 100644 --- a/internal/graph/graph_test.go +++ b/internal/graph/graph_test.go @@ -39,14 +39,6 @@ func (e *errLister) Referrers(ctx context.Context, desc ocispec.Descriptor, arti return errors.New("") } -type errFinder struct { - oras.ReadOnlyGraphTarget -} - -func (e *errFinder) Predecessors(ctx context.Context, node ocispec.Descriptor) ([]ocispec.Descriptor, error) { - return nil, errors.New("") -} - type refLister struct { referrers []ocispec.Descriptor oras.ReadOnlyGraphTarget @@ -89,19 +81,6 @@ func TestReferrers(t *testing.T) { } appendBlob(ocispec.MediaTypeImageManifest, manifestJSON) } - generateArtifact := func(artifactType string, subject *ocispec.Descriptor, annotations map[string]string, blobs ...ocispec.Descriptor) { - manifest := ocispec.Artifact{ - Subject: subject, - Blobs: blobs, - Annotations: annotations, - ArtifactType: artifactType, - } - manifestJSON, err := json.Marshal(manifest) - if err != nil { - t.Fatal(err) - } - appendBlob(ocispec.MediaTypeArtifactManifest, manifestJSON) - } generateIndex := func(manifests ...ocispec.Descriptor) { index := ocispec.Index{ Manifests: manifests, @@ -117,11 +96,10 @@ func TestReferrers(t *testing.T) { imgConfig subject image - artifact index ) anno := map[string]string{"test": "foo"} - appendBlob(ocispec.MediaTypeArtifactManifest, []byte(`{"name":"subject content"}`)) + appendBlob(ocispec.MediaTypeImageLayer, []byte("blob")) imageType := "test.image" appendBlob(imageType, []byte("config content")) generateImage(nil, nil, descs[imgConfig], descs[blob]) @@ -129,12 +107,7 @@ func TestReferrers(t *testing.T) { imageDesc := descs[image] imageDesc.Annotations = anno imageDesc.ArtifactType = imageType - artifactType := "test.artifact" - generateArtifact(artifactType, &descs[subject], anno, descs[blob]) generateIndex(descs[subject]) - artifactDesc := descs[artifact] - artifactDesc.Annotations = anno - artifactDesc.ArtifactType = artifactType referrers := []ocispec.Descriptor{descs[image], descs[image]} memory := memory.New() @@ -163,7 +136,6 @@ func TestReferrers(t *testing.T) { {"should return nil for config node", args{ctx, finder, descs[imgConfig], ""}, nil, false}, {"should return nil for blob/layer node", args{ctx, finder, descs[blob], ""}, nil, false}, {"should find filtered image referrer", args{ctx, finder, descs[subject], imageType}, []ocispec.Descriptor{imageDesc}, false}, - {"should find filtered artifact referrer", args{ctx, finder, descs[subject], artifactType}, []ocispec.Descriptor{artifactDesc}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -179,15 +151,14 @@ func TestReferrers(t *testing.T) { } t.Run("should find referrers in predecessors", func(t *testing.T) { - want1 := []ocispec.Descriptor{artifactDesc, imageDesc} - want2 := []ocispec.Descriptor{imageDesc, artifactDesc} + want := []ocispec.Descriptor{imageDesc} got, err := Referrers(ctx, finder, descs[subject], "") if err != nil { t.Errorf("Referrers() error = %v", err) return } - if !reflect.DeepEqual(got, want1) && !reflect.DeepEqual(got, want2) { - t.Errorf("Referrers() = %v, want %v", got, want1) + if !reflect.DeepEqual(got, want) { + t.Errorf("Referrers() = %v, want %v", got, want) } }) } @@ -216,18 +187,6 @@ func TestSuccessors(t *testing.T) { } appendBlob(mediaType, manifestJSON) } - generateArtifact := func(artifactType string, subject *ocispec.Descriptor, blobs ...ocispec.Descriptor) { - manifest := ocispec.Artifact{ - MediaType: ocispec.MediaTypeArtifactManifest, - Subject: subject, - Blobs: blobs, - } - manifestJSON, err := json.Marshal(manifest) - if err != nil { - t.Fatal(err) - } - appendBlob(ocispec.MediaTypeArtifactManifest, manifestJSON) - } generateIndex := func(manifests ...ocispec.Descriptor) { index := ocispec.Index{ Manifests: manifests, @@ -243,16 +202,13 @@ func TestSuccessors(t *testing.T) { config ociImage dockerImage - artifact index ) - appendBlob(ocispec.MediaTypeArtifactManifest, []byte(`{"name":"subject content"}`)) + appendBlob(ocispec.MediaTypeImageLayer, []byte("blob")) imageType := "test.image" appendBlob(imageType, []byte("config content")) generateImage(&descs[subject], ocispec.MediaTypeImageManifest, descs[config]) generateImage(&descs[subject], docker.MediaTypeManifest, descs[config]) - artifactType := "test.artifact" - generateArtifact(artifactType, &descs[subject]) generateIndex(descs[subject]) memory := memory.New() ctx := context.Background() @@ -276,12 +232,10 @@ func TestSuccessors(t *testing.T) { wantConfig *ocispec.Descriptor wantErr bool }{ - {"should failed to get non-existent artifact", args{ctx, fetcher, ocispec.Descriptor{MediaType: ocispec.MediaTypeArtifactManifest}}, nil, nil, nil, true}, {"should failed to get non-existent OCI image", args{ctx, fetcher, ocispec.Descriptor{MediaType: ocispec.MediaTypeImageManifest}}, nil, nil, nil, true}, {"should failed to get non-existent docker image", args{ctx, fetcher, ocispec.Descriptor{MediaType: docker.MediaTypeManifest}}, nil, nil, nil, true}, {"should get success of a docker image", args{ctx, fetcher, descs[dockerImage]}, nil, &descs[subject], &descs[config], false}, {"should get success of an OCI image", args{ctx, fetcher, descs[ociImage]}, nil, &descs[subject], &descs[config], false}, - {"should get success of an artifact", args{ctx, fetcher, descs[artifact]}, nil, &descs[subject], nil, false}, {"should get success of an index", args{ctx, fetcher, descs[index]}, []ocispec.Descriptor{descs[subject]}, nil, nil, false}, } for _, tt := range tests { @@ -303,92 +257,3 @@ func TestSuccessors(t *testing.T) { }) } } - -func TestFindReferrerPredecessors(t *testing.T) { - ctx := context.Background() - var blobs [][]byte - var descs []ocispec.Descriptor - appendBlob := func(mediaType string, blob []byte) { - blobs = append(blobs, blob) - descs = append(descs, ocispec.Descriptor{ - MediaType: mediaType, - Digest: digest.FromBytes(blob), - Size: int64(len(blob)), - }) - } - generateImage := func(subject *ocispec.Descriptor, annotations map[string]string, config ocispec.Descriptor, layers ...ocispec.Descriptor) { - manifest := ocispec.Manifest{ - Subject: subject, - Config: config, - Layers: layers, - Annotations: annotations, - } - manifestJSON, err := json.Marshal(manifest) - if err != nil { - t.Fatal(err) - } - appendBlob(ocispec.MediaTypeImageManifest, manifestJSON) - } - generateIndex := func(manifests ...ocispec.Descriptor) { - index := ocispec.Index{ - Manifests: manifests, - } - manifestJSON, err := json.Marshal(index) - if err != nil { - t.Fatal(err) - } - appendBlob(ocispec.MediaTypeImageIndex, manifestJSON) - } - const ( - subject = iota - imgConfig - image - ) - var anno map[string]string - appendBlob(ocispec.MediaTypeArtifactManifest, []byte(`{"name":"subject content"}`)) - imageType := "test.image" - appendBlob(imageType, []byte("config content")) - generateImage(&descs[subject], anno, descs[imgConfig]) - imageDesc := descs[image] - imageDesc.Annotations = anno - imageDesc.ArtifactType = imageType - generateIndex(descs[subject]) - - referrers := []ocispec.Descriptor{descs[image], descs[image]} - memory := memory.New() - for i := range descs { - if err := memory.Push(ctx, descs[i], bytes.NewReader(blobs[i])); err != nil { - t.Errorf("Error pushing %v\n", err) - } - } - finder := &predecessorFinder{Store: memory} - type args struct { - ctx context.Context - src content.ReadOnlyGraphStorage - desc ocispec.Descriptor - } - tests := []struct { - name string - args args - want []ocispec.Descriptor - wantErr bool - }{ - {"should failed to get referrers", args{ctx, &errLister{}, ocispec.Descriptor{}}, nil, true}, - {"should failed to get predecessor", args{ctx, &errFinder{}, ocispec.Descriptor{}}, nil, true}, - {"should return referrers when target is a referrer lister", args{ctx, &refLister{referrers: referrers}, ocispec.Descriptor{}}, referrers, false}, - {"should return image for config node", args{ctx, finder, descs[imgConfig]}, []ocispec.Descriptor{descs[image]}, false}, - {"should return image for subject node", args{ctx, finder, descs[subject]}, []ocispec.Descriptor{descs[image]}, false}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := FindReferrerPredecessors(tt.args.ctx, tt.args.src, tt.args.desc) - if (err != nil) != tt.wantErr { - t.Errorf("FindReferrerPredecessors() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("FindReferrerPredecessors() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 09b86ff2c..9f1bee561 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -6,9 +6,9 @@ require ( github.com/onsi/ginkgo/v2 v2.11.0 github.com/onsi/gomega v1.27.10 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc2 + github.com/opencontainers/image-spec v1.1.0-rc4 gopkg.in/yaml.v2 v2.4.0 - oras.land/oras-go/v2 v2.2.1-0.20230627113607-6b5bd4b4372b + oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 ) require ( diff --git a/test/e2e/go.sum b/test/e2e/go.sum index bac81e704..350be0911 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -20,8 +20,8 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= +github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -47,5 +47,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -oras.land/oras-go/v2 v2.2.1-0.20230627113607-6b5bd4b4372b h1:NYynybpqtG3lLTZMWNlrvUlcyGakCke57tg4TX6w2kA= -oras.land/oras-go/v2 v2.2.1-0.20230627113607-6b5bd4b4372b/go.mod h1:goptA58HogB/6sLN7KV6FgoiurcVxd5QBqv8wMVB0as= +oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 h1:lK/VtXN9+dzSD3EMuCXu0D28OJadBxB9yUpaJBDIABM= +oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ= diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index a3083e86b..b0e5fba68 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -43,7 +43,6 @@ var _ = Describe("ORAS beginners:", func() { It("should show preview and help doc", func() { out := ORAS("attach", "--help").MatchKeyWords(feature.Preview.Mark+" Attach", feature.Preview.Description, ExampleDesc).Exec() gomega.Expect(out).Should(gbytes.Say("--distribution-spec string\\s+%s", regexp.QuoteMeta(feature.Preview.Mark))) - gomega.Expect(out).Should(gbytes.Say("--image-spec string\\s+%s", regexp.QuoteMeta(feature.Experimental.Mark))) }) It("should fail when no subject reference provided", func() { @@ -65,11 +64,6 @@ var _ = Describe("ORAS beginners:", func() { ORAS("attach", "--artifact-type", "oras.test", RegistryRef(Host, ImageRepo, foobar.Tag), "--distribution-spec", "???"). ExpectFailure().MatchErrKeyWords("unknown distribution specification flag").Exec() }) - - It("should fail if image spec is unkown", func() { - ORAS("attach", "--artifact-type", "oras.test", RegistryRef(Host, ImageRepo, foobar.Tag), "--image-spec", "???"). - ExpectFailure().MatchErrKeyWords("unknown image specification flag").Exec() - }) }) }) @@ -111,10 +105,9 @@ var _ = Describe("Common registry users:", func() { subjectRef := RegistryRef(Host, testRepo, foobar.Tag) prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image"). + ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - // validate var index ocispec.Index bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents() @@ -148,24 +141,6 @@ var _ = Describe("Common registry users:", func() { ExpectFailure(). Exec() }) - - It("should attach a file via a OCI Artifact", func() { - testRepo := attachTestRepo("artifact") - tempDir := PrepareTempFiles() - subjectRef := RegistryRef(Host, testRepo, foobar.Tag) - prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) - // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-artifact"). - WithWorkDir(tempDir). - MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - - // validate - var index ocispec.Index - bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents() - Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred()) - Expect(len(index.Manifests)).To(Equal(1)) - Expect(index.Manifests[0].MediaType).To(Equal("application/vnd.oci.artifact.manifest.v1+json")) - }) }) }) @@ -177,7 +152,7 @@ var _ = Describe("Fallback registry users:", func() { subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image"). + ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -195,7 +170,7 @@ var _ = Describe("Fallback registry users:", func() { subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image"). + ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -213,7 +188,7 @@ var _ = Describe("Fallback registry users:", func() { subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image", "--distribution-spec", "v1.1-referrers-tag"). + ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--distribution-spec", "v1.1-referrers-tag"). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -265,7 +240,7 @@ var _ = Describe("OCI image layout users:", func() { subjectRef := LayoutRef(root, foobar.Tag) prepare(root) // test - ORAS("attach", "--artifact-type", "test.attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image"). + ORAS("attach", "--artifact-type", "test.attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(root). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -276,21 +251,5 @@ var _ = Describe("OCI image layout users:", func() { Expect(len(index.Manifests)).To(Equal(1)) Expect(index.Manifests[0].MediaType).To(Equal("application/vnd.oci.image.manifest.v1+json")) }) - It("should attach a file via a OCI Artifact", func() { - root := PrepareTempFiles() - subjectRef := LayoutRef(root, foobar.Tag) - prepare(root) - // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, Flags.Layout, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-artifact"). - WithWorkDir(root). - MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() - - // validate - var index ocispec.Index - bytes := ORAS("discover", subjectRef, Flags.Layout, "-o", "json").Exec().Out.Contents() - Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred()) - Expect(len(index.Manifests)).To(Equal(1)) - Expect(index.Manifests[0].MediaType).To(Equal("application/vnd.oci.artifact.manifest.v1+json")) - }) }) }) diff --git a/test/e2e/suite/command/discover.go b/test/e2e/suite/command/discover.go index c753edfce..22d717d02 100644 --- a/test/e2e/suite/command/discover.go +++ b/test/e2e/suite/command/discover.go @@ -262,7 +262,7 @@ var _ = Describe("OCI image layout users:", func() { When("running discover command with table output", func() { format := "table" - It("should direct referrers of a subject", func() { + It("should get direct referrers of a subject", func() { referrers := []ocispec.Descriptor{foobar.SBOMImageReferrer, foobar.SBOMArtifactReferrer} // prepare subjectRef := LayoutRef(GinkgoT().TempDir(), foobar.Tag) diff --git a/test/e2e/suite/command/push.go b/test/e2e/suite/command/push.go index 17139fed4..0fe788a79 100644 --- a/test/e2e/suite/command/push.go +++ b/test/e2e/suite/command/push.go @@ -47,7 +47,7 @@ var _ = Describe("Remote registry users:", func() { When("pushing to registy without OCI artifact support", func() { repoPrefix := fmt.Sprintf("command/push/%d", GinkgoRandomSeed()) statusKeys := []match.StateKey{ - foobar.ImageConfigStateKey("application/vnd.unknown.config.v1+json"), + foobar.ImageConfigStateKey("application/vnd.oci.empty.v1+json"), foobar.FileBarStateKey, } It("should push files without customized media types", func() { @@ -230,7 +230,7 @@ var _ = Describe("OCI image layout users:", func() { tag := "e2e" When("pushing to registy without OCI artifact support", func() { statusKeys := []match.StateKey{ - foobar.ImageConfigStateKey("application/vnd.unknown.config.v1+json"), + foobar.ImageConfigStateKey("application/vnd.oci.empty.v1+json"), foobar.FileBarStateKey, } From 742b044a4fe0962012dad152610f524b16ec423b Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 22 Aug 2023 20:19:40 +0800 Subject: [PATCH 18/22] bump: use new packing function in oras-go (#1070) Signed-off-by: Billy Zha --- cmd/oras/internal/option/spec.go | 8 +++----- cmd/oras/root/attach.go | 6 +++--- cmd/oras/root/push.go | 11 +++++------ go.mod | 2 +- go.sum | 4 ++-- test/e2e/go.mod | 2 +- test/e2e/go.sum | 4 ++-- test/e2e/suite/scenario/oci_artifact.go | 10 ++++++---- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/cmd/oras/internal/option/spec.go b/cmd/oras/internal/option/spec.go index aa08fcae6..3b9e833b1 100644 --- a/cmd/oras/internal/option/spec.go +++ b/cmd/oras/internal/option/spec.go @@ -25,23 +25,21 @@ import ( const ( ImageSpecV1_1 = "v1.1" ImageSpecV1_0 = "v1.0" - // TODO: pending on https://github.com/oras-project/oras-go/issues/568 - PackManifestTypeImageV1_0 = 0 ) // ImageSpec option struct. type ImageSpec struct { flag string - PackType oras.PackManifestType + PackType oras.PackManifestVersion } // Parse parses flags into the option. func (opts *ImageSpec) Parse() error { switch opts.flag { case ImageSpecV1_1: - opts.PackType = oras.PackManifestTypeImageV1_1_0_RC4 + opts.PackType = oras.PackManifestVersion1_1_RC4 case ImageSpecV1_0: - opts.PackType = PackManifestTypeImageV1_0 + opts.PackType = oras.PackManifestVersion1_0 default: return fmt.Errorf("unknown image specification flag: %q", opts.flag) } diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index 540de3a1c..7560e9c1e 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -126,13 +126,13 @@ func runAttach(ctx context.Context, opts attachOptions) error { } // prepare push - packOpts := oras.PackOptions{ + packOpts := oras.PackManifestOptions{ Subject: &subject, ManifestAnnotations: annotations[option.AnnotationManifest], - PackImageManifest: true, + Layers: descs, } pack := func() (ocispec.Descriptor, error) { - return oras.Pack(ctx, store, opts.artifactType, descs, packOpts) + return oras.PackManifest(ctx, store, oras.PackManifestVersion1_1_RC4, opts.artifactType, packOpts) } graphCopyOptions := oras.DefaultCopyGraphOptions diff --git a/cmd/oras/root/push.go b/cmd/oras/root/push.go index 206a742b7..c3cefdd80 100644 --- a/cmd/oras/root/push.go +++ b/cmd/oras/root/push.go @@ -102,11 +102,11 @@ Example - Push file "hi.txt" into an OCI image layout folder 'layout-dir' with t return err } switch opts.PackType { - case option.PackManifestTypeImageV1_0: + case oras.PackManifestVersion1_0: if opts.manifestConfigRef != "" && opts.artifactType != "" { return errors.New("--artifact-type and --config cannot both be provided for 1.0 OCI image") } - case oras.PackManifestTypeImageV1_1_0_RC4: + case oras.PackManifestVersion1_1_RC4: if opts.manifestConfigRef == "" && opts.artifactType == "" { opts.artifactType = oras.MediaTypeUnknownArtifact } @@ -133,11 +133,9 @@ func runPush(ctx context.Context, opts pushOptions) error { } // prepare pack - packOpts := oras.PackOptions{ + packOpts := oras.PackManifestOptions{ ConfigAnnotations: annotations[option.AnnotationConfig], ManifestAnnotations: annotations[option.AnnotationManifest], - PackImageManifest: true, - PackManifestType: opts.ImageSpec.PackType, } store, err := file.New("") if err != nil { @@ -160,9 +158,10 @@ func runPush(ctx context.Context, opts pushOptions) error { if err != nil { return err } + packOpts.Layers = descs memoryStore := memory.New() pack := func() (ocispec.Descriptor, error) { - root, err := oras.Pack(ctx, memoryStore, opts.artifactType, descs, packOpts) + root, err := oras.PackManifest(ctx, memoryStore, opts.PackType, opts.artifactType, packOpts) if err != nil { return ocispec.Descriptor{}, err } diff --git a/go.mod b/go.mod index 63a6ecf28..8b3455205 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/spf13/pflag v1.0.5 golang.org/x/term v0.11.0 gopkg.in/yaml.v3 v3.0.1 - oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 + oras.land/oras-go/v2 v2.2.1-0.20230822062013-e6d40b6ff29f ) require ( diff --git a/go.sum b/go.sum index 7134a6c8b..56f34e990 100644 --- a/go.sum +++ b/go.sum @@ -34,5 +34,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 h1:lK/VtXN9+dzSD3EMuCXu0D28OJadBxB9yUpaJBDIABM= -oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ= +oras.land/oras-go/v2 v2.2.1-0.20230822062013-e6d40b6ff29f h1:2Lx/b6oqh6vZST55SxNYNQJSZmOQZDQckdw34tI2bc4= +oras.land/oras-go/v2 v2.2.1-0.20230822062013-e6d40b6ff29f/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ= diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 9f1bee561..aa8614a48 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -8,7 +8,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc4 gopkg.in/yaml.v2 v2.4.0 - oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 + oras.land/oras-go/v2 v2.2.1-0.20230822062013-e6d40b6ff29f ) require ( diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 350be0911..7987d01d9 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -47,5 +47,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542 h1:lK/VtXN9+dzSD3EMuCXu0D28OJadBxB9yUpaJBDIABM= -oras.land/oras-go/v2 v2.2.1-0.20230807082644-bbe92af00542/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ= +oras.land/oras-go/v2 v2.2.1-0.20230822062013-e6d40b6ff29f h1:2Lx/b6oqh6vZST55SxNYNQJSZmOQZDQckdw34tI2bc4= +oras.land/oras-go/v2 v2.2.1-0.20230822062013-e6d40b6ff29f/go.mod h1:GeAwLuC4G/JpNwkd+bSZ6SkDMGaaYglt6YK2WvZP7uQ= diff --git a/test/e2e/suite/scenario/oci_artifact.go b/test/e2e/suite/scenario/oci_artifact.go index c426b7d79..bbd744e3c 100644 --- a/test/e2e/suite/scenario/oci_artifact.go +++ b/test/e2e/suite/scenario/oci_artifact.go @@ -82,10 +82,12 @@ var _ = Describe("Common OCI artifact users:", Ordered, func() { WithWorkDir(tempDir). WithDescription("attach again with manifest exported").Exec() - session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test.artifact2").Exec() - digest = string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) - fetched = ORAS("manifest", "fetch", RegistryRef(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() - MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) + // FIXME: oras distribution doesn't support OCI image with artifactType field + // Below test can be run after https://github.com/oras-project/oras/issues/1071 is done. + // session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test.artifact2").Exec() + // digest = string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) + // fetched = ORAS("manifest", "fetch", RegistryRef(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() + // MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) ORAS("pull", RegistryRef(Host, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject"). MatchStatus(append(foobar.FileStateKeys, foobar.AttachFileStateKey), true, 4). From 63194161fab297ea55133885044aa56f58a647fe Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 20:58:40 +0800 Subject: [PATCH 19/22] feat: support warning in remote targets (#1057) Signed-off-by: Billy Zha --- cmd/oras/internal/option/remote.go | 42 +++++++++++++++++++------ cmd/oras/internal/option/remote_test.go | 7 +++-- cmd/oras/internal/option/target.go | 12 ++++--- cmd/oras/root/attach.go | 4 +-- cmd/oras/root/blob/delete.go | 4 +-- cmd/oras/root/blob/fetch.go | 4 +-- cmd/oras/root/blob/push.go | 4 +-- cmd/oras/root/cp.go | 6 ++-- cmd/oras/root/discover.go | 6 ++-- cmd/oras/root/login.go | 4 +-- cmd/oras/root/manifest/delete.go | 4 +-- cmd/oras/root/manifest/fetch.go | 4 +-- cmd/oras/root/manifest/fetch_config.go | 4 +-- cmd/oras/root/manifest/push.go | 4 +-- cmd/oras/root/pull.go | 4 +-- cmd/oras/root/push.go | 4 +-- cmd/oras/root/repo/ls.go | 4 +-- cmd/oras/root/repo/tags.go | 2 +- cmd/oras/root/tag.go | 4 +-- internal/credential/store_test.go | 4 ++- 20 files changed, 80 insertions(+), 51 deletions(-) diff --git a/cmd/oras/internal/option/remote.go b/cmd/oras/internal/option/remote.go index 0f9e3fe42..f56b90bf5 100644 --- a/cmd/oras/internal/option/remote.go +++ b/cmd/oras/internal/option/remote.go @@ -25,8 +25,10 @@ import ( "os" "strconv" "strings" + "sync" credentials "github.com/oras-project/oras-credentials-go" + "github.com/sirupsen/logrus" "github.com/spf13/pflag" "oras.land/oras-go/v2/registry/remote" "oras.land/oras-go/v2/registry/remote/auth" @@ -53,6 +55,7 @@ type Remote struct { distributionSpec distributionSpec headerFlags []string headers http.Header + warned map[string]*sync.Map } // EnableDistributionSpecFlag set distribution specification flag as applicable. @@ -247,32 +250,51 @@ func (opts *Remote) Credential() auth.Credential { return credential.Credential(opts.Username, opts.Password) } +func (opts *Remote) handleWarning(registry string, logger logrus.FieldLogger) func(warning remote.Warning) { + if opts.warned == nil { + opts.warned = make(map[string]*sync.Map) + } + warned := opts.warned[registry] + if warned == nil { + warned = &sync.Map{} + opts.warned[registry] = warned + } + logger = logger.WithField("registry", registry) + return func(warning remote.Warning) { + if _, loaded := warned.LoadOrStore(warning.WarningValue, struct{}{}); !loaded { + logger.Warn(warning.Text) + } + } +} + // NewRegistry assembles a oras remote registry. -func (opts *Remote) NewRegistry(hostname string, common Common) (reg *remote.Registry, err error) { - reg, err = remote.NewRegistry(hostname) +func (opts *Remote) NewRegistry(registry string, common Common, logger logrus.FieldLogger) (reg *remote.Registry, err error) { + reg, err = remote.NewRegistry(registry) if err != nil { return nil, err } - hostname = reg.Reference.Registry - reg.PlainHTTP = opts.isPlainHttp(hostname) - if reg.Client, err = opts.authClient(hostname, common.Debug); err != nil { + registry = reg.Reference.Registry + reg.PlainHTTP = opts.isPlainHttp(registry) + reg.HandleWarning = opts.handleWarning(registry, logger) + if reg.Client, err = opts.authClient(registry, common.Debug); err != nil { return nil, err } return } // NewRepository assembles a oras remote repository. -func (opts *Remote) NewRepository(reference string, common Common) (repo *remote.Repository, err error) { +func (opts *Remote) NewRepository(reference string, common Common, logger logrus.FieldLogger) (repo *remote.Repository, err error) { repo, err = remote.NewRepository(reference) if err != nil { return nil, err } - hostname := repo.Reference.Registry - repo.PlainHTTP = opts.isPlainHttp(hostname) - repo.SkipReferrersGC = true - if repo.Client, err = opts.authClient(hostname, common.Debug); err != nil { + registry := repo.Reference.Registry + repo.PlainHTTP = opts.isPlainHttp(registry) + repo.HandleWarning = opts.handleWarning(registry, logger) + if repo.Client, err = opts.authClient(registry, common.Debug); err != nil { return nil, err } + repo.SkipReferrersGC = true if opts.distributionSpec.referrersAPI != nil { if err := repo.SetReferrersCapability(*opts.distributionSpec.referrersAPI); err != nil { return nil, err diff --git a/cmd/oras/internal/option/remote_test.go b/cmd/oras/internal/option/remote_test.go index abd1c3029..9c60d939b 100644 --- a/cmd/oras/internal/option/remote_test.go +++ b/cmd/oras/internal/option/remote_test.go @@ -30,6 +30,7 @@ import ( "reflect" "testing" + "github.com/sirupsen/logrus" "github.com/spf13/pflag" "oras.land/oras-go/v2/registry/remote/auth" ) @@ -180,7 +181,7 @@ func TestRemote_NewRegistry(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - reg, err := opts.NewRegistry(uri.Host, opts.Common) + reg, err := opts.NewRegistry(uri.Host, opts.Common, logrus.New()) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -208,7 +209,7 @@ func TestRemote_NewRepository(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - repo, err := opts.NewRepository(uri.Host+"/"+testRepo, opts.Common) + repo, err := opts.NewRepository(uri.Host+"/"+testRepo, opts.Common, logrus.New()) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -255,7 +256,7 @@ func TestRemote_NewRepository_Retry(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - repo, err := opts.NewRepository(uri.Host+"/"+testRepo, opts.Common) + repo, err := opts.NewRepository(uri.Host+"/"+testRepo, opts.Common, logrus.New()) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/cmd/oras/internal/option/target.go b/cmd/oras/internal/option/target.go index 9494e1789..36290204e 100644 --- a/cmd/oras/internal/option/target.go +++ b/cmd/oras/internal/option/target.go @@ -21,7 +21,9 @@ import ( "fmt" "os" "strings" + "sync" + "github.com/sirupsen/logrus" "github.com/spf13/pflag" "oras.land/oras-go/v2" "oras.land/oras-go/v2/content/oci" @@ -111,7 +113,7 @@ func parseOCILayoutReference(raw string) (path string, ref string, err error) { } // NewTarget generates a new target based on opts. -func (opts *Target) NewTarget(common Common) (oras.GraphTarget, error) { +func (opts *Target) NewTarget(common Common, logger logrus.FieldLogger) (oras.GraphTarget, error) { switch opts.Type { case TargetTypeOCILayout: var err error @@ -121,7 +123,7 @@ func (opts *Target) NewTarget(common Common) (oras.GraphTarget, error) { } return oci.New(opts.Path) case TargetTypeRemote: - repo, err := opts.NewRepository(opts.RawReference, common) + repo, err := opts.NewRepository(opts.RawReference, common, logger) if err != nil { return nil, err } @@ -142,7 +144,7 @@ type ReadOnlyGraphTagFinderTarget interface { } // NewReadonlyTargets generates a new read only target based on opts. -func (opts *Target) NewReadonlyTarget(ctx context.Context, common Common) (ReadOnlyGraphTagFinderTarget, error) { +func (opts *Target) NewReadonlyTarget(ctx context.Context, common Common, logger logrus.FieldLogger) (ReadOnlyGraphTagFinderTarget, error) { switch opts.Type { case TargetTypeOCILayout: var err error @@ -159,7 +161,7 @@ func (opts *Target) NewReadonlyTarget(ctx context.Context, common Common) (ReadO } return oci.NewFromTar(ctx, opts.Path) case TargetTypeRemote: - repo, err := opts.NewRepository(opts.RawReference, common) + repo, err := opts.NewRepository(opts.RawReference, common, logger) if err != nil { return nil, err } @@ -203,6 +205,8 @@ func (opts *BinaryTarget) ApplyFlags(fs *pflag.FlagSet) { // Parse parses user-provided flags and arguments into option struct. func (opts *BinaryTarget) Parse() error { + opts.From.warned = make(map[string]*sync.Map) + opts.To.warned = opts.From.warned // resolve are parsed in array order, latter will overwrite former opts.From.resolveFlag = append(opts.resolveFlag, opts.From.resolveFlag...) opts.To.resolveFlag = append(opts.resolveFlag, opts.To.resolveFlag...) diff --git a/cmd/oras/root/attach.go b/cmd/oras/root/attach.go index 7560e9c1e..b67ca0c99 100644 --- a/cmd/oras/root/attach.go +++ b/cmd/oras/root/attach.go @@ -93,7 +93,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI image layout folder } func runAttach(ctx context.Context, opts attachOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) annotations, err := opts.LoadManifestAnnotations() if err != nil { return err @@ -109,7 +109,7 @@ func runAttach(ctx context.Context, opts attachOptions) error { } defer store.Close() - dst, err := opts.NewTarget(opts.Common) + dst, err := opts.NewTarget(opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/blob/delete.go b/cmd/oras/root/blob/delete.go index 0f55d044b..e1fbb09ac 100644 --- a/cmd/oras/root/blob/delete.go +++ b/cmd/oras/root/blob/delete.go @@ -71,8 +71,8 @@ Example - Delete a blob and print its descriptor: } func deleteBlob(ctx context.Context, opts deleteBlobOptions) (err error) { - ctx, _ = opts.WithContext(ctx) - repo, err := opts.NewRepository(opts.targetRef, opts.Common) + ctx, logger := opts.WithContext(ctx) + repo, err := opts.NewRepository(opts.targetRef, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/blob/fetch.go b/cmd/oras/root/blob/fetch.go index 7f53873a4..d43ae382d 100644 --- a/cmd/oras/root/blob/fetch.go +++ b/cmd/oras/root/blob/fetch.go @@ -90,9 +90,9 @@ Example - Fetch and print a blob from OCI image layout archive file 'layout.tar' } func fetchBlob(ctx context.Context, opts fetchBlobOptions) (fetchErr error) { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) var target oras.ReadOnlyTarget - target, err := opts.NewReadonlyTarget(ctx, opts.Common) + target, err := opts.NewReadonlyTarget(ctx, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/blob/push.go b/cmd/oras/root/blob/push.go index 9de6c45fe..ea3bffaee 100644 --- a/cmd/oras/root/blob/push.go +++ b/cmd/oras/root/blob/push.go @@ -96,9 +96,9 @@ Example - Push blob 'hi.txt' into an OCI image layout folder 'layout-dir': } func pushBlob(ctx context.Context, opts pushBlobOptions) (err error) { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) - repo, err := opts.NewTarget(opts.Common) + repo, err := opts.NewTarget(opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/cp.go b/cmd/oras/root/cp.go index 224de53f7..90f7cb090 100644 --- a/cmd/oras/root/cp.go +++ b/cmd/oras/root/cp.go @@ -97,10 +97,10 @@ Example - Copy an artifact with multiple tags with concurrency tuned: } func runCopy(ctx context.Context, opts copyOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) // Prepare source - src, err := opts.From.NewReadonlyTarget(ctx, opts.Common) + src, err := opts.From.NewReadonlyTarget(ctx, opts.Common, logger) if err != nil { return err } @@ -109,7 +109,7 @@ func runCopy(ctx context.Context, opts copyOptions) error { } // Prepare destination - dst, err := opts.To.NewTarget(opts.Common) + dst, err := opts.To.NewTarget(opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/discover.go b/cmd/oras/root/discover.go index b7dd372ae..801710ead 100644 --- a/cmd/oras/root/discover.go +++ b/cmd/oras/root/discover.go @@ -91,8 +91,8 @@ Example - Discover referrers of the manifest tagged 'v1' in an OCI image layout } func runDiscover(ctx context.Context, opts discoverOptions) error { - ctx, _ = opts.WithContext(ctx) - repo, err := opts.NewReadonlyTarget(ctx, opts.Common) + ctx, logger := opts.WithContext(ctx) + repo, err := opts.NewReadonlyTarget(ctx, opts.Common, logger) if err != nil { return err } @@ -189,7 +189,7 @@ func printDiscoveredReferrersTable(refs []ocispec.Descriptor, verbose bool) erro print(ref.ArtifactType, ref.Digest) if verbose { if err := printJSON(ref); err != nil { - return fmt.Errorf("Error printing JSON: %w", err) + return fmt.Errorf("error printing JSON: %w", err) } } } diff --git a/cmd/oras/root/login.go b/cmd/oras/root/login.go index aa862fd4d..d6cc65d5d 100644 --- a/cmd/oras/root/login.go +++ b/cmd/oras/root/login.go @@ -75,7 +75,7 @@ Example - Log in with username and password in an interactive terminal and no TL } func runLogin(ctx context.Context, opts loginOptions) (err error) { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) // prompt for credential if opts.Password == "" { @@ -108,7 +108,7 @@ func runLogin(ctx context.Context, opts loginOptions) (err error) { if err != nil { return err } - remote, err := opts.Remote.NewRegistry(opts.Hostname, opts.Common) + remote, err := opts.Remote.NewRegistry(opts.Hostname, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/manifest/delete.go b/cmd/oras/root/manifest/delete.go index 8ece10400..4458fae77 100644 --- a/cmd/oras/root/manifest/delete.go +++ b/cmd/oras/root/manifest/delete.go @@ -76,8 +76,8 @@ Example - Delete a manifest by digest 'sha256:99e4703fbf30916f549cd6bfa9cdbab614 } func deleteManifest(ctx context.Context, opts deleteOptions) error { - ctx, _ = opts.WithContext(ctx) - repo, err := opts.NewRepository(opts.targetRef, opts.Common) + ctx, logger := opts.WithContext(ctx) + repo, err := opts.NewRepository(opts.targetRef, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/manifest/fetch.go b/cmd/oras/root/manifest/fetch.go index 850ac915f..52ec2f80b 100644 --- a/cmd/oras/root/manifest/fetch.go +++ b/cmd/oras/root/manifest/fetch.go @@ -90,9 +90,9 @@ Example - Fetch raw manifest from an OCI layout archive file 'layout.tar': } func fetchManifest(ctx context.Context, opts fetchOptions) (fetchErr error) { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) - target, err := opts.NewReadonlyTarget(ctx, opts.Common) + target, err := opts.NewReadonlyTarget(ctx, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/manifest/fetch_config.go b/cmd/oras/root/manifest/fetch_config.go index a909a4d38..e0f871f34 100644 --- a/cmd/oras/root/manifest/fetch_config.go +++ b/cmd/oras/root/manifest/fetch_config.go @@ -86,9 +86,9 @@ Example - Fetch and print the prettified descriptor of the config: } func fetchConfig(ctx context.Context, opts fetchConfigOptions) (fetchErr error) { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) - repo, err := opts.NewReadonlyTarget(ctx, opts.Common) + repo, err := opts.NewReadonlyTarget(ctx, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/manifest/push.go b/cmd/oras/root/manifest/push.go index c932e8e3f..d9e737918 100644 --- a/cmd/oras/root/manifest/push.go +++ b/cmd/oras/root/manifest/push.go @@ -104,10 +104,10 @@ Example - Push a manifest to an OCI image layout folder 'layout-dir' and tag wit } func pushManifest(ctx context.Context, opts pushOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) var target oras.Target var err error - target, err = opts.NewTarget(opts.Common) + target, err = opts.NewTarget(opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/pull.go b/cmd/oras/root/pull.go index c10f330a4..6baf93091 100644 --- a/cmd/oras/root/pull.go +++ b/cmd/oras/root/pull.go @@ -103,7 +103,7 @@ Example - Pull artifact files from an OCI layout archive 'layout.tar': } func runPull(ctx context.Context, opts pullOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) // Copy Options var printed sync.Map copyOptions := oras.DefaultCopyOptions @@ -182,7 +182,7 @@ func runPull(ctx context.Context, opts pullOptions) error { return ret, nil } - target, err := opts.NewReadonlyTarget(ctx, opts.Common) + target, err := opts.NewReadonlyTarget(ctx, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/push.go b/cmd/oras/root/push.go index c3cefdd80..5bad2955e 100644 --- a/cmd/oras/root/push.go +++ b/cmd/oras/root/push.go @@ -126,7 +126,7 @@ Example - Push file "hi.txt" into an OCI image layout folder 'layout-dir' with t } func runPush(ctx context.Context, opts pushOptions) error { - ctx, _ = opts.WithContext(ctx) + ctx, logger := opts.WithContext(ctx) annotations, err := opts.LoadManifestAnnotations() if err != nil { return err @@ -172,7 +172,7 @@ func runPush(ctx context.Context, opts pushOptions) error { } // prepare push - dst, err := opts.NewTarget(opts.Common) + dst, err := opts.NewTarget(opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/repo/ls.go b/cmd/oras/root/repo/ls.go index f2da5e5f3..cea8dd334 100644 --- a/cmd/oras/root/repo/ls.go +++ b/cmd/oras/root/repo/ls.go @@ -69,8 +69,8 @@ Example - List the repositories under the registry that include values lexically } func listRepository(ctx context.Context, opts repositoryOptions) error { - ctx, _ = opts.WithContext(ctx) - reg, err := opts.Remote.NewRegistry(opts.hostname, opts.Common) + ctx, logger := opts.WithContext(ctx) + reg, err := opts.Remote.NewRegistry(opts.hostname, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/repo/tags.go b/cmd/oras/root/repo/tags.go index 2e7bde777..45e37dba9 100644 --- a/cmd/oras/root/repo/tags.go +++ b/cmd/oras/root/repo/tags.go @@ -79,7 +79,7 @@ Example - [Experimental] Show tags associated with a digest: func showTags(ctx context.Context, opts showTagsOptions) error { ctx, logger := opts.WithContext(ctx) - finder, err := opts.NewReadonlyTarget(ctx, opts.Common) + finder, err := opts.NewReadonlyTarget(ctx, opts.Common, logger) if err != nil { return err } diff --git a/cmd/oras/root/tag.go b/cmd/oras/root/tag.go index a6540ea80..4524d4fb9 100644 --- a/cmd/oras/root/tag.go +++ b/cmd/oras/root/tag.go @@ -76,8 +76,8 @@ Example - Tag the manifest 'v1.0.1' to 'v1.0.2' in an OCI image layout folder 'l } func tagManifest(ctx context.Context, opts tagOptions) error { - ctx, _ = opts.WithContext(ctx) - target, err := opts.NewTarget(opts.Common) + ctx, logger := opts.WithContext(ctx) + target, err := opts.NewTarget(opts.Common, logger) if err != nil { return err } diff --git a/internal/credential/store_test.go b/internal/credential/store_test.go index c7f94569b..3a873ab14 100644 --- a/internal/credential/store_test.go +++ b/internal/credential/store_test.go @@ -26,10 +26,12 @@ import ( func TestNewStoreError(t *testing.T) { tmpDir := t.TempDir() filename := path.Join(tmpDir, "testfile.txt") - _, err := os.Create(filename) + file, err := os.Create(filename) if err != nil { t.Errorf("error: cannot create file : %v", err) } + defer file.Close() + err = os.Chmod(filename, 000) if err != nil { t.Errorf("error: cannot change file permissions: %v", err) From 49f58abd35c2c45aee4e8449cd8ed551ded77bde Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Thu, 24 Aug 2023 09:26:03 +0800 Subject: [PATCH 20/22] chore: align naming of pack option to oras-go (#1073) Signed-off-by: Billy Zha --- cmd/oras/internal/option/spec.go | 8 ++++---- cmd/oras/root/push.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/oras/internal/option/spec.go b/cmd/oras/internal/option/spec.go index 3b9e833b1..837959761 100644 --- a/cmd/oras/internal/option/spec.go +++ b/cmd/oras/internal/option/spec.go @@ -29,17 +29,17 @@ const ( // ImageSpec option struct. type ImageSpec struct { - flag string - PackType oras.PackManifestVersion + flag string + PackVersion oras.PackManifestVersion } // Parse parses flags into the option. func (opts *ImageSpec) Parse() error { switch opts.flag { case ImageSpecV1_1: - opts.PackType = oras.PackManifestVersion1_1_RC4 + opts.PackVersion = oras.PackManifestVersion1_1_RC4 case ImageSpecV1_0: - opts.PackType = oras.PackManifestVersion1_0 + opts.PackVersion = oras.PackManifestVersion1_0 default: return fmt.Errorf("unknown image specification flag: %q", opts.flag) } diff --git a/cmd/oras/root/push.go b/cmd/oras/root/push.go index 5bad2955e..c8e10a86c 100644 --- a/cmd/oras/root/push.go +++ b/cmd/oras/root/push.go @@ -101,7 +101,7 @@ Example - Push file "hi.txt" into an OCI image layout folder 'layout-dir' with t if err := option.Parse(&opts); err != nil { return err } - switch opts.PackType { + switch opts.PackVersion { case oras.PackManifestVersion1_0: if opts.manifestConfigRef != "" && opts.artifactType != "" { return errors.New("--artifact-type and --config cannot both be provided for 1.0 OCI image") @@ -161,7 +161,7 @@ func runPush(ctx context.Context, opts pushOptions) error { packOpts.Layers = descs memoryStore := memory.New() pack := func() (ocispec.Descriptor, error) { - root, err := oras.PackManifest(ctx, memoryStore, opts.PackType, opts.artifactType, packOpts) + root, err := oras.PackManifest(ctx, memoryStore, opts.PackVersion, opts.artifactType, packOpts) if err != nil { return ocispec.Descriptor{}, err } From 08a1a9f3da184d8834188b791cd78a96a6dd4dba Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Thu, 24 Aug 2023 13:40:13 +0800 Subject: [PATCH 21/22] bump: update golang to 1.21 (#1074) Signed-off-by: Billy Zha --- .github/workflows/build.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/golangci-lint.yml | 2 +- .github/workflows/release-github.yml | 2 +- Dockerfile | 2 +- go.mod | 2 +- snapcraft.yaml | 2 +- test/e2e/go.mod | 2 +- test/e2e/go.work | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f7c7a38d6..87928b367 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: ['1.20'] + go-version: ['1.21'] fail-fast: true steps: - name: Checkout diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 152cab650..b9e75f8d6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,7 +35,7 @@ jobs: security-events: write strategy: matrix: - go-version: ['1.20'] + go-version: ['1.21'] fail-fast: false steps: - name: Checkout repository diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index fe2f952c1..052c86175 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: ['1.20'] + go-version: ['1.21'] fail-fast: true steps: - name: Checkout diff --git a/.github/workflows/release-github.yml b/.github/workflows/release-github.yml index 26ee00e19..b622fb753 100644 --- a/.github/workflows/release-github.yml +++ b/.github/workflows/release-github.yml @@ -29,7 +29,7 @@ jobs: - name: setup go environment uses: actions/setup-go@v3 with: - go-version: '1.20.5' + go-version: '1.21.0' - name: run goreleaser uses: goreleaser/goreleaser-action@v2 with: diff --git a/Dockerfile b/Dockerfile index e10ce407a..1525123e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20.5-alpine as builder +FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21.0-alpine as builder ARG TARGETPLATFORM RUN apk add git make ENV ORASPKG /oras diff --git a/go.mod b/go.mod index 8b3455205..eb141b539 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module oras.land/oras -go 1.20 +go 1.21 require ( github.com/opencontainers/go-digest v1.0.0 diff --git a/snapcraft.yaml b/snapcraft.yaml index 6fb0ab02d..4a3f47b58 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -42,7 +42,7 @@ parts: - on amd64 to s390x: - TARGET_ARCH: "s390x" build-snaps: - - go/1.20/stable + - go/1.21/stable build-packages: - make stage-packages: diff --git a/test/e2e/go.mod b/test/e2e/go.mod index aa8614a48..18d54c038 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -1,6 +1,6 @@ module oras.land/oras/test/e2e -go 1.20 +go 1.21 require ( github.com/onsi/ginkgo/v2 v2.11.0 diff --git a/test/e2e/go.work b/test/e2e/go.work index 602d10f96..01071242e 100644 --- a/test/e2e/go.work +++ b/test/e2e/go.work @@ -1,4 +1,4 @@ -go 1.20 +go 1.21 use ( . From b848c93f9a6840278e6e379394efa67b1f3fc5be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 14:16:47 +0800 Subject: [PATCH 22/22] build(deps): bump github.com/onsi/ginkgo/v2 from 2.11.0 to 2.12.0 in /test/e2e (#1075) Signed-off-by: dependabot[bot] --- test/e2e/go.mod | 10 +++++----- test/e2e/go.sum | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 18d54c038..20fca6995 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -3,7 +3,7 @@ module oras.land/oras/test/e2e go 1.21 require ( - github.com/onsi/ginkgo/v2 v2.11.0 + github.com/onsi/ginkgo/v2 v2.12.0 github.com/onsi/gomega v1.27.10 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc4 @@ -16,10 +16,10 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect - golang.org/x/net v0.12.0 // indirect + golang.org/x/net v0.14.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect - golang.org/x/tools v0.9.3 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect + golang.org/x/tools v0.12.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/test/e2e/go.sum b/test/e2e/go.sum index 7987d01d9..52dde5267 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -14,8 +14,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= +github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -27,18 +27,18 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= -golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=