From 2aadfd172c01f227aaec23176e096055a2946f1b Mon Sep 17 00:00:00 2001 From: Archit Sharma Date: Wed, 20 Nov 2019 19:38:24 +0530 Subject: [PATCH 1/2] add following for new bintray dep: - json -> yaml: add yaml based config parser - add forked bintray go client as dep - godotenv mod to parse configs from .env / env vars all the same - update documentation --- .env | 8 + .gitignore | 3 + DISCUSSION.md | 37 +++++ README.md | 21 ++- go.mod | 13 +- go.sum | 103 ++++++++++-- main.go | 384 +++++++++++++------------------------------- package_config.yaml | 35 ++++ plugin.go | 283 ++++++++++++++++++++++++++++++++ utils.go | 47 ++++++ 10 files changed, 643 insertions(+), 291 deletions(-) create mode 100644 .env create mode 100644 DISCUSSION.md create mode 100644 package_config.yaml create mode 100644 plugin.go create mode 100644 utils.go diff --git a/.env b/.env new file mode 100644 index 0000000..46c8753 --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +BINTRAY_KEY=f4g8ef@***223 +BINTRAY_USER=foobar +BINTRAY_ADMIN_GPG_PASSPHRASE='F33d.e!0cE**********' +PLUGIN_BINTRAY_CFG=/opt/bintray/package_config.yaml +UPLOAD_PACKAGE=true +SIGN_PACKAGE=false +CALC_META=false +SHOW_PACKAGE=false diff --git a/.gitignore b/.gitignore index a23541d..4f7a58a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ release/ coverage.out drone-bintray + +*~ +.*~ diff --git a/DISCUSSION.md b/DISCUSSION.md new file mode 100644 index 0000000..b4be1c5 --- /dev/null +++ b/DISCUSSION.md @@ -0,0 +1,37 @@ +## Aim + +- discussion @ https://gitter.im/drone/plugins?at=5d7fd98572fe125111b77576 + +### Plugin Design + +> execute for each upload - or for multi-upload in a single step load the configuration from file. + +> best practice - a plugin with super-complex configuration should define its own configuration file +> Need to check if globs could make sense as well + +> so a plugin could support both this: + +``` +- name: upload + settings: + token: + from_secret: token + bucket: foo + files: + - bar.tar.gz + - baz.tar.gz + +OR + +- name: upload + settings: + import: path/to/file.yaml + token: + from_secret: token +``` + +### Changes required + +> old plugins required a json payload via stdin while newer plugins are simply listening to env variables. The nested array had been a poor design decision, that should be replaced by multiple calls of the bintray plugin instead. so keep the parameters as simple as possible, best would be plain types like int, float, string, boolean or slices of these simple types. + +> Execute the plugin for every different upload instead of the nested attributes diff --git a/README.md b/README.md index 57cc393..c2478ce 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,19 @@ docker build \ ```console docker run --rm \ - -e PLUGIN_USERNAME=octocat \ - -e PLUGIN_PASSWORD=p455w0rd \ - -e PLUGIN_BRANCH=master \ - -v $(pwd):$(pwd) \ - -w $(pwd) \ - plugins/bintray + -e PLUGIN_BINTRAY_USERNAME=$BINTRAY_USER \ + -e PLUGIN_BINTRAY_API_KEY=$BINTRAY_KEY \ + -e PLUGIN_BINTRAY_CFG=./package_config_new.yaml \ + -e PLUGIN_BINTRAY_GPG_PASSPHRASE=$BINTRAY_ADMIN_GPG_PASSPHRASE \ + -v $(pwd):$(pwd) \ + -w $(pwd) \ + plugins/bintray + +OR + +docker run --rm \ + --env-file .env \ + -v $(pwd):$(pwd) \ + -w $(pwd) \ + plugins/bintray ``` diff --git a/go.mod b/go.mod index 3f7dbdc..ccb25ea 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,12 @@ -module github.com/drone-plugins/drone-bintray +module github.com/arcolife/drone-bintray + +go 1.13 require ( - github.com/drone/drone-go v0.0.0-20160502151758-eaa41f7836a1 - golang.org/x/net v0.0.0-20190206195030-65e2d4e15006 // indirect - golang.org/x/oauth2 v0.0.0-20190211080642-99b60b757ec1 // indirect + github.com/arcolife/jfrog-client-go v0.6.0 + github.com/joho/godotenv v1.3.0 + github.com/pkg/errors v0.8.1 + github.com/sirupsen/logrus v1.4.2 + github.com/urfave/cli/v2 v2.0.0 + gopkg.in/yaml.v2 v2.2.7 ) diff --git a/go.sum b/go.sum index f871586..bf98fee 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,92 @@ -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/drone/drone-go v0.0.0-20160502151758-eaa41f7836a1 h1:2fZ6NZF8Z37FLn5NIElsW3OELMY2xzQ2XPuXJmnAowE= -github.com/drone/drone-go v0.0.0-20160502151758-eaa41f7836a1/go.mod h1:qVb1k1w9X5jgoGyLtbnfWNnd4XZfAwokxBmiutbpGqw= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190206195030-65e2d4e15006 h1:bx6u+jqzTwhkIPkHih58ERnKkrT2ANvYKfnvdm/9zCs= -golang.org/x/net v0.0.0-20190206195030-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/oauth2 v0.0.0-20190211080642-99b60b757ec1 h1:7PVimBH9iupN32nLnAgGqfNi/x8zoAheuTRsCNBkqjo= -golang.org/x/oauth2 v0.0.0-20190211080642-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/arcolife/jfrog-client-go v0.6.0 h1:OJ0bWwg7JMG75kaKhAfUWCWyR3/xqZntRugvODq7j3I= +github.com/arcolife/jfrog-client-go v0.6.0/go.mod h1:n7AMgu/4tmpO92TVoM69tfeNvKHi7fykZ6I8y9ZQ3OA= +github.com/buger/jsonparser v0.0.0-20180910192245-6acdf747ae99/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jfrog/gofrog v1.0.5/go.mod h1:4Caxvc8B2K1A798G1Ne+SsUICRPPre4GpgcFqj+EXJ8= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mholt/archiver v2.1.0+incompatible h1:1ivm7KAHPtPere1YDOdrY6xGdbMNGRWThZbYh5lWZT0= +github.com/mholt/archiver v2.1.0+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs= +github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pierrec/lz4 v2.3.0+incompatible h1:CZzRn4Ut9GbUkHlQ7jqBXeZQV41ZSKWFc302ZU6lUTk= +github.com/pierrec/lz4 v2.3.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= +github.com/src-d/gcfg v1.3.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= +github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg= +github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= +gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.7.0/go.mod h1:CzbUWqMn4pvmvndg3gnh5iZFmSsbhyhUWdI0IQ60AQo= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index ca86806..4f0e356 100644 --- a/main.go +++ b/main.go @@ -1,288 +1,134 @@ /* Drone plugin to upload one or more packages to Bintray. -See DOCS.md for usage. - -Author: David Tootill November 2015 (GitHub tooda02) +See README.md for usage. +Author: Archit Sharma December 2019 (Github arcolife) +Previous: David Tootill November 2015 (GitHub tooda02) */ + package main import ( - "crypto/tls" - "crypto/x509" - "encoding/json" + // "log" "fmt" - "io/ioutil" - "net/http" - "net/http/httputil" "os" - "path" - "strings" - "github.com/drone/drone-go/drone" - "github.com/drone/drone-go/plugin" + "github.com/arcolife/jfrog-client-go/utils/log" + "github.com/joho/godotenv" + "github.com/sirupsen/logrus" + "github.com/urfave/cli/v2" ) -const defaultHost = "https://api.bintray.com" - -type Bintray struct { - Username string `json:"username"` - APIKey string `json:"api_key"` - Branch string `json:"branch"` - Host string `json:"host"` - Debug bool `json:"debug"` - Insecure bool `json:"insecure"` - Artifacts []Artifact `json:"artifacts"` -} - -type Artifact struct { - File string `json:"file"` - Type string `json:"type"` - Owner string `json:"owner"` - Repository string `json:"repository"` - Artifact string `json:"package"` - Target string `json:"target"` - Distr string `json:"distr,omitempty"` - Component string `json:"component,omitempty"` - Arch []string `json:"arch,omitempty"` - Publish bool `json:"publish,omitempty"` - Override bool `json:"override,omitempty"` - Versioni interface{} `json:"version"` - Version string -} - var ( - version string - bintray Bintray + Version = "unknown" + file *os.File ) -type MessageText struct { - Message string `json:"message"` -} - func main() { - fmt.Printf("Drone Bintray Plugin built from %s\n", version) - - var workspace = drone.Workspace{} - - plugin.Param("workspace", &workspace) - plugin.Param("vargs", &bintray) - if err := plugin.Parse(); err != nil { - fmt.Printf("ERROR Can't parse yaml config: %s", err.Error()) - os.Exit(1) - } - - if bintray.Host == "" { - bintray.Host = defaultHost - } - - if bintray.Debug { - saveApikey := bintray.APIKey - bintray.APIKey = "******" - fmt.Printf("DEBUG plugin input:\n%#v\n%#v\n", workspace, bintray) - bintray.APIKey = saveApikey - } - if len(bintray.Branch) == 0 || bintray.Branch == "master" { - fmt.Printf("\nPublishing %d artifacts to Bintray for user %s\n", len(bintray.Artifacts), bintray.Username) - } else { - fmt.Printf("\nPublishing %d artifacts on branch %s to Bintray for user %s\n", len(bintray.Artifacts), bintray.Branch, bintray.Username) - } - for i, artifact := range bintray.Artifacts { - artifact.Version = fmt.Sprintf("%v", artifact.Versioni) - fmt.Printf("\nUploading file %d %s to %s\n", i+1, - artifact.File, artifact.getEndpoint()) - artifact.Upload(workspace.Path) + if filename, found := os.LookupEnv("PLUGIN_ENV_FILE"); found { + _ = godotenv.Load(filename) + } + + app := cli.NewApp() + app.Name = "bintray-uploader plugin" + app.Usage = "bintray-uploader plugin" + app.Action = run + app.Version = Version + app.Flags = []cli.Flag{ + &cli.IntFlag{ + Name: "bintray.threads,t", + Usage: "bintray threads", + EnvVars: []string{"PLUGIN_BINTRAY_THREADS", "BINTRAY_THREADS"}, + Value: 1, + }, + &cli.BoolFlag{ + Name: "bintray.cleanup,D", + Usage: "bintray cleanup", + EnvVars: []string{"PLUGIN_BINTRAY_CLEANUP", "CLEANUP"}, + Value: false, + }, + &cli.StringFlag{ + Name: "bintray.username,u", + Usage: "bintray username", + EnvVars: []string{"PLUGIN_BINTRAY_USERNAME", "USER", "USERNAME", "BINTRAY_USER"}, + }, + &cli.StringFlag{ + Name: "bintray.config,c", + Usage: "bintray config file path", + EnvVars: []string{"PLUGIN_BINTRAY_CFG", "PACKAGE_CONFIG"}, + }, + &cli.StringFlag{ + Name: "bintray.api-key", + Usage: "bintray api-key", + EnvVars: []string{"PLUGIN_BINTRAY_API_KEY", "API_KEY", "BINTRAY_KEY"}, + }, + &cli.StringFlag{ + Name: "bintray.gpg-passphrase,P", + Usage: "bintray GPG Passphrase", + EnvVars: []string{"PLUGIN_BINTRAY_GPG_PASSPHRASE", "GPG_PASSPHRASE", "BINTRAY_ADMIN_GPG_PASSPHRASE"}, + }, + &cli.BoolFlag{ + Name: "file.upload", + Usage: "upload files to package", + EnvVars: []string{"PLUGIN_BINTRAY_UPLOAD", "UPLOAD_PACKAGE"}, + Value: true, + }, + &cli.BoolFlag{ + Name: "package.sign", + Usage: "sign bintray package", + EnvVars: []string{"PLUGIN_BINTRAY_SIGN", "SIGN_PACKAGE"}, + Value: true, + }, + &cli.BoolFlag{ + Name: "package.publish", + Usage: "publish bintray package", + EnvVars: []string{"PLUGIN_BINTRAY_PUBLISH", "PUBLISH_PACKAGE"}, + Value: true, + }, + &cli.BoolFlag{ + Name: "repo.calc-metadata", + Usage: "Calculate Metadata for bintray repo", + EnvVars: []string{"PLUGIN_BINTRAY_CALC_METADATA", "CALC_META"}, + Value: true, + }, + &cli.BoolFlag{ + Name: "package.show", + Usage: "package show", + EnvVars: []string{"PLUGIN_BINTRAY_SHOW", "SHOW_PACKAGE"}, + Value: true, + }, + &cli.StringSliceFlag{ + Name: "envs", + Usage: "pass environment variable to shell script", + EnvVars: []string{"PLUGIN_ENVS", "INPUT_ENVS"}, + }, + } + + if err := app.Run(os.Args); err != nil { + logrus.Fatal(err) } } -// Upload a package to Bintray -func (this *Artifact) Upload(filename string) { - // Build file upload request - - filepath := path.Join(filename, this.File) - file, err := os.Open(filepath) - if err != nil { - fmt.Printf("Unable to open input file %s: %s\n", filepath, err.Error()) - os.Exit(1) - } - req, err := http.NewRequest("PUT", this.getEndpoint(), file) - if err != nil { - fmt.Printf("Unable to build REST request: %s\n", err.Error()) - os.Exit(1) - } - req.SetBasicAuth(bintray.Username, bintray.APIKey) - req.Header.Add("X-Bintray-Override", boolToString(this.Override)) - req.Header.Add("X-Bintray-Publish", boolToString(this.Publish)) - if this.Type == "Debian" { - this.addDebianHeaders(req) - } - - // Set up an HTTP client with a bundled root CA certificate (borrowed from Ubuntu 14.04) - // This is necessary because the required certificate is missing from the root image and - // without it the upload fails with "x509: failed to load system roots and no roots provided" - - client := http.Client{} - pool := x509.NewCertPool() - if pemCerts, err := ioutil.ReadFile("/etc/ssl/certs/ca-certificates.crt"); err != nil { - fmt.Printf("Unable to read ca-certificates.crt: %s\n", err.Error()) - os.Exit(1) - } else { - pool.AppendCertsFromPEM(pemCerts) - client.Transport = &http.Transport{ - TLSClientConfig: &tls.Config{ - RootCAs: pool, - InsecureSkipVerify: bintray.Insecure, - }, - } - } - if bintray.Debug { - dumpRequest("DEBUG HTTP Request", req) - } - - // Execute the upload request and format the response - - resp, err := client.Do(req) - if err != nil { - fmt.Printf("Upload request failed: %s\n", err.Error()) - dumpRequest("Failing request", req) - os.Exit(1) - } - defer resp.Body.Close() - respBody, err := ioutil.ReadAll(resp.Body) - if err != nil { - fmt.Printf("Unable to read request response: %s\n", err.Error()) - dumpRequest("Failing request", req) - os.Exit(1) - } - messageText := new(MessageText) - if len(respBody) > 0 { - json.Unmarshal(respBody, messageText) - } - if resp.StatusCode > 299 { - errorText := fmt.Sprintf("Error %d", resp.StatusCode) - httpErrorText := http.StatusText(resp.StatusCode) - if len(httpErrorText) > 0 { - errorText += " " + httpErrorText - } - if len(messageText.Message) > 0 { - errorText += " - " + messageText.Message - } - fmt.Printf("%s\n", errorText) - dumpRequest("Failing request", req) - os.Exit(1) - } - - if len(messageText.Message) == 0 && len(respBody) > 0 { - messageText.Message = string(respBody) - } - fmt.Printf("Result: %s\n", messageText.Message) - if messageText.Message != "success" { - if this.Override || !strings.Contains(messageText.Message, "already exists") { - dumpRequest("\nRequest was:", req) - os.Exit(1) - } - } -} - -// Add headers required to upload a Debian package -func (this *Artifact) addDebianHeaders(req *http.Request) { - if len(this.Distr) == 0 || len(this.Component) == 0 || len(this.Arch) == 0 { - fmt.Printf("ERROR Cannot process package %s - Missing Debian argument(s):\n", this.Artifact) - - if len(this.Distr) == 0 { - fmt.Printf(" distr not defined in yaml config\n") - } - - if len(this.Component) == 0 { - fmt.Printf(" component not defined in yaml config\n") - } - - if len(this.Arch) == 0 { - fmt.Printf(" arch not defined in yaml config\n") - } - - os.Exit(1) - } - - req.Header.Add("X-Bintray-Debian-Distribution", this.Distr) - req.Header.Add("X-Bintray-Debian-Component", this.Component) - req.Header.Add("X-Bintray-Debian-Architecture", strings.Join(this.Arch, ",")) -} - -// Get the Bintray endpoint corresponding to this package and version -func (this *Artifact) getEndpoint() string { - if len(this.File) == 0 || - len(this.Owner) == 0 || - len(this.Repository) == 0 || - len(this.Artifact) == 0 || - (len(this.Version) == 0 && this.Type != "Maven") || - len(this.Target) == 0 { - fmt.Printf("ERROR Cannot process package %s - Missing argument(s):\n", this.Artifact) - - if len(this.Artifact) == 0 { - fmt.Printf(" package not defined in yaml config\n") - } - - if len(this.File) == 0 { - fmt.Printf(" file not defined in yaml config\n") - } - - if len(this.Owner) == 0 { - fmt.Printf(" owner not defined in yaml config\n") - } - - if len(this.Repository) == 0 { - fmt.Printf(" repository not defined in yaml config\n") - } - - if len(this.Version) == 0 && this.Type != "Maven" { - fmt.Printf(" version not defined in yaml config\n") - } - - if len(this.Target) == 0 { - fmt.Printf(" target not defined in yaml config\n") - } - - os.Exit(1) - } - - contentType := "content" - if this.Type == "Maven" { - contentType = "maven" - } - - endpoint := fmt.Sprintf("%s/%s/%s/%s/%s/", bintray.Host, contentType, this.Owner, this.Repository, this.Artifact) - if len(this.Version) > 0 && this.Type != "Maven" { - endpoint = fmt.Sprintf("%s%s/", endpoint, this.Version) - } - if len(bintray.Branch) == 0 || bintray.Branch == "master" { - return endpoint + this.Target - } - return fmt.Sprintf("%stest/%s/%s", endpoint, bintray.Branch, this.Target) -} - -// Dump an HTTP request to stdout, hiding the authorization tag -func dumpRequest(prefix string, req *http.Request) { - fmt.Printf("%s:\n", prefix) - if dumpedRequest, err := httputil.DumpRequestOut(req, false); err != nil { - fmt.Printf(" %s\n", err.Error()) - } else { - for _, line := range strings.Split(string(dumpedRequest), "\n") { - line = strings.TrimSpace(line) - if len(line) > 0 { - if strings.HasPrefix(line, "Authorization:") { - line = "Authorization: Basic xxxxxxxxxx" - } - fmt.Printf(" %s\n", line) - } - } - } -} - -// Convert a boolean value to string "1" or "0" -func boolToString(val bool) string { - if val { - return "1" - } else { - return "0" - } +func run(c *cli.Context) error { + log.SetLogger(log.NewLogger(log.INFO, file)) + + fmt.Println("CFG Path:- ", c.String("bintray.config")) + + plugin := Plugin{ + BintrayConfig: BintrayConfig{ + Threads: c.Int("bintray.threads"), + Cleanup: c.Bool("bintray.cleanup"), + Username: c.String("bintray.username"), + APIKey: c.String("bintray.api-key"), + GPGPassphrase: c.String("bintray.gpg-passphrase"), + }, + Version: c.String("version"), + UploadPackage: c.Bool("file.upload"), + SignPackageVersion: c.Bool("package.sign"), + PublishPackage: c.Bool("package.publish"), + CalcMetadata: c.Bool("repo.calc-metadata"), + ShowPackage: c.Bool("package.show"), + BintrayConfigPath: c.String("bintray.config"), + Envs: c.StringSlice("envs"), + } + return plugin.Exec() } diff --git a/package_config.yaml b/package_config.yaml new file mode 100644 index 0000000..18a4270 --- /dev/null +++ b/package_config.yaml @@ -0,0 +1,35 @@ +# max value of threads matche GOMAXPROCS (total logical CPUs) +threads: 10 +cleanup: false + +# documentation for options +# https://www.jfrog.com/confluence/display/CLI/CLI+for+JFrog+Artifactory#CLIforJFrogArtifactory-UploadingFiles +bintray: + repos: + - name: debian + subject: arcolife + config: + repoconfigfilepath: repo_config_debian.json + + packages: + - package: CasperLabs + config: + desc: Debian packages + licenses: Apache-2.0 + vcsurl: https://github.com/CasperLabs/CasperLabs.git + githubrepo: CasperLabs/CasperLabs + publicdownloadnumbers: false + publicstats: true + upload: + params: + path: + version: v0.9.1 + publish: true + pkgdeb: bionic/main/amd64,i386 + target: ./ + # use this option when the entire path is regex + regex: false + recursive: false + file_pattern: /opt/bintray/artifacts/*.deb + # upload all under target path, without reflecting upload path hierachy + flat: true diff --git a/plugin.go b/plugin.go new file mode 100644 index 0000000..4298779 --- /dev/null +++ b/plugin.go @@ -0,0 +1,283 @@ +/* +Drone plugin to upload one or more packages to Bintray. +See README.md for usage. +Author: Archit Sharma December 2019 (Github arcolife) +Previous: David Tootill November 2015 (GitHub tooda02) +*/ + +package main + +import ( + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/arcolife/jfrog-client-go/bintray" + "github.com/arcolife/jfrog-client-go/bintray/auth" + "github.com/arcolife/jfrog-client-go/bintray/services" + "github.com/arcolife/jfrog-client-go/bintray/services/packages" + "github.com/arcolife/jfrog-client-go/bintray/services/repositories" + "github.com/arcolife/jfrog-client-go/bintray/services/versions" + "github.com/pkg/errors" + // "github.com/jfrog/jfrog-client-go/utils/io/fileutils" +) + +type ( + // Package - struct fields must be public in order for unmarshal to + // correctly populate the data. + Package struct { + Package string `yaml:"package"` + Config packages.Params `yaml:"config"` + Upload services.UploadParams `yaml:"upload"` + } + + // Repo - struct fields must be public in order for unmarshal to + // correctly populate the data. + Repo struct { + Name string `yaml:"name"` + Subject string `yaml:"subject"` + Config repositories.Config `yaml:"config"` + Packages []Package `yaml:"packages"` + } + + // Bintray - struct fields must be public in order for unmarshal to + // correctly populate the data. + Bintray struct { + Repos []Repo `yaml:"repos"` + } + + // BintrayConfig -> entrypoint for all configs + BintrayConfig struct { + Threads int `yaml:"threads"` + Cleanup bool `yaml:"cleanup"` + Bintray `yaml:"bintray"` + Username string `yaml:"username"` + APIKey string `yaml:"api_key"` + GPGPassphrase string `yaml:"gpg_passphrase"` + } + + Plugin struct { + BintrayConfig `yaml:"bintray_config"` + ServicesManager *bintray.ServicesManager + BintrayConfigPath string `yaml:"bintray_cfg_path"` + Version string `yaml:"verison"` + UploadPackage bool `yaml:"uploadpackage"` + SignPackageVersion bool `yaml:"signpackageversion"` + PublishPackage bool `yaml:"publishpackage"` + CalcMetadata bool `yaml:"calcmetadata"` + ShowPackage bool `yaml:"showpackage"` + Envs []string `yaml:"envs"` + } +) + +const defaultLicense = "Apache 2.0" + +func (p Plugin) Exec() error { + // var ( + // files []string + // ) + // fmt.Printf("Drone Bintray Plugin built from %s\n", p.Version) + cSig := make(chan os.Signal) + signal.Notify(cSig, os.Interrupt, syscall.SIGTERM) + go func() { + <-cSig + cleanup() + os.Exit(1) + }() + + if p.BintrayConfigPath != "" { + p.BintrayConfig.ReadConfig(p.BintrayConfigPath) + } + + p.ServicesManager = p.BintrayConfig.InitConfig() + + if p.BintrayConfig.Cleanup { + p.BintrayConfig.cleanup(p.ServicesManager) + p.BintrayConfig.checkDetails(p.ServicesManager) + } + + for _, repo := range p.BintrayConfig.Bintray.Repos { + for _, pack := range repo.Packages { + uploaded := 0 + if p.UploadPackage { + uploaded, _, _ = p.BintrayConfig.uploadPackage(p.ServicesManager, &repo, &pack) + } + if uploaded > 0 || p.SignPackageVersion { + p.BintrayConfig.signPackageVersion(p.ServicesManager, &repo, &pack) + } + if uploaded > 0 && pack.Upload.Publish { + p.BintrayConfig.publishPackage(p.ServicesManager, &repo, &pack) + } + if uploaded > 0 || p.CalcMetadata { + p.BintrayConfig.calcMetadata(p.ServicesManager, &repo, &pack) + } + if uploaded > 0 || p.ShowPackage { + p.BintrayConfig.showPackage(p.ServicesManager, &repo, &pack) + } + } + } + return nil +} + +// InitConfig for initializing service manager for bintray functionalities +func (config *BintrayConfig) InitConfig() *bintray.ServicesManager { + + btDetails := auth.NewBintrayDetails() + btDetails.SetUser(config.Username) + btDetails.SetKey(config.APIKey) + btDetails.SetDefPackageLicense(defaultLicense) + + serviceConfig := bintray.NewConfigBuilder(). + SetBintrayDetails(btDetails). + SetDryRun(false). + SetThreads(config.Threads). + Build() + + btManager, err := bintray.New(serviceConfig) + if err != nil { + fmt.Printf("Error: %s\n", err.Error()) + } + + return btManager +} + +func (config *BintrayConfig) deleteRepo(btManager *bintray.ServicesManager, repo *Repo) error { + fmt.Printf("\nDeleting Repo.. [%s]\n", repo.Name) + repoPath := repositories.Path{Subject: repo.Subject, Repo: repo.Name} + return errors.Wrap(btManager.ExecDeleteRepoRest(&repoPath), "Repo non-existent") +} + +func (config *BintrayConfig) deletePackage(btManager *bintray.ServicesManager, repo *Repo, pack *Package) error { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + fmt.Printf("\nDeleting Package.. [%s]\n", pkg) + packagePath, _ := packages.CreatePath(pkg) + return errors.Wrap(btManager.DeletePackage(packagePath), "Package non-existent") +} + +func (config *BintrayConfig) createRepo(btManager *bintray.ServicesManager, repo *Repo) (bool, error) { + repoPath := repositories.Path{Subject: repo.Subject, Repo: repo.Name} + return btManager.CreateReposIfNeeded(&repoPath, &repo.Config, repo.Config.RepoConfigFilePath) +} + +func (config *BintrayConfig) createPackage(btManager *bintray.ServicesManager, repo *Repo, pack *Package) error { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + pack.Config.Path, _ = packages.CreatePath(pkg) + return btManager.CreatePackage(&pack.Config) +} + +func (config *BintrayConfig) publishPackage(btManager *bintray.ServicesManager, repo *Repo, pack *Package) error { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + fmt.Printf("\nPublishing GPG Signatures.. [%s]", pkg) + versionPathString := fmt.Sprintf("%s/%s", pkg, pack.Upload.Version) + versionPath, _ := versions.CreatePath(versionPathString) + err := btManager.PublishVersion(versionPath) + if err != nil { + fmt.Println("ERROR: ", err) + } + return err +} + +func (config *BintrayConfig) uploadPackage(btManager *bintray.ServicesManager, repo *Repo, pack *Package) (totalUploaded, totalFailed int, err error) { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + fmt.Printf("\nUploading Files to Package [%s] with Publish: [%t]\n", pkg, pack.Upload.Publish) + versionPath := fmt.Sprintf("%s/%s", pkg, pack.Upload.Version) + pack.Upload.Path, _ = versions.CreatePath(versionPath) + PrettyPrint(&pack, "Package") + totalUploaded, totalFailed, err = btManager.UploadFiles(&pack.Upload) + fmt.Println("UPLOADED", totalUploaded) + fmt.Println("FAILED: ", totalFailed) + if err != nil { + fmt.Println("ERROR: ", err) + } + return totalUploaded, totalFailed, err +} + +func (config *BintrayConfig) signPackageVersion(btManager *bintray.ServicesManager, repo *Repo, pack *Package) error { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + fmt.Printf("\nSigning versioned Package files.. [%s]", pkg) + versionPath := fmt.Sprintf("%s/%s", pkg, pack.Upload.Version) + path, _ := versions.CreatePath(versionPath) + err := btManager.GpgSignVersion(path, config.GPGPassphrase) + if err != nil { + fmt.Println(err) + } + return err +} + +func (config *BintrayConfig) calcMetadata(btManager *bintray.ServicesManager, repo *Repo, pack *Package) bool { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + fmt.Printf("\nScheduling metadata calculation.. [%s]\n", pkg) + versionPath := fmt.Sprintf("%s/%s", pkg, pack.Upload.Version) + path, _ := versions.CreatePath(versionPath) + scheduledOk, err := btManager.CalcMetadata(path) + if err != nil { + fmt.Println("ERROR: ", err) + } + return scheduledOk +} + +func (config *BintrayConfig) showPackage(btManager *bintray.ServicesManager, repo *Repo, pack *Package) error { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + fmt.Printf("\nPackage details.. [%s]", pkg) + pkgPath, _ := packages.CreatePath(pkg) + err := btManager.ShowPackage(pkgPath) + if err != nil { + fmt.Println(err) + } + return err +} + +func (config *BintrayConfig) checkDetails(btManager *bintray.ServicesManager) { + var err error + for _, repo := range config.Bintray.Repos { + for _, pack := range repo.Packages { + pkg := fmt.Sprintf("%s/%s/%s", repo.Subject, repo.Name, pack.Package) + fmt.Printf("\nChecking details.. [%s]", pkg) + + // Repository + RepoExistsOk, _ := btManager.IsRepoExists(&repositories.Path{Subject: repo.Subject, Repo: repo.Name}) + repoPath := fmt.Sprintf("%s/%s", repo.Subject, repo.Name) + if RepoExistsOk != true { + fmt.Printf("\nRepo does not exist.. [%s]", repoPath) + fmt.Printf("\nCreating Repo..") + _, err = config.createRepo(btManager, &repo) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } else { + fmt.Printf("\nRepo already exists.. [%s]", repoPath) + } + + // Package + pkgPath, _ := packages.CreatePath(pkg) + PackageExistsOk, _ := btManager.IsPackageExists(pkgPath) + if PackageExistsOk != true { + fmt.Printf("\nPackage [%s] does not exist", pkg) + fmt.Printf("\nCreating Package..\n") + err = config.createPackage(btManager, &repo, &pack) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } else { + fmt.Printf("\nPackage already exists.. [%s]\n", pkg) + } + } + } +} + +func (config *BintrayConfig) cleanup(btManager *bintray.ServicesManager) { + var err error + for _, repo := range config.Bintray.Repos { + for _, pack := range repo.Packages { + err = config.deletePackage(btManager, &repo, &pack) + if err != nil { + fmt.Print(err) + } else { + config.deleteRepo(btManager, &repo) + } + } + } +} diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..3d1e585 --- /dev/null +++ b/utils.go @@ -0,0 +1,47 @@ +/* +Drone plugin to upload one or more packages to Bintray. +See README.md for usage. +Author: Archit Sharma December 2019 (Github arcolife) +Previous: David Tootill November 2015 (GitHub tooda02) +*/ + +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + + "github.com/pkg/errors" + "gopkg.in/yaml.v2" +) + +// PrettyPrint to print a struct like JSON +func PrettyPrint(v interface{}, label string) (err error) { + fmt.Println(label, "=>") + b, err := json.MarshalIndent(v, "", " ") + if err == nil { + fmt.Println(string(b)) + } + return +} + +// ReadConfig to UnMarshall tunables and settings from YAML file +func (config *BintrayConfig) ReadConfig(cfgPath string) { + configdata, err := ioutil.ReadFile(cfgPath) + if err != nil { + fmt.Print(errors.Wrap(err, "Error reading file")) + os.Exit(1) + } + + err = yaml.Unmarshal(configdata, &config) + if err != nil { + fmt.Print(errors.Wrap(err, "Error Unmarshalling file")) + os.Exit(1) + } +} + +func cleanup() { + fmt.Printf("\nAborting. Caught a signal fron os.Interrupt\n") +} From 8cc856499235a5d3b37e89da976ba6342589d94c Mon Sep 17 00:00:00 2001 From: Archit Sharma Date: Mon, 10 Feb 2020 19:35:46 +0530 Subject: [PATCH 2/2] fix env var issues --- examples/dot-env | 8 +++++++ .../package_config.yaml | 0 examples/repo_config_debian.json | 10 +++++++++ examples/repo_config_rpm.json | 12 +++++++++++ main.go | 2 +- plugin.go | 21 ++++++++++++++----- utils.go | 10 +++++++++ 7 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 examples/dot-env rename package_config.yaml => examples/package_config.yaml (100%) create mode 100644 examples/repo_config_debian.json create mode 100644 examples/repo_config_rpm.json diff --git a/examples/dot-env b/examples/dot-env new file mode 100644 index 0000000..46c8753 --- /dev/null +++ b/examples/dot-env @@ -0,0 +1,8 @@ +BINTRAY_KEY=f4g8ef@***223 +BINTRAY_USER=foobar +BINTRAY_ADMIN_GPG_PASSPHRASE='F33d.e!0cE**********' +PLUGIN_BINTRAY_CFG=/opt/bintray/package_config.yaml +UPLOAD_PACKAGE=true +SIGN_PACKAGE=false +CALC_META=false +SHOW_PACKAGE=false diff --git a/package_config.yaml b/examples/package_config.yaml similarity index 100% rename from package_config.yaml rename to examples/package_config.yaml diff --git a/examples/repo_config_debian.json b/examples/repo_config_debian.json new file mode 100644 index 0000000..c8a099e --- /dev/null +++ b/examples/repo_config_debian.json @@ -0,0 +1,10 @@ +{ + "name": "debian", + "type": "debian", + "private": false, + "desc": "This repo is for CasperLabs debian packages", + "labels":["casperlabs", "debian"], + "gpg_sign_metadata": false, + "gpg_sign_files":false, + "gpg_use_owner_key":false, +} diff --git a/examples/repo_config_rpm.json b/examples/repo_config_rpm.json new file mode 100644 index 0000000..b4baef5 --- /dev/null +++ b/examples/repo_config_rpm.json @@ -0,0 +1,12 @@ +{ + "name": "rpm", + "type": "rpm", + "private": false, + "desc": "This repo is for CasperLabs debian packages", + "labels":["casperlabs", "rpm"], + "gpg_sign_metadata": false, + "gpg_sign_files":false, + "gpg_use_owner_key":false, + "yum_metadata_depth": 0, + "yum_groups_file": "" +} diff --git a/main.go b/main.go index 4f0e356..d616aeb 100644 --- a/main.go +++ b/main.go @@ -116,13 +116,13 @@ func run(c *cli.Context) error { plugin := Plugin{ BintrayConfig: BintrayConfig{ Threads: c.Int("bintray.threads"), - Cleanup: c.Bool("bintray.cleanup"), Username: c.String("bintray.username"), APIKey: c.String("bintray.api-key"), GPGPassphrase: c.String("bintray.gpg-passphrase"), }, Version: c.String("version"), UploadPackage: c.Bool("file.upload"), + Cleanup: c.Bool("bintray.cleanup"), SignPackageVersion: c.Bool("package.sign"), PublishPackage: c.Bool("package.publish"), CalcMetadata: c.Bool("repo.calc-metadata"), diff --git a/plugin.go b/plugin.go index 4298779..1b31730 100644 --- a/plugin.go +++ b/plugin.go @@ -62,6 +62,7 @@ type ( ServicesManager *bintray.ServicesManager BintrayConfigPath string `yaml:"bintray_cfg_path"` Version string `yaml:"verison"` + Cleanup bool `yaml:"cleanup"` UploadPackage bool `yaml:"uploadpackage"` SignPackageVersion bool `yaml:"signpackageversion"` PublishPackage bool `yaml:"publishpackage"` @@ -92,7 +93,8 @@ func (p Plugin) Exec() error { p.ServicesManager = p.BintrayConfig.InitConfig() - if p.BintrayConfig.Cleanup { + if p.BintrayConfig.Cleanup || p.Cleanup { + fmt.Printf("\nCleaning up") p.BintrayConfig.cleanup(p.ServicesManager) p.BintrayConfig.checkDetails(p.ServicesManager) } @@ -106,7 +108,7 @@ func (p Plugin) Exec() error { if uploaded > 0 || p.SignPackageVersion { p.BintrayConfig.signPackageVersion(p.ServicesManager, &repo, &pack) } - if uploaded > 0 && pack.Upload.Publish { + if uploaded > 0 || (pack.Upload.Publish && p.PublishPackage) { p.BintrayConfig.publishPackage(p.ServicesManager, &repo, &pack) } if uploaded > 0 || p.CalcMetadata { @@ -124,6 +126,8 @@ func (p Plugin) Exec() error { func (config *BintrayConfig) InitConfig() *bintray.ServicesManager { btDetails := auth.NewBintrayDetails() + btDetails.SetApiUrl("https://api.bintray.com/") + fmt.Printf("API url: [%s]\n", btDetails.GetApiUrl()) btDetails.SetUser(config.Username) btDetails.SetKey(config.APIKey) btDetails.SetDefPackageLicense(defaultLicense) @@ -155,9 +159,16 @@ func (config *BintrayConfig) deletePackage(btManager *bintray.ServicesManager, r return errors.Wrap(btManager.DeletePackage(packagePath), "Package non-existent") } -func (config *BintrayConfig) createRepo(btManager *bintray.ServicesManager, repo *Repo) (bool, error) { +func (config *BintrayConfig) createRepo(btManager *bintray.ServicesManager, repo *Repo) error { + var err error + var existsOk bool + repoPath := repositories.Path{Subject: repo.Subject, Repo: repo.Name} - return btManager.CreateReposIfNeeded(&repoPath, &repo.Config, repo.Config.RepoConfigFilePath) + existsOk, err = btManager.CreateReposIfNeeded(&repoPath, &repo.Config, repo.Config.RepoConfigFilePath) + if existsOk == true && err == nil { + fmt.Println("Success") + } + return errors.Wrap(err, "RepoConfigFilePath non-existent") } func (config *BintrayConfig) createPackage(btManager *bintray.ServicesManager, repo *Repo, pack *Package) error { @@ -241,7 +252,7 @@ func (config *BintrayConfig) checkDetails(btManager *bintray.ServicesManager) { if RepoExistsOk != true { fmt.Printf("\nRepo does not exist.. [%s]", repoPath) fmt.Printf("\nCreating Repo..") - _, err = config.createRepo(btManager, &repo) + err = config.createRepo(btManager, &repo) if err != nil { fmt.Println(err) os.Exit(1) diff --git a/utils.go b/utils.go index 3d1e585..80139b6 100644 --- a/utils.go +++ b/utils.go @@ -45,3 +45,13 @@ func (config *BintrayConfig) ReadConfig(cfgPath string) { func cleanup() { fmt.Printf("\nAborting. Caught a signal fron os.Interrupt\n") } + +// fileExists checks if a file exists and is not a directory before we +// try using it to prevent further errors. +func fileExists(filename string) bool { + info, err := os.Stat(filename) + if os.IsNotExist(err) { + return false + } + return !info.IsDir() +}