From 0f4c512f91e08d4d643e6307c5c8d8e3d37b81ee Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Wed, 8 Aug 2018 14:43:53 -0700 Subject: [PATCH] initial commit --- .dockerignore | 7 + .drone.yml | 53 +++++++ .github/issue_template.md | 9 ++ .github/pull_request_template.md | 0 LICENSE | 191 +++++++++++++++++++++++ docker/Dockerfile.linux.amd64 | 5 + docker/Dockerfile.linux.arm | 5 + docker/Dockerfile.linux.arm64 | 5 + docker/Dockerfile.windows.amd64 | 1 + posix/clone | 56 +++++++ posix/clone-commit | 17 ++ posix/clone-pull-request | 20 +++ posix/clone-tag | 17 ++ posix/fixtures.sh | 40 +++++ posix/fixtures.tar | Bin 0 -> 66048 bytes posix/posix.go | 1 + posix/posix_test.go | 259 +++++++++++++++++++++++++++++++ 17 files changed, 686 insertions(+) create mode 100644 .dockerignore create mode 100644 .drone.yml create mode 100644 .github/issue_template.md create mode 100644 .github/pull_request_template.md create mode 100644 LICENSE 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.amd64 create mode 100755 posix/clone create mode 100755 posix/clone-commit create mode 100755 posix/clone-pull-request create mode 100755 posix/clone-tag create mode 100755 posix/fixtures.sh create mode 100644 posix/fixtures.tar create mode 100644 posix/posix.go create mode 100644 posix/posix_test.go diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2f8ee75 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.github +.gitignore +.drone.yml +LICENSE +README.md +*/fixtures* +*.go diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..44de69e --- /dev/null +++ b/.drone.yml @@ -0,0 +1,53 @@ +--- +metadata: + name: linux-amd64 + +platform: + name: linux/amd64 + +pipeline: +- test: + image: golang:1.10 + commands: + - cd posix + - tar -xf fixtures.tar -C / + - go test -v + +- publish: + image: plugins/docker + dockerfile: docker/Dockerfile.linux.amd64 + repo: drone/git + auto_tag: true + auto_tag_suffix: linux-amd64 + dry_run: true + when: + event: + - push + - tag + +--- +metadata: + name: linux-arm64 + +platform: + name: linux/arm64 + +pipeline: + test: + image: arm64v8/golang:1.10 + commands: + - cd posix + - tar -xf fixtures.tar -C / + - go test -v + + publish: + image: plugins/docker:linux-arm64 + dockerfile: docker/Dockerfile.linux.arm64 + repo: drone/git + auto_tag: true + auto_tag_suffix: linux-arm64 + dry_run: true + when: + event: + - push + - tag 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/LICENSE b/LICENSE new file mode 100644 index 0000000..f2e144f --- /dev/null +++ b/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://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 + + Copyright 2017 Drone.IO, Inc. + + 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 + + https://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/docker/Dockerfile.linux.amd64 b/docker/Dockerfile.linux.amd64 new file mode 100644 index 0000000..3c4cb6b --- /dev/null +++ b/docker/Dockerfile.linux.amd64 @@ -0,0 +1,5 @@ +FROM alpine:3.6 +RUN apk add --no-cache ca-certificates git openssh curl perl + +ADD posix/* /usr/local/bin/ +ENTRYPOINT ["/usr/local/bin/clone"] diff --git a/docker/Dockerfile.linux.arm b/docker/Dockerfile.linux.arm new file mode 100644 index 0000000..3c4cb6b --- /dev/null +++ b/docker/Dockerfile.linux.arm @@ -0,0 +1,5 @@ +FROM alpine:3.6 +RUN apk add --no-cache ca-certificates git openssh curl perl + +ADD posix/* /usr/local/bin/ +ENTRYPOINT ["/usr/local/bin/clone"] diff --git a/docker/Dockerfile.linux.arm64 b/docker/Dockerfile.linux.arm64 new file mode 100644 index 0000000..f8991fb --- /dev/null +++ b/docker/Dockerfile.linux.arm64 @@ -0,0 +1,5 @@ +FROM arm64v8/alpine:3.6 +RUN apk add --no-cache ca-certificates git openssh curl perl + +ADD posix/* /usr/local/bin/ +ENTRYPOINT ["/usr/local/bin/clone"] diff --git a/docker/Dockerfile.windows.amd64 b/docker/Dockerfile.windows.amd64 new file mode 100644 index 0000000..afcaa9d --- /dev/null +++ b/docker/Dockerfile.windows.amd64 @@ -0,0 +1 @@ +FROM microsoft/nanoserver:10.0.14393.1593 diff --git a/posix/clone b/posix/clone new file mode 100755 index 0000000..11f88fd --- /dev/null +++ b/posix/clone @@ -0,0 +1,56 @@ +#!/bin/sh + +if [[ ! -z "${DRONE_WORKSPACE}" ]]; then + cd ${DRONE_WORKSPACE} +fi + +# if the netrc enviornment variables exist, write +# the netrc file. + +if [[ ! -z "${DRONE_NETRC_MACHINE}" ]]; then + cat < /root/.netrc +machine ${DRONE_NETRC_MACHINE} +login ${DRONE_NETRC_USERNAME} +password ${DRONE_NETRC_PASSWORD} +EOF +fi + +# if the ssh_key environment variable exists, write +# the ssh key and add the netrc machine to the +# known hosts file. + +if [[ ! -z "${SSH_KEY}" ]]; then + mkdir /root/.ssh + echo -n "$SSH_KEY" > /root/.ssh/id_rsa + chmod 600 /root/.ssh/id_rsa + + touch /root/.ssh/known_hosts + chmod 600 /root/.ssh/known_hosts + ssh-keyscan -H ${DRONE_NETRC_MACHINE} > /etc/ssh/ssh_known_hosts 2> /dev/null +fi + +# configure git global behavior and parameters via the +# following environment variables: + +export GIT_AUTHOR_NAME=${DRONE_COMMIT_AUTHOR_NAME=drone} +export GIT_AUTHOR_EMAIL=${DRONE_COMMIT_AUTHOR_EMAIL=drone@localhost} +export GIT_COMMITTER_NAME=${GIT_AUTHOR_NAME} +export GIT_COMMITTER_EMAIL=${GIT_AUTHOR_EMAIL} +# GIT_SSL_NO_VERIFY= + + +# invoke the sub-script based on the drone event type. +# TODO we should ultimately look at the ref, since +# we need something compatible with deployment events. + +case $DRONE_BUILD_EVENT in +pull_request) + clone-pull-request + ;; +tag) + clone-tag + ;; +*) + clone-commit + ;; +esac diff --git a/posix/clone-commit b/posix/clone-commit new file mode 100755 index 0000000..641a9ca --- /dev/null +++ b/posix/clone-commit @@ -0,0 +1,17 @@ +#!/bin/sh + +FLAGS="" +if [[ ! -z "${PLUGIN_DEPTH}" ]]; then + FLAGS="--depth=${PLUGIN_DEPTH}" +fi + +if [ ! -d .git ]; then + git init + git remote add origin ${DRONE_REMOTE_URL} +fi + +set -e +set -x + +git fetch ${FLAGS} origin +refs/heads/${DRONE_COMMIT_BRANCH}: +git checkout ${DRONE_COMMIT_SHA} -b ${DRONE_COMMIT_BRANCH} diff --git a/posix/clone-pull-request b/posix/clone-pull-request new file mode 100755 index 0000000..10b309e --- /dev/null +++ b/posix/clone-pull-request @@ -0,0 +1,20 @@ +#!/bin/sh + +FLAGS="" +if [[ ! -z "${PLUGIN_DEPTH}" ]]; then + FLAGS="--depth=${PLUGIN_DEPTH}" +fi + +if [ ! -d .git ]; then + git init + git remote add origin ${DRONE_REMOTE_URL} +fi + +set -e +set -x + +git fetch ${FLAGS} origin +refs/heads/${DRONE_COMMIT_BRANCH}: +git checkout ${DRONE_COMMIT_BRANCH} + +git fetch origin ${DRONE_COMMIT_REF}: +git rebase ${DRONE_COMMIT_SHA} diff --git a/posix/clone-tag b/posix/clone-tag new file mode 100755 index 0000000..d02378c --- /dev/null +++ b/posix/clone-tag @@ -0,0 +1,17 @@ +#!/bin/sh + +FLAGS="" +if [[ ! -z "${PLUGIN_DEPTH}" ]]; then + FLAGS="--depth=${PLUGIN_DEPTH}" +fi + +if [ ! -d .git ]; then + git init + git remote add origin ${DRONE_REMOTE_URL} +fi + +set -e +set -x + +git fetch ${FLAGS} origin +refs/tags/${DRONE_TAG}: +git checkout -qf FETCH_HEAD diff --git a/posix/fixtures.sh b/posix/fixtures.sh new file mode 100755 index 0000000..f3ef1aa --- /dev/null +++ b/posix/fixtures.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# This script creates a git repository and seeds with +# commit history. Used by unit tests. + +set -e +set -x + +rm -rf /tmp/remote/greeting +mkdir -p /tmp/remote/greeting +pushd /tmp/remote/greeting + +git init + +echo "hi world" > hello.txt +git add hello.txt +git commit -m "say hi" +git tag v1.0.0 + +echo "hello world" > hello.txt +git add hello.txt +git commit -m "say hello" +git tag v1.1.0 + +git checkout -b fr + +echo "salut monde" > hello.txt +git add hello.txt +git commit -m "say hello in french" +git tag v2.0.0 + +echo "bonjour monde" > hello.txt +git add hello.txt +git commit -m "say hello en francais" +git tag v2.1.0 + +git checkout master + +popd +tar -cvf fixtures.tar /tmp/remote/greeting diff --git a/posix/fixtures.tar b/posix/fixtures.tar new file mode 100644 index 0000000000000000000000000000000000000000..c26335677c461f0da1dec1015129dd1ceb5f0ff6 GIT binary patch literal 66048 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