commit cc621215e397cdaa177919cefb25053dfb6815f6 Author: Thomas Boerger Date: Fri Jun 7 12:32:16 2019 +0200 Initial commit diff --git a/.dockeringore b/.dockeringore new file mode 100644 index 0000000..c13ca3f --- /dev/null +++ b/.dockeringore @@ -0,0 +1,2 @@ +* +!release/ diff --git a/.drone.jsonnet b/.drone.jsonnet new file mode 100644 index 0000000..0582bd8 --- /dev/null +++ b/.drone.jsonnet @@ -0,0 +1,14 @@ +local pipeline = import 'pipeline.libsonnet'; +local name = 'drone-git-action'; + +[ + pipeline.test('linux', 'amd64'), + pipeline.build(name, 'linux', 'amd64'), + pipeline.build(name, 'linux', 'arm64'), + pipeline.build(name, 'linux', 'arm'), + pipeline.notifications(depends_on=[ + 'linux-amd64', + 'linux-arm64', + 'linux-arm', + ]), +] diff --git a/.drone.windows.jsonnet b/.drone.windows.jsonnet new file mode 100644 index 0000000..cbac768 --- /dev/null +++ b/.drone.windows.jsonnet @@ -0,0 +1,9 @@ +local pipeline = import 'pipeline.libsonnet'; +local name = 'drone-git-action'; + +[ + pipeline.test('windows', 'amd64', '1803'), + pipeline.build(name, 'windows', 'amd64', '1803'), + pipeline.build(name, 'windows', 'amd64', '1809'), + pipeline.notifications('windows', 'amd64', '1809', ['windows-1803', 'windows-1809']), +] diff --git a/.drone.windows.yml b/.drone.windows.yml new file mode 100644 index 0000000..71f6fd5 --- /dev/null +++ b/.drone.windows.yml @@ -0,0 +1,273 @@ +--- +kind: pipeline +name: testing + +platform: + os: windows + arch: amd64 + version: 1803 + +steps: +- name: vet + pull: always + image: golang:1.11-windowsservercore-1803 + commands: + - go vet ./... + environment: + GO111MODULE: on + volumes: + - name: gopath + path: C:\\gopath + +- name: test + pull: always + image: golang:1.11-windowsservercore-1803 + commands: + - go test -cover ./... + environment: + GO111MODULE: on + volumes: + - name: gopath + path: C:\\gopath + +volumes: +- name: gopath + temp: {} + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + +--- +kind: pipeline +name: windows-1803 + +platform: + os: windows + arch: amd64 + version: 1803 + +steps: +- name: build-push + pull: always + image: golang:1.11-windowsservercore-1803 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/windows/amd64/drone-git-action.exe" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + exclude: + - tag + +- name: build-tag + pull: always + image: golang:1.11-windowsservercore-1803 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/windows/amd64/drone-git-action.exe" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + - tag + +- name: executable + pull: always + image: golang:1.11-windowsservercore-1803 + commands: + - ./release/windows/amd64/drone-git-action.exe --help + +- name: dryrun + pull: always + image: plugins/docker:windows-1803 + settings: + daemon_off: true + dockerfile: docker/Dockerfile.windows.1803 + dry_run: true + password: + from_secret: docker_password + repo: plugins/git-action + tags: windows-1803 + username: + from_secret: docker_username + volumes: + - name: docker_pipe + path: \\\\.\\pipe\\docker_engine + when: + event: + - pull_request + +- name: publish + pull: always + image: plugins/docker:windows-1803 + settings: + auto_tag: true + auto_tag_suffix: windows-1803 + daemon_off: true + dockerfile: docker/Dockerfile.windows.1803 + password: + from_secret: docker_password + repo: plugins/git-action + username: + from_secret: docker_username + volumes: + - name: docker_pipe + path: \\\\.\\pipe\\docker_engine + when: + event: + exclude: + - pull_request + +volumes: +- name: docker_pipe + host: + path: \\\\.\\pipe\\docker_engine + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + +depends_on: +- testing + +--- +kind: pipeline +name: windows-1809 + +platform: + os: windows + arch: amd64 + version: 1809 + +steps: +- name: build-push + pull: always + image: golang:1.11-windowsservercore-1809 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/windows/amd64/drone-git-action.exe" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + exclude: + - tag + +- name: build-tag + pull: always + image: golang:1.11-windowsservercore-1809 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/windows/amd64/drone-git-action.exe" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + - tag + +- name: executable + pull: always + image: golang:1.11-windowsservercore-1809 + commands: + - ./release/windows/amd64/drone-git-action.exe --help + +- name: dryrun + pull: always + image: plugins/docker:windows-1809 + settings: + daemon_off: true + dockerfile: docker/Dockerfile.windows.1809 + dry_run: true + password: + from_secret: docker_password + repo: plugins/git-action + tags: windows-1809 + username: + from_secret: docker_username + volumes: + - name: docker_pipe + path: \\\\.\\pipe\\docker_engine + when: + event: + - pull_request + +- name: publish + pull: always + image: plugins/docker:windows-1809 + settings: + auto_tag: true + auto_tag_suffix: windows-1809 + daemon_off: true + dockerfile: docker/Dockerfile.windows.1809 + password: + from_secret: docker_password + repo: plugins/git-action + username: + from_secret: docker_username + volumes: + - name: docker_pipe + path: \\\\.\\pipe\\docker_engine + when: + event: + exclude: + - pull_request + +volumes: +- name: docker_pipe + host: + path: \\\\.\\pipe\\docker_engine + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + +depends_on: +- testing + +--- +kind: pipeline +name: notifications + +platform: + os: windows + arch: amd64 + version: 1809 + +steps: +- name: manifest + pull: always + image: plugins/manifest + settings: + auto_tag: true + ignore_missing: true + password: + from_secret: docker_password + spec: docker/manifest.tmpl + username: + from_secret: docker_username + +- name: microbadger + pull: always + image: plugins/webhook + settings: + urls: + from_secret: microbadger_url + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + +depends_on: +- windows-1803 +- windows-1809 + +... diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..79c568e --- /dev/null +++ b/.drone.yml @@ -0,0 +1,332 @@ +--- +kind: pipeline +name: testing + +platform: + os: linux + arch: amd64 + +steps: +- name: vet + pull: always + image: golang:1.11 + commands: + - go vet ./... + environment: + GO111MODULE: on + volumes: + - name: gopath + path: /go + +- name: test + pull: always + image: golang:1.11 + commands: + - go test -cover ./... + environment: + GO111MODULE: on + volumes: + - name: gopath + path: /go + +volumes: +- name: gopath + temp: {} + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + +--- +kind: pipeline +name: linux-amd64 + +platform: + os: linux + arch: amd64 + +steps: +- name: build-push + pull: always + image: golang:1.11 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/linux/amd64/drone-git-action" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + exclude: + - tag + +- name: build-tag + pull: always + image: golang:1.11 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/linux/amd64/drone-git-action" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + - tag + +- name: executable + pull: always + image: golang:1.11 + commands: + - ./release/linux/amd64/drone-git-action --help + +- name: dryrun + pull: always + image: plugins/docker:linux-amd64 + settings: + daemon_off: false + dockerfile: docker/Dockerfile.linux.amd64 + dry_run: true + password: + from_secret: docker_password + repo: plugins/git-action + tags: linux-amd64 + username: + from_secret: docker_username + when: + event: + - pull_request + +- name: publish + pull: always + image: plugins/docker:linux-amd64 + settings: + auto_tag: true + auto_tag_suffix: linux-amd64 + daemon_off: false + dockerfile: docker/Dockerfile.linux.amd64 + password: + from_secret: docker_password + repo: plugins/git-action + username: + from_secret: docker_username + when: + event: + exclude: + - pull_request + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + +depends_on: +- testing + +--- +kind: pipeline +name: linux-arm64 + +platform: + os: linux + arch: arm64 + +steps: +- name: build-push + pull: always + image: golang:1.11 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/linux/arm64/drone-git-action" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + exclude: + - tag + +- name: build-tag + pull: always + image: golang:1.11 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/linux/arm64/drone-git-action" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + - tag + +- name: executable + pull: always + image: golang:1.11 + commands: + - ./release/linux/arm64/drone-git-action --help + +- name: dryrun + pull: always + image: plugins/docker:linux-arm64 + settings: + daemon_off: false + dockerfile: docker/Dockerfile.linux.arm64 + dry_run: true + password: + from_secret: docker_password + repo: plugins/git-action + tags: linux-arm64 + username: + from_secret: docker_username + when: + event: + - pull_request + +- name: publish + pull: always + image: plugins/docker:linux-arm64 + settings: + auto_tag: true + auto_tag_suffix: linux-arm64 + daemon_off: false + dockerfile: docker/Dockerfile.linux.arm64 + password: + from_secret: docker_password + repo: plugins/git-action + username: + from_secret: docker_username + when: + event: + exclude: + - pull_request + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + +depends_on: +- testing + +--- +kind: pipeline +name: linux-arm + +platform: + os: linux + arch: arm + +steps: +- name: build-push + pull: always + image: golang:1.11 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_COMMIT_SHA:0:8}\" -a -tags netgo -o release/linux/arm/drone-git-action" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + exclude: + - tag + +- name: build-tag + pull: always + image: golang:1.11 + commands: + - "go build -v -ldflags \"-X main.version=${DRONE_TAG##v}\" -a -tags netgo -o release/linux/arm/drone-git-action" + environment: + CGO_ENABLED: 0 + GO111MODULE: on + when: + event: + - tag + +- name: executable + pull: always + image: golang:1.11 + commands: + - ./release/linux/arm/drone-git-action --help + +- name: dryrun + pull: always + image: plugins/docker:linux-arm + settings: + daemon_off: false + dockerfile: docker/Dockerfile.linux.arm + dry_run: true + password: + from_secret: docker_password + repo: plugins/git-action + tags: linux-arm + username: + from_secret: docker_username + when: + event: + - pull_request + +- name: publish + pull: always + image: plugins/docker:linux-arm + settings: + auto_tag: true + auto_tag_suffix: linux-arm + daemon_off: false + dockerfile: docker/Dockerfile.linux.arm + password: + from_secret: docker_password + repo: plugins/git-action + username: + from_secret: docker_username + when: + event: + exclude: + - pull_request + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + - "refs/pull/**" + +depends_on: +- testing + +--- +kind: pipeline +name: notifications + +platform: + os: linux + arch: amd64 + +steps: +- name: manifest + pull: always + image: plugins/manifest + settings: + auto_tag: true + ignore_missing: true + password: + from_secret: docker_password + spec: docker/manifest.tmpl + username: + from_secret: docker_username + +- name: microbadger + pull: always + image: plugins/webhook + settings: + urls: + from_secret: microbadger_url + +trigger: + ref: + - refs/heads/master + - "refs/tags/**" + +depends_on: +- linux-amd64 +- linux-arm64 +- linux-arm + +... diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 0000000..3f95605 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,9 @@ + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..e69de29 diff --git a/.github/settings.yml b/.github/settings.yml new file mode 100644 index 0000000..28400f9 --- /dev/null +++ b/.github/settings.yml @@ -0,0 +1,73 @@ +repository: + name: drone-codacy + description: Drone plugin to publish coverage to Codacy + homepage: http://plugins.drone.io/drone-plugins/drone-codacy + topics: drone, drone-plugin + + private: false + has_issues: true + has_wiki: false + has_downloads: false + + default_branch: master + + allow_squash_merge: true + allow_merge_commit: true + allow_rebase_merge: true + +labels: + - name: bug + color: d73a4a + description: Something isn't working + - name: duplicate + color: cfd3d7 + description: This issue or pull request already exists + - name: enhancement + color: a2eeef + description: New feature or request + - name: good first issue + color: 7057ff + description: Good for newcomers + - name: help wanted + color: 008672 + description: Extra attention is needed + - name: invalid + color: e4e669 + description: This doesn't seem right + - name: question + color: d876e3 + description: Further information is requested + - name: renovate + color: e99695 + description: Automated action from Renovate + - name: wontfix + color: ffffff + description: This will not be worked on + +teams: + - name: Admins + permission: admin + - name: Captain + permission: admin + - name: Maintainers + permission: push + +branches: + - name: master + protection: + required_pull_request_reviews: + required_approving_review_count: 1 + dismiss_stale_reviews: false + require_code_owner_reviews: false + dismissal_restrictions: + teams: + - Admins + - Captain + required_status_checks: + strict: true + contexts: + - continuous-integration/drone/pr + enforce_admins: false + restrictions: + users: [] + teams: [] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a38da8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +release/ +vendor/ + +coverage.out +drone-git-action diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + 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/README.md b/README.md new file mode 100644 index 0000000..0e86ec7 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# drone-git-action + +[![Build Status](http://cloud.drone.io/api/badges/drone-plugins/drone-git-action/status.svg)](http://cloud.drone.io/drone-plugins/drone-git-action) +[![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/git-action.svg)](https://microbadger.com/images/plugins/git-action "Get your own image badge on microbadger.com") +[![Go Doc](https://godoc.org/github.com/drone-plugins/drone-git-action?status.svg)](http://godoc.org/github.com/drone-plugins/drone-git-action) +[![Go Report](https://goreportcard.com/badge/github.com/drone-plugins/drone-git-action)](https://goreportcard.com/report/github.com/drone-plugins/drone-git-action) + +Drone plugin to handle Git actions like `clone`, `commit` and `push`. For the usage information and a listing of the available options please take a look at [the docs](http://plugins.drone.io/drone-plugins/drone-git-action/). + +## Build + +Build the binary with the following command: + +```console +export GOOS=linux +export GOARCH=amd64 +export CGO_ENABLED=0 +export GO111MODULE=on + +go build -v -a -tags netgo -o release/linux/amd64/drone-git-action +``` + +## Docker + +Build the Docker image with the following command: + +```console +docker build \ + --label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \ + --label org.label-schema.vcs-ref=$(git rev-parse --short HEAD) \ + --file docker/Dockerfile.linux.amd64 --tag plugins/git-action . +``` + +### Usage + +```console +docker run --rm \ + -v $(pwd):$(pwd) \ + -w $(pwd) \ + plugins/git-action +``` diff --git a/docker/Dockerfile.linux.amd64 b/docker/Dockerfile.linux.amd64 new file mode 100644 index 0000000..ae6918d --- /dev/null +++ b/docker/Dockerfile.linux.amd64 @@ -0,0 +1,11 @@ +FROM plugins/base:linux-amd64 + +LABEL maintainer="Drone.IO Community " \ + org.label-schema.name="Drone Git Action" \ + org.label-schema.vendor="Drone.IO Community" \ + org.label-schema.schema-version="1.0" + +RUN apk add --no-cache ca-certificates git openssh curl perl + +ADD release/linux/amd64/drone-git-action /bin/ +ENTRYPOINT ["/bin/drone-git-action"] diff --git a/docker/Dockerfile.linux.arm b/docker/Dockerfile.linux.arm new file mode 100644 index 0000000..d98f466 --- /dev/null +++ b/docker/Dockerfile.linux.arm @@ -0,0 +1,11 @@ +FROM plugins/base:linux-arm + +LABEL maintainer="Drone.IO Community " \ + org.label-schema.name="Drone Git Action" \ + org.label-schema.vendor="Drone.IO Community" \ + org.label-schema.schema-version="1.0" + +RUN apk add --no-cache ca-certificates git openssh curl perl + +ADD release/linux/arm/drone-git-action /bin/ +ENTRYPOINT ["/bin/drone-git-action"] diff --git a/docker/Dockerfile.linux.arm64 b/docker/Dockerfile.linux.arm64 new file mode 100644 index 0000000..d97fbfd --- /dev/null +++ b/docker/Dockerfile.linux.arm64 @@ -0,0 +1,11 @@ +FROM plugins/base:linux-arm64 + +LABEL maintainer="Drone.IO Community " \ + org.label-schema.name="Drone Git Action" \ + org.label-schema.vendor="Drone.IO Community" \ + org.label-schema.schema-version="1.0" + +RUN apk add --no-cache ca-certificates git openssh curl perl + +ADD release/linux/arm64/drone-git-action /bin/ +ENTRYPOINT ["/bin/drone-git-action"] diff --git a/docker/Dockerfile.windows.1803 b/docker/Dockerfile.windows.1803 new file mode 100644 index 0000000..8fb1b3c --- /dev/null +++ b/docker/Dockerfile.windows.1803 @@ -0,0 +1,16 @@ +# escape=` +FROM plugins/base:windows-1803 + +LABEL maintainer="Drone.IO Community " ` + org.label-schema.name="Drone Git Action" ` + org.label-schema.vendor="Drone.IO Community" ` + org.label-schema.schema-version="1.0" + +RUN Invoke-WebRequest 'https://github.com/git-for-windows/git/releases/download/v2.12.2.windows.2/MinGit-2.12.2.2-64-bit.zip' -OutFile 'git.zip'; ` + Expand-Archive -Path git.zip -DestinationPath c:\git\ -Force; ` + $env:PATH = 'c:\git\cmd;c:\git\mingw64\bin;c:\git\usr\bin;{0}' -f $env:PATH; ` + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\' -Name Path -Value $env:PATH; ` + Remove-Item -Path git.zip + +ADD release/windows/amd64/drone-git-action.exe C:/bin/drone-git-action.exe +ENTRYPOINT [ "C:\\bin\\drone-git-action.exe" ] diff --git a/docker/Dockerfile.windows.1809 b/docker/Dockerfile.windows.1809 new file mode 100644 index 0000000..8f73dc8 --- /dev/null +++ b/docker/Dockerfile.windows.1809 @@ -0,0 +1,16 @@ +# escape=` +FROM plugins/base:windows-1809 + +LABEL maintainer="Drone.IO Community " ` + org.label-schema.name="Drone Git Action" ` + org.label-schema.vendor="Drone.IO Community" ` + org.label-schema.schema-version="1.0" + +RUN Invoke-WebRequest 'https://github.com/git-for-windows/git/releases/download/v2.12.2.windows.2/MinGit-2.12.2.2-64-bit.zip' -OutFile 'git.zip'; ` + Expand-Archive -Path git.zip -DestinationPath c:\git\ -Force; ` + $env:PATH = 'c:\git\cmd;c:\git\mingw64\bin;c:\git\usr\bin;{0}' -f $env:PATH; ` + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\' -Name Path -Value $env:PATH; ` + Remove-Item -Path git.zip + +ADD release/windows/amd64/drone-git-action.exe C:/bin/drone-git-action.exe +ENTRYPOINT [ "C:\\bin\\drone-git-action.exe" ] diff --git a/docker/manifest.tmpl b/docker/manifest.tmpl new file mode 100644 index 0000000..57a1778 --- /dev/null +++ b/docker/manifest.tmpl @@ -0,0 +1,37 @@ +image: plugins/git-action:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}} +{{#if build.tags}} +tags: +{{#each build.tags}} + - {{this}} +{{/each}} +{{/if}} +manifests: + - + image: plugins/git-action:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64 + platform: + architecture: amd64 + os: linux + - + image: plugins/git-action:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64 + platform: + architecture: arm64 + os: linux + variant: v8 + - + image: plugins/git-action:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm + platform: + architecture: arm + os: linux + variant: v7 + - + image: plugins/git-action:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1803 + platform: + architecture: amd64 + os: windows + version: 1803 + - + image: plugins/git-action:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1809 + platform: + architecture: amd64 + os: windows + version: 1809 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..645a371 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/drone-plugins/drone-git-action + +go 1.12 + +require github.com/urfave/cli v1.20.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..03e08fc --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= diff --git a/main.go b/main.go new file mode 100644 index 0000000..c0ddc8c --- /dev/null +++ b/main.go @@ -0,0 +1,144 @@ +package main + +import ( + "log" + "os" + + "github.com/urfave/cli" +) + +var ( + version = "unknown" +) + +func main() { + app := cli.NewApp() + app.Name = "git-action plugin" + app.Usage = "git-action plugin" + app.Action = run + app.Version = version + app.Flags = []cli.Flag{ + cli.StringSliceFlag{ + Name: "actions", + Usage: "actions to execute", + EnvVar: "PLUGIN_ACTIONS", + }, + + cli.StringFlag{ + Name: "commit.author.name", + Usage: "git author name", + EnvVar: "PLUGIN_AUTHOR_NAME,DRONE_COMMIT_AUTHOR", + }, + cli.StringFlag{ + Name: "commit.author.email", + Usage: "git author email", + EnvVar: "PLUGIN_AUTHOR_EMAIL,DRONE_COMMIT_AUTHOR_EMAIL", + }, + + cli.StringFlag{ + Name: "netrc.machine", + Usage: "netrc machine", + EnvVar: "PLUGIN_NETRC_MACHINE,DRONE_NETRC_MACHINE", + }, + cli.StringFlag{ + Name: "netrc.username", + Usage: "netrc username", + EnvVar: "PLUGIN_NETRC_USERNAME,DRONE_NETRC_USERNAME", + }, + cli.StringFlag{ + Name: "netrc.password", + Usage: "netrc password", + EnvVar: "PLUGIN_NETRC_PASSWORD,DRONE_NETRC_PASSWORD", + }, + cli.StringFlag{ + Name: "ssh-key", + Usage: "private ssh key", + EnvVar: "PLUGIN_SSH_KEY", + }, + + cli.StringFlag{ + Name: "remote", + Usage: "url of the repo", + EnvVar: "PLUGIN_REMOTE", + }, + cli.StringFlag{ + Name: "branch", + Usage: "name of branch", + EnvVar: "PLUGIN_BRANCH", + Value: "master", + }, + + cli.StringFlag{ + Name: "path", + Usage: "path to git repo", + EnvVar: "PLUGIN_PATH", + }, + + cli.StringFlag{ + Name: "message", + Usage: "commit message", + EnvVar: "PLUGIN_MESSAGE", + }, + + cli.BoolFlag{ + Name: "force", + Usage: "force push to remote", + EnvVar: "PLUGIN_FORCE", + }, + cli.BoolFlag{ + Name: "followtags", + Usage: "push to remote with tags", + EnvVar: "PLUGIN_FOLLOWTAGS", + }, + cli.BoolFlag{ + Name: "skip-verify", + Usage: "skip ssl verification", + EnvVar: "PLUGIN_SKIP_VERIFY", + }, + cli.BoolFlag{ + Name: "empty-commit", + Usage: "allow empty commits", + EnvVar: "PLUGIN_EMPTY_COMMIT", + }, + cli.BoolFlag{ + Name: "no-verify", + Usage: "bypasses commit hooks", + EnvVar: "PLUGIN_NO_VERIFY", + }, + } + + if err := app.Run(os.Args); err != nil { + log.Fatal(err) + } +} + +func run(c *cli.Context) error { + plugin := Plugin{ + Netrc: Netrc{ + Login: c.String("netrc.username"), + Machine: c.String("netrc.machine"), + Password: c.String("netrc.password"), + }, + Commit: Commit{ + Author: Author{ + Name: c.String("commit.author.name"), + Email: c.String("commit.author.email"), + }, + }, + Config: Config{ + Actions: c.StringSlice("actions"), + Key: c.String("ssh-key"), + Remote: c.String("remote"), + Branch: c.String("branch"), + Path: c.String("path"), + Message: c.String("message"), + Force: c.Bool("force"), + FollowTags: c.Bool("followtags"), + SkipVerify: c.Bool("skip-verify"), + EmptyCommit: c.Bool("empty-commit"), + NoVerify: c.Bool("no-verify"), + }, + } + + return plugin.Exec() +} diff --git a/pipeline.libsonnet b/pipeline.libsonnet new file mode 100644 index 0000000..54a07b2 --- /dev/null +++ b/pipeline.libsonnet @@ -0,0 +1,205 @@ +local windows_pipe = '\\\\\\\\.\\\\pipe\\\\docker_engine'; +local windows_pipe_volume = 'docker_pipe'; +local test_pipeline_name = 'testing'; + +local windows(os) = os == 'windows'; + +local golang_image(os, version) = + 'golang:' + '1.11' + if windows(os) then '-windowsservercore-' + version else ''; + +{ + test(os='linux', arch='amd64', version=''):: + local is_windows = windows(os); + local golang = golang_image(os, version); + local volumes = if is_windows then [{name: 'gopath', path: 'C:\\\\gopath'}] else [{name: 'gopath', path: '/go',}]; + { + kind: 'pipeline', + name: test_pipeline_name, + platform: { + os: os, + arch: arch, + version: if std.length(version) > 0 then version, + }, + steps: [ + { + name: 'vet', + image: golang, + pull: 'always', + environment: { + GO111MODULE: 'on', + }, + commands: [ + 'go vet ./...', + ], + volumes: volumes, + }, + { + name: 'test', + image: golang, + pull: 'always', + environment: { + GO111MODULE: 'on', + }, + commands: [ + 'go test -cover ./...', + ], + volumes: volumes, + }, + ], + trigger: { + ref: [ + 'refs/heads/master', + 'refs/tags/**', + 'refs/pull/**', + ], + }, + volumes: [{name: 'gopath', temp: {}}] + }, + + build(name, os='linux', arch='amd64', version=''):: + local is_windows = windows(os); + local tag = if is_windows then os + '-' + version else os + '-' + arch; + local file_suffix = std.strReplace(tag, '-', '.'); + local volumes = if is_windows then [{ name: windows_pipe_volume, path: windows_pipe }] else []; + local golang = golang_image(os, version); + local plugin_repo = 'plugins/' + std.splitLimit(name, '-', 1)[1]; + local extension = if is_windows then '.exe' else ''; + { + kind: 'pipeline', + name: tag, + platform: { + os: os, + arch: arch, + version: if std.length(version) > 0 then version, + }, + steps: [ + { + name: 'build-push', + image: golang, + pull: 'always', + environment: { + CGO_ENABLED: '0', + GO111MODULE: 'on', + }, + commands: [ + 'go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/' + os + '/' + arch + '/' + name + extension, + ], + when: { + event: { + exclude: ['tag'], + }, + }, + }, + { + name: 'build-tag', + image: golang, + pull: 'always', + environment: { + CGO_ENABLED: '0', + GO111MODULE: 'on', + }, + commands: [ + 'go build -v -ldflags "-X main.version=${DRONE_TAG##v}" -a -tags netgo -o release/' + os + '/' + arch + '/' + name + extension, + ], + when: { + event: ['tag'], + }, + }, + { + name: 'executable', + image: golang, + pull: 'always', + commands: [ + './release/' + os + '/' + arch + '/' + name + extension + ' --help', + ], + }, + { + name: 'dryrun', + image: 'plugins/docker:' + tag, + pull: 'always', + settings: { + dry_run: true, + tags: tag, + dockerfile: 'docker/Dockerfile.' + file_suffix, + daemon_off: if is_windows then 'true' else 'false', + repo: plugin_repo, + username: { from_secret: 'docker_username' }, + password: { from_secret: 'docker_password' }, + }, + volumes: if std.length(volumes) > 0 then volumes, + when: { + event: ['pull_request'], + }, + }, + { + name: 'publish', + image: 'plugins/docker:' + tag, + pull: 'always', + settings: { + auto_tag: true, + auto_tag_suffix: tag, + daemon_off: if is_windows then 'true' else 'false', + dockerfile: 'docker/Dockerfile.' + file_suffix, + repo: plugin_repo, + username: { from_secret: 'docker_username' }, + password: { from_secret: 'docker_password' }, + }, + volumes: if std.length(volumes) > 0 then volumes, + when: { + event: { + exclude: ['pull_request'], + }, + }, + }, + ], + trigger: { + ref: [ + 'refs/heads/master', + 'refs/tags/**', + 'refs/pull/**', + ], + }, + depends_on: [test_pipeline_name], + volumes: if is_windows then [{ name: windows_pipe_volume, host: { path: windows_pipe } }], + }, + + notifications(os='linux', arch='amd64', version='', depends_on=[]):: + { + kind: 'pipeline', + name: 'notifications', + platform: { + os: os, + arch: arch, + version: if std.length(version) > 0 then version, + }, + steps: [ + { + name: 'manifest', + image: 'plugins/manifest', + pull: 'always', + settings: { + username: { from_secret: 'docker_username' }, + password: { from_secret: 'docker_password' }, + spec: 'docker/manifest.tmpl', + ignore_missing: true, + auto_tag: true, + }, + }, + { + name: 'microbadger', + image: 'plugins/webhook', + pull: 'always', + settings: { + urls: { from_secret: 'microbadger_url' }, + }, + }, + ], + trigger: { + ref: [ + 'refs/heads/master', + 'refs/tags/**', + ], + }, + depends_on: depends_on, + }, +} diff --git a/plugin.go b/plugin.go new file mode 100644 index 0000000..66363a4 --- /dev/null +++ b/plugin.go @@ -0,0 +1,223 @@ +package main + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + + "github.com/drone-plugins/drone-git-action/repo" +) + +type ( + Netrc struct { + Machine string + Login string + Password string + } + + Commit struct { + Author Author + } + + Author struct { + Name string + Email string + } + + Config struct { + Actions []string + Key string + Remote string + Branch string + Path string + Message string + Force bool + FollowTags bool + SkipVerify bool + EmptyCommit bool + NoVerify bool + } + + Plugin struct { + Netrc Netrc + Commit Commit + Config Config + } +) + +func (p *Plugin) Exec() error { + if err := p.HandlePath(); err != nil { + return err + } + + if err := p.WriteConfig(); err != nil { + return err + } + + if err := p.WriteKey(); err != nil { + return err + } + + if err := p.WriteNetrc(); err != nil { + return err + } + + for _, action := range p.Config.Actions { + switch action { + case "clone": + if err := p.InitRepo(); err != nil { + return err + } + + if err := p.AddRemote(); err != nil { + return err + } + + if err := p.FetchSource(); err != nil { + return err + } + + if err := p.CheckoutHead(); err != nil { + return err + } + case "commit": + if err := p.HandleCommit(); err != nil { + return err + } + case "push": + if err := p.HandlePush(); err != nil { + return err + } + default: + return fmt.Errorf("Unknown action %s", action) + } + } + + return nil +} + +// HandlePath changes to a different directory if required +func (p Plugin) HandlePath() error { + if p.Config.Path != "" { + if err := os.MkdirAll(p.Config.Path, os.ModePerm); err != nil { + return err + } + + if err := os.Chdir(p.Config.Path); err != nil { + return err + } + } + + return nil +} + +// WriteConfig writes all required configurations. +func (p Plugin) WriteConfig() error { + if err := repo.GlobalName(p.Commit.Author.Name).Run(); err != nil { + return err + } + + if err := repo.GlobalUser(p.Commit.Author.Email).Run(); err != nil { + return err + } + + if p.Config.SkipVerify { + if err := repo.SkipVerify().Run(); err != nil { + return err + } + } + + return nil +} + +// WriteKey writes the private SSH key. +func (p Plugin) WriteKey() error { + return repo.WriteKey( + p.Config.Key, + ) +} + +// WriteNetrc writes the netrc config. +func (p Plugin) WriteNetrc() error { + return repo.WriteNetrc( + p.Netrc.Machine, + p.Netrc.Login, + p.Netrc.Password, + ) +} + +// InitRepo initializes the repository. +func (p Plugin) InitRepo() error { + if isDirEmpty(filepath.Join(p.Config.Path, ".git")) { + return execute(exec.Command( + "git", + "init", + )) + } + + return nil +} + +// AddRemote adds a remote to repository. +func (p Plugin) AddRemote() error { + if p.Config.Remote != "" { + if err := execute(repo.RemoteAdd("origin", p.Config.Remote)); err != nil { + return err + } + } + + return nil +} + +// FetchSource fetches the source from remote. +func (p Plugin) FetchSource() error { + return execute(exec.Command( + "git", + "fetch", + "origin", + fmt.Sprintf("+%s:", p.Config.Branch), + )) +} + +// CheckoutHead handles branch checkout. +func (p Plugin) CheckoutHead() error { + return execute(exec.Command( + "git", + "checkout", + "-qf", + "FETCH_HEAD", + )) +} + +// HandleCommit commits changes locally. +func (p Plugin) HandleCommit() error { + if err := execute(repo.Add()); err != nil { + return err + } + + if err := execute(repo.TestCleanTree()); err != nil { + if err := execute(repo.ForceCommit(p.Config.Message, p.Config.NoVerify)); err != nil { + return err + } + } else { + if p.Config.EmptyCommit { + if err := execute(repo.EmptyCommit(p.Config.Message, p.Config.NoVerify)); err != nil { + return err + } + } + } + + return nil +} + +// HandlePush pushs changes to remote. +func (p Plugin) HandlePush() error { + return execute(repo.RemotePushNamedBranch( + "origin", + p.Config.Branch, + p.Config.Branch, + p.Config.Force, + p.Config.FollowTags, + )) +} diff --git a/repo/commit.go b/repo/commit.go new file mode 100644 index 0000000..d2581ed --- /dev/null +++ b/repo/commit.go @@ -0,0 +1,85 @@ +package repo + +import ( + "os/exec" +) + +const defaultCommitMessage = "[skip ci] Commit dirty state" + +// ForceAdd forces the addition of all dirty files. +func ForceAdd() *exec.Cmd { + cmd := exec.Command( + "git", + "add", + "--all", + "--force") + + return cmd +} + +// Add updates the index to match the working tree. +func Add() *exec.Cmd { + cmd := exec.Command( + "git", + "add", + "--all") + + return cmd +} + +// TestCleanTree returns non-zero if diff between index and local repository +func TestCleanTree() *exec.Cmd { + cmd := exec.Command( + "git", + "diff-index", + "--quiet", + "HEAD", + "--ignore-submodules") + + return cmd +} + +// EmptyCommit simply create an empty commit +func EmptyCommit(msg string, noVerify bool) *exec.Cmd { + if msg == "" { + msg = defaultCommitMessage + } + + cmd := exec.Command( + "git", + "commit", + "--allow-empty", + "-m", + msg, + ) + + if noVerify { + cmd.Args = append( + cmd.Args, + "--no-verify") + } + + return cmd +} + +// ForceCommit commits every change while skipping CI. +func ForceCommit(msg string, noVerify bool) *exec.Cmd { + if msg == "" { + msg = defaultCommitMessage + } + + cmd := exec.Command( + "git", + "commit", + "-m", + msg, + ) + + if noVerify { + cmd.Args = append( + cmd.Args, + "--no-verify") + } + + return cmd +} diff --git a/repo/config.go b/repo/config.go new file mode 100644 index 0000000..3bef72d --- /dev/null +++ b/repo/config.go @@ -0,0 +1,29 @@ +package repo + +import ( + "os/exec" +) + +// GlobalUser sets the global git author email. +func GlobalUser(email string) *exec.Cmd { + cmd := exec.Command( + "git", + "config", + "--global", + "user.email", + email) + + return cmd +} + +// GlobalName sets the global git author name. +func GlobalName(author string) *exec.Cmd { + cmd := exec.Command( + "git", + "config", + "--global", + "user.name", + author) + + return cmd +} diff --git a/repo/key.go b/repo/key.go new file mode 100644 index 0000000..bb6afef --- /dev/null +++ b/repo/key.go @@ -0,0 +1,100 @@ +package repo + +import ( + "fmt" + "io/ioutil" + "os" + "os/user" + "path/filepath" +) + +const netrcFile = ` +machine %s +login %s +password %s +` + +const configFile = ` +Host * +StrictHostKeyChecking no +UserKnownHostsFile=/dev/null +` + +// WriteKey writes the private key. +func WriteKey(privateKey string) error { + if privateKey == "" { + return nil + } + + home := "/root" + + if currentUser, err := user.Current(); err == nil { + home = currentUser.HomeDir + } + + sshpath := filepath.Join( + home, + ".ssh") + + if err := os.MkdirAll(sshpath, 0700); err != nil { + return err + } + + confpath := filepath.Join( + sshpath, + "config") + + if err := ioutil.WriteFile( + confpath, + []byte(configFile), + 0700, + ); err != nil { + return err + } + + privpath := filepath.Join( + sshpath, + "id_rsa", + ) + + if err := ioutil.WriteFile( + privpath, + []byte(privateKey), + 0600, + ); err != nil { + return err + } + + return nil +} + +// WriteNetrc writes the netrc file. +func WriteNetrc(machine, login, password string) error { + if machine == "" { + return nil + } + + netrcContent := fmt.Sprintf( + netrcFile, + machine, + login, + password, + ) + + home := "/root" + + if currentUser, err := user.Current(); err == nil { + home = currentUser.HomeDir + } + + netpath := filepath.Join( + home, + ".netrc", + ) + + return ioutil.WriteFile( + netpath, + []byte(netrcContent), + 0600, + ) +} diff --git a/repo/remote.go b/repo/remote.go new file mode 100644 index 0000000..82082c7 --- /dev/null +++ b/repo/remote.go @@ -0,0 +1,56 @@ +package repo + +import ( + "os/exec" +) + +// RemoteRemove drops the defined remote from a git repo. +func RemoteRemove(name string) *exec.Cmd { + cmd := exec.Command( + "git", + "remote", + "rm", + name) + + return cmd +} + +// RemoteAdd adds an additional remote to a git repo. +func RemoteAdd(name, url string) *exec.Cmd { + cmd := exec.Command( + "git", + "remote", + "add", + name, + url) + + return cmd +} + +// RemotePush pushs the changes from the local head to a remote branch.. +func RemotePush(remote, branch string, force bool, followtags bool) *exec.Cmd { + return RemotePushNamedBranch(remote, "HEAD", branch, force, followtags) +} + +// RemotePushNamedBranch puchs changes from a local to a remote branch. +func RemotePushNamedBranch(remote, localbranch string, branch string, force bool, followtags bool) *exec.Cmd { + cmd := exec.Command( + "git", + "push", + remote, + localbranch+":"+branch) + + if force { + cmd.Args = append( + cmd.Args, + "--force") + } + + if followtags { + cmd.Args = append( + cmd.Args, + "--follow-tags") + } + + return cmd +} diff --git a/repo/verify.go b/repo/verify.go new file mode 100644 index 0000000..8e4b767 --- /dev/null +++ b/repo/verify.go @@ -0,0 +1,17 @@ +package repo + +import ( + "os/exec" +) + +// SkipVerify disables globally the git ssl verification. +func SkipVerify() *exec.Cmd { + cmd := exec.Command( + "git", + "config", + "--global", + "http.sslVerify", + "false") + + return cmd +} diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..9507012 --- /dev/null +++ b/utils.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "io" + "os" + "os/exec" + "strings" +) + +// helper function to simply wrap os execte command. +func execute(cmd *exec.Cmd) error { + fmt.Println("+", strings.Join(cmd.Args, " ")) + + cmd.Env = os.Environ() + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + + return cmd.Run() +} + +// helper function returns true if directory dir is empty. +func isDirEmpty(dir string) bool { + f, err := os.Open(dir) + + if err != nil { + return true + } + + defer f.Close() + + _, err = f.Readdir(1) + return err == io.EOF +}