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