github.com/kubri/kubri@v0.5.1-0.20240317001612-bda2aaef967e/integrations/apk/build.go (about) 1 package apk 2 3 import ( 4 "context" 5 "io/fs" 6 "os" 7 "path" 8 "strings" 9 "unsafe" 10 11 "gitlab.alpinelinux.org/alpine/go/repository" 12 13 "github.com/kubri/kubri/pkg/crypto/rsa" 14 "github.com/kubri/kubri/source" 15 "github.com/kubri/kubri/target" 16 ) 17 18 type Config struct { 19 Source *source.Source 20 Version string 21 Prerelease bool 22 Target target.Target 23 RSAKey *rsa.PrivateKey 24 KeyName string 25 } 26 27 //nolint:funlen 28 func Build(ctx context.Context, c *Config) error { 29 repo, err := openRepo(ctx, c.Target) 30 if err != nil { 31 return err 32 } 33 defer os.RemoveAll(repo.dir) 34 35 version := c.Version 36 if v := getVersionConstraint(repo.repos); v != "" { 37 version += "," + v 38 } 39 40 releases, err := c.Source.ListReleases(ctx, &source.ListOptions{ 41 Version: version, 42 Prerelease: c.Prerelease, 43 }) 44 if err == source.ErrNoReleaseFound { 45 return nil 46 } 47 if err != nil { 48 return err 49 } 50 51 var hasReleases bool 52 for _, release := range releases { 53 for _, asset := range release.Assets { 54 if path.Ext(asset.Name) != ".apk" { 55 continue 56 } 57 b, err := c.Source.DownloadAsset(ctx, release.Version, asset.Name) 58 if err != nil { 59 return err 60 } 61 if err = repo.Add(b); err != nil { 62 return err 63 } 64 hasReleases = true 65 } 66 } 67 if !hasReleases { 68 return nil 69 } 70 71 if err = repo.Write(c.RSAKey, c.KeyName+".rsa.pub"); err != nil { 72 return err 73 } 74 75 files := os.DirFS(repo.dir) 76 err = fs.WalkDir(files, ".", func(path string, d fs.DirEntry, err error) error { 77 if err != nil || d.IsDir() { 78 return err 79 } 80 b, err := fs.ReadFile(files, path) 81 if err != nil { 82 return err 83 } 84 w, err := c.Target.NewWriter(ctx, path) 85 if err != nil { 86 return err 87 } 88 if _, err = w.Write(b); err != nil { 89 return err 90 } 91 return w.Close() 92 }) 93 if err != nil { 94 return err 95 } 96 97 return nil 98 } 99 100 func getVersionConstraint(repo map[string]*repository.ApkIndex) string { 101 if len(repo) == 0 { 102 return "" 103 } 104 105 replace := strings.NewReplacer("_p", "+", "_", "-") 106 v := make([]byte, 0) 107 for _, r := range repo { 108 for _, p := range r.Packages { 109 v = append(v, '!', '=') 110 v = append(v, replace.Replace(p.Version)...) 111 v = append(v, ',') 112 } 113 } 114 115 return unsafe.String(unsafe.SliceData(v), len(v)-1) 116 }