1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16package gitee_common 17 18import ( 19 "context" 20 "fmt" 21 "fotff/res" 22 "fotff/utils" 23 "github.com/sirupsen/logrus" 24 "os" 25 "path/filepath" 26) 27 28type BuildConfig struct { 29 Pkg string 30 PreCompileCMD string 31 CompileCMD string 32 ImgList []string 33} 34 35func (m *Manager) Build(config BuildConfig, ctx context.Context) error { 36 if m.PkgAvailable(config) { 37 return nil 38 } 39 logrus.Infof("%s is not available", config.Pkg) 40 err := m.BuildNoRetry(config, false, ctx) 41 if err == nil { 42 return nil 43 } 44 logrus.Errorf("build pkg %s err: %v", config.Pkg, err) 45 logrus.Infof("rm out and build pkg %s again...", config.Pkg) 46 err = m.BuildNoRetry(config, true, ctx) 47 if err == nil { 48 return nil 49 } 50 logrus.Errorf("build pkg %s err: %v", config.Pkg, err) 51 return err 52} 53 54// PkgAvailable returns true if all necessary images are all available to flash. 55func (m *Manager) PkgAvailable(config BuildConfig) bool { 56 for _, img := range config.ImgList { 57 imgName := filepath.Base(img) 58 if _, err := os.Stat(filepath.Join(m.Workspace, config.Pkg, imgName)); err != nil { 59 return false 60 } 61 } 62 return true 63} 64 65// BuildNoRetry obtain an available server, download corresponding codes, and run compile commands 66// to build the corresponding package images, then transfer these images to the 'pkg' directory. 67func (m *Manager) BuildNoRetry(config BuildConfig, rm bool, ctx context.Context) error { 68 logrus.Infof("now Build %s", config.Pkg) 69 server := res.GetBuildServer() 70 defer res.ReleaseBuildServer(server) 71 cmd := fmt.Sprintf("mkdir -p %s && cd %s && repo init -u https://gitee.com/openharmony/manifest.git", server.WorkSpace, server.WorkSpace) 72 if err := utils.RunCmdViaSSHContext(ctx, server.Addr, server.User, server.Passwd, cmd); err != nil { 73 return fmt.Errorf("remote: mkdir error: %w", err) 74 } 75 if err := utils.TransFileViaSSH(utils.Upload, server.Addr, server.User, server.Passwd, 76 fmt.Sprintf("%s/.repo/manifest.xml", server.WorkSpace), filepath.Join(m.Workspace, config.Pkg, "manifest_tag.xml")); err != nil { 77 return fmt.Errorf("upload and replace manifest error: %w", err) 78 } 79 // 'git lfs install' may fail due to some git hooks. Call 'git lfs update --force' before install to avoid this situation. 80 cmd = fmt.Sprintf("cd %s && repo sync -c --no-tags --force-remove-dirty && repo forall -c 'git reset --hard && git clean -dfx && git lfs update --force && git lfs install && git lfs pull'", server.WorkSpace) 81 if err := utils.RunCmdViaSSHContext(ctx, server.Addr, server.User, server.Passwd, cmd); err != nil { 82 return fmt.Errorf("remote: repo sync error: %w", err) 83 } 84 cmd = fmt.Sprintf("cd %s && %s", server.WorkSpace, config.PreCompileCMD) 85 if err := utils.RunCmdViaSSHContextNoRetry(ctx, server.Addr, server.User, server.Passwd, cmd); err != nil { 86 return fmt.Errorf("remote: pre-compile command error: %w", err) 87 } 88 if rm { 89 cmd = fmt.Sprintf("cd %s && rm -rf out", server.WorkSpace) 90 if err := utils.RunCmdViaSSHContext(ctx, server.Addr, server.User, server.Passwd, cmd); err != nil { 91 return fmt.Errorf("remote: rm ./out command error: %w", err) 92 } 93 } 94 cmd = fmt.Sprintf("cd %s && %s", server.WorkSpace, config.CompileCMD) 95 if err := utils.RunCmdViaSSHContextNoRetry(ctx, server.Addr, server.User, server.Passwd, cmd); err != nil { 96 return fmt.Errorf("remote: compile command error: %w", err) 97 } 98 // has been built already, pitiful if canceled, so continue copying 99 for _, f := range config.ImgList { 100 imgName := filepath.Base(f) 101 if err := utils.TransFileViaSSH(utils.Download, server.Addr, server.User, server.Passwd, 102 fmt.Sprintf("%s/%s", server.WorkSpace, f), filepath.Join(m.Workspace, config.Pkg, imgName)); err != nil { 103 return fmt.Errorf("download file %s error: %w", f, err) 104 } 105 } 106 return nil 107} 108