Skip to content

Commit 4a2b508

Browse files
committed
[feat]: [CI-17150]: plugin changes to support binary sources as arguments
1 parent 2baac65 commit 4a2b508

3 files changed

Lines changed: 130 additions & 54 deletions

File tree

main.go

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@ import (
1515
"github.com/drone/plugin/plugin/bitrise"
1616
"github.com/drone/plugin/plugin/github"
1717
"github.com/drone/plugin/plugin/harness"
18+
"github.com/drone/plugin/utils"
1819
)
1920

2021
var (
21-
name string // plugin name
22-
repo string // plugin repository
23-
ref string // plugin repository reference
24-
sha string // plugin repository commit
25-
kind string // plugin kind (action, bitrise, harness)
26-
downloadOnly bool // plugin won't be executed on setting this flag. Only source will be downloaded. Used for caching the plugin dependencies
22+
name string // plugin name
23+
repo string // plugin repository
24+
ref string // plugin repository reference
25+
sha string // plugin repository commit
26+
kind string // plugin kind (action, bitrise, harness)
27+
downloadOnly bool // plugin won't be executed on setting this flag. Only source will be downloaded. Used for caching the plugin dependencies
28+
disableClone bool // plugin does not clone when this flag is enabled
29+
binarySources utils.CustomStringSliceFlag // plugin uses these binary source urls in the same order to download the binaires
2730
)
2831

2932
func main() {
@@ -43,6 +46,7 @@ func main() {
4346
flag.StringVar(&sha, "sha", "", "plugin commit")
4447
flag.StringVar(&kind, "kind", "", "plugin kind")
4548
flag.BoolVar(&downloadOnly, "download-only", false, "plugin downloadOnly")
49+
flag.Var(&binarySources, "sources", "source urls to download binaries")
4650
flag.Parse()
4751

4852
// the user may specific the action plugin alias instead
@@ -87,19 +91,26 @@ func main() {
8791
}
8892

8993
// clone the plugin repository
90-
clone := cloner.NewCache(cloner.NewDefault())
91-
codedir, err := clone.Clone(ctx, repo, ref, sha)
92-
if err != nil {
93-
slog.Error("cannot clone the plugin", "error", err)
94-
os.Exit(1)
94+
var codedir string
95+
96+
if !disableClone {
97+
clone := cloner.NewCache(cloner.NewDefault())
98+
codedir, err = clone.Clone(ctx, repo, ref, sha)
99+
if err != nil {
100+
slog.Error("cannot clone the plugin", "error", err)
101+
os.Exit(1)
102+
}
95103
}
96104

97105
outputFile := os.Getenv("DRONE_OUTPUT")
98106

99107
switch {
100108
// execute harness plugin
101109
case kind == "harness" || (kind == "" && harness.Is(codedir)):
102-
slog.Info("detected harness plugin.yml")
110+
111+
if !disableClone {
112+
slog.Info("detected harness plugin.yml")
113+
}
103114
execer := harness.Execer{
104115
Source: codedir,
105116
Workdir: workdir,

plugin/harness/execer.go

Lines changed: 74 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,65 +16,67 @@ import (
1616

1717
"github.com/drone/plugin/cache"
1818
"github.com/drone/plugin/plugin/internal/file"
19+
"github.com/drone/plugin/utils"
1920
"golang.org/x/exp/slog"
2021
)
2122

2223
// Execer executes a harness plugin.
2324
type Execer struct {
24-
Ref string // Git ref for source code
25-
Source string // plugin source code directory
26-
Workdir string // pipeline working directory (aka workspace)
27-
DownloadOnly bool
28-
Environ []string
29-
Stdout io.Writer
30-
Stderr io.Writer
25+
Ref string // Git ref for source code
26+
Source string // plugin source code directory
27+
Workdir string // pipeline working directory (aka workspace)
28+
DownloadOnly bool
29+
binarySources utils.CustomStringSliceFlag
30+
disableClone bool
31+
Environ []string
32+
Stdout io.Writer
33+
Stderr io.Writer
3134
}
3235

3336
// Exec executes a bitrise plugin.
3437
func (e *Execer) Exec(ctx context.Context) error {
35-
// parse the bitrise plugin yaml
36-
out, err := parseFile(filepath.Join(e.Source, "plugin.yml"))
37-
if err != nil {
38-
return err
39-
}
38+
if !e.disableClone {
39+
// parse the bitrise plugin yaml
40+
out, err := parseFile(filepath.Join(e.Source, "plugin.yml"))
41+
if err != nil {
42+
return err
43+
}
4044

41-
// install dependencies
42-
if runtime.GOOS == "linux" {
43-
e.installAptDeps(ctx, out.Deps.Apt.Packages, out.Deps.Apt.Sources)
44-
} else if runtime.GOOS == "darwin" {
45-
e.installBrewDeps(ctx, out.Deps.Brew)
46-
} else if runtime.GOOS == "windows" {
47-
e.installChocoDeps(ctx, out.Deps.Choco)
48-
}
45+
// install dependencies
46+
if runtime.GOOS == "linux" {
47+
e.installAptDeps(ctx, out.Deps.Apt.Packages, out.Deps.Apt.Sources)
48+
} else if runtime.GOOS == "darwin" {
49+
e.installBrewDeps(ctx, out.Deps.Brew)
50+
} else if runtime.GOOS == "windows" {
51+
e.installChocoDeps(ctx, out.Deps.Choco)
52+
}
4953

50-
if len(out.Deps.Run) != 0 {
51-
e.installRunScripts(ctx, out.Deps.Run)
52-
}
54+
if len(out.Deps.Run) != 0 {
55+
e.installRunScripts(ctx, out.Deps.Run)
56+
}
5357

54-
// execute the plugin. thxe execution logic differs
55-
// based on programming language.
56-
if source := out.Run.Binary.Source; source != "" {
57-
return e.runSourceExecutable(ctx, out.Run.Binary.Source, out.Run.Binary.FallbackSource)
58-
} else if module := out.Run.Go.Module; module != "" {
59-
return e.runGoExecutable(ctx, module)
58+
// execute the plugin. thxe execution logic differs
59+
// based on programming language.
60+
sources := e.getBinarySources(out.Run.Binary.Source, out.Run.Binary.FallbackSource)
61+
if len(sources) > 0 {
62+
return e.runSourceExecutable(ctx, sources)
63+
} else if module := out.Run.Go.Module; module != "" {
64+
return e.runGoExecutable(ctx, module)
65+
} else {
66+
return e.runShellExecutable(ctx, out)
67+
}
68+
} else if len(e.binarySources.GetValue()) > 0 {
69+
return e.runSourceExecutable(ctx, e.binarySources.GetValue())
6070
} else {
61-
return e.runShellExecutable(ctx, out)
71+
slog.Error("clone is disabled and binary sources are empty. Aborting")
72+
return nil
6273
}
6374
}
6475

65-
func (e *Execer) runSourceExecutable(ctx context.Context, source string, fallback string) error {
66-
binpath, err := e.downloadBinary(source)
76+
func (e *Execer) runSourceExecutable(ctx context.Context, sources []string) error {
77+
binpath, err := e.downloadBinaryFromSources(sources)
6778
if err != nil {
68-
slog.Info("Primary source download failed. Retrying with fallback...")
69-
70-
if fallback != "" {
71-
binpath, err = e.downloadBinary(fallback)
72-
if err != nil {
73-
return err
74-
}
75-
} else {
76-
return err
77-
}
79+
return err
7880
}
7981

8082
if e.DownloadOnly {
@@ -90,6 +92,22 @@ func (e *Execer) runSourceExecutable(ctx context.Context, source string, fallbac
9092
return runCmds(ctx, cmds, e.Environ, e.Workdir, e.Stdout, e.Stderr)
9193
}
9294

95+
func (e *Execer) downloadBinaryFromSources(sources []string) (string, error) {
96+
var err error
97+
var binpath string
98+
for _, source := range sources {
99+
if source != "" {
100+
binpath, err = e.downloadBinary(source)
101+
if err == nil {
102+
return binpath, nil
103+
} else {
104+
slog.Info("binary download failed moving on to next source")
105+
}
106+
}
107+
}
108+
return "", err
109+
}
110+
93111
func (e *Execer) downloadBinary(source string) (string, error) {
94112
parsedURL, err := NewMetadata(source, e.Ref).Generate()
95113
if err != nil {
@@ -266,6 +284,20 @@ func runCmds(ctx context.Context, cmds []*exec.Cmd, env []string, workdir string
266284
return nil
267285
}
268286

287+
func (e *Execer) getBinarySources(source string, fallback string) []string {
288+
var sources []string
289+
if len(e.binarySources.GetValue()) > 0 {
290+
sources = append(sources, e.binarySources.GetValue()...)
291+
}
292+
if source != "" {
293+
sources = append(sources, source)
294+
}
295+
if fallback != "" {
296+
sources = append(sources, fallback)
297+
}
298+
return sources
299+
}
300+
269301
// trace writes each command to stdout with the command wrapped in an xml
270302
// tag so that it can be extracted and displayed in the logs.
271303
func trace(ctx context.Context, cmd *exec.Cmd) {

utils/custom_string_slice.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package utils
2+
3+
import (
4+
"strings"
5+
)
6+
7+
// CustomStringSliceFlag is like a regular StringSlice flag but with
8+
// semicolon as a delimiter
9+
type CustomStringSliceFlag struct {
10+
Value []string
11+
}
12+
13+
func (f *CustomStringSliceFlag) GetValue() []string {
14+
if f.Value == nil {
15+
return make([]string, 0)
16+
}
17+
return f.Value
18+
}
19+
20+
func (f *CustomStringSliceFlag) String() string {
21+
if f.Value == nil {
22+
return ""
23+
}
24+
return strings.Join(f.Value, ";")
25+
}
26+
27+
func (f *CustomStringSliceFlag) Set(v string) error {
28+
for _, s := range strings.Split(v, ";") {
29+
s = strings.TrimSpace(s)
30+
f.Value = append(f.Value, s)
31+
}
32+
return nil
33+
}

0 commit comments

Comments
 (0)