github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/packager/publish.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2021-Present The Jackal Authors 3 4 // Package packager contains functions for interacting with, managing and deploying Jackal packages. 5 package packager 6 7 import ( 8 "context" 9 "fmt" 10 "os" 11 "strings" 12 13 "github.com/Racer159/jackal/src/config" 14 "github.com/Racer159/jackal/src/pkg/layout" 15 "github.com/Racer159/jackal/src/pkg/message" 16 "github.com/Racer159/jackal/src/pkg/packager/creator" 17 "github.com/Racer159/jackal/src/pkg/packager/filters" 18 "github.com/Racer159/jackal/src/pkg/packager/sources" 19 "github.com/Racer159/jackal/src/pkg/utils" 20 "github.com/Racer159/jackal/src/pkg/zoci" 21 "github.com/Racer159/jackal/src/types" 22 "github.com/defenseunicorns/pkg/helpers" 23 "github.com/defenseunicorns/pkg/oci" 24 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 25 ) 26 27 // Publish publishes the package to a registry 28 func (p *Packager) Publish() (err error) { 29 _, isOCISource := p.source.(*sources.OCISource) 30 if isOCISource && p.cfg.PublishOpts.SigningKeyPath == "" { 31 ctx := context.TODO() 32 // oci --> oci is a special case, where we will use oci.CopyPackage so that we can transfer the package 33 // w/o layers touching the filesystem 34 srcRemote := p.source.(*sources.OCISource).Remote 35 36 parts := strings.Split(srcRemote.Repo().Reference.Repository, "/") 37 packageName := parts[len(parts)-1] 38 39 p.cfg.PublishOpts.PackageDestination = p.cfg.PublishOpts.PackageDestination + "/" + packageName 40 41 arch := config.GetArch() 42 43 dstRemote, err := zoci.NewRemote(p.cfg.PublishOpts.PackageDestination, oci.PlatformForArch(arch)) 44 if err != nil { 45 return err 46 } 47 48 return zoci.CopyPackage(ctx, srcRemote, dstRemote, config.CommonOptions.OCIConcurrency) 49 } 50 51 if p.cfg.CreateOpts.IsSkeleton { 52 if err := os.Chdir(p.cfg.CreateOpts.BaseDir); err != nil { 53 return fmt.Errorf("unable to access directory %q: %w", p.cfg.CreateOpts.BaseDir, err) 54 } 55 56 sc := creator.NewSkeletonCreator(p.cfg.CreateOpts, p.cfg.PublishOpts) 57 58 if err := helpers.CreatePathAndCopy(layout.JackalYAML, p.layout.JackalYAML); err != nil { 59 return err 60 } 61 62 p.cfg.Pkg, p.warnings, err = sc.LoadPackageDefinition(p.layout) 63 if err != nil { 64 return err 65 } 66 67 if err := sc.Assemble(p.layout, p.cfg.Pkg.Components, ""); err != nil { 68 return err 69 } 70 71 if err := sc.Output(p.layout, &p.cfg.Pkg); err != nil { 72 return err 73 } 74 } else { 75 filter := filters.Empty() 76 p.cfg.Pkg, p.warnings, err = p.source.LoadPackage(p.layout, filter, false) 77 if err != nil { 78 return fmt.Errorf("unable to load the package: %w", err) 79 } 80 81 // Sign the package if a key has been provided 82 if err := p.layout.SignPackage(p.cfg.PublishOpts.SigningKeyPath, p.cfg.PublishOpts.SigningKeyPassword, !config.CommonOptions.Confirm); err != nil { 83 return err 84 } 85 } 86 87 // Get a reference to the registry for this package 88 ref, err := zoci.ReferenceFromMetadata(p.cfg.PublishOpts.PackageDestination, &p.cfg.Pkg.Metadata, &p.cfg.Pkg.Build) 89 if err != nil { 90 return err 91 } 92 var platform ocispec.Platform 93 if p.cfg.CreateOpts.IsSkeleton { 94 platform = zoci.PlatformForSkeleton() 95 } else { 96 platform = oci.PlatformForArch(p.cfg.Pkg.Build.Architecture) 97 } 98 remote, err := zoci.NewRemote(ref, platform) 99 if err != nil { 100 return err 101 } 102 103 message.HeaderInfof("📦 PACKAGE PUBLISH %s:%s", p.cfg.Pkg.Metadata.Name, ref) 104 105 // Publish the package/skeleton to the registry 106 ctx := context.TODO() 107 if err := remote.PublishPackage(ctx, &p.cfg.Pkg, p.layout, config.CommonOptions.OCIConcurrency); err != nil { 108 return err 109 } 110 if p.cfg.CreateOpts.IsSkeleton { 111 message.Title("How to import components from this skeleton:", "") 112 ex := []types.JackalComponent{} 113 for _, c := range p.cfg.Pkg.Components { 114 ex = append(ex, types.JackalComponent{ 115 Name: fmt.Sprintf("import-%s", c.Name), 116 Import: types.JackalComponentImport{ 117 ComponentName: c.Name, 118 URL: helpers.OCIURLPrefix + remote.Repo().Reference.String(), 119 }, 120 }) 121 } 122 utils.ColorPrintYAML(ex, nil, true) 123 } 124 return nil 125 }