|
2 | 2 | // Use of this source code is governed by a BSD-style
|
3 | 3 | // license that can be found in the LICENSE file.
|
4 | 4 |
|
5 |
| -// Command release builds a Go release. |
| 5 | +// Command release was used to build Go releases before relui fully replaced its functionality. |
| 6 | +// |
| 7 | +// Deprecated: Use relui instead. |
6 | 8 | package main
|
7 | 9 |
|
8 | 10 | import (
|
9 |
| - "bytes" |
10 |
| - "context" |
11 | 11 | "flag"
|
12 | 12 | "fmt"
|
13 |
| - "io" |
14 |
| - "io/ioutil" |
15 |
| - "log" |
16 |
| - "math" |
17 |
| - "math/rand" |
18 |
| - "net/http" |
19 | 13 | "os"
|
20 |
| - "path/filepath" |
21 |
| - "regexp" |
22 |
| - "runtime" |
23 |
| - "strings" |
24 |
| - "time" |
25 |
| - |
26 |
| - "golang.org/x/build/buildenv" |
27 |
| - "golang.org/x/build/buildlet" |
28 |
| - "golang.org/x/build/dashboard" |
29 |
| - "golang.org/x/build/internal/gomote/protos" |
30 |
| - "golang.org/x/build/internal/iapclient" |
31 |
| - "golang.org/x/build/internal/releasetargets" |
32 |
| - "golang.org/x/build/internal/task" |
33 |
| - "golang.org/x/build/internal/workflow" |
34 |
| - "golang.org/x/sync/errgroup" |
35 |
| -) |
36 |
| - |
37 |
| -var ( |
38 |
| - flagTarget = flag.String("target", "", "The specific target to build.") |
39 |
| - flagWatch = flag.Bool("watch", false, "Watch the build.") |
40 |
| - |
41 |
| - flagStagingDir = flag.String("staging_dir", "", "If specified, use this as the staging directory for untested release artifacts. Default is the system temporary directory.") |
42 |
| - |
43 |
| - flagRevision = flag.String("rev", "", "Go revision to build") |
44 |
| - flagVersion = flag.String("version", "", "Version string (go1.5.2)") |
45 |
| - user = flag.String("user", username(), "coordinator username, appended to 'user-'") |
46 |
| - flagSkipTests = flag.Bool("skip_tests", false, "skip all tests (only use if sufficient testing was done elsewhere)") |
47 |
| - flagSkipLongTests = flag.Bool("skip_long_tests", false, "skip long tests (only use if sufficient testing was done elsewhere)") |
48 |
| - |
49 |
| - uploadMode = flag.Bool("upload", false, "Upload files (exclusive to all other flags)") |
50 |
| -) |
51 |
| - |
52 |
| -var ( |
53 |
| - coordClient *buildlet.GRPCCoordinatorClient |
54 |
| - buildEnv *buildenv.Environment |
55 | 14 | )
|
56 | 15 |
|
57 | 16 | func main() {
|
58 |
| - flag.Parse() |
59 |
| - rand.Seed(time.Now().UnixNano()) |
60 |
| - |
61 |
| - if *uploadMode { |
62 |
| - buildenv.CheckUserCredentials() |
63 |
| - userToken() // Call userToken for the side-effect of exiting if a gomote token doesn't exist. |
64 |
| - if err := upload(flag.Args()); err != nil { |
65 |
| - log.Fatal(err) |
66 |
| - } |
67 |
| - return |
68 |
| - } |
69 |
| - |
70 |
| - ctx := &workflow.TaskContext{ |
71 |
| - Context: context.TODO(), |
72 |
| - Logger: &logger{*flagTarget}, |
73 |
| - } |
74 |
| - |
75 |
| - if *flagRevision == "" { |
76 |
| - log.Fatal("must specify -rev") |
77 |
| - } |
78 |
| - if *flagTarget == "" { |
79 |
| - log.Fatal("must specify -target") |
80 |
| - } |
81 |
| - if *flagVersion == "" { |
82 |
| - log.Fatal(`must specify -version flag (such as "go1.12" or "go1.13beta1")`) |
83 |
| - } |
84 |
| - stagingDir := *flagStagingDir |
85 |
| - if stagingDir == "" { |
86 |
| - var err error |
87 |
| - stagingDir, err = ioutil.TempDir("", "go-release-staging_") |
88 |
| - if err != nil { |
89 |
| - log.Fatal(err) |
90 |
| - } |
91 |
| - } |
92 |
| - if *flagTarget == "src" { |
93 |
| - if err := writeSourceFile(ctx, *flagRevision, *flagVersion, *flagVersion+".src.tar.gz"); err != nil { |
94 |
| - log.Fatalf("building source archive: %v", err) |
95 |
| - } |
96 |
| - return |
97 |
| - } |
98 |
| - |
99 |
| - cc, err := iapclient.GRPCClient(ctx, "build.golang.org:443") |
100 |
| - if err != nil { |
101 |
| - log.Fatalf("Could not connect to coordinator: %v", err) |
102 |
| - } |
103 |
| - coordClient = &buildlet.GRPCCoordinatorClient{ |
104 |
| - Client: protos.NewGomoteServiceClient(cc), |
105 |
| - } |
106 |
| - buildEnv = buildenv.Production |
107 |
| - |
108 |
| - targets, ok := releasetargets.TargetsForVersion(*flagVersion) |
109 |
| - if !ok { |
110 |
| - log.Fatalf("could not parse version %q", *flagVersion) |
111 |
| - } |
112 |
| - target, ok := targets[*flagTarget] |
113 |
| - if !ok { |
114 |
| - log.Fatalf("no such target %q in version %q", *flagTarget, *flagVersion) |
115 |
| - } |
116 |
| - if *flagSkipTests { |
117 |
| - target.BuildOnly = true |
118 |
| - } |
119 |
| - if *flagSkipLongTests { |
120 |
| - target.LongTestBuilder = "" |
121 |
| - } |
122 |
| - |
123 |
| - ctx.Printf("Start.") |
124 |
| - if err := doRelease(ctx, *flagRevision, *flagVersion, target, stagingDir, *flagWatch); err != nil { |
125 |
| - ctx.Printf("Error: %v", err) |
126 |
| - os.Exit(1) |
127 |
| - } else { |
128 |
| - ctx.Printf("Done.") |
129 |
| - } |
130 |
| -} |
131 |
| - |
132 |
| -const gerritURL = "https://go.googlesource.com/go" |
133 |
| - |
134 |
| -func doRelease(ctx *workflow.TaskContext, revision, version string, target *releasetargets.Target, stagingDir string, watch bool) error { |
135 |
| - srcBuf := &bytes.Buffer{} |
136 |
| - if err := task.WriteSourceArchive(ctx, http.DefaultClient, gerritURL, revision, version, srcBuf); err != nil { |
137 |
| - return fmt.Errorf("Building source archive: %v", err) |
138 |
| - } |
139 |
| - |
140 |
| - var stagingFiles []*os.File |
141 |
| - stagingFile := func(ext string) (*os.File, error) { |
142 |
| - f, err := ioutil.TempFile(stagingDir, fmt.Sprintf("%v.%v.%v.release-staging-*", version, target.Name, ext)) |
143 |
| - stagingFiles = append(stagingFiles, f) |
144 |
| - return f, err |
145 |
| - } |
146 |
| - // runWithBuildlet runs f with a newly-created builder. |
147 |
| - runWithBuildlet := func(builder string, f func(*task.BuildletStep) error) error { |
148 |
| - buildConfig, ok := dashboard.Builders[builder] |
149 |
| - if !ok { |
150 |
| - return fmt.Errorf("unknown builder: %v", buildConfig) |
151 |
| - } |
152 |
| - client, err := coordClient.CreateBuildlet(ctx, builder) |
153 |
| - if err != nil { |
154 |
| - return err |
155 |
| - } |
156 |
| - defer client.Close() |
157 |
| - buildletStep := &task.BuildletStep{ |
158 |
| - Target: target, |
159 |
| - Buildlet: client, |
160 |
| - BuildConfig: buildConfig, |
161 |
| - LogWriter: os.Stdout, |
162 |
| - } |
163 |
| - if err := f(buildletStep); err != nil { |
164 |
| - return err |
165 |
| - } |
166 |
| - return client.Close() |
| 17 | + flag.Usage = func() { |
| 18 | + fmt.Fprintln(os.Stderr, "Command golang.org/x/build/cmd/release is deprecated.") |
| 19 | + fmt.Fprintln(os.Stderr, "Use golang.org/x/build/cmd/relui instead.") |
| 20 | + flag.PrintDefaults() |
167 | 21 | }
|
168 |
| - defer func() { |
169 |
| - for _, f := range stagingFiles { |
170 |
| - f.Close() |
171 |
| - } |
172 |
| - }() |
173 |
| - |
174 |
| - // Build the binary distribution. |
175 |
| - binary, err := stagingFile("tar.gz") |
176 |
| - if err != nil { |
177 |
| - return err |
178 |
| - } |
179 |
| - if err := runWithBuildlet(target.Builder, func(step *task.BuildletStep) error { |
180 |
| - return step.BuildBinary(ctx, srcBuf, binary) |
181 |
| - }); err != nil { |
182 |
| - return fmt.Errorf("Building binary archive: %v", err) |
183 |
| - } |
184 |
| - // Multiple tasks need to read the binary archive concurrently. Use a |
185 |
| - // new SectionReader for each to keep them from conflicting. |
186 |
| - binaryReader := func() io.Reader { return io.NewSectionReader(binary, 0, math.MaxInt64) } |
187 |
| - |
188 |
| - // Do everything else in parallel. |
189 |
| - group, groupCtx := errgroup.WithContext(ctx) |
190 |
| - |
191 |
| - // If windows, produce the zip and MSI. |
192 |
| - if target.GOOS == "windows" { |
193 |
| - ctx := &workflow.TaskContext{Context: groupCtx, Logger: ctx.Logger} |
194 |
| - msi, err := stagingFile("msi") |
195 |
| - if err != nil { |
196 |
| - return err |
197 |
| - } |
198 |
| - zip, err := stagingFile("zip") |
199 |
| - if err != nil { |
200 |
| - return err |
201 |
| - } |
202 |
| - group.Go(func() error { |
203 |
| - if err := runWithBuildlet(target.Builder, func(step *task.BuildletStep) error { |
204 |
| - return step.BuildWindowsMSI(ctx, binaryReader(), msi) |
205 |
| - }); err != nil { |
206 |
| - return fmt.Errorf("Building Windows artifacts: %v", err) |
207 |
| - } |
208 |
| - return nil |
209 |
| - }) |
210 |
| - group.Go(func() error { |
211 |
| - return task.ConvertTGZToZIP(binaryReader(), zip) |
212 |
| - }) |
213 |
| - } |
214 |
| - |
215 |
| - // Run tests. |
216 |
| - if !target.BuildOnly { |
217 |
| - runTest := func(builder string) error { |
218 |
| - ctx := &workflow.TaskContext{ |
219 |
| - Context: groupCtx, |
220 |
| - Logger: &logger{fmt.Sprintf("%v (tests on %v)", target.Name, builder)}, |
221 |
| - } |
222 |
| - if err := runWithBuildlet(builder, func(step *task.BuildletStep) error { |
223 |
| - return step.TestTarget(ctx, binaryReader()) |
224 |
| - }); err != nil { |
225 |
| - return fmt.Errorf("Testing on %v: %v", builder, err) |
226 |
| - } |
227 |
| - return nil |
228 |
| - } |
229 |
| - group.Go(func() error { return runTest(target.Builder) }) |
230 |
| - if target.LongTestBuilder != "" { |
231 |
| - group.Go(func() error { return runTest(target.LongTestBuilder) }) |
232 |
| - } |
233 |
| - } |
234 |
| - if err := group.Wait(); err != nil { |
235 |
| - return err |
236 |
| - } |
237 |
| - |
238 |
| - // If we get this far, the all.bash tests have passed (or been skipped). |
239 |
| - // Move untested release files to their final locations. |
240 |
| - stagingRe := regexp.MustCompile(`([^/]*)\.release-staging-.*`) |
241 |
| - for _, f := range stagingFiles { |
242 |
| - if err := f.Close(); err != nil { |
243 |
| - return err |
244 |
| - } |
245 |
| - match := stagingRe.FindStringSubmatch(f.Name()) |
246 |
| - if len(match) != 2 { |
247 |
| - return fmt.Errorf("unexpected file name %q didn't match %v", f.Name(), stagingRe) |
248 |
| - } |
249 |
| - finalName := match[1] |
250 |
| - ctx.Printf("Moving %q to %q.", f.Name(), finalName) |
251 |
| - if err := os.Rename(f.Name(), finalName); err != nil { |
252 |
| - return err |
253 |
| - } |
254 |
| - } |
255 |
| - return nil |
256 |
| -} |
257 |
| - |
258 |
| -type logger struct { |
259 |
| - Name string |
260 |
| -} |
261 |
| - |
262 |
| -func (l *logger) Printf(format string, args ...interface{}) { |
263 |
| - format = fmt.Sprintf("%v: %s", l.Name, format) |
264 |
| - log.Printf(format, args...) |
265 |
| -} |
266 |
| - |
267 |
| -func writeSourceFile(ctx *workflow.TaskContext, revision, version, outPath string) error { |
268 |
| - w, err := os.Create(outPath) |
269 |
| - if err != nil { |
270 |
| - return err |
271 |
| - } |
272 |
| - if err := task.WriteSourceArchive(ctx, http.DefaultClient, gerritURL, revision, version, w); err != nil { |
273 |
| - return err |
274 |
| - } |
275 |
| - return w.Close() |
276 |
| -} |
277 |
| - |
278 |
| -func homeDir() string { |
279 |
| - if runtime.GOOS == "windows" { |
280 |
| - return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") |
281 |
| - } |
282 |
| - return os.Getenv("HOME") |
283 |
| -} |
284 |
| - |
285 |
| -func configDir() string { |
286 |
| - if runtime.GOOS == "windows" { |
287 |
| - return filepath.Join(os.Getenv("APPDATA"), "Gomote") |
288 |
| - } |
289 |
| - if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" { |
290 |
| - return filepath.Join(xdg, "gomote") |
291 |
| - } |
292 |
| - return filepath.Join(homeDir(), ".config", "gomote") |
293 |
| -} |
294 |
| - |
295 |
| -func username() string { |
296 |
| - if runtime.GOOS == "windows" { |
297 |
| - return os.Getenv("USERNAME") |
298 |
| - } |
299 |
| - return os.Getenv("USER") |
300 |
| -} |
| 22 | + flag.Parse() |
301 | 23 |
|
302 |
| -func userToken() string { |
303 |
| - if *user == "" { |
304 |
| - panic("userToken called with user flag empty") |
305 |
| - } |
306 |
| - keyDir := configDir() |
307 |
| - baseFile := "user-" + *user + ".token" |
308 |
| - tokenFile := filepath.Join(keyDir, baseFile) |
309 |
| - slurp, err := ioutil.ReadFile(tokenFile) |
310 |
| - if os.IsNotExist(err) { |
311 |
| - log.Printf("Missing file %s for user %q. Change --user or obtain a token and place it there.", |
312 |
| - tokenFile, *user) |
313 |
| - } |
314 |
| - if err != nil { |
315 |
| - log.Fatal(err) |
316 |
| - } |
317 |
| - return strings.TrimSpace(string(slurp)) |
| 24 | + flag.Usage() |
| 25 | + os.Exit(1) |
318 | 26 | }
|
0 commit comments