github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/syz-cluster/pkg/service/build.go (about) 1 // Copyright 2025 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package service 5 6 import ( 7 "bytes" 8 "context" 9 "fmt" 10 "github.com/google/syzkaller/syz-cluster/pkg/api" 11 "github.com/google/syzkaller/syz-cluster/pkg/app" 12 "github.com/google/syzkaller/syz-cluster/pkg/blob" 13 "github.com/google/syzkaller/syz-cluster/pkg/db" 14 "github.com/google/uuid" 15 ) 16 17 type BuildService struct { 18 buildRepo *db.BuildRepository 19 blobStorage blob.Storage 20 } 21 22 func NewBuildService(env *app.AppEnvironment) *BuildService { 23 return &BuildService{ 24 buildRepo: db.NewBuildRepository(env.Spanner), 25 blobStorage: env.BlobStorage, 26 } 27 } 28 29 func (s *BuildService) Upload(ctx context.Context, req *api.UploadBuildReq) (*api.UploadBuildResp, error) { 30 build := &db.Build{ 31 ID: uuid.NewString(), 32 Arch: req.Arch, 33 ConfigName: req.ConfigName, 34 TreeName: req.TreeName, 35 TreeURL: req.TreeURL, 36 CommitHash: req.CommitHash, 37 CommitDate: req.CommitDate, 38 Compiler: req.Compiler, 39 } 40 if req.SeriesID != "" { 41 build.SetSeriesID(req.SeriesID) 42 } 43 if req.BuildSuccess { 44 build.Status = db.BuildSuccess 45 } else { 46 build.Status = db.BuildFailed 47 } 48 if len(req.Log) > 0 { 49 var err error 50 build.LogURI, err = s.blobStorage.Write(bytes.NewReader(req.Log), "Build", build.ID, "log") 51 if err != nil { 52 return nil, fmt.Errorf("failed to write log: %w", err) 53 } 54 } 55 if len(req.Config) > 0 { 56 var err error 57 build.ConfigURI, err = s.blobStorage.Write(bytes.NewReader(req.Config), "Build", build.ID, "config") 58 if err != nil { 59 return nil, fmt.Errorf("failed to write kernel config: %w", err) 60 } 61 } 62 err := s.buildRepo.Insert(ctx, build) 63 if err != nil { 64 return nil, err 65 } 66 return &api.UploadBuildResp{ 67 ID: build.ID, 68 }, nil 69 } 70 71 func (s *BuildService) LastBuild(ctx context.Context, req *api.LastBuildReq) (*api.Build, error) { 72 build, err := s.buildRepo.LastBuiltTree(ctx, &db.LastBuildParams{ 73 Arch: req.Arch, 74 TreeName: req.TreeName, 75 ConfigName: req.ConfigName, 76 Commit: req.Commit, 77 Status: req.Status, 78 }) 79 if build == nil || err != nil { 80 return nil, err 81 } 82 resp := &api.Build{ 83 Arch: build.Arch, 84 TreeName: build.TreeName, 85 TreeURL: build.TreeURL, 86 ConfigName: build.ConfigName, 87 CommitHash: build.CommitHash, 88 CommitDate: build.CommitDate, 89 BuildSuccess: build.Status == db.BuildSuccess, 90 } 91 if !build.SeriesID.IsNull() { 92 resp.SeriesID = build.SeriesID.String() 93 } 94 return resp, nil 95 } 96 97 func makeBuildInfo(url *api.URLGenerator, build *db.Build) api.BuildInfo { 98 return api.BuildInfo{ 99 TreeName: build.TreeName, 100 TreeURL: build.TreeURL, 101 BaseCommit: build.CommitHash, 102 Arch: build.Arch, 103 Compiler: build.Compiler, 104 ConfigLink: url.BuildConfig(build.ID), 105 } 106 }