golang.org/x/build@v0.0.0-20240506185731-218518f32b70/internal/task/scratchfs.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package task 6 7 import ( 8 "fmt" 9 "io/fs" 10 "math/rand" 11 12 "cloud.google.com/go/storage" 13 "golang.org/x/build/internal/gcsfs" 14 wf "golang.org/x/build/internal/workflow" 15 ) 16 17 // ScratchFS manages scratch storage for workflows. 18 type ScratchFS struct { 19 BaseURL string // BaseURL is a gs:// or file:// URL, no trailing slash. E.g., "gs://golang-release-staging/relui-scratch". 20 GCS *storage.Client 21 } 22 23 // OpenRead opens a file in the workflow's scratch storage. 24 func (s *ScratchFS) OpenRead(ctx *wf.TaskContext, name string) (fs.File, error) { 25 sfs, err := s.fs(ctx) 26 if err != nil { 27 return nil, err 28 } 29 return sfs.Open(name) 30 } 31 32 // ReadFile fully reads a file in the workflow's scratch storage. 33 func (s *ScratchFS) ReadFile(ctx *wf.TaskContext, name string) ([]byte, error) { 34 sfs, err := s.fs(ctx) 35 if err != nil { 36 return nil, err 37 } 38 return fs.ReadFile(sfs, name) 39 } 40 41 // OpenWrite creates a new file in the workflow's scratch storage, with a name 42 // based on baseName. It returns that name, as well as the open file. 43 func (s *ScratchFS) OpenWrite(ctx *wf.TaskContext, baseName string) (name string, _ gcsfs.WriterFile, _ error) { 44 sfs, err := s.fs(ctx) 45 if err != nil { 46 return "", nil, err 47 } 48 name = fmt.Sprintf("%v-%v", rand.Int63(), baseName) 49 f, err := gcsfs.Create(sfs, name) 50 return name, f, err 51 } 52 53 // WriteFilename returns a filename that can be used to write a new scratch file 54 // suitable for writing from an external systems. 55 func (s *ScratchFS) WriteFilename(ctx *wf.TaskContext, baseName string) string { 56 return fmt.Sprintf("%v-%v", rand.Int63(), baseName) 57 } 58 59 // URL returns the URL of a file in the workflow's scratch storage, suitable 60 // for passing to external systems. 61 func (s *ScratchFS) URL(ctx *wf.TaskContext, name string) string { 62 return fmt.Sprintf("%v/%v/%v", s.BaseURL, ctx.WorkflowID.String(), name) 63 } 64 65 func (s *ScratchFS) fs(ctx *wf.TaskContext) (fs.FS, error) { 66 sfs, err := gcsfs.FromURL(ctx, s.GCS, s.BaseURL) 67 if err != nil { 68 return nil, err 69 } 70 return fs.Sub(sfs, ctx.WorkflowID.String()) 71 }