From 4c76b3e39adf2ed7b9226801dc6cb9cde58018fc Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Fri, 24 Mar 2023 14:15:13 +0530 Subject: [PATCH 1/5] Clone with both refs/heads & refs/tags if exact ref type is unknown (#18) --- cloner/default.go | 20 +++++++++++++++++++- plugin/github/utils.go | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cloner/default.go b/cloner/default.go index 47cc1c2..d687bf9 100644 --- a/cloner/default.go +++ b/cloner/default.go @@ -6,8 +6,10 @@ package cloner import ( "context" + "errors" "io" "os" + "strings" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" @@ -66,9 +68,25 @@ func (c *cloner) Clone(ctx context.Context, params Params) error { } // clone the repository r, err := git.PlainClone(params.Dir, false, opts) - if err != nil { + if errors.Is(plumbing.ErrReferenceNotFound, err) && !strings.HasPrefix(params.Ref, "refs/") { + // If params.Ref is provided without refs/*, then we are assuming it to either refs/heads/ or refs/tags. + // Try clone again with inverse ref. + if opts.ReferenceName.IsBranch() { + opts.ReferenceName = plumbing.ReferenceName("refs/tags/" + params.Ref) + } else if opts.ReferenceName.IsTag() { + opts.ReferenceName = plumbing.ReferenceName("refs/heads/" + params.Ref) + } else { + return err + } + + r, err = git.PlainClone(params.Dir, false, opts) + if err != nil { + return err + } + } else if err != nil { return err } + if params.Sha == "" { return nil } diff --git a/plugin/github/utils.go b/plugin/github/utils.go index 1b1a39f..b9495a1 100644 --- a/plugin/github/utils.go +++ b/plugin/github/utils.go @@ -22,7 +22,7 @@ func getOutputVars(codedir, name string) []string { slog.Warn(fmt.Sprintf("failed to parse output vars: %v", err)) } - if spec.Outputs != nil { + if spec != nil && spec.Outputs != nil { for k := range spec.Outputs { outputVars = append(outputVars, k) } From 93dd99e9c2373143fc9d456db77d039584b6695c Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Mon, 27 Mar 2023 11:27:34 +0530 Subject: [PATCH 2/5] Add support for passing ref for drone plugin by name (#20) --- cloner/default_test.go | 50 +++++++++++++++++++++++++++++++++++ go.mod | 13 +++++---- go.sum | 27 ++++++++++++------- main.go | 7 ++--- plugin/harness/lookup.go | 16 ++++++----- plugin/harness/lookup_test.go | 23 +++++++++++++++- plugin/internal/file/file.go | 7 +++-- 7 files changed, 116 insertions(+), 27 deletions(-) diff --git a/cloner/default_test.go b/cloner/default_test.go index 5fd75e5..a4768c2 100644 --- a/cloner/default_test.go +++ b/cloner/default_test.go @@ -3,3 +3,53 @@ // license that can be found in the LICENSE file. package cloner + +import ( + "context" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestClone(t *testing.T) { + for name, tt := range map[string]struct { + Err error + URL, Ref string + }{ + "tag": { + Err: nil, + URL: "https://github.com/actions/checkout", + Ref: "v2", + }, + "branch": { + Err: nil, + URL: "https://github.com/anchore/scan-action", + Ref: "act-fails", + }, + "tag-special": { + Err: nil, + URL: "https://github.com/shubham149/drone-s3", + Ref: "setup-node-and-dependencies+1.0.9", + }, + } { + t.Run(name, func(t *testing.T) { + c := NewDefault() + err := c.Clone(context.Background(), Params{Repo: tt.URL, Ref: tt.Ref, Dir: testDir(t)}) + if tt.Err != nil { + assert.Error(t, err) + assert.Equal(t, tt.Err, err) + } else { + assert.Empty(t, err) + } + }) + } +} + +func testDir(t *testing.T) string { + basedir, err := os.MkdirTemp("", "act-test") + require.NoError(t, err) + t.Cleanup(func() { _ = os.RemoveAll(basedir) }) + return basedir +} diff --git a/go.mod b/go.mod index 16e4ba3..1afd977 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,8 @@ require ( github.com/nektos/act v0.2.43 github.com/pkg/errors v0.9.1 github.com/rogpeppe/go-internal v1.9.0 - golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 + github.com/stretchr/testify v1.8.2 + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -24,13 +25,14 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230316153859-cb82d937a5d9 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect github.com/adrg/xdg v0.4.0 // indirect github.com/andreaskoch/go-fswatch v1.0.0 // indirect github.com/cloudflare/circl v1.3.2 // indirect github.com/containerd/containerd v1.7.0 // indirect github.com/creack/pty v1.1.18 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/cli v23.0.1+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v23.0.1+incompatible // indirect @@ -43,19 +45,19 @@ require ( github.com/go-git/go-billy/v5 v5.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/imdario/mergo v0.3.14 // indirect + github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moby/buildkit v0.11.4 // indirect + github.com/moby/buildkit v0.11.5 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect @@ -63,6 +65,7 @@ require ( github.com/opencontainers/runc v1.1.4 // indirect github.com/opencontainers/selinux v1.11.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rhysd/actionlint v1.6.23 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron v1.2.0 // indirect diff --git a/go.sum b/go.sum index 21bbcee..14a5e6f 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Microsoft/hcsshim v0.10.0-rc.7 h1:HBytQPxcv8Oy4244zbQbe6hnOnx544eL5QP github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= -github.com/ProtonMail/go-crypto v0.0.0-20230316153859-cb82d937a5d9 h1:rndY7RCFW5vUcdVvhfIRsQhYm1MdvwI+dTFbyrWiGHY= -github.com/ProtonMail/go-crypto v0.0.0-20230316153859-cb82d937a5d9/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310 h1:dGAdTcqheKrQ/TW76sAcmO2IorwXplUw2inPkOzykbw= +github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= @@ -94,8 +94,8 @@ github.com/harness/nektos-act v0.0.0-20230314172414-8d69c367d137/go.mod h1:iLHCX github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/imdario/mergo v0.3.14 h1:fOqeC1+nCuuk6PKQdg9YmosXX7Y7mHX6R/0ZldI9iHo= -github.com/imdario/mergo v0.3.14/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -128,8 +128,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -140,8 +140,8 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= -github.com/moby/buildkit v0.11.4 h1:mleVHr+n7HUD65QNUkgkT3d8muTzhYUoHE9FM3Ej05s= -github.com/moby/buildkit v0.11.4/go.mod h1:P5Qi041LvCfhkfYBHry+Rwoo3Wi6H971J2ggE+PcIoo= +github.com/moby/buildkit v0.11.5 h1:S6YrFJ0bfBT2w9e8kOxqsDV8Bw+HtfqdB6eHL17BXRI= +github.com/moby/buildkit v0.11.5/go.mod h1:P5Qi041LvCfhkfYBHry+Rwoo3Wi6H971J2ggE+PcIoo= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= @@ -196,13 +196,18 @@ github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUq github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= @@ -231,12 +236,13 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= -golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -312,6 +318,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/main.go b/main.go index 2ef110e..72cbfc3 100644 --- a/main.go +++ b/main.go @@ -60,9 +60,10 @@ func main() { // of the git repository. We are able to lookup the plugin // by alias to find the corresponding repository and commit. if repo == "" && kind == "harness" { - repo_, sha_, ok := harness.ParseLookup(name) + repo_, ref_, sha_, ok := harness.ParseLookup(name) if ok { repo = repo_ + ref = ref_ sha = sha_ } } @@ -97,7 +98,7 @@ func main() { switch { // execute harness plugin - case harness.Is(codedir) || kind == "harness": + case kind == "harness" || (kind == "" && harness.Is(codedir)): slog.Info("detected harness plugin.yml") execer := harness.Execer{ Source: codedir, @@ -114,7 +115,7 @@ func main() { } // execute bitrise plugin - case bitrise.Is(codedir) || kind == "bitrise": + case kind == "bitrise" || (kind == "" && bitrise.Is(codedir)): slog.Info("detected bitrise step.yml") execer := bitrise.Execer{ Source: codedir, diff --git a/plugin/harness/lookup.go b/plugin/harness/lookup.go index 0091613..b8075df 100644 --- a/plugin/harness/lookup.go +++ b/plugin/harness/lookup.go @@ -8,7 +8,7 @@ import "strings" // Lookup returns the repository and commit associated // with the named step and version. -func Lookup(name, version string) (repo string, commit string, ok bool) { +func Lookup(name, version string) (repo string, ref string, commit string, ok bool) { // find the named step plugin_, ok := index[name] if !ok { @@ -16,7 +16,7 @@ func Lookup(name, version string) (repo string, commit string, ok bool) { } // use head commit if no version is provided. if version == "" { - return plugin_.repo, "", ok + return plugin_.repo, "", "", ok } // TODO(bradrydzeski) we should be able to use smart @@ -28,12 +28,12 @@ func Lookup(name, version string) (repo string, commit string, ok bool) { if !ok { return } - return plugin_.repo, version_, ok + return plugin_.repo, "", version_, ok } // ParseLookup parses the step string and returns the // associated repository and commit. -func ParseLookup(s string) (repo string, commit string, ok bool) { +func ParseLookup(s string) (repo string, ref string, commit string, ok bool) { // if the strings is prefixed with git:: it means the // repository url was provided directly. if strings.HasPrefix(s, "git:") || strings.HasPrefix(s, "github.com") { @@ -43,7 +43,11 @@ func ParseLookup(s string) (repo string, commit string, ok bool) { // extract the version from the string, if provided. if parts := strings.SplitN(s, "@", 2); len(parts) == 2 { repo = parts[0] - commit = parts[1] + if strings.HasPrefix(parts[1], "refs/") { + ref = parts[1] + } else { + commit = parts[1] + } } // prepend the https scheme if not includes in the @@ -58,7 +62,7 @@ func ParseLookup(s string) (repo string, commit string, ok bool) { } } - return repo, commit, true + return repo, ref, commit, true } if parts := strings.SplitN(s, "@", 2); len(parts) == 2 { diff --git a/plugin/harness/lookup_test.go b/plugin/harness/lookup_test.go index fe03613..ba44314 100644 --- a/plugin/harness/lookup_test.go +++ b/plugin/harness/lookup_test.go @@ -11,35 +11,56 @@ func TestParseLookup(t *testing.T) { name string repo string hash string + ref string }{ { name: "git::https://github.com/ocotcat/hello-world.git", repo: "https://github.com/ocotcat/hello-world.git", hash: "", + ref: "", }, { name: "github.com/ocotcat/hello-world.git", repo: "https://github.com/ocotcat/hello-world.git", hash: "", + ref: "", }, { name: "github.com/ocotcat/hello-world", repo: "https://github.com/ocotcat/hello-world.git", hash: "", + ref: "", }, { name: "github.com/ocotcat/hello-world@a8b99ea78c8f99326516d6b875075ead642b4ca5", repo: "https://github.com/ocotcat/hello-world.git", hash: "a8b99ea78c8f99326516d6b875075ead642b4ca5", + ref: "", + }, + { + name: "github.com/drone-plugins/drone-s3@refs/heads/master", + repo: "https://github.com/drone-plugins/drone-s3.git", + hash: "", + ref: "refs/heads/master", + }, + { + name: "github.com/drone-plugins/drone-s3@refs/tags/v1", + repo: "https://github.com/drone-plugins/drone-s3.git", + hash: "", + ref: "refs/tags/v1", }, } for _, test := range tests { - repo, commit, _ := ParseLookup(test.name) + repo, ref, commit, _ := ParseLookup(test.name) if got, want := repo, test.repo; got != want { t.Errorf("Expect repository %s, got %s", want, got) } if got, want := commit, test.hash; got != want { t.Errorf("Expect commit %s, got %s", want, got) } + + if got, want := ref, test.ref; got != want { + t.Errorf("Expect ref %s, got %s", want, got) + } } } diff --git a/plugin/internal/file/file.go b/plugin/internal/file/file.go index f727ea3..f948447 100644 --- a/plugin/internal/file/file.go +++ b/plugin/internal/file/file.go @@ -24,7 +24,10 @@ func Download(url string) (string, error) { binPath := filepath.Join(key, "step.exe") downloadFn := func() error { - return download(url, binPath) + if err := download(url, binPath); err != nil { + return errors.Wrap(err, fmt.Sprintf("url: %s", url)) + } + return nil } if err := cache.Add(key, downloadFn); err != nil { @@ -42,7 +45,7 @@ func download(url, path string) error { } resp, err := client.Get(url) if err != nil { - return errors.Wrap(err, fmt.Sprintf("failed to download url: %s", url)) + return errors.Wrap(err, "failed to download url") } defer resp.Body.Close() From 9a70dc323c7067bc0926af2a2befb3fdebb002ef Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 28 Mar 2023 23:27:08 +0530 Subject: [PATCH 3/5] Add retries during source url download (#21) --- plugin/harness/execer.go | 18 ++++++++---------- plugin/internal/file/file.go | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/plugin/harness/execer.go b/plugin/harness/execer.go index 3863b7e..8906b8a 100644 --- a/plugin/harness/execer.go +++ b/plugin/harness/execer.go @@ -127,15 +127,7 @@ func (e *Execer) Exec(ctx context.Context) error { return nil } - // else if the plugin is a Bash script - - // determine the default script path - script := out.Run.Bash.Path - shell := "/bin/bash" - path := filepath.Join(e.Source, script) - - slog.Debug("execute", slog.String("file", script)) - + var path, shell string // if the bash shell does not exist fallback // to posix shell. switch runtime.GOOS { @@ -143,13 +135,19 @@ func (e *Execer) Exec(ctx context.Context) error { // TODO we may want to disable profile and interactive mode // when executing powershell scripts -noprofile -noninteractive shell = "powershell" + path = filepath.Join(e.Source, out.Run.Pwsh.Path) + case "linux", "darwin": + shell = "bash" + path = filepath.Join(e.Source, out.Run.Bash.Path) + // fallback to the posix shell if bash // is not available on the host. if _, err := exec.LookPath("bash"); err != nil { - shell = "/bin/sh" + shell = "sh" } } + slog.Debug("execute", slog.String("file", path)) // execute the binary cmd := exec.Command(shell, path) diff --git a/plugin/internal/file/file.go b/plugin/internal/file/file.go index f948447..4f93f49 100644 --- a/plugin/internal/file/file.go +++ b/plugin/internal/file/file.go @@ -13,6 +13,7 @@ import ( "github.com/drone/plugin/cache" "github.com/klauspost/compress/zstd" "github.com/pkg/errors" + "golang.org/x/exp/slog" ) const ( @@ -24,7 +25,7 @@ func Download(url string) (string, error) { binPath := filepath.Join(key, "step.exe") downloadFn := func() error { - if err := download(url, binPath); err != nil { + if err := downloadWithRetries(url, binPath); err != nil { return errors.Wrap(err, fmt.Sprintf("url: %s", url)) } return nil @@ -36,6 +37,18 @@ func Download(url string) (string, error) { return binPath, nil } +func downloadWithRetries(url, path string) error { + var err error + for i := 0; i < 3; i++ { + if err = download(url, path); err == nil { + return nil + } + slog.Error("failed to download url, retrying", slog.String("url", url), "error", err) + time.Sleep(1 * time.Second) + } + return err +} + // download method downloads a source & writes it to a file. // If file is compressed, it also decompresses the file on the basis of // file extension in url. Currently it supports zstd format. From 75a63f8d2371a75587df8178d85182ec955b5380 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Wed, 29 Mar 2023 12:33:21 +0530 Subject: [PATCH 4/5] Fix powershell command to execute step on windows (#22) --- plugin/harness/execer.go | 140 ++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 69 deletions(-) diff --git a/plugin/harness/execer.go b/plugin/harness/execer.go index 8906b8a..b517cfb 100644 --- a/plugin/harness/execer.go +++ b/plugin/harness/execer.go @@ -79,85 +79,87 @@ func (e *Execer) Exec(ctx context.Context) error { // execute the plugin. the execution logic differs // based on programming language. if source := out.Run.Binary.Source; source != "" { - parsedURL, err := NewMetadata(source, e.Ref).Generate() - if err != nil { - return err - } - binpath, err := file.Download(parsedURL) - if err != nil { - return err - } + return e.runSourceExecutable(ctx, out.Run.Binary.Source) + } else if module := out.Run.Go.Module; module != "" { + return e.runGoExecutable(ctx, module) + } else { + return e.runShellExecutable(ctx, out) + } - if e.DownloadOnly { - slog.Info("Download only flag is set. Not executing the plugin") - return nil - } + return nil +} - var cmds []*exec.Cmd - if runtime.GOOS != "windows" { - cmds = append(cmds, exec.Command("chmod", "+x", binpath)) - } - cmds = append(cmds, exec.Command(binpath)) - err = runCmds(ctx, cmds, e.Environ, e.Workdir, e.Stdout, e.Stderr) - if err != nil { - return err - } - } else if module := out.Run.Go.Module; module != "" { - // if the plugin is a Go module - binpath, err := e.buildGoExecutable(ctx, module) - if err != nil { - return err - } +func (e *Execer) runSourceExecutable(ctx context.Context, source string) error { + parsedURL, err := NewMetadata(source, e.Ref).Generate() + if err != nil { + return err + } + binpath, err := file.Download(parsedURL) + if err != nil { + return err + } - if e.DownloadOnly { - slog.Info("Download only flag is set. Not executing the plugin") - return nil - } + if e.DownloadOnly { + slog.Info("Download only flag is set. Not executing the plugin") + return nil + } - slog.Debug("go run", slog.String("module", module)) - // execute the binary - cmd := exec.Command(binpath) - err = runCmds(ctx, []*exec.Cmd{cmd}, e.Environ, e.Workdir, e.Stdout, e.Stderr) - if err != nil { - return err - } - } else { - if e.DownloadOnly { - slog.Info("Download only flag is set. Not executing the plugin") - return nil - } + var cmds []*exec.Cmd + if runtime.GOOS != "windows" { + cmds = append(cmds, exec.Command("chmod", "+x", binpath)) + } + cmds = append(cmds, exec.Command(binpath)) + return runCmds(ctx, cmds, e.Environ, e.Workdir, e.Stdout, e.Stderr) +} + +func (e *Execer) runGoExecutable(ctx context.Context, module string) error { + // if the plugin is a Go module + binpath, err := e.buildGoExecutable(ctx, module) + if err != nil { + return err + } - var path, shell string - // if the bash shell does not exist fallback - // to posix shell. - switch runtime.GOOS { - case "windows": - // TODO we may want to disable profile and interactive mode - // when executing powershell scripts -noprofile -noninteractive - shell = "powershell" - path = filepath.Join(e.Source, out.Run.Pwsh.Path) - - case "linux", "darwin": - shell = "bash" - path = filepath.Join(e.Source, out.Run.Bash.Path) - - // fallback to the posix shell if bash - // is not available on the host. - if _, err := exec.LookPath("bash"); err != nil { - shell = "sh" - } + if e.DownloadOnly { + slog.Info("Download only flag is set. Not executing the plugin") + return nil + } + + slog.Debug("go run", slog.String("module", module)) + // execute the binary + cmd := exec.Command(binpath) + return runCmds(ctx, []*exec.Cmd{cmd}, e.Environ, e.Workdir, e.Stdout, e.Stderr) +} + +func (e *Execer) runShellExecutable(ctx context.Context, out *spec) error { + if e.DownloadOnly { + slog.Info("Download only flag is set. Not executing the plugin") + return nil + } + + switch runtime.GOOS { + case "windows": + // TODO we may want to disable profile and interactive mode + // when executing powershell scripts -noprofile -noninteractive + path := filepath.Join(e.Source, out.Run.Pwsh.Path) + slog.Debug("execute", slog.String("file", path)) + cmd := exec.Command("pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; %s", path) + return runCmds(ctx, []*exec.Cmd{cmd}, e.Environ, e.Workdir, e.Stdout, e.Stderr) + case "linux", "darwin": + path := filepath.Join(e.Source, out.Run.Bash.Path) + + // fallback to the posix shell if bash + // is not available on the host. + shell := "bash" + if _, err := exec.LookPath("bash"); err != nil { + shell = "sh" } slog.Debug("execute", slog.String("file", path)) - // execute the binary cmd := exec.Command(shell, path) - err = runCmds(ctx, []*exec.Cmd{cmd}, e.Environ, e.Workdir, e.Stdout, e.Stderr) - if err != nil { - return err - } + return runCmds(ctx, []*exec.Cmd{cmd}, e.Environ, e.Workdir, e.Stdout, e.Stderr) + default: + return fmt.Errorf("unsupported operating system: %s", runtime.GOOS) } - - return nil } func (e *Execer) buildGoExecutable(ctx context.Context, module string) ( From ef226b42a2b6b1d0a16e3ecede3e4d235f95e3ca Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Wed, 29 Mar 2023 13:22:15 +0530 Subject: [PATCH 5/5] Fix windows powershell script --- plugin/harness/execer.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/harness/execer.go b/plugin/harness/execer.go index b517cfb..99f0a68 100644 --- a/plugin/harness/execer.go +++ b/plugin/harness/execer.go @@ -142,7 +142,9 @@ func (e *Execer) runShellExecutable(ctx context.Context, out *spec) error { // when executing powershell scripts -noprofile -noninteractive path := filepath.Join(e.Source, out.Run.Pwsh.Path) slog.Debug("execute", slog.String("file", path)) - cmd := exec.Command("pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; %s", path) + script := fmt.Sprintf( + "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; %s", path) + cmd := exec.Command("pwsh", "-Command", script) return runCmds(ctx, []*exec.Cmd{cmd}, e.Environ, e.Workdir, e.Stdout, e.Stderr) case "linux", "darwin": path := filepath.Join(e.Source, out.Run.Bash.Path)