| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package version |
| |
| import ( |
| "context" |
| "encoding/json" |
| "fmt" |
| "os" |
| |
| lab_platform "go.chromium.org/chromiumos/infra/proto/go/lab_platform" |
| "go.chromium.org/luci/common/errors" |
| |
| "go.chromium.org/infra/cros/recovery/models" |
| ) |
| |
| func readLocalVersion(ctx context.Context, board, model, deviceType string) (Data, error) { |
| localDir := os.Getenv("DRONE_RECOVERY_VERSIONS_DIR") |
| if localDir == "" { |
| return nil, errors.New("read local version: target directory is not defined") |
| } |
| return readLocalVersionFile(ctx, localDir, board, model, deviceType) |
| } |
| |
| func readLocalVersionFile(ctx context.Context, localDir, board, model, deviceType string) (Data, error) { |
| if localDir == "" { |
| return nil, errors.New("read local version file: directory is not provider") |
| } |
| if board == "" || model == "" { |
| return nil, errors.New("read local version file: board or model is empty") |
| } |
| svFilePath := fmt.Sprintf("%s/%s-%s.json", localDir, board, model) |
| svByteArr, err := os.ReadFile(svFilePath) |
| if err != nil { |
| return nil, errors.Fmt("read local version file %q: failed to read file: %w", svFilePath, err) |
| } |
| |
| rvs := &models.RecoveryVersionList{} |
| if err := json.Unmarshal(svByteArr, rvs); err != nil { |
| return nil, errors.Fmt("read local version file %q: failed to unmarshal: %w", svFilePath, err) |
| } |
| if len(rvs.Versions) > 0 { |
| for _, rv := range rvs.Versions { |
| if rv.GetDeviceType() == deviceType { |
| return &lab_platform.StableVersion{ |
| Target: &lab_platform.StableVersionTarget{ |
| Board: rv.GetBoard(), |
| Model: rv.GetModel(), |
| DeviceType: deviceType, |
| }, |
| OsVersion: rv.GetOsImage(), |
| OsImagePath: rv.GetOsImagePath(), |
| FirmwareRoVersion: rv.GetFwVersion(), |
| FirmwareRoImagePath: rv.GetFwImage(), |
| }, nil |
| } |
| } |
| return nil, errors.Fmt("read local version file %q: failed to find version for requested type (%s)", svFilePath, deviceType) |
| } |
| // TODO(filipek): remove when old format will be fully deprecated. |
| // Fall back to the old format, but only for classic. |
| if deviceType != toDeviceType(CrOSType) { |
| return nil, errors.Fmt("read local version file %q: failed to find version for requested type", svFilePath) |
| } |
| rv := &models.RecoveryVersion{} |
| if err := json.Unmarshal(svByteArr, rv); err != nil { |
| return nil, errors.Fmt("read local version file %q: failed to parse: %w", svFilePath, err) |
| } |
| return &lab_platform.StableVersion{ |
| Target: &lab_platform.StableVersionTarget{ |
| Board: rv.GetBoard(), |
| Model: rv.GetModel(), |
| DeviceType: deviceType, |
| }, |
| OsVersion: rv.GetOsImage(), |
| OsImagePath: toOSImagePath(ctx, rv, deviceType), |
| FirmwareRoVersion: rv.GetFwVersion(), |
| FirmwareRoImagePath: rv.GetFwImage(), |
| }, nil |
| } |
| |
| func toOSImagePath(ctx context.Context, rv *models.RecoveryVersion, deviceType string) string { |
| switch ToType(deviceType) { |
| case CrOSType: |
| return fmt.Sprintf("%s-release/%s", rv.GetBoard(), rv.GetOsImage()) |
| case AndroidOSType: |
| return fmt.Sprintf("android-build/build_explorer/artifacts_list/%s/%s-trunk_staging-userdebug/%s-ota-%s.zip", rv.GetOsImage(), rv.GetBoard(), rv.GetBoard(), rv.GetOsImage()) |
| } |
| |
| return "" |
| } |