Skip to content

Commit 2f25515

Browse files
Merge pull request #49 from T0MASD/boilerplate
common boilerplate for go tools using github source
2 parents 221fb20 + d227d93 commit 2f25515

File tree

7 files changed

+135
-107
lines changed

7 files changed

+135
-107
lines changed

pkg/tools/backplanecli/backplanecli.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (t *Tool) Install() error {
3838
if len(matches) != 1 {
3939
return fmt.Errorf("unexpected number of assets found matching system spec: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4040
}
41-
backplaneArchiveAsset := matches[0]
41+
toolArchiveAsset := matches[0]
4242

4343
matches = github.FindAssetsContaining([]string{"checksums.txt"}, release.Assets)
4444
if len(matches) != 1 {
@@ -54,20 +54,20 @@ func (t *Tool) Install() error {
5454
return fmt.Errorf("failed to create version-specific directory '%s': %w", versionedDir, err)
5555
}
5656

57-
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, backplaneArchiveAsset}, versionedDir)
57+
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, toolArchiveAsset}, versionedDir)
5858
if err != nil {
5959
return fmt.Errorf("failed to download one or more assets: %w", err)
6060
}
6161

6262
// Verify checksum of downloaded assets
63-
backplaneArchiveFilepath := filepath.Join(versionedDir, backplaneArchiveAsset.GetName())
64-
binarySum, err := utils.Sha256sum(backplaneArchiveFilepath)
63+
toolArchiveFilepath := filepath.Join(versionedDir, toolArchiveAsset.GetName())
64+
binarySum, err := utils.Sha256sum(toolArchiveFilepath)
6565
if err != nil {
66-
return fmt.Errorf("failed to calculate checksum for '%s': %w", backplaneArchiveFilepath, err)
66+
return fmt.Errorf("failed to calculate checksum for '%s': %w", toolArchiveFilepath, err)
6767
}
6868

6969
checksumFilePath := filepath.Join(versionedDir, checksumAsset.GetName())
70-
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, backplaneArchiveAsset.GetName())
70+
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, toolArchiveAsset.GetName())
7171
if err != nil {
7272
return fmt.Errorf("failed to retrieve checksum from file '%s': %w", checksumFilePath, err)
7373
}
@@ -77,27 +77,28 @@ func (t *Tool) Install() error {
7777
}
7878
actual := checksumTokens[0]
7979

80+
toolExecutable := t.ExecutableName()
8081
if strings.TrimSpace(binarySum) != strings.TrimSpace(actual) {
81-
return fmt.Errorf("warning: Checksum for backplane-cli does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", backplaneArchiveAsset.GetBrowserDownloadURL())
82+
return fmt.Errorf("warning: Checksum for '%s' does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", toolExecutable, toolArchiveAsset.GetBrowserDownloadURL())
8283
}
8384

8485
// Untar binary bundle
85-
err = utils.Unarchive(backplaneArchiveFilepath, versionedDir)
86+
err = utils.Unarchive(toolArchiveFilepath, versionedDir)
8687
if err != nil {
87-
return fmt.Errorf("failed to unarchive the osdctl asset file '%s': %w", backplaneArchiveFilepath, err)
88+
return fmt.Errorf("failed to unarchive the '%s' asset file '%s': %w", toolExecutable, toolArchiveFilepath, err)
8889
}
8990

9091
// Link as latest
9192
latestFilePath := t.SymlinkPath()
9293
err = os.Remove(latestFilePath)
9394
if err != nil && !os.IsNotExist(err) {
94-
return fmt.Errorf("failed to remove existing 'ocm-backplane' binary at '%s': %w", base.LatestDir, err)
95+
return fmt.Errorf("failed to remove existing '%s' binary at '%s': %w", toolExecutable, base.LatestDir, err)
9596
}
9697

97-
backplaneBinaryFilepath := filepath.Join(versionedDir, "ocm-backplane")
98-
err = os.Symlink(backplaneBinaryFilepath, latestFilePath)
98+
toolBinaryFilepath := filepath.Join(versionedDir, toolExecutable)
99+
err = os.Symlink(toolBinaryFilepath, latestFilePath)
99100
if err != nil {
100-
return fmt.Errorf("failed to link new 'ocm-backplane' binary to '%s': %w", base.LatestDir, err)
101+
return fmt.Errorf("failed to link new '%s' binary to '%s': %w", toolExecutable, base.LatestDir, err)
101102
}
102103
return nil
103104
}

pkg/tools/ocm/ocm.go

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package ocm
22

33
import (
4-
"crypto/sha256"
5-
"encoding/hex"
64
"fmt"
75
"os"
86
"path/filepath"
@@ -11,6 +9,7 @@ import (
119
gogithub "github.com/google/go-github/v51/github"
1210
"github.com/openshift/backplane-tools/pkg/sources/github"
1311
"github.com/openshift/backplane-tools/pkg/tools/base"
12+
"github.com/openshift/backplane-tools/pkg/utils"
1413
)
1514

1615
// Tool implements the interface to manage the 'ocm-cli' binary
@@ -36,17 +35,16 @@ func (t *Tool) Install() error {
3635
}
3736

3837
matches := github.FindAssetsForArchAndOS(release.Assets)
39-
binaryMatches := github.FindAssetsExcluding([]string{"sha256"}, matches)
40-
if len(binaryMatches) != 1 {
38+
if len(matches) != 1 {
4139
return fmt.Errorf("unexpected number of assets found matching system spec: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4240
}
43-
ocmBinaryAsset := binaryMatches[0]
41+
toolArchiveAsset := matches[0]
4442

45-
checksumMatches := github.FindAssetsContaining([]string{"sha256"}, matches)
46-
if len(checksumMatches) != 1 {
43+
matches = github.FindAssetsContaining([]string{"checksums.txt"}, release.Assets)
44+
if len(matches) != 1 {
4745
return fmt.Errorf("unexpected number of checksum assets found: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4846
}
49-
checksumAsset := checksumMatches[0]
47+
checksumAsset := matches[0]
5048

5149
// Download the arch- & os-specific assets
5250
toolDir := t.ToolDir()
@@ -56,42 +54,51 @@ func (t *Tool) Install() error {
5654
return fmt.Errorf("failed to create version-specific directory '%s': %w", versionedDir, err)
5755
}
5856

59-
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, ocmBinaryAsset}, versionedDir)
57+
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, toolArchiveAsset}, versionedDir)
6058
if err != nil {
6159
return fmt.Errorf("failed to download one or more assets: %w", err)
6260
}
6361

6462
// Verify checksum of downloaded assets
65-
ocmBinaryFilepath := filepath.Join(versionedDir, ocmBinaryAsset.GetName())
66-
fileBytes, err := os.ReadFile(ocmBinaryFilepath)
63+
toolArchiveFilepath := filepath.Join(versionedDir, toolArchiveAsset.GetName())
64+
binarySum, err := utils.Sha256sum(toolArchiveFilepath)
6765
if err != nil {
68-
return fmt.Errorf("failed to read ocm-cli binary file '%s' while generating sha256sum: %w", ocmBinaryFilepath, err)
66+
return fmt.Errorf("failed to calculate checksum for '%s': %w", toolArchiveFilepath, err)
6967
}
70-
sumBytes := sha256.Sum256(fileBytes)
71-
binarySum := hex.EncodeToString(sumBytes[:])
7268

7369
checksumFilePath := filepath.Join(versionedDir, checksumAsset.GetName())
74-
checksumBytes, err := os.ReadFile(checksumFilePath)
70+
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, toolArchiveAsset.GetName())
7571
if err != nil {
76-
return fmt.Errorf("failed to read ocm-cli checksum file '%s': %w", checksumFilePath, err)
72+
return fmt.Errorf("failed to retrieve checksum from file '%s': %w", checksumFilePath, err)
7773
}
78-
checksum := strings.Split(string(checksumBytes), " ")[0]
79-
if strings.TrimSpace(binarySum) != strings.TrimSpace(checksum) {
80-
fmt.Printf("WARNING: Checksum for ocm-cli does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s\n", ocmBinaryAsset.GetBrowserDownloadURL())
81-
// We shouldn't link this binary to latest if the checksum isn't valid
82-
return nil
74+
checksumTokens := strings.Fields(checksumLine)
75+
if len(checksumTokens) != 2 {
76+
return fmt.Errorf("the checksum file '%s' is invalid: expected 2 fields, got %d", checksumFilePath, len(checksumTokens))
77+
}
78+
actual := checksumTokens[0]
79+
80+
toolExecutable := t.ExecutableName()
81+
if strings.TrimSpace(binarySum) != strings.TrimSpace(actual) {
82+
return fmt.Errorf("warning: Checksum for '%s' does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", toolExecutable, toolArchiveAsset.GetBrowserDownloadURL())
83+
}
84+
85+
// Untar binary bundle
86+
err = utils.Unarchive(toolArchiveFilepath, versionedDir)
87+
if err != nil {
88+
return fmt.Errorf("failed to unarchive the '%s' asset file '%s': %w", toolExecutable, toolArchiveFilepath, err)
8389
}
8490

8591
// Link as latest
8692
latestFilePath := t.SymlinkPath()
8793
err = os.Remove(latestFilePath)
8894
if err != nil && !os.IsNotExist(err) {
89-
return fmt.Errorf("failed to remove existing 'ocm' binary at '%s': %w", base.LatestDir, err)
95+
return fmt.Errorf("failed to remove existing '%s' binary at '%s': %w", toolExecutable, base.LatestDir, err)
9096
}
9197

92-
err = os.Symlink(ocmBinaryFilepath, latestFilePath)
98+
toolBinaryFilepath := filepath.Join(versionedDir, toolExecutable)
99+
err = os.Symlink(toolBinaryFilepath, latestFilePath)
93100
if err != nil {
94-
return fmt.Errorf("failed to link new 'ocm' binary to '%s': %w", base.LatestDir, err)
101+
return fmt.Errorf("failed to link new '%s' binary to '%s': %w", toolExecutable, base.LatestDir, err)
95102
}
96103
return nil
97104
}

pkg/tools/ocmaddons/ocmaddons.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (t *Tool) Install() error {
3838
if len(matches) != 1 {
3939
return fmt.Errorf("unexpected number of assets found matching system spec: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4040
}
41-
ocmaddonsArchiveAsset := matches[0]
41+
toolArchiveAsset := matches[0]
4242

4343
matches = github.FindAssetsContaining([]string{"checksums.txt"}, release.Assets)
4444
if len(matches) != 1 {
@@ -54,20 +54,20 @@ func (t *Tool) Install() error {
5454
return fmt.Errorf("failed to create version-specific directory '%s': %w", versionedDir, err)
5555
}
5656

57-
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, ocmaddonsArchiveAsset}, versionedDir)
57+
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, toolArchiveAsset}, versionedDir)
5858
if err != nil {
5959
return fmt.Errorf("failed to download one or more assets: %w", err)
6060
}
6161

6262
// Verify checksum of downloaded assets
63-
ocmaddonsArchiveFilepath := filepath.Join(versionedDir, ocmaddonsArchiveAsset.GetName())
64-
binarySum, err := utils.Sha256sum(ocmaddonsArchiveFilepath)
63+
toolArchiveFilepath := filepath.Join(versionedDir, toolArchiveAsset.GetName())
64+
binarySum, err := utils.Sha256sum(toolArchiveFilepath)
6565
if err != nil {
66-
return fmt.Errorf("failed to calculate checksum for '%s': %w", ocmaddonsArchiveFilepath, err)
66+
return fmt.Errorf("failed to calculate checksum for '%s': %w", toolArchiveFilepath, err)
6767
}
6868

6969
checksumFilePath := filepath.Join(versionedDir, checksumAsset.GetName())
70-
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, ocmaddonsArchiveAsset.GetName())
70+
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, toolArchiveAsset.GetName())
7171
if err != nil {
7272
return fmt.Errorf("failed to retrieve checksum from file '%s': %w", checksumFilePath, err)
7373
}
@@ -79,13 +79,13 @@ func (t *Tool) Install() error {
7979

8080
toolExecutable := t.ExecutableName()
8181
if strings.TrimSpace(binarySum) != strings.TrimSpace(actual) {
82-
return fmt.Errorf("warning: Checksum for '%s' does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", toolExecutable, ocmaddonsArchiveAsset.GetBrowserDownloadURL())
82+
return fmt.Errorf("warning: Checksum for '%s' does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", toolExecutable, toolArchiveAsset.GetBrowserDownloadURL())
8383
}
8484

8585
// Untar binary bundle
86-
err = utils.Unarchive(ocmaddonsArchiveFilepath, versionedDir)
86+
err = utils.Unarchive(toolArchiveFilepath, versionedDir)
8787
if err != nil {
88-
return fmt.Errorf("failed to unarchive the '%s' asset file '%s': %w", toolExecutable, ocmaddonsArchiveFilepath, err)
88+
return fmt.Errorf("failed to unarchive the '%s' asset file '%s': %w", toolExecutable, toolArchiveFilepath, err)
8989
}
9090

9191
// Link as latest

pkg/tools/osdctl/osdctl.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ func (t *Tool) Install() error {
3939
if len(matches) != 1 {
4040
return fmt.Errorf("unexpected number of assets found matching system spec: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4141
}
42-
osdctlBinaryAsset := matches[0]
42+
toolArchiveAsset := matches[0]
4343

44-
matches = github.FindAssetsContaining([]string{"sha256sum.txt"}, release.Assets)
44+
matches = github.FindAssetsContaining([]string{"checksums.txt"}, release.Assets)
4545
if len(matches) != 1 {
4646
return fmt.Errorf("unexpected number of checksum assets found: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4747
}
@@ -55,20 +55,20 @@ func (t *Tool) Install() error {
5555
return fmt.Errorf("failed to create version-specific directory '%s': %w", versionedDir, err)
5656
}
5757

58-
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, osdctlBinaryAsset}, versionedDir)
58+
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, toolArchiveAsset}, versionedDir)
5959
if err != nil {
6060
return fmt.Errorf("failed to download one or more assets: %w", err)
6161
}
6262

6363
// Verify checksum of downloaded assets
64-
osdctlBinaryFilepath := filepath.Join(versionedDir, osdctlBinaryAsset.GetName())
65-
binarySum, err := utils.Sha256sum(osdctlBinaryFilepath)
64+
toolArchiveFilepath := filepath.Join(versionedDir, toolArchiveAsset.GetName())
65+
binarySum, err := utils.Sha256sum(toolArchiveFilepath)
6666
if err != nil {
67-
return fmt.Errorf("failed to calculate checksum for '%s': %w", osdctlBinaryFilepath, err)
67+
return fmt.Errorf("failed to calculate checksum for '%s': %w", toolArchiveFilepath, err)
6868
}
6969

7070
checksumFilePath := filepath.Join(versionedDir, checksumAsset.GetName())
71-
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, osdctlBinaryAsset.GetName())
71+
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, toolArchiveAsset.GetName())
7272
if err != nil {
7373
return fmt.Errorf("failed to retrieve checksum from file '%s': %w", checksumFilePath, err)
7474
}
@@ -78,25 +78,28 @@ func (t *Tool) Install() error {
7878
}
7979
actual := checksumTokens[0]
8080

81+
toolExecutable := t.ExecutableName()
8182
if strings.TrimSpace(binarySum) != strings.TrimSpace(actual) {
82-
return fmt.Errorf("warning: Checksum for osdctl does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", osdctlBinaryAsset.GetBrowserDownloadURL())
83+
return fmt.Errorf("warning: Checksum for '%s' does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", toolExecutable, toolArchiveAsset.GetBrowserDownloadURL())
8384
}
8485

85-
// Untar osdctl file
86-
err = utils.Unarchive(osdctlBinaryFilepath, versionedDir)
86+
// Untar binary bundle
87+
err = utils.Unarchive(toolArchiveFilepath, versionedDir)
8788
if err != nil {
88-
return fmt.Errorf("failed to unarchive the osdctl asset file '%s': %w", osdctlBinaryFilepath, err)
89+
return fmt.Errorf("failed to unarchive the '%s' asset file '%s': %w", toolExecutable, toolArchiveFilepath, err)
8990
}
9091

9192
// Link as latest
9293
latestFilePath := t.SymlinkPath()
9394
err = os.Remove(latestFilePath)
9495
if err != nil && !os.IsNotExist(err) {
95-
return fmt.Errorf("failed to remove existing 'osdctl' binary at '%s': %w", base.LatestDir, err)
96+
return fmt.Errorf("failed to remove existing '%s' binary at '%s': %w", toolExecutable, base.LatestDir, err)
9697
}
97-
err = os.Symlink(filepath.Join(versionedDir, "osdctl"), latestFilePath)
98+
99+
toolBinaryFilepath := filepath.Join(versionedDir, toolExecutable)
100+
err = os.Symlink(toolBinaryFilepath, latestFilePath)
98101
if err != nil {
99-
return fmt.Errorf("failed to link new 'osdctl' binary to '%s': %w", base.LatestDir, err)
102+
return fmt.Errorf("failed to link new '%s' binary to '%s': %w", toolExecutable, base.LatestDir, err)
100103
}
101104
return nil
102105
}

pkg/tools/rosa/rosa.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,16 @@ func (t *Tool) Install() error {
3535
}
3636

3737
matches := github.FindAssetsForArchAndOS(release.Assets)
38-
binaryMatches := github.FindAssetsExcluding([]string{"sha256"}, matches)
39-
if len(binaryMatches) != 1 {
40-
return fmt.Errorf("unexpected number of assets found matching system spec: expected 1, got %d.\nMatching assets: %v", len(binaryMatches), binaryMatches)
38+
if len(matches) != 1 {
39+
return fmt.Errorf("unexpected number of assets found matching system spec: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4140
}
42-
rosaBinaryAsset := binaryMatches[0]
41+
toolArchiveAsset := matches[0]
4342

44-
checksumMatches := github.FindAssetsContaining([]string{"sha256"}, matches)
45-
if len(checksumMatches) != 1 {
43+
matches = github.FindAssetsContaining([]string{"checksums.txt"}, release.Assets)
44+
if len(matches) != 1 {
4645
return fmt.Errorf("unexpected number of checksum assets found: expected 1, got %d.\nMatching assets: %v", len(matches), matches)
4746
}
48-
checksumAsset := checksumMatches[0]
47+
checksumAsset := matches[0]
4948

5049
// Download the arch- & os-specific assets
5150
toolDir := t.ToolDir()
@@ -55,20 +54,20 @@ func (t *Tool) Install() error {
5554
return fmt.Errorf("failed to create version-specific directory '%s': %w", versionedDir, err)
5655
}
5756

58-
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, rosaBinaryAsset}, versionedDir)
57+
err = t.Source.DownloadReleaseAssets([]*gogithub.ReleaseAsset{checksumAsset, toolArchiveAsset}, versionedDir)
5958
if err != nil {
6059
return fmt.Errorf("failed to download one or more assets: %w", err)
6160
}
6261

6362
// Verify checksum of downloaded assets
64-
rosaBinaryFilepath := filepath.Join(versionedDir, rosaBinaryAsset.GetName())
65-
binarySum, err := utils.Sha256sum(rosaBinaryFilepath)
63+
toolArchiveFilepath := filepath.Join(versionedDir, toolArchiveAsset.GetName())
64+
binarySum, err := utils.Sha256sum(toolArchiveFilepath)
6665
if err != nil {
67-
return fmt.Errorf("failed to calculate checksum for '%s': %w", rosaBinaryFilepath, err)
66+
return fmt.Errorf("failed to calculate checksum for '%s': %w", toolArchiveFilepath, err)
6867
}
6968

7069
checksumFilePath := filepath.Join(versionedDir, checksumAsset.GetName())
71-
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, rosaBinaryAsset.GetName())
70+
checksumLine, err := utils.GetLineInFileMatchingKey(checksumFilePath, toolArchiveAsset.GetName())
7271
if err != nil {
7372
return fmt.Errorf("failed to retrieve checksum from file '%s': %w", checksumFilePath, err)
7473
}
@@ -78,20 +77,28 @@ func (t *Tool) Install() error {
7877
}
7978
actual := checksumTokens[0]
8079

80+
toolExecutable := t.ExecutableName()
8181
if strings.TrimSpace(binarySum) != strings.TrimSpace(actual) {
82-
return fmt.Errorf("warning: Checksum for rosa does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", rosaBinaryAsset.GetBrowserDownloadURL())
82+
return fmt.Errorf("warning: Checksum for '%s' does not match the calculated value. Please retry installation. If issue persists, this tool can be downloaded manually at %s", toolExecutable, toolArchiveAsset.GetBrowserDownloadURL())
83+
}
84+
85+
// Untar binary bundle
86+
err = utils.Unarchive(toolArchiveFilepath, versionedDir)
87+
if err != nil {
88+
return fmt.Errorf("failed to unarchive the '%s' asset file '%s': %w", toolExecutable, toolArchiveFilepath, err)
8389
}
8490

8591
// Link as latest
8692
latestFilePath := t.SymlinkPath()
8793
err = os.Remove(latestFilePath)
8894
if err != nil && !os.IsNotExist(err) {
89-
return fmt.Errorf("failed to remove existing 'rosa' binary at '%s': %w", base.LatestDir, err)
95+
return fmt.Errorf("failed to remove existing '%s' binary at '%s': %w", toolExecutable, base.LatestDir, err)
9096
}
9197

92-
err = os.Symlink(rosaBinaryFilepath, latestFilePath)
98+
toolBinaryFilepath := filepath.Join(versionedDir, toolExecutable)
99+
err = os.Symlink(toolBinaryFilepath, latestFilePath)
93100
if err != nil {
94-
return fmt.Errorf("failed to link new 'rosa' binary to '%s': %w", base.LatestDir, err)
101+
return fmt.Errorf("failed to link new '%s' binary to '%s': %w", toolExecutable, base.LatestDir, err)
95102
}
96103
return nil
97104
}

0 commit comments

Comments
 (0)