1 package promote
2
3 import (
4 "context"
5 "errors"
6 "flag"
7 "fmt"
8
9 "github.com/go-logr/logr"
10
11 "edge-infra.dev/pkg/edge/api/types"
12 "edge-infra.dev/pkg/f8n/warehouse/packagelock"
13 "edge-infra.dev/pkg/lib/gcp/pubsub"
14 )
15
16 const (
17 PromoteTag = "promote"
18 Latest = "latest"
19 )
20
21 func Run(ctx context.Context, log logr.Logger) error {
22 cfg, err := newConfig()
23 if err != nil {
24 if errors.Is(err, flag.ErrHelp) {
25 return nil
26 }
27 log.Error(err, "failed to load config")
28 return err
29 }
30
31 log.Info("loaded config", "config", cfg)
32 log.Info("promotion started", "description", cfg.Description())
33
34 ps, err := pubsub.New(ctx, cfg.ForwarderProjectID)
35 if err != nil {
36 log.Error(err, "failed to create Pub/Sub connection to project", "project-id", cfg.ForwarderProjectID)
37 return err
38 }
39
40 plr, err := packagelock.NewRules()
41 if err != nil {
42 log.Error(err, "failed to create package lock rules")
43 return err
44 }
45
46 pl, err := plr.ParsePackageLock(cfg.LockFile)
47 if err != nil {
48 log.Error(err, "failed to parse package lock")
49 return err
50 }
51
52 digests, err := Promote(ctx, cfg, pl, ps)
53 if err != nil {
54 log.Error(err, "promotion failed")
55 return err
56 }
57
58
59
60 log.Info("promotion complete", "digests", digests)
61 return nil
62 }
63
64 func Promote(ctx context.Context, cfg *Config, pl packagelock.PackageLock, ps types.PubSubService) ([]string, error) {
65 sourceRepo := cfg.SourceRepo
66 destinationRepo := cfg.DestinationRepo
67 digests := []string{}
68
69 for _, lockPkg := range pl.Packages {
70 for _, version := range lockPkg.Versions {
71 if err := sourceRepo.EnsurePackageDigestExists(lockPkg.Name, version.Digest); err != nil {
72 return nil, fmt.Errorf("failed to get hash for package: %s, reason: %v", lockPkg.Name, err)
73 }
74 }
75 }
76
77 for _, lockPkg := range pl.Packages {
78 pkgDigests, err := promotePackage(ctx, lockPkg, sourceRepo, destinationRepo, ps)
79 if err != nil {
80 return nil, err
81 }
82 digests = append(digests, pkgDigests...)
83 }
84
85 return digests, nil
86 }
87
88 func promotePackage(ctx context.Context, lockPkg packagelock.LockPackage, sourceRepo, destinationRepo Repository, ps types.PubSubService) ([]string, error) {
89 tagsSent := []string{}
90 for _, version := range lockPkg.Versions {
91
92 for _, tag := range version.Tags {
93
94 sourceDigest, err := sourceRepo.NewPackageDigest(lockPkg.Name, version.Digest)
95 if err != nil {
96 return nil, err
97 }
98
99
100 destinationTag, err := destinationRepo.NewPackageTag(lockPkg.Name, tag)
101 if err != nil {
102 return nil, err
103 }
104 msg := newPromotionMessage(sourceDigest, destinationTag, destinationRepo)
105 if err := msg.Send(ctx, ps); err != nil {
106 return nil, fmt.Errorf("failed to publish promotion message to topic: %s, reason: %v", PromotionsTopic, err)
107 }
108 tagsSent = append(tagsSent, tag)
109 }
110 }
111 return destinationRepo.PackageTagRefs(lockPkg.Name, tagsSent), nil
112 }
113
View as plain text