From 9be18f54734217558f0eae7261b1f36e977b5523 Mon Sep 17 00:00:00 2001 From: Don Date: Tue, 19 May 2020 11:37:54 -0700 Subject: [PATCH 01/14] Remove old plugin code --- .drone.sec | 1 - .drone.yml | 36 --------- .gitignore | 2 - DOCS.md | 28 ------- Dockerfile | 23 ------ LICENSE | 201 -------------------------------------------------- MAINTAINERS | 46 ------------ Makefile | 14 ---- index.js | 82 -------------------- logo.svg | 144 ------------------------------------ package.json | 25 ------- renovate.json | 13 ---- 12 files changed, 615 deletions(-) delete mode 100644 .drone.sec delete mode 100644 .drone.yml delete mode 100644 .gitignore delete mode 100644 DOCS.md delete mode 100644 Dockerfile delete mode 100644 LICENSE delete mode 100644 MAINTAINERS delete mode 100644 Makefile delete mode 100644 index.js delete mode 100644 logo.svg delete mode 100644 package.json delete mode 100644 renovate.json diff --git a/.drone.sec b/.drone.sec deleted file mode 100644 index 3d9ec90..0000000 --- a/.drone.sec +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.NgmTjpX8KTXg8d46V6rGUUYHhs-VKWUtBzWXcT2z8erxS4lPzi4kvM1KxDP_ZV1WOlXXZRnHyE-qBNr9tyt2SDbLqUi4tAjievKarihQ6ECXDX_Kpdow1_Zo96P9X5s8g9N0bxaev2v17_i0zvk14eL72I8PLQY_9sZLuqDI-862zqFv_LvMaGbKWawhCj4EYpm8qXY6WkVounc8akQOCe2LfYlpSFSKK6O9mOP1IuaUuLNSRama0oAFFkZo8xZWB6vYM39hHtvps1LBdKi21hwWOpKER8U7i1YMxhTBoDSn357_-smyITPPhB4B0CL3TQp117CkFBg1LrNpYhuYPA.Fy281xlLnP6AqOgd.FLEy00qJShp8F2gNEFlhUFz_WAy3bUizhE9Gwf0OFnXmepwUgmFGtTusp9BXlBqbT-ufToJkqmezD0cyGRtvhD1b1WeRUWCIyWi7JJI2XSZNi7JeGztezb-5kFLZ82b0nmZs8F3-1jsDPmrzS9nUOjEme2qxhIrILodSKazrT1J4lKAyVbpfwbl1JYFz1neF6RXOEelXIxjTRb_Y1sCXKFWwXx9009K8SwXdizpF.Gv_srOzRrGYgLajQf-sG3g \ No newline at end of file diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 4b05258..0000000 --- a/.drone.yml +++ /dev/null @@ -1,36 +0,0 @@ -build: - image: node:4.2 - commands: - - make install - - make test - -publish: - coverage: - # Must match parts of the absolute path - include: drone-nuget/coverage/lcov.info - when: - branch: master - docker: - username: $$DOCKER_USER - password: $$DOCKER_PASS - email: $$DOCKER_EMAIL - repo: plugins/drone-nuget - tag: latest - when: - branch: master - docker: - username: $$DOCKER_USER - password: $$DOCKER_PASS - email: $$DOCKER_EMAIL - repo: plugins/drone-nuget - tag: develop - when: - branch: develop - -plugin: - name: NuGet - desc: Publish files and artifacts to NuGet repository - type: publish - image: plugins/drone-nuget - labels: - - nuget diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 25fbf5a..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -coverage/ diff --git a/DOCS.md b/DOCS.md deleted file mode 100644 index b26eff8..0000000 --- a/DOCS.md +++ /dev/null @@ -1,28 +0,0 @@ -Use this plugin to publish artifacts from the build to a NuGet Repository -You can override the default configuration with the following parameters: - -* `source` - NuGet Repository URL -* `api_key` - Api Key used for authentication -* `verbosity` - NuGet output verbosity, default to 'quiet'. Accept: normal, quiet or detailed -* `files` - List of files to upload - -All file paths must be relative to current project sources - -## Example - -The following is a sample configuration in your .drone.yml file: - -```yaml -publish: - nuget: - source: http://nuget.company.com - api_key: - files: - - *.nupkg -``` - -## .nuspec / .nupkg - -If a file to upload does have ```.nuspec``` extension, the __nuget pack__ command is called before a push - -If a file to upload does have ```.nupkg``` extension, it is pushed directly diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 877db12..0000000 --- a/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM alpine:3.3 - -RUN echo "@testing http://dl-4.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories - -RUN apk update && \ - apk add \ - ca-certificates \ - nodejs \ - mono@testing && \ - rm -rf \ - /var/cache/apk/* - -RUN mkdir -p /usr/lib/nuget && \ - wget \ - https://dist.nuget.org/win-x86-commandline/v2.8.6/nuget.exe \ - -O /usr/lib/nuget/NuGet.exe - -WORKDIR /node -ADD package.json /node/ -ADD index.js /node/ -RUN npm install --production - -ENTRYPOINT ["node", "index.js"] diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8dada3e..0000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/MAINTAINERS b/MAINTAINERS deleted file mode 100644 index 0ecaf19..0000000 --- a/MAINTAINERS +++ /dev/null @@ -1,46 +0,0 @@ -[people] - [people.bradrydzewski] - name = "Brad Rydzewski" - email = "brad@drone.io" - login = "bradrydzewski" - [people.Bugagazavr] - name = "Kirill" - email = "" - login = "Bugagazavr" - [people.donny-dont] - name = "Don Olmstead" - email = "donny-dont@gmail.com" - login = "donny-dont" - [people.jackspirou] - name = "Jack Spirou" - email = "" - login = "jackspirou" - [people.msteinert] - name = "Mike Steinert" - email = "" - login = "msteinert" - [people.nlf] - name = "Nathan LaFreniere" - email = "" - login = "nlf" - [people.tboerger] - name = "Thomas Boerger" - email = "thomas@webhippie.de" - login = "tboerger" - [people.athieriot] - name = "Aurélien Thieriot" - email = "a.thieriot@gmail.com" - login = "athieriot" - -[org] - [org.core] - people = [ - "bradrydzewski", - "Bugagazavr", - "donny-dont", - "jackspirou", - "msteinert", - "nlf", - "tboerger", - "athieriot" - ] diff --git a/Makefile b/Makefile deleted file mode 100644 index 39840a2..0000000 --- a/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -.PHONY: all install test docker - -IMAGE ?= plugins/drone-nuget - -all: install test - -install: - npm install --quiet - -test: - @echo "Currently we don't provide test cases!" - -docker: - docker build --rm -t $(IMAGE) . diff --git a/index.js b/index.js deleted file mode 100644 index 81aafe5..0000000 --- a/index.js +++ /dev/null @@ -1,82 +0,0 @@ -const Drone = require('drone-node'); -const plugin = new Drone.Plugin(); - -const Nuget = require('nuget-runner'); - -const path = require('path'); -const shelljs = require('shelljs'); - -const do_push = function (nuget, workspace, vargs, file) { - var relative_path = path.relative('.', file); - - console.log('Start pushing ' + file); - nuget.push(relative_path, { - source: vargs.source - }).then(function (stdout) { - - console.log('Successfully pushed ' + file); - }).catch(function (err) { - - console.log('An error happened while pushing: ' + err); - }); -} - -const do_pack_then_push = function (nuget, workspace, vargs, file) { - - console.log('Start packing ' + file); - nuget.pack({ - spec: file, - outputDirectory: path.dirname(file) - }).then(function(stdout) { - console.log('Successfully packed ' + file); - var package_path = file.replace('.nuspec', '*.nupkg') - var resolved_package_file = shelljs.ls(package_path) - - do_push(nuget, workspace, vargs, resolved_package_file[0]); - - }).catch(function (err) { - console.log('An error happened while packing: ' + err); - }); -} - -const do_upload = function (workspace, vargs) { - if (vargs.source) { - - var nuget = new Nuget({ - apiKey: vargs.api_key, - verbosity: vargs.verbosity, - nugetPath: '/usr/lib/nuget/NuGet.exe' - }); - - var resolved_files = [].concat.apply([], vargs.files.map((f) => { return shelljs.ls(workspace.path + '/' + f); })); - resolved_files.forEach((file) => { - - if (path.extname(file) === '.nuspec') { - do_pack_then_push(nuget, workspace, vargs, file); - } else { - do_push(nuget, workspace, vargs, file); - } - }); - } else { - console.log("Parameter missing: NuGet source URL"); - process.exit(1) - } -} - -plugin.parse().then((params) => { - - // gets build and repository information for - // the current running build - const build = params.build; - const repo = params.repo; - const workspace = params.workspace; - - // gets plugin-specific parameters defined in - // the .drone.yml file - const vargs = params.vargs; - - vargs.verbosity || (vargs.verbosity = 'quiet'); - vargs.files || (vargs.files = []); - - do_upload(workspace, vargs); -}); diff --git a/logo.svg b/logo.svg deleted file mode 100644 index f9f735a..0000000 --- a/logo.svg +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - NuGet logo - - - - - - - - - - - - - - diff --git a/package.json b/package.json deleted file mode 100644 index 0d555f0..0000000 --- a/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "drone-nuget", - "version": "1.0.0", - "description": "Drone plugin to publish files and artifacts to NuGet repository", - "main": "index.js", - "repository": { - "type": "git", - "url": "https://github.com/drone-plugins/drone-nuget.git" - }, - "keywords": [ - "drone", - "nuget" - ], - "author": "Aurélien Thieriot", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/drone-plugins/drone-nuget/issues" - }, - "homepage": "https://github.com/drone-plugins/drone-nuget#README.md", - "dependencies": { - "drone-node": "^1.0.1", - "nuget-runner": "^0.1.7", - "shelljs": "^0.5.3" - } -} diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 9980624..0000000 --- a/renovate.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": [ - "config:base" - ], - "docker": { - "fileMatch": [ - "/docker/Dockerfile" - ] - }, - "labels": [ - "renovate" - ] -} From fe0207032558bbbc0dfe868ae0c7b92f83022511 Mon Sep 17 00:00:00 2001 From: Don Date: Tue, 19 May 2020 12:04:04 -0700 Subject: [PATCH 02/14] Create from boilr plugin --- .dockerignore | 2 + .drone.star | 357 +++++++++++++++++++++++++++++++++ .gitignore | 5 + LICENSE | 201 +++++++++++++++++++ cmd/drone-nuget/config.go | 18 ++ cmd/drone-nuget/main.go | 64 ++++++ docker/Dockerfile.linux.amd64 | 9 + docker/Dockerfile.linux.arm | 9 + docker/Dockerfile.linux.arm64 | 9 + docker/Dockerfile.windows.1809 | 10 + docker/Dockerfile.windows.1903 | 10 + docker/Dockerfile.windows.1909 | 10 + docker/Dockerfile.windows.2004 | 10 + docker/manifest.tmpl | 44 ++++ go.mod | 8 + go.sum | 25 +++ plugin/impl.go | 23 +++ plugin/impl_test.go | 18 ++ plugin/plugin.go | 26 +++ plugin/plugin_test.go | 14 ++ 20 files changed, 872 insertions(+) create mode 100644 .dockerignore create mode 100644 .drone.star create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 cmd/drone-nuget/config.go create mode 100644 cmd/drone-nuget/main.go create mode 100644 docker/Dockerfile.linux.amd64 create mode 100644 docker/Dockerfile.linux.arm create mode 100644 docker/Dockerfile.linux.arm64 create mode 100644 docker/Dockerfile.windows.1809 create mode 100644 docker/Dockerfile.windows.1903 create mode 100644 docker/Dockerfile.windows.1909 create mode 100644 docker/Dockerfile.windows.2004 create mode 100644 docker/manifest.tmpl create mode 100644 go.mod create mode 100644 go.sum create mode 100644 plugin/impl.go create mode 100644 plugin/impl_test.go create mode 100644 plugin/plugin.go create mode 100644 plugin/plugin_test.go diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c13ca3f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +* +!release/ diff --git a/.drone.star b/.drone.star new file mode 100644 index 0000000..a14650c --- /dev/null +++ b/.drone.star @@ -0,0 +1,357 @@ +def main(ctx): + before = testing(ctx) + + stages = [ + linux(ctx, 'amd64'), + linux(ctx, 'arm64'), + linux(ctx, 'arm'), + windows(ctx, '1903'), + windows(ctx, '1809'), + ] + + after = manifest(ctx) + gitter(ctx) + + for b in before: + for s in stages: + s['depends_on'].append(b['name']) + + for s in stages: + for a in after: + a['depends_on'].append(s['name']) + + return before + stages + after + +def testing(ctx): + return [{ + 'kind': 'pipeline', + 'type': 'docker', + 'name': 'testing', + 'platform': { + 'os': 'linux', + 'arch': 'amd64', + }, + 'steps': [ + { + 'name': 'staticcheck', + 'image': 'golang:1.13', + 'pull': 'always', + 'commands': [ + 'go run honnef.co/go/tools/cmd/staticcheck ./...', + ], + 'volumes': [ + { + 'name': 'gopath', + 'path': '/go', + }, + ], + }, + { + 'name': 'lint', + 'image': 'golang:1.13', + 'pull': 'always', + 'commands': [ + 'go run golang.org/x/lint/golint -set_exit_status ./...', + ], + 'volumes': [ + { + 'name': 'gopath', + 'path': '/go', + }, + ], + }, + { + 'name': 'vet', + 'image': 'golang:1.13', + 'pull': 'always', + 'commands': [ + 'go vet ./...', + ], + 'volumes': [ + { + 'name': 'gopath', + 'path': '/go', + }, + ], + }, + { + 'name': 'test', + 'image': 'golang:1.13', + 'pull': 'always', + 'commands': [ + 'go test -cover ./...', + ], + 'volumes': [ + { + 'name': 'gopath', + 'path': '/go', + }, + ], + }, + ], + 'volumes': [ + { + 'name': 'gopath', + 'temp': {}, + }, + ], + 'trigger': { + 'ref': [ + 'refs/heads/master', + 'refs/tags/**', + 'refs/pull/**', + ], + }, + }] + +def linux(ctx, arch): + docker = { + 'dockerfile': 'docker/Dockerfile.linux.%s' % (arch), + 'repo': 'plugins/nuget', + 'username': { + 'from_secret': 'docker_username', + }, + 'password': { + 'from_secret': 'docker_password', + }, + } + + if ctx.build.event == 'pull_request': + docker.update({ + 'dry_run': True, + 'tags': 'linux-%s' % (arch), + }) + else: + docker.update({ + 'auto_tag': True, + 'auto_tag_suffix': 'linux-%s' % (arch), + }) + + if ctx.build.event == 'tag': + build = [ + 'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/linux/%s/drone-nuget ./cmd/drone-nuget' % (ctx.build.ref.replace("refs/tags/v", ""), arch), + ] + else: + build = [ + 'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/linux/%s/drone-nuget ./cmd/drone-nuget' % (ctx.build.commit[0:8], arch), + ] + + return { + 'kind': 'pipeline', + 'type': 'docker', + 'name': 'linux-%s' % (arch), + 'platform': { + 'os': 'linux', + 'arch': arch, + }, + 'steps': [ + { + 'name': 'environment', + 'image': 'golang:1.13', + 'pull': 'always', + 'environment': { + 'CGO_ENABLED': '0', + }, + 'commands': [ + 'go version', + 'go env', + ], + }, + { + 'name': 'build', + 'image': 'golang:1.13', + 'pull': 'always', + 'environment': { + 'CGO_ENABLED': '0', + }, + 'commands': build, + }, + { + 'name': 'executable', + 'image': 'golang:1.13', + 'pull': 'always', + 'commands': [ + './release/linux/%s/drone-nuget --help' % (arch), + ], + }, + { + 'name': 'docker', + 'image': 'plugins/docker', + 'pull': 'always', + 'settings': docker, + }, + ], + 'depends_on': [], + 'trigger': { + 'ref': [ + 'refs/heads/master', + 'refs/tags/**', + 'refs/pull/**', + ], + }, + } + +def windows(ctx, version): + docker = [ + 'echo $env:PASSWORD | docker login --username $env:USERNAME --password-stdin', + ] + + if ctx.build.event == 'tag': + build = [ + 'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/windows/amd64/drone-nuget.exe ./cmd/drone-nuget' % (ctx.build.ref.replace("refs/tags/v", "")), + ] + + docker = docker + [ + 'docker build --pull -f docker/Dockerfile.windows.%s -t plugins/nuget:%s-windows-%s-amd64 .' % (version, ctx.build.ref.replace("refs/tags/v", ""), version), + 'docker run --rm plugins/nuget:%s-windows-%s-amd64 --help' % (ctx.build.ref.replace("refs/tags/v", ""), version), + 'docker push plugins/nuget:%s-windows-%s-amd64' % (ctx.build.ref.replace("refs/tags/v", ""), version), + ] + else: + build = [ + 'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/windows/amd64/drone-nuget.exe ./cmd/drone-nuget' % (ctx.build.commit[0:8]), + ] + + docker = docker + [ + 'docker build --pull -f docker/Dockerfile.windows.%s -t plugins/nuget:windows-%s-amd64 .' % (version, version), + 'docker run --rm plugins/nuget:windows-%s-amd64 --help' % (version), + 'docker push plugins/nuget:windows-%s-amd64' % (version), + ] + + return { + 'kind': 'pipeline', + 'type': 'ssh', + 'name': 'windows-%s' % (version), + 'platform': { + 'os': 'windows', + }, + 'server': { + 'host': { + 'from_secret': 'windows_server_%s' % (version), + }, + 'user': { + 'from_secret': 'windows_username', + }, + 'password': { + 'from_secret': 'windows_password', + }, + }, + 'steps': [ + { + 'name': 'environment', + 'environment': { + 'CGO_ENABLED': '0', + }, + 'commands': [ + 'go version', + 'go env', + ], + }, + { + 'name': 'build', + 'environment': { + 'CGO_ENABLED': '0', + }, + 'commands': build, + }, + { + 'name': 'executable', + 'commands': [ + './release/windows/amd64/drone-nuget.exe --help', + ], + }, + { + 'name': 'docker', + 'environment': { + 'USERNAME': { + 'from_secret': 'docker_username', + }, + 'PASSWORD': { + 'from_secret': 'docker_password', + }, + }, + 'commands': docker, + }, + ], + 'depends_on': [], + 'trigger': { + 'ref': [ + 'refs/heads/master', + 'refs/tags/**', + ], + }, + } + +def manifest(ctx): + return [{ + 'kind': 'pipeline', + 'type': 'docker', + 'name': 'manifest', + 'steps': [ + { + 'name': 'manifest', + 'image': 'plugins/manifest', + 'pull': 'always', + 'settings': { + 'auto_tag': 'true', + 'username': { + 'from_secret': 'docker_username', + }, + 'password': { + 'from_secret': 'docker_password', + }, + 'spec': 'docker/manifest.tmpl', + 'ignore_missing': 'true', + }, + }, + { + 'name': 'microbadger', + 'image': 'plugins/webhook', + 'pull': 'always', + 'settings': { + 'urls': { + 'from_secret': 'microbadger_url', + }, + }, + }, + ], + 'depends_on': [], + 'trigger': { + 'ref': [ + 'refs/heads/master', + 'refs/tags/**', + ], + }, + }] + +def gitter(ctx): + return [{ + 'kind': 'pipeline', + 'type': 'docker', + 'name': 'gitter', + 'clone': { + 'disable': True, + }, + 'steps': [ + { + 'name': 'gitter', + 'image': 'plugins/gitter', + 'pull': 'always', + 'settings': { + 'webhook': { + 'from_secret': 'gitter_webhook', + } + }, + }, + ], + 'depends_on': [ + 'manifest', + ], + 'trigger': { + 'ref': [ + 'refs/heads/master', + 'refs/tags/**', + ], + 'status': [ + 'failure', + ], + }, + }] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cd50026 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/release/ +/drone-nuget* + +coverage.out +.drone.yml diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/cmd/drone-nuget/config.go b/cmd/drone-nuget/config.go new file mode 100644 index 0000000..4ce154e --- /dev/null +++ b/cmd/drone-nuget/config.go @@ -0,0 +1,18 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package main + +import ( + "github.com/drone-plugins/drone-nuget/plugin" + "github.com/urfave/cli/v2" +) + +// settingsFlags has the cli.Flags for the plugin.Settings. +func settingsFlags(settings *plugin.Settings) []cli.Flag { + // Replace below with all the flags required for the plugin. + // Use Destination within the cli.Flags to populate settings + return []cli.Flag{} +} diff --git a/cmd/drone-nuget/main.go b/cmd/drone-nuget/main.go new file mode 100644 index 0000000..f4009b4 --- /dev/null +++ b/cmd/drone-nuget/main.go @@ -0,0 +1,64 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +// DO NOT MODIFY THIS FILE DIRECTLY + +package main + +import ( + "os" + + "github.com/drone-plugins/drone-nuget/plugin" + "github.com/drone-plugins/drone-plugin-lib/errors" + "github.com/drone-plugins/drone-plugin-lib/urfave" + "github.com/urfave/cli/v2" +) + +var version = "unknown" + +func main() { + app := cli.NewApp() + app.Name = "drone-nuget" + app.Usage = "pushes a package to a nuget repository" + app.Version = version + + settings := plugin.Settings{} + app.Flags = append(settingsFlags(&settings), urfave.Flags()...) + app.Action = run(&settings) + + if err := app.Run(os.Args); err != nil { + errors.HandleExit(err) + } +} + +func run(settings *plugin.Settings) cli.ActionFunc { + return func(ctx *cli.Context) error { + urfave.LoggingFromContext(ctx) + + plugin := plugin.New( + *settings, + urfave.PipelineFromContext(ctx), + urfave.NetworkFromContext(ctx), + ) + + if err := plugin.Validate(); err != nil { + if e, ok := err.(errors.ExitCoder); ok { + return e + } + + return errors.ExitMessagef("validation failed: %w", err) + } + + if err := plugin.Execute(); err != nil { + if e, ok := err.(errors.ExitCoder); ok { + return e + } + + return errors.ExitMessagef("execution failed: %w", err) + } + + return nil + } +} diff --git a/docker/Dockerfile.linux.amd64 b/docker/Dockerfile.linux.amd64 new file mode 100644 index 0000000..5eb333b --- /dev/null +++ b/docker/Dockerfile.linux.amd64 @@ -0,0 +1,9 @@ +FROM plugins/base:linux-amd64 + +LABEL maintainer="Drone.IO Community " \ + org.label-schema.name="Drone NuGet" \ + org.label-schema.vendor="Drone.IO Community" \ + org.label-schema.schema-version="1.0" + +ADD release/linux/amd64/drone-nuget /bin/ +ENTRYPOINT [ "/bin/drone-nuget" ] diff --git a/docker/Dockerfile.linux.arm b/docker/Dockerfile.linux.arm new file mode 100644 index 0000000..8a340dd --- /dev/null +++ b/docker/Dockerfile.linux.arm @@ -0,0 +1,9 @@ +FROM plugins/base:linux-arm + +LABEL maintainer="Drone.IO Community " \ + org.label-schema.name="Drone NuGet" \ + org.label-schema.vendor="Drone.IO Community" \ + org.label-schema.schema-version="1.0" + +ADD release/linux/arm/drone-nuget /bin/ +ENTRYPOINT [ "/bin/drone-nuget" ] diff --git a/docker/Dockerfile.linux.arm64 b/docker/Dockerfile.linux.arm64 new file mode 100644 index 0000000..d409b43 --- /dev/null +++ b/docker/Dockerfile.linux.arm64 @@ -0,0 +1,9 @@ +FROM plugins/base:linux-arm64 + +LABEL maintainer="Drone.IO Community " \ + org.label-schema.name="Drone NuGet" \ + org.label-schema.vendor="Drone.IO Community" \ + org.label-schema.schema-version="1.0" + +ADD release/linux/arm64/drone-nuget /bin/ +ENTRYPOINT [ "/bin/drone-nuget" ] diff --git a/docker/Dockerfile.windows.1809 b/docker/Dockerfile.windows.1809 new file mode 100644 index 0000000..bf4d261 --- /dev/null +++ b/docker/Dockerfile.windows.1809 @@ -0,0 +1,10 @@ +# escape=` +FROM plugins/base:windows-1809-amd64 + +LABEL maintainer="Drone.IO Community " ` + org.label-schema.name="Drone NuGet" ` + org.label-schema.vendor="Drone.IO Community" ` + org.label-schema.schema-version="1.0" + +ADD release/windows/amd64/drone-nuget.exe C:/bin/drone-nuget.exe +ENTRYPOINT [ "C:\\bin\\drone-nuget.exe" ] diff --git a/docker/Dockerfile.windows.1903 b/docker/Dockerfile.windows.1903 new file mode 100644 index 0000000..6f33519 --- /dev/null +++ b/docker/Dockerfile.windows.1903 @@ -0,0 +1,10 @@ +# escape=` +FROM plugins/base:windows-1903-amd64 + +LABEL maintainer="Drone.IO Community " ` + org.label-schema.name="Drone NuGet" ` + org.label-schema.vendor="Drone.IO Community" ` + org.label-schema.schema-version="1.0" + +ADD release/windows/amd64/drone-nuget.exe C:/bin/drone-nuget.exe +ENTRYPOINT [ "C:\\bin\\drone-nuget.exe" ] diff --git a/docker/Dockerfile.windows.1909 b/docker/Dockerfile.windows.1909 new file mode 100644 index 0000000..9f2fb3f --- /dev/null +++ b/docker/Dockerfile.windows.1909 @@ -0,0 +1,10 @@ +# escape=` +FROM plugins/base:windows-1909-amd64 + +LABEL maintainer="Drone.IO Community " ` + org.label-schema.name="Drone NuGet" ` + org.label-schema.vendor="Drone.IO Community" ` + org.label-schema.schema-version="1.0" + +ADD release/windows/amd64/drone-nuget.exe C:/bin/drone-nuget.exe +ENTRYPOINT [ "C:\\bin\\drone-nuget.exe" ] diff --git a/docker/Dockerfile.windows.2004 b/docker/Dockerfile.windows.2004 new file mode 100644 index 0000000..56873eb --- /dev/null +++ b/docker/Dockerfile.windows.2004 @@ -0,0 +1,10 @@ +# escape=` +FROM plugins/base:windows-2004-amd64 + +LABEL maintainer="Drone.IO Community " ` + org.label-schema.name="Drone NuGet" ` + org.label-schema.vendor="Drone.IO Community" ` + org.label-schema.schema-version="1.0" + +ADD release/windows/amd64/drone-nuget.exe C:/bin/drone-nuget.exe +ENTRYPOINT [ "C:\\bin\\drone-nuget.exe" ] diff --git a/docker/manifest.tmpl b/docker/manifest.tmpl new file mode 100644 index 0000000..139f827 --- /dev/null +++ b/docker/manifest.tmpl @@ -0,0 +1,44 @@ +image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}} + +{{#if build.tags}} +tags: +{{#each build.tags}} + - {{this}} +{{/each}} +{{/if}} + +manifests: + - image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64 + platform: + architecture: amd64 + os: linux + - image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64 + platform: + architecture: arm64 + os: linux + variant: v8 + - image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm + platform: + architecture: arm + os: linux + variant: v7 + - image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-2004-amd64 + platform: + architecture: amd64 + os: windows + version: 2004 + - image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1909-amd64 + platform: + architecture: amd64 + os: windows + version: 1909 + - image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1903-amd64 + platform: + architecture: amd64 + os: windows + version: 1903 + - image: plugins/nuget:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1809-amd64 + platform: + architecture: amd64 + os: windows + version: 1809 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..948b8be --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/drone-plugins/drone-nuget + +go 1.13 + +require ( + github.com/drone-plugins/drone-plugin-lib v0.3.1 + github.com/urfave/cli/v2 v2.2.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..83100ea --- /dev/null +++ b/go.sum @@ -0,0 +1,25 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/drone-plugins/drone-plugin-lib v0.3.1 h1:Br43wRnot2CpDGKPIKOnIxkTsuII5q4xxKROirs5hxc= +github.com/drone-plugins/drone-plugin-lib v0.3.1/go.mod h1:ZUKtwSoUmeCj7DXMS3WktDdMAWudW7O6dYAZZRISv4M= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +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/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.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +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= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/plugin/impl.go b/plugin/impl.go new file mode 100644 index 0000000..5c777ad --- /dev/null +++ b/plugin/impl.go @@ -0,0 +1,23 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package plugin + +// Settings for the plugin. +type Settings struct { + // Fill in the data structure with appropriate values +} + +// Validate handles the settings validation of the plugin. +func (p *Plugin) Validate() error { + // Validation of the settings. + return nil +} + +// Execute provides the implementation of the plugin. +func (p *Plugin) Execute() error { + // Implementation of the plugin. + return nil +} diff --git a/plugin/impl_test.go b/plugin/impl_test.go new file mode 100644 index 0000000..badfaa0 --- /dev/null +++ b/plugin/impl_test.go @@ -0,0 +1,18 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package plugin + +import ( + "testing" +) + +func TestValidate(t *testing.T) { + t.Skip() +} + +func TestExecute(t *testing.T) { + t.Skip() +} diff --git a/plugin/plugin.go b/plugin/plugin.go new file mode 100644 index 0000000..bb8248b --- /dev/null +++ b/plugin/plugin.go @@ -0,0 +1,26 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package plugin + +import ( + "github.com/drone-plugins/drone-plugin-lib/drone" +) + +// Plugin implements drone.Plugin to provide the plugin implementation. +type Plugin struct { + settings Settings + pipeline drone.Pipeline + network drone.Network +} + +// New initializes a plugin from the given Settings, Pipeline, and Network. +func New(settings Settings, pipeline drone.Pipeline, network drone.Network) drone.Plugin { + return &Plugin{ + settings: settings, + pipeline: pipeline, + network: network, + } +} diff --git a/plugin/plugin_test.go b/plugin/plugin_test.go new file mode 100644 index 0000000..3cb461f --- /dev/null +++ b/plugin/plugin_test.go @@ -0,0 +1,14 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package plugin + +import ( + "testing" +) + +func TestPlugin(t *testing.T) { + t.Skip() +} From b81ed2364f36ec3f25c451fe035aa7d3af1191ad Mon Sep 17 00:00:00 2001 From: Don Date: Fri, 5 Jun 2020 07:21:41 -0700 Subject: [PATCH 03/14] Update README --- README.md | 122 ++++++++++++++---------------------------------------- 1 file changed, 31 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index d504f02..8c42b7d 100644 --- a/README.md +++ b/README.md @@ -1,107 +1,47 @@ # drone-nuget -[![Build Status](http://beta.drone.io/api/badges/drone-plugins/drone-nuget/status.svg)](http://beta.drone.io/drone-plugins/drone-nuget) -[![Coverage Status](https://aircover.co/badges/drone-plugins/drone-nuget/coverage.svg)](https://aircover.co/drone-plugins/drone-nuget) -[![](https://badge.imagelayers.io/plugins/drone-nuget:latest.svg)](https://imagelayers.io/?images=plugins/drone-nuget:latest 'Get your own badge on imagelayers.io') +[![Build Status](http://cloud.drone.io/api/badges/drone-plugins/drone-nuget/status.svg)](http://cloud.drone.io/drone-plugins/drone-nuget) +[![Gitter chat](https://badges.gitter.im/drone/drone.png)](https://gitter.im/drone/drone) +[![Join the discussion at https://discourse.drone.io](https://img.shields.io/badge/discourse-forum-orange.svg)](https://discourse.drone.io) +[![Drone questions at https://stackoverflow.com](https://img.shields.io/badge/drone-stackoverflow-orange.svg)](https://stackoverflow.com/questions/tagged/drone.io) +[![](https://images.microbadger.com/badges/image/plugins/nuget.svg)](https://microbadger.com/images/plugins/nuget "Get your own image badge on microbadger.com") +[![Go Doc](https://godoc.org/github.com/drone-plugins/drone-nuget?status.svg)](http://godoc.org/github.com/drone-plugins/drone-nuget) +[![Go Report](https://goreportcard.com/badge/github.com/drone-plugins/drone-nuget)](https://goreportcard.com/report/github.com/drone-plugins/drone-nuget) -Drone plugin to publish files and artifacts to NuGet repository. For the usage information and a listing of the available options please take a look at [the docs](DOCS.md). +Drone plugin to publish files and artifacts to a NuGet repository. For the usage information and a listing of the available options please take a look at [the docs](DOCS.md). -## Execute +## Build -Install the deps using `make`: +Build the binary with the following command: -``` -make install -``` +```console +export GOOS=linux +export GOARCH=amd64 +export CGO_ENABLED=0 +export GO111MODULE=on -### Example - -```sh -npm start < Date: Fri, 5 Jun 2020 09:28:38 -0700 Subject: [PATCH 04/14] Use mcr.microsoft.com/dotnet/core/sdk as the base for windows --- docker/Dockerfile.windows.1809 | 2 +- docker/Dockerfile.windows.1903 | 2 +- docker/Dockerfile.windows.1909 | 2 +- docker/Dockerfile.windows.2004 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile.windows.1809 b/docker/Dockerfile.windows.1809 index bf4d261..53cfa9f 100644 --- a/docker/Dockerfile.windows.1809 +++ b/docker/Dockerfile.windows.1809 @@ -1,5 +1,5 @@ # escape=` -FROM plugins/base:windows-1809-amd64 +FROM mcr.microsoft.com/dotnet/core/sdk:3.1-nanoserver-1809 LABEL maintainer="Drone.IO Community " ` org.label-schema.name="Drone NuGet" ` diff --git a/docker/Dockerfile.windows.1903 b/docker/Dockerfile.windows.1903 index 6f33519..b419c9f 100644 --- a/docker/Dockerfile.windows.1903 +++ b/docker/Dockerfile.windows.1903 @@ -1,5 +1,5 @@ # escape=` -FROM plugins/base:windows-1903-amd64 +FROM mcr.microsoft.com/dotnet/core/sdk:3.1-nanoserver-1903 LABEL maintainer="Drone.IO Community " ` org.label-schema.name="Drone NuGet" ` diff --git a/docker/Dockerfile.windows.1909 b/docker/Dockerfile.windows.1909 index 9f2fb3f..af056e6 100644 --- a/docker/Dockerfile.windows.1909 +++ b/docker/Dockerfile.windows.1909 @@ -1,5 +1,5 @@ # escape=` -FROM plugins/base:windows-1909-amd64 +FROM mcr.microsoft.com/dotnet/core/sdk:3.1-nanoserver-1909 LABEL maintainer="Drone.IO Community " ` org.label-schema.name="Drone NuGet" ` diff --git a/docker/Dockerfile.windows.2004 b/docker/Dockerfile.windows.2004 index 56873eb..2e777ae 100644 --- a/docker/Dockerfile.windows.2004 +++ b/docker/Dockerfile.windows.2004 @@ -1,5 +1,5 @@ # escape=` -FROM plugins/base:windows-2004-amd64 +FROM mcr.microsoft.com/dotnet/core/sdk:3.1-nanoserver-2004 LABEL maintainer="Drone.IO Community " ` org.label-schema.name="Drone NuGet" ` From 09bf78803b1b28a891b7d823cac75db2f590ea97 Mon Sep 17 00:00:00 2001 From: Don Date: Fri, 5 Jun 2020 09:30:51 -0700 Subject: [PATCH 05/14] Add settings for source and name --- cmd/drone-nuget/config.go | 17 ++++++++++++++--- plugin/impl.go | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/cmd/drone-nuget/config.go b/cmd/drone-nuget/config.go index 4ce154e..17e26ac 100644 --- a/cmd/drone-nuget/config.go +++ b/cmd/drone-nuget/config.go @@ -12,7 +12,18 @@ import ( // settingsFlags has the cli.Flags for the plugin.Settings. func settingsFlags(settings *plugin.Settings) []cli.Flag { - // Replace below with all the flags required for the plugin. - // Use Destination within the cli.Flags to populate settings - return []cli.Flag{} + return []cli.Flag{ + &cli.StringFlag{ + Name: "source", + Usage: "nuget package repository source url", + EnvVars: []string{"PLUGIN_SOURCE"}, + Destination: &settings.Source, + }, + &cli.StringFlag{ + Name: "name", + Usage: "nuget package repository name", + EnvVars: []string{"PLUGIN_NAME"}, + Destination: &settings.Name, + }, + } } diff --git a/plugin/impl.go b/plugin/impl.go index 5c777ad..f4bef93 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -5,14 +5,47 @@ package plugin +import ( + "fmt" + "net/url" +) + // Settings for the plugin. type Settings struct { - // Fill in the data structure with appropriate values + Source string + Name string } +const ( + nugetOrgName = "nuget.org" + nugetOrgSource = "https://api.nuget.org/v3/index.json" +) + // Validate handles the settings validation of the plugin. func (p *Plugin) Validate() error { - // Validation of the settings. + // Set defaults for source and name + if p.settings.Source == "" { + p.settings.Source = nugetOrgSource + } + if p.settings.Name == "" { + if p.settings.Source == nugetOrgSource { + p.settings.Name = nugetOrgName + } else { + p.settings.Name = "drone-nuget" + } + } + + // Validate the source and name + if p.settings.Name == nugetOrgName && p.settings.Source != nugetOrgSource { + return fmt.Errorf("repository named %s must use %s as its source", nugetOrgName, nugetOrgSource) + } + if p.settings.Name != nugetOrgName && p.settings.Source == nugetOrgSource { + return fmt.Errorf("source %s must use %s as its repository name", nugetOrgSource, nugetOrgName) + } + if _, err := url.Parse(p.settings.Source); err != nil { + return fmt.Errorf("could not parse source url %s: %w", p.settings.Source, err) + } + return nil } From 13dbd8a500713f398659a2c35c1c34b9111d3b5f Mon Sep 17 00:00:00 2001 From: Don Date: Fri, 5 Jun 2020 09:39:23 -0700 Subject: [PATCH 06/14] Add nuget cli wrapper --- plugin/cli/cli.go | 80 ++++++++++++++++++++++++++++++++++++++++++++ plugin/cli/dotnet.go | 22 ++++++++++++ plugin/cli/nuget.go | 22 ++++++++++++ plugin/impl.go | 15 +++++++-- 4 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 plugin/cli/cli.go create mode 100644 plugin/cli/dotnet.go create mode 100644 plugin/cli/nuget.go diff --git a/plugin/cli/cli.go b/plugin/cli/cli.go new file mode 100644 index 0000000..fe39bc5 --- /dev/null +++ b/plugin/cli/cli.go @@ -0,0 +1,80 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package cli + +import ( + "fmt" + "os" + "os/exec" + "strings" +) + +// NuGet is an interface for the command line interface for NuGet. +type NuGet interface { + // VersionCmd creates a command that will display the version of NuGet. + VersionCmd() *exec.Cmd + + // ListSources creates a command that will display the NuGet package sources. + ListSourcesCmd() *exec.Cmd +} + +func New() (NuGet, error) { + if n, err := NewDotNet(); err == nil { + return n, err + } + + return NewNuGet() +} + +func NewDotNet() (NuGet, error) { + path, err := exec.LookPath("dotnet") + if err != nil { + return nil, fmt.Errorf("could not find dotnet in path") + } + + return &dotnet{ + path: path, + }, nil +} + +func NewNuGet() (NuGet, error) { + path, err := exec.LookPath("nuget") + if err != nil { + return nil, fmt.Errorf("could not find nuget in path") + } + + return &nuget{ + path: path, + }, nil +} + +// runCommands executes the list of cmds in the given directory. +func RunCommands(cmds []*exec.Cmd, dir string) error { + for _, cmd := range cmds { + err := RunCommand(cmd, dir) + + if err != nil { + return err + } + } + + return nil +} + +func RunCommand(cmd *exec.Cmd, dir string) error { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Dir = dir + trace(cmd) + + return cmd.Run() +} + +// trace writes each command to standard error (preceded by a ‘$ ’) before it +// is executed. Used for debugging your build. +func trace(cmd *exec.Cmd) { + fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " ")) +} diff --git a/plugin/cli/dotnet.go b/plugin/cli/dotnet.go new file mode 100644 index 0000000..49ce53d --- /dev/null +++ b/plugin/cli/dotnet.go @@ -0,0 +1,22 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package cli + +import ( + "os/exec" +) + +type dotnet struct { + path string +} + +func (n *dotnet) VersionCmd() *exec.Cmd { + return exec.Command("dotnet", "nuget", "--version") +} + +func (n *dotnet) ListSourcesCmd() *exec.Cmd { + return exec.Command("dotnet", "nuget", "list", "source") +} diff --git a/plugin/cli/nuget.go b/plugin/cli/nuget.go new file mode 100644 index 0000000..b66cc4c --- /dev/null +++ b/plugin/cli/nuget.go @@ -0,0 +1,22 @@ +// Copyright (c) 2020, the Drone Plugins project authors. +// Please see the AUTHORS file for details. All rights reserved. +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file. + +package cli + +import ( + "os/exec" +) + +type nuget struct { + path string +} + +func (n *nuget) VersionCmd() *exec.Cmd { + return exec.Command("nuget") +} + +func (n *nuget) ListSourcesCmd() *exec.Cmd { + return exec.Command("nuget", "sources") +} diff --git a/plugin/impl.go b/plugin/impl.go index f4bef93..22e8bec 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -8,6 +8,9 @@ package plugin import ( "fmt" "net/url" + "os/exec" + + "github.com/drone-plugins/drone-nuget/plugin/cli" ) // Settings for the plugin. @@ -51,6 +54,14 @@ func (p *Plugin) Validate() error { // Execute provides the implementation of the plugin. func (p *Plugin) Execute() error { - // Implementation of the plugin. - return nil + nuget, err := cli.New() + if err != nil { + return err + } + + var cmds []*exec.Cmd + + cmds = append(cmds, nuget.VersionCmd(), nuget.ListSourcesCmd()) + + return cli.RunCommands(cmds, "") } From a78bba875a63b88414c7a3a81f7009cb28d8ee02 Mon Sep 17 00:00:00 2001 From: Don Date: Fri, 5 Jun 2020 10:08:08 -0700 Subject: [PATCH 07/14] Add NuGet.AddSourceCmd --- plugin/cli/cli.go | 3 +++ plugin/cli/dotnet.go | 4 ++++ plugin/cli/nuget.go | 6 +++++- plugin/impl.go | 10 ++++++++-- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/plugin/cli/cli.go b/plugin/cli/cli.go index fe39bc5..d2d8414 100644 --- a/plugin/cli/cli.go +++ b/plugin/cli/cli.go @@ -19,6 +19,9 @@ type NuGet interface { // ListSources creates a command that will display the NuGet package sources. ListSourcesCmd() *exec.Cmd + + // AddSourceCmd creates a command that will add a NuGet package source. + AddSourceCmd(source, name string) *exec.Cmd } func New() (NuGet, error) { diff --git a/plugin/cli/dotnet.go b/plugin/cli/dotnet.go index 49ce53d..3d8bdec 100644 --- a/plugin/cli/dotnet.go +++ b/plugin/cli/dotnet.go @@ -20,3 +20,7 @@ func (n *dotnet) VersionCmd() *exec.Cmd { func (n *dotnet) ListSourcesCmd() *exec.Cmd { return exec.Command("dotnet", "nuget", "list", "source") } + +func (n *dotnet) AddSourceCmd(source, name string) *exec.Cmd { + return exec.Command("dotnet", "nuget", "add", "source", source, "--name", name) +} diff --git a/plugin/cli/nuget.go b/plugin/cli/nuget.go index b66cc4c..b754034 100644 --- a/plugin/cli/nuget.go +++ b/plugin/cli/nuget.go @@ -18,5 +18,9 @@ func (n *nuget) VersionCmd() *exec.Cmd { } func (n *nuget) ListSourcesCmd() *exec.Cmd { - return exec.Command("nuget", "sources") + return exec.Command("nuget", "sources", "list") +} + +func (n *nuget) AddSourceCmd(source, name string) *exec.Cmd { + return exec.Command("nuget", "sources", "add", "-Source", source, "-Name", name, "-NonInteractive") } diff --git a/plugin/impl.go b/plugin/impl.go index 22e8bec..7f8d14e 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -59,9 +59,15 @@ func (p *Plugin) Execute() error { return err } - var cmds []*exec.Cmd + cmds := []*exec.Cmd{ + nuget.VersionCmd(), + } + + if p.settings.Name != nugetOrgSource { + cmds = append(cmds, nuget.AddSourceCmd(p.settings.Source, p.settings.Name)) + } - cmds = append(cmds, nuget.VersionCmd(), nuget.ListSourcesCmd()) + cmds = append(cmds, nuget.ListSourcesCmd()) return cli.RunCommands(cmds, "") } From 0bc6c2aaef6685675fab6ad42f5d71030006b752 Mon Sep 17 00:00:00 2001 From: Don Date: Fri, 5 Jun 2020 13:17:58 -0700 Subject: [PATCH 08/14] Add initial support for pushing a package --- cmd/drone-nuget/config.go | 12 ++++++++++++ plugin/cli/cli.go | 3 +++ plugin/cli/dotnet.go | 4 ++++ plugin/cli/nuget.go | 4 ++++ plugin/impl.go | 22 +++++++++++++++++++++- 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/cmd/drone-nuget/config.go b/cmd/drone-nuget/config.go index 17e26ac..d202598 100644 --- a/cmd/drone-nuget/config.go +++ b/cmd/drone-nuget/config.go @@ -13,6 +13,18 @@ import ( // settingsFlags has the cli.Flags for the plugin.Settings. func settingsFlags(settings *plugin.Settings) []cli.Flag { return []cli.Flag{ + &cli.StringFlag{ + Name: "api-key", + Usage: "api key to access nuget source", + EnvVars: []string{"PLUGIN_API_KEY"}, + Destination: &settings.APIKey, + }, + &cli.StringFlag{ + Name: "file", + Usage: "nuget package to upload", + EnvVars: []string{"PLUGIN_FILE"}, + Destination: &settings.File, + }, &cli.StringFlag{ Name: "source", Usage: "nuget package repository source url", diff --git a/plugin/cli/cli.go b/plugin/cli/cli.go index d2d8414..06de0c5 100644 --- a/plugin/cli/cli.go +++ b/plugin/cli/cli.go @@ -22,6 +22,9 @@ type NuGet interface { // AddSourceCmd creates a command that will add a NuGet package source. AddSourceCmd(source, name string) *exec.Cmd + + // PushPackageCmd creates a command that will push a package to a NuGet package source. + PushPackageCmd(path, name, key string) *exec.Cmd } func New() (NuGet, error) { diff --git a/plugin/cli/dotnet.go b/plugin/cli/dotnet.go index 3d8bdec..6e132dc 100644 --- a/plugin/cli/dotnet.go +++ b/plugin/cli/dotnet.go @@ -24,3 +24,7 @@ func (n *dotnet) ListSourcesCmd() *exec.Cmd { func (n *dotnet) AddSourceCmd(source, name string) *exec.Cmd { return exec.Command("dotnet", "nuget", "add", "source", source, "--name", name) } + +func (n *dotnet) PushPackageCmd(path, name, key string) *exec.Cmd { + return exec.Command("dotnet", "nuget", "push", path, "--source", name, "--api-key", key) +} diff --git a/plugin/cli/nuget.go b/plugin/cli/nuget.go index b754034..e968fb6 100644 --- a/plugin/cli/nuget.go +++ b/plugin/cli/nuget.go @@ -24,3 +24,7 @@ func (n *nuget) ListSourcesCmd() *exec.Cmd { func (n *nuget) AddSourceCmd(source, name string) *exec.Cmd { return exec.Command("nuget", "sources", "add", "-Source", source, "-Name", name, "-NonInteractive") } + +func (n *nuget) PushPackageCmd(path, name, key string) *exec.Cmd { + return nil +} diff --git a/plugin/impl.go b/plugin/impl.go index 7f8d14e..8ba3bde 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -8,6 +8,7 @@ package plugin import ( "fmt" "net/url" + "os" "os/exec" "github.com/drone-plugins/drone-nuget/plugin/cli" @@ -15,8 +16,10 @@ import ( // Settings for the plugin. type Settings struct { + APIKey string Source string Name string + File string } const ( @@ -26,6 +29,22 @@ const ( // Validate handles the settings validation of the plugin. func (p *Plugin) Validate() error { + if p.settings.APIKey == "" { + return fmt.Errorf("no api key provided") + } + + // Verify specified file + if p.settings.File == "" { + return fmt.Errorf("no package specified") + } + info, err := os.Stat(p.settings.File) + if os.IsNotExist(err) { + return fmt.Errorf("file does not exist: %w", err) + } + if info.IsDir() { + return fmt.Errorf("file is a directory") + } + // Set defaults for source and name if p.settings.Source == "" { p.settings.Source = nugetOrgSource @@ -63,11 +82,12 @@ func (p *Plugin) Execute() error { nuget.VersionCmd(), } - if p.settings.Name != nugetOrgSource { + if p.settings.Name != nugetOrgName { cmds = append(cmds, nuget.AddSourceCmd(p.settings.Source, p.settings.Name)) } cmds = append(cmds, nuget.ListSourcesCmd()) + cmds = append(cmds, nuget.PushPackageCmd(p.settings.File, p.settings.Name, p.settings.APIKey)) return cli.RunCommands(cmds, "") } From 3b1fda4cc9a75448ef824225257bab27e4b69fa8 Mon Sep 17 00:00:00 2001 From: Don Date: Sat, 6 Jun 2020 09:21:13 -0700 Subject: [PATCH 09/14] Add support for reading nuspec file --- go.mod | 1 + plugin/impl.go | 117 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 948b8be..4f13d77 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,6 @@ go 1.13 require ( github.com/drone-plugins/drone-plugin-lib v0.3.1 + github.com/sirupsen/logrus v1.6.0 github.com/urfave/cli/v2 v2.2.0 ) diff --git a/plugin/impl.go b/plugin/impl.go index 8ba3bde..312592c 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -6,21 +6,36 @@ package plugin import ( + "encoding/xml" "fmt" + "io/ioutil" "net/url" "os" "os/exec" + "path" + "path/filepath" + "strings" "github.com/drone-plugins/drone-nuget/plugin/cli" + "github.com/sirupsen/logrus" ) -// Settings for the plugin. -type Settings struct { - APIKey string - Source string - Name string - File string -} +type ( + // Settings for the plugin. + Settings struct { + APIKey string + Source string + Name string + File string + + nupkg string + } + + nuspecMetadata struct { + Name string `xml:"id"` + Version string `xml:"version"` + } +) const ( nugetOrgName = "nuget.org" @@ -33,18 +48,41 @@ func (p *Plugin) Validate() error { return fmt.Errorf("no api key provided") } - // Verify specified file - if p.settings.File == "" { + file := p.settings.File + if file == "" { return fmt.Errorf("no package specified") } - info, err := os.Stat(p.settings.File) - if os.IsNotExist(err) { - return fmt.Errorf("file does not exist: %w", err) + + // Convert to / separators from os specific ones and then use path + // Windows works fine with / but unix does not work with \ + file = filepath.ToSlash(file) + + // Clean the path + file = path.Clean(file) + + // Determine file type + if strings.HasSuffix(file, ".nuspec") { + nuspec := file + logrus.WithField("file", nuspec).Info("Loading .nuspec file") + + var err error + file, err = nupkgFromNuspec(nuspec) + if err != nil { + return fmt.Errorf("could not determine nupkg file from %s: %w", nuspec, err) + } + } else if !strings.HasSuffix(file, ".nupkg") { + return fmt.Errorf("file %s isn't a nuspec or a nupkg", file) } - if info.IsDir() { - return fmt.Errorf("file is a directory") + + if !fileExists(file) { + return fmt.Errorf(".nupkg file does not exist at %s", file) } + logrus.WithField("file", file).Info("Publishing .nupkg file") + + // Store nupkg file and convert to os specific path + p.settings.nupkg = filepath.FromSlash(file) + // Set defaults for source and name if p.settings.Source == "" { p.settings.Source = nugetOrgSource @@ -68,6 +106,11 @@ func (p *Plugin) Validate() error { return fmt.Errorf("could not parse source url %s: %w", p.settings.Source, err) } + logrus.WithFields(logrus.Fields{ + "name": p.settings.Name, + "source": p.settings.Source, + }).Info("Using NuGet repository") + return nil } @@ -87,7 +130,51 @@ func (p *Plugin) Execute() error { } cmds = append(cmds, nuget.ListSourcesCmd()) - cmds = append(cmds, nuget.PushPackageCmd(p.settings.File, p.settings.Name, p.settings.APIKey)) + cmds = append(cmds, nuget.PushPackageCmd(p.settings.nupkg, p.settings.Name, p.settings.APIKey)) return cli.RunCommands(cmds, "") } + +func nupkgFromNuspec(file string) (string, error) { + if !fileExists(file) { + return "", fmt.Errorf(".nuspec file not found at %s", file) + } + + // Read the file + nuspec, err := os.Open(file) + if err != nil { + return "", fmt.Errorf("unable to open .nuspec file %s: %w", file, err) + } + + bytes, err := ioutil.ReadAll(nuspec) + if err != nil { + return "", fmt.Errorf("unable to read .nuspec file %s: %w", file, err) + } + + // Unmarshal the file + var doc struct { + XMLName xml.Name `xml:"package"` + Metadata nuspecMetadata `xml:"metadata"` + } + if err := xml.Unmarshal(bytes, &doc); err != nil { + return "", fmt.Errorf("unable to parse .nuspec file %s: %w", file, err) + } + + logrus.WithFields(logrus.Fields{ + "name": doc.Metadata.Name, + "version": doc.Metadata.Version, + }).Info("Found .nupsec file") + + nupkgName := fmt.Sprintf("%s.%s.nupkg", doc.Metadata.Name, doc.Metadata.Version) + + return path.Join(path.Dir(file), nupkgName), nil +} + +func fileExists(file string) bool { + info, err := os.Stat(file) + if os.IsNotExist(err) { + return false + } + + return !info.IsDir() +} From 55ecc93e997bb065ea7c78079fd87158b8a6a078 Mon Sep 17 00:00:00 2001 From: Don Date: Sat, 6 Jun 2020 09:34:10 -0700 Subject: [PATCH 10/14] Remove plugin/cli library Just standardize on using the dotnet executable and simplify accordingly. --- plugin/cli/cli.go | 86 -------------------------------------------- plugin/cli/dotnet.go | 30 ---------------- plugin/cli/nuget.go | 30 ---------------- plugin/impl.go | 67 ++++++++++++++++++++++++++++------ 4 files changed, 56 insertions(+), 157 deletions(-) delete mode 100644 plugin/cli/cli.go delete mode 100644 plugin/cli/dotnet.go delete mode 100644 plugin/cli/nuget.go diff --git a/plugin/cli/cli.go b/plugin/cli/cli.go deleted file mode 100644 index 06de0c5..0000000 --- a/plugin/cli/cli.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2020, the Drone Plugins project authors. -// Please see the AUTHORS file for details. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license that can be -// found in the LICENSE file. - -package cli - -import ( - "fmt" - "os" - "os/exec" - "strings" -) - -// NuGet is an interface for the command line interface for NuGet. -type NuGet interface { - // VersionCmd creates a command that will display the version of NuGet. - VersionCmd() *exec.Cmd - - // ListSources creates a command that will display the NuGet package sources. - ListSourcesCmd() *exec.Cmd - - // AddSourceCmd creates a command that will add a NuGet package source. - AddSourceCmd(source, name string) *exec.Cmd - - // PushPackageCmd creates a command that will push a package to a NuGet package source. - PushPackageCmd(path, name, key string) *exec.Cmd -} - -func New() (NuGet, error) { - if n, err := NewDotNet(); err == nil { - return n, err - } - - return NewNuGet() -} - -func NewDotNet() (NuGet, error) { - path, err := exec.LookPath("dotnet") - if err != nil { - return nil, fmt.Errorf("could not find dotnet in path") - } - - return &dotnet{ - path: path, - }, nil -} - -func NewNuGet() (NuGet, error) { - path, err := exec.LookPath("nuget") - if err != nil { - return nil, fmt.Errorf("could not find nuget in path") - } - - return &nuget{ - path: path, - }, nil -} - -// runCommands executes the list of cmds in the given directory. -func RunCommands(cmds []*exec.Cmd, dir string) error { - for _, cmd := range cmds { - err := RunCommand(cmd, dir) - - if err != nil { - return err - } - } - - return nil -} - -func RunCommand(cmd *exec.Cmd, dir string) error { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Dir = dir - trace(cmd) - - return cmd.Run() -} - -// trace writes each command to standard error (preceded by a ‘$ ’) before it -// is executed. Used for debugging your build. -func trace(cmd *exec.Cmd) { - fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " ")) -} diff --git a/plugin/cli/dotnet.go b/plugin/cli/dotnet.go deleted file mode 100644 index 6e132dc..0000000 --- a/plugin/cli/dotnet.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2020, the Drone Plugins project authors. -// Please see the AUTHORS file for details. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license that can be -// found in the LICENSE file. - -package cli - -import ( - "os/exec" -) - -type dotnet struct { - path string -} - -func (n *dotnet) VersionCmd() *exec.Cmd { - return exec.Command("dotnet", "nuget", "--version") -} - -func (n *dotnet) ListSourcesCmd() *exec.Cmd { - return exec.Command("dotnet", "nuget", "list", "source") -} - -func (n *dotnet) AddSourceCmd(source, name string) *exec.Cmd { - return exec.Command("dotnet", "nuget", "add", "source", source, "--name", name) -} - -func (n *dotnet) PushPackageCmd(path, name, key string) *exec.Cmd { - return exec.Command("dotnet", "nuget", "push", path, "--source", name, "--api-key", key) -} diff --git a/plugin/cli/nuget.go b/plugin/cli/nuget.go deleted file mode 100644 index e968fb6..0000000 --- a/plugin/cli/nuget.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2020, the Drone Plugins project authors. -// Please see the AUTHORS file for details. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license that can be -// found in the LICENSE file. - -package cli - -import ( - "os/exec" -) - -type nuget struct { - path string -} - -func (n *nuget) VersionCmd() *exec.Cmd { - return exec.Command("nuget") -} - -func (n *nuget) ListSourcesCmd() *exec.Cmd { - return exec.Command("nuget", "sources", "list") -} - -func (n *nuget) AddSourceCmd(source, name string) *exec.Cmd { - return exec.Command("nuget", "sources", "add", "-Source", source, "-Name", name, "-NonInteractive") -} - -func (n *nuget) PushPackageCmd(path, name, key string) *exec.Cmd { - return nil -} diff --git a/plugin/impl.go b/plugin/impl.go index 312592c..480a68d 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -16,7 +16,6 @@ import ( "path/filepath" "strings" - "github.com/drone-plugins/drone-nuget/plugin/cli" "github.com/sirupsen/logrus" ) @@ -116,25 +115,21 @@ func (p *Plugin) Validate() error { // Execute provides the implementation of the plugin. func (p *Plugin) Execute() error { - nuget, err := cli.New() - if err != nil { - return err - } - cmds := []*exec.Cmd{ - nuget.VersionCmd(), + versionCmd(), } if p.settings.Name != nugetOrgName { - cmds = append(cmds, nuget.AddSourceCmd(p.settings.Source, p.settings.Name)) + cmds = append(cmds, addSourceCmd(p.settings.Source, p.settings.Name)) } - cmds = append(cmds, nuget.ListSourcesCmd()) - cmds = append(cmds, nuget.PushPackageCmd(p.settings.nupkg, p.settings.Name, p.settings.APIKey)) + cmds = append(cmds, listSourcesCmd()) + cmds = append(cmds, pushPackageCmd(p.settings.nupkg, p.settings.Name, p.settings.APIKey)) - return cli.RunCommands(cmds, "") + return runCommands(cmds, "") } +// nupkgFromNuspec reads the nuspec file and determines the filename. func nupkgFromNuspec(file string) (string, error) { if !fileExists(file) { return "", fmt.Errorf(".nuspec file not found at %s", file) @@ -170,6 +165,7 @@ func nupkgFromNuspec(file string) (string, error) { return path.Join(path.Dir(file), nupkgName), nil } +// fileExists determines if the file is present. func fileExists(file string) bool { info, err := os.Stat(file) if os.IsNotExist(err) { @@ -178,3 +174,52 @@ func fileExists(file string) bool { return !info.IsDir() } + +// versionCmd gets the nuget version. +func versionCmd() *exec.Cmd { + return exec.Command("dotnet", "nuget", "--version") +} + +// listSourcesCmd lists the nuget repositories. +func listSourcesCmd() *exec.Cmd { + return exec.Command("dotnet", "nuget", "list", "source") +} + +// addSourceCmd creates a new nuget repository source. +func addSourceCmd(source, name string) *exec.Cmd { + return exec.Command("dotnet", "nuget", "add", "source", source, "--name", name) +} + +// pushPackageCmd pushes a package to the nuget repository. +func pushPackageCmd(path, name, key string) *exec.Cmd { + return exec.Command("dotnet", "nuget", "push", path, "--source", name, "--api-key", key) +} + +// trace writes each command to standard error (preceded by a ‘$ ’) before it +// is executed. Used for debugging your build. +func trace(cmd *exec.Cmd) { + fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " ")) +} + +// runCommands executes the list of cmds in the given directory. +func runCommands(cmds []*exec.Cmd, dir string) error { + for _, cmd := range cmds { + err := runCommand(cmd, dir) + + if err != nil { + return err + } + } + + return nil +} + +// runCommand executes a cmd in the given directory. +func runCommand(cmd *exec.Cmd, dir string) error { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Dir = dir + trace(cmd) + + return cmd.Run() +} From 432160815d8cb8cc804b157e7b028f5b782c4d06 Mon Sep 17 00:00:00 2001 From: Don Date: Mon, 15 Jun 2020 09:11:13 -0700 Subject: [PATCH 11/14] Update to latest boilr template --- .drone.star | 14 +++++++------- cmd/drone-nuget/main.go | 24 +++++++++++++++--------- go.mod | 3 ++- go.sum | 2 ++ 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/.drone.star b/.drone.star index a14650c..952d69a 100644 --- a/.drone.star +++ b/.drone.star @@ -33,7 +33,7 @@ def testing(ctx): 'steps': [ { 'name': 'staticcheck', - 'image': 'golang:1.13', + 'image': 'golang:1.14', 'pull': 'always', 'commands': [ 'go run honnef.co/go/tools/cmd/staticcheck ./...', @@ -47,7 +47,7 @@ def testing(ctx): }, { 'name': 'lint', - 'image': 'golang:1.13', + 'image': 'golang:1.14', 'pull': 'always', 'commands': [ 'go run golang.org/x/lint/golint -set_exit_status ./...', @@ -61,7 +61,7 @@ def testing(ctx): }, { 'name': 'vet', - 'image': 'golang:1.13', + 'image': 'golang:1.14', 'pull': 'always', 'commands': [ 'go vet ./...', @@ -75,7 +75,7 @@ def testing(ctx): }, { 'name': 'test', - 'image': 'golang:1.13', + 'image': 'golang:1.14', 'pull': 'always', 'commands': [ 'go test -cover ./...', @@ -146,7 +146,7 @@ def linux(ctx, arch): 'steps': [ { 'name': 'environment', - 'image': 'golang:1.13', + 'image': 'golang:1.14', 'pull': 'always', 'environment': { 'CGO_ENABLED': '0', @@ -158,7 +158,7 @@ def linux(ctx, arch): }, { 'name': 'build', - 'image': 'golang:1.13', + 'image': 'golang:1.14', 'pull': 'always', 'environment': { 'CGO_ENABLED': '0', @@ -167,7 +167,7 @@ def linux(ctx, arch): }, { 'name': 'executable', - 'image': 'golang:1.13', + 'image': 'golang:1.14', 'pull': 'always', 'commands': [ './release/linux/%s/drone-nuget --help' % (arch), diff --git a/cmd/drone-nuget/main.go b/cmd/drone-nuget/main.go index f4009b4..e042ac3 100644 --- a/cmd/drone-nuget/main.go +++ b/cmd/drone-nuget/main.go @@ -10,23 +10,29 @@ package main import ( "os" - "github.com/drone-plugins/drone-nuget/plugin" "github.com/drone-plugins/drone-plugin-lib/errors" "github.com/drone-plugins/drone-plugin-lib/urfave" + "github.com/joho/godotenv" "github.com/urfave/cli/v2" + "github.com/drone-plugins/drone-nuget/plugin" ) var version = "unknown" func main() { - app := cli.NewApp() - app.Name = "drone-nuget" - app.Usage = "pushes a package to a nuget repository" - app.Version = version - - settings := plugin.Settings{} - app.Flags = append(settingsFlags(&settings), urfave.Flags()...) - app.Action = run(&settings) + settings := &plugin.Settings{} + + if _, err := os.Stat("/run/drone/env"); err == nil { + godotenv.Overload("/run/drone/env") + } + + app := &cli.App{ + Name: "drone-nuget", + Usage: "push a package to a nuget repository", + Version: version, + Flags: append(settingsFlags(settings), urfave.Flags()...), + Action: run(settings), + } if err := app.Run(os.Args); err != nil { errors.HandleExit(err) diff --git a/go.mod b/go.mod index 4f13d77..f4f4350 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ module github.com/drone-plugins/drone-nuget -go 1.13 +go 1.14 require ( github.com/drone-plugins/drone-plugin-lib v0.3.1 + github.com/joho/godotenv v1.3.0 github.com/sirupsen/logrus v1.6.0 github.com/urfave/cli/v2 v2.2.0 ) diff --git a/go.sum b/go.sum index 83100ea..0d41dc0 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/drone-plugins/drone-plugin-lib v0.3.1 h1:Br43wRnot2CpDGKPIKOnIxkTsuII5q4xxKROirs5hxc= github.com/drone-plugins/drone-plugin-lib v0.3.1/go.mod h1:ZUKtwSoUmeCj7DXMS3WktDdMAWudW7O6dYAZZRISv4M= +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/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= From 58fa72ce8f531506ecaa8d2b4a36777a1f6d3106 Mon Sep 17 00:00:00 2001 From: Don Date: Mon, 15 Jun 2020 09:28:23 -0700 Subject: [PATCH 12/14] Format code --- cmd/drone-nuget/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/drone-nuget/main.go b/cmd/drone-nuget/main.go index e042ac3..ddf20d9 100644 --- a/cmd/drone-nuget/main.go +++ b/cmd/drone-nuget/main.go @@ -10,11 +10,11 @@ package main import ( "os" + "github.com/drone-plugins/drone-nuget/plugin" "github.com/drone-plugins/drone-plugin-lib/errors" "github.com/drone-plugins/drone-plugin-lib/urfave" "github.com/joho/godotenv" "github.com/urfave/cli/v2" - "github.com/drone-plugins/drone-nuget/plugin" ) var version = "unknown" From 3eeae775e748a0a2a2a3bc7ddf3f5fac68810b65 Mon Sep 17 00:00:00 2001 From: Don Date: Wed, 8 Jul 2020 13:36:53 -0700 Subject: [PATCH 13/14] Use switch when finding nupkg file --- plugin/impl.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugin/impl.go b/plugin/impl.go index 480a68d..cd96573 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -59,8 +59,9 @@ func (p *Plugin) Validate() error { // Clean the path file = path.Clean(file) - // Determine file type - if strings.HasSuffix(file, ".nuspec") { + // Find .nupkg file + switch path.Ext(file) { + case ".nuspec": nuspec := file logrus.WithField("file", nuspec).Info("Loading .nuspec file") @@ -69,7 +70,9 @@ func (p *Plugin) Validate() error { if err != nil { return fmt.Errorf("could not determine nupkg file from %s: %w", nuspec, err) } - } else if !strings.HasSuffix(file, ".nupkg") { + case ".nupkg": + // Do nothing + default: return fmt.Errorf("file %s isn't a nuspec or a nupkg", file) } From aeaf6a1706048a4cb3df91457d142fdbc16c75f3 Mon Sep 17 00:00:00 2001 From: Don Date: Wed, 8 Jul 2020 13:46:49 -0700 Subject: [PATCH 14/14] Nest XML struct --- plugin/impl.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/plugin/impl.go b/plugin/impl.go index cd96573..28e682b 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -29,11 +29,6 @@ type ( nupkg string } - - nuspecMetadata struct { - Name string `xml:"id"` - Version string `xml:"version"` - } ) const ( @@ -151,8 +146,11 @@ func nupkgFromNuspec(file string) (string, error) { // Unmarshal the file var doc struct { - XMLName xml.Name `xml:"package"` - Metadata nuspecMetadata `xml:"metadata"` + XMLName xml.Name `xml:"package"` + Metadata struct { + Name string `xml:"id"` + Version string `xml:"version"` + } `xml:"metadata"` } if err := xml.Unmarshal(bytes, &doc); err != nil { return "", fmt.Errorf("unable to parse .nuspec file %s: %w", file, err)