Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/dev/gpctl/cmd/imagebuilds-build.go
2496 views
1
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package cmd
6
7
import (
8
"context"
9
"fmt"
10
"io"
11
"os"
12
13
"github.com/spf13/cobra"
14
"google.golang.org/protobuf/encoding/protojson"
15
16
"github.com/gitpod-io/gitpod/common-go/log"
17
csapi "github.com/gitpod-io/gitpod/content-service/api"
18
builder "github.com/gitpod-io/gitpod/image-builder/api"
19
)
20
21
// imagebuildsBuildCmd represents the build command
22
var imagebuildsBuildCmd = &cobra.Command{
23
Use: "build <source.json>",
24
Short: "Runs a full workspace image build",
25
Args: cobra.ExactArgs(1),
26
Run: func(cmd *cobra.Command, args []string) {
27
fc, err := os.ReadFile(args[0])
28
if err != nil {
29
log.Fatal(err)
30
}
31
32
var example builder.BuildSource
33
example.From = &builder.BuildSource_File{
34
File: &builder.BuildSourceDockerfile{
35
DockerfilePath: "Dockerfile",
36
ContextPath: ".",
37
Source: &csapi.WorkspaceInitializer{
38
Spec: &csapi.WorkspaceInitializer_Git{
39
Git: &csapi.GitInitializer{
40
RemoteUri: "https://github.com/32leaves/test-repo",
41
TargetMode: csapi.CloneTargetMode_REMOTE_BRANCH,
42
CloneTaget: "test-baseimg",
43
CheckoutLocation: ".",
44
Config: &csapi.GitConfig{
45
Authentication: csapi.GitAuthMethod_NO_AUTH,
46
},
47
},
48
},
49
},
50
},
51
}
52
53
marshaler := protojson.MarshalOptions{
54
Indent: " ",
55
}
56
57
b, _ := marshaler.Marshal(&example)
58
fmt.Println("example config:")
59
fmt.Fprint(os.Stdout, string(b))
60
fmt.Println()
61
62
var source builder.BuildSource
63
err = protojson.Unmarshal(fc, &source)
64
if err != nil {
65
log.Fatal(err)
66
}
67
b, _ = marshaler.Marshal(&source)
68
fmt.Println("actual config:")
69
fmt.Fprint(os.Stdout, string(b))
70
fmt.Println()
71
72
forceRebuild, _ := cmd.Flags().GetBool("force-rebuild")
73
74
ctx, cancel := context.WithCancel(context.Background())
75
defer cancel()
76
77
conn, client, err := getImagebuildsClient(ctx)
78
if err != nil {
79
log.WithError(err).Fatal("cannot connect")
80
}
81
defer conn.Close()
82
83
br, err := client.Build(ctx, &builder.BuildRequest{
84
Source: &source,
85
ForceRebuild: forceRebuild,
86
Auth: &builder.BuildRegistryAuth{Mode: &builder.BuildRegistryAuth_Total{Total: &builder.BuildRegistryAuthTotal{AllowAll: true}}},
87
})
88
if err != nil {
89
log.Fatal(err)
90
}
91
r, err := br.Recv()
92
if err != nil {
93
log.Fatal(err)
94
}
95
log.WithField("r", r).Info("received build response")
96
97
switch r.Status {
98
case builder.BuildStatus_done_failure, builder.BuildStatus_done_success:
99
log.Infof("build done: %s", builder.BuildStatus_name[int32(r.Status)])
100
return
101
case builder.BuildStatus_unknown:
102
log.Fatal("build status unknown")
103
return
104
}
105
106
// build did start, print log until done
107
censor, _ := cmd.Flags().GetBool("censor")
108
lc, err := client.Logs(ctx, &builder.LogsRequest{
109
BuildId: r.Info.BuildId,
110
BuildRef: r.Ref,
111
Censored: censor,
112
})
113
if err != nil && err != io.EOF {
114
log.Fatal(err)
115
}
116
log.Info("listening for build logs")
117
buildMessage, logs := make(chan *builder.BuildResponse), make(chan []byte)
118
go func() {
119
r, err := br.Recv()
120
if err != nil {
121
if err != io.EOF {
122
log.Fatal(err)
123
} else {
124
log.Info("logs ended")
125
}
126
127
return
128
}
129
buildMessage <- r
130
}()
131
go func() {
132
for {
133
l, err := lc.Recv()
134
if err == io.EOF {
135
break
136
}
137
if err != nil {
138
log.WithError(err).Fatal("recv err")
139
}
140
logs <- l.Content
141
}
142
}()
143
144
for {
145
select {
146
case bm := <-buildMessage:
147
log.Print(bm)
148
switch bm.Status {
149
case builder.BuildStatus_done_failure, builder.BuildStatus_done_success:
150
log.Infof("build done: %s", builder.BuildStatus_name[int32(bm.Status)])
151
return
152
case builder.BuildStatus_unknown:
153
log.Fatal("build status unknown")
154
return
155
}
156
case logdata := <-logs:
157
// fmt.Fprint(log.Log.Writer(), string(logdata))
158
fmt.Print(string(logdata))
159
}
160
}
161
},
162
}
163
164
func init() {
165
imagebuildsCmd.AddCommand(imagebuildsBuildCmd)
166
167
imagebuildsBuildCmd.Flags().Bool("censor", false, "censor the log output")
168
imagebuildsBuildCmd.Flags().Bool("force-rebuild", false, "force an image build even if the image exists already")
169
}
170
171