1 package push
2
3 import (
4 "context"
5 "fmt"
6
7 "github.com/google/go-containerregistry/pkg/crane"
8
9 "edge-infra.dev/hack/build/ci"
10 "edge-infra.dev/pkg/lib/cli/rags"
11 "edge-infra.dev/pkg/lib/cli/sink"
12 "edge-infra.dev/pkg/tools/hack/bazelx"
13 "edge-infra.dev/pkg/tools/hack/containers"
14 )
15
16 func New(name string) *sink.Command {
17 var (
18 repo string
19 tags []string
20 insecure, relTags, rc bool
21 bzlx = &bazelx.Bazelx{}
22 )
23
24 return &sink.Command{
25 Use: fmt.Sprintf("%s [flags] <bazel expressions ...> [-- bazel flags]", name),
26 Short: "Push OCI build artifacts to registries using Bazel",
27 Extensions: []sink.Extension{bzlx},
28 Flags: []*rags.Rag{
29 {
30 Name: "repo",
31 Short: "r",
32 Usage: "Override the default destination repository",
33 Value: &rags.String{Var: &repo},
34 },
35 {
36 Name: "tag",
37 Short: "t",
38 Usage: "One or more tags to apply to pushed containers. Multiple flags can be provided as comma separated strings or multiple instances of the flag.",
39 Value: &rags.StringSet{Var: &tags},
40 },
41
42
43
44
45 {
46 Name: "release-tags",
47 Usage: "Tag pushed containers with build information",
48 Value: &rags.Bool{Var: &relTags},
49 },
50 {
51 Name: "rc",
52 Usage: "Whether or not this build is a release candidate",
53 Value: &rags.Bool{Var: &rc, Default: true},
54 },
55
56
57
58 {
59 Name: "insecure-repository",
60 Usage: "Allow HTTP repositories. Only valid for rules_docker push rules",
61 Value: &rags.Bool{Var: &insecure},
62 },
63 },
64 Exec: func(_ context.Context, r sink.Run) error {
65 if len(r.Args()) == 0 {
66 return fmt.Errorf("one or more Bazel expressions required")
67 }
68
69 log := r.Log
70
71 pushes, err := containers.QueryPushes(r.Args()...)
72 if err != nil {
73 return err
74 }
75 if len(pushes) == 0 {
76 return fmt.Errorf("no container_push targets found")
77 }
78 log.Info("container_push targets to execute", "targets", pushes)
79
80 opts := []containers.Option{}
81 if repo != "" {
82 opts = append(opts, containers.ToRepository(repo))
83 }
84 if insecure {
85 opts = append(opts, containers.Insecure)
86 }
87
88 refs, err := containers.Push(bzlx.Bazel, pushes, opts...)
89 if err != nil {
90 return err
91 }
92 log.Info("successfully pushed", "refs", refs)
93
94 if relTags {
95 rt, err := containerTags(rc)
96 if err != nil {
97 return err
98 }
99 tags = append(tags, rt...)
100 }
101
102
103 if len(tags) == 0 {
104 return nil
105 }
106
107
108
109 for _, r := range refs {
110 for _, t := range tags {
111 if err := crane.Tag(r.String(), t); err != nil {
112 return fmt.Errorf("failed to tag %s with %s: %w", r, t, err)
113 }
114 }
115 log.Info("tagged", "ref", r, "tags", tags)
116 }
117
118 return nil
119 },
120 }
121 }
122
123 func containerTags(rc bool) ([]string, error) {
124 version, branch, err := ci.BuildInfo(rc, ci.RepoRoot)
125 if err != nil {
126 return nil, err
127 }
128
129
130 return version.ContainerTags(branch)
131 }
132
View as plain text