Skip to content

Commit d6d301c

Browse files
authored
[feat]: [CI-16417]: added support fallback binary url (#37)
1 parent 9a67992 commit d6d301c

File tree

6 files changed

+121
-11
lines changed

6 files changed

+121
-11
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ replace github.com/nektos/act => github.com/harness/nektos-act v0.0.0-2023031417
66

77
require (
88
github.com/buildkite/yaml v2.1.0+incompatible
9+
github.com/cenkalti/backoff/v4 v4.3.0
910
github.com/ghodss/yaml v1.0.0
1011
github.com/go-git/go-git/v5 v5.6.1
1112
github.com/google/go-cmp v0.5.9
@@ -29,7 +30,6 @@ require (
2930
github.com/acomagu/bufpipe v1.0.4 // indirect
3031
github.com/adrg/xdg v0.4.0 // indirect
3132
github.com/andreaskoch/go-fswatch v1.0.0 // indirect
32-
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
3333
github.com/cloudflare/circl v1.3.2 // indirect
3434
github.com/containerd/containerd v1.7.0 // indirect
3535
github.com/creack/pty v1.1.18 // indirect

plugin/harness/execer.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,27 @@ func (e *Execer) Exec(ctx context.Context) error {
5050
// execute the plugin. the execution logic differs
5151
// based on programming language.
5252
if source := out.Run.Binary.Source; source != "" {
53-
return e.runSourceExecutable(ctx, out.Run.Binary.Source)
53+
return e.runSourceExecutable(ctx, out.Run.Binary.Source, out.Run.Binary.FallbackSource)
5454
} else if module := out.Run.Go.Module; module != "" {
5555
return e.runGoExecutable(ctx, module)
5656
} else {
5757
return e.runShellExecutable(ctx, out)
5858
}
5959
}
6060

61-
func (e *Execer) runSourceExecutable(ctx context.Context, source string) error {
62-
parsedURL, err := NewMetadata(source, e.Ref).Generate()
63-
if err != nil {
64-
return err
65-
}
66-
binpath, err := file.Download(parsedURL)
61+
func (e *Execer) runSourceExecutable(ctx context.Context, source string, fallback string) error {
62+
binpath, err := e.downloadBinary(source)
6763
if err != nil {
68-
return err
64+
slog.Info("Primary source download failed. Retrying with fallback...")
65+
66+
if fallback != "" {
67+
binpath, err = e.downloadBinary(fallback)
68+
if err != nil {
69+
return err
70+
}
71+
} else {
72+
return err
73+
}
6974
}
7075

7176
if e.DownloadOnly {
@@ -81,6 +86,18 @@ func (e *Execer) runSourceExecutable(ctx context.Context, source string) error {
8186
return runCmds(ctx, cmds, e.Environ, e.Workdir, e.Stdout, e.Stderr)
8287
}
8388

89+
func (e *Execer) downloadBinary(source string) (string, error) {
90+
parsedURL, err := NewMetadata(source, e.Ref).Generate()
91+
if err != nil {
92+
return "", err
93+
}
94+
binpath, err := file.Download(parsedURL)
95+
if err != nil {
96+
return "", err
97+
}
98+
return binpath, nil
99+
}
100+
84101
func (e *Execer) runGoExecutable(ctx context.Context, module string) error {
85102
// if the plugin is a Go module
86103
binpath, err := e.buildGoExecutable(ctx, module)

plugin/harness/parse_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,86 @@
33
// license that can be found in the LICENSE file.
44

55
package harness
6+
7+
import (
8+
"path/filepath"
9+
"testing"
10+
)
11+
12+
func TestParseFile(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
filename string
16+
wantErr bool
17+
validate func(*testing.T, *spec)
18+
}{
19+
{
20+
name: "valid plugin with binary source",
21+
filename: "binary_source.yml",
22+
wantErr: false,
23+
validate: func(t *testing.T, s *spec) {
24+
wantSource := "https://github.com/drone-plugins/plugin/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst"
25+
wantFallback := ""
26+
27+
if got := s.Run.Binary.Source; got != wantSource {
28+
t.Errorf("Expected source %q, got %q", wantSource, got)
29+
}
30+
if got := s.Run.Binary.FallbackSource; got != wantFallback {
31+
t.Errorf("Expected fallback source %q, got %q", wantFallback, got)
32+
}
33+
},
34+
},
35+
{
36+
name: "valid plugin with binary source and fallback",
37+
filename: "binary_source_fallback.yml",
38+
wantErr: false,
39+
validate: func(t *testing.T, s *spec) {
40+
wantSource := "https://github.com/drone-plugins/plugin/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst"
41+
wantFallback := "https://mirror.example.com/plugin/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst"
42+
43+
if got := s.Run.Binary.Source; got != wantSource {
44+
t.Errorf("Expected source %q, got %q", wantSource, got)
45+
}
46+
if got := s.Run.Binary.FallbackSource; got != wantFallback {
47+
t.Errorf("Expected fallback source %q, got %q", wantFallback, got)
48+
}
49+
},
50+
},
51+
}
52+
53+
for _, tt := range tests {
54+
t.Run(tt.name, func(t *testing.T) {
55+
// Use testdata directory
56+
testFile := filepath.Join("testdata", tt.filename)
57+
got, err := parseFile(testFile)
58+
if (err != nil) != tt.wantErr {
59+
t.Errorf("parseFile() error = %v, wantErr %v", err, tt.wantErr)
60+
return
61+
}
62+
63+
if !tt.wantErr {
64+
tt.validate(t, got)
65+
}
66+
})
67+
}
68+
}
69+
70+
func TestParseBinaryWithFallback(t *testing.T) {
71+
yaml := `
72+
run:
73+
binary:
74+
source: https://github.com/drone-plugins/drone-meltwater-cache/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst
75+
fallback_source: https://backup-mirror.example.com/drone-plugins/drone-meltwater-cache/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst
76+
`
77+
out, err := parseString(yaml)
78+
if err != nil {
79+
t.Error(err)
80+
return
81+
}
82+
if got, want := out.Run.Binary.Source, "https://github.com/drone-plugins/drone-meltwater-cache/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst"; got != want {
83+
t.Errorf("Want source URL %q, got %q", want, got)
84+
}
85+
if got, want := out.Run.Binary.FallbackSource, "https://backup-mirror.example.com/drone-plugins/drone-meltwater-cache/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst"; got != want {
86+
t.Errorf("Want fallback source URL %q, got %q", want, got)
87+
}
88+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
run:
2+
binary:
3+
source: https://github.com/drone-plugins/plugin/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
run:
2+
binary:
3+
source: https://github.com/drone-plugins/plugin/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst
4+
fallback_source: https://mirror.example.com/plugin/releases/download/{{ release }}/plugin-{{ os }}-{{ arch }}.zst

plugin/harness/types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
package harness
66

7-
import "errors"
7+
import (
8+
"errors"
9+
)
810

911
// spec defines the bitrise plugin.
1012
type (
@@ -41,7 +43,8 @@ type spec struct {
4143
Module string
4244
}
4345
Binary struct {
44-
Source string
46+
Source string
47+
FallbackSource string `yaml:"fallback_source,omitempty"`
4548
}
4649
}
4750
}

0 commit comments

Comments
 (0)